Friday 7 November 2014

2014 reversing the reverse-challenge binary from coursera.

One more reverse challenge from coursera malware class. This is the 2014 class.
similar to previous challenge which is posted in previous blog.

seed@seed-desktop:~/projects/2$ ./reverse-challenge
Are you feeling lucky today? s
^C
[6]+  Stopped                 ./reverse-challenge

seed@seed-desktop:~/projects/2$ file reverse-challenge
reverse-challenge: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, stripped

seed@seed-desktop:~/projects/2$ grep "41 72" rc
 8048cba:    00 41 72                 add    %al,0x72(%ecx)

 8048a54:       c7 04 24 bb 8c 04 08    movl   $0x8048cbb,(%esp)
 8048a5b:       e8 c0 fa ff ff          call   8048520 <printf@plt>
This is where the question "Are you feeling lucky today?" gets asked as detailed in previous blog.

Then we have switch of 0x43, 0x4e and 0x41.

0x4e (N) case is interesting which jumps to 0x8048743 others are dead-end.

 804872d:       55                      push   %ebp
 804872e:       89 e5                   mov    %esp,%ebp
 8048730:       31 db                   xor    %ebx,%ebx
 8048732:       6a 04                   push   $0x4
 8048734:       5b                      pop    %ebx
 8048735:       01 e3                   add    %esp,%ebx
 8048737:       8b 1b                   mov    (%ebx),%ebx
 8048739:       83 c3 10                add    $0x10,%ebx
 804873c:       b8 11 00 00 00          mov    $0x11,%eax
 8048741:       5d                      pop    %ebp
 8048742:       c3                      ret
 8048743:       55                      push   %ebp
 8048744:       89 e5                   mov    %esp,%ebp
 8048746:       83 ec 28                sub    $0x28,%esp
 8048749:       8b 45 08                mov    0x8(%ebp),%eax
 804874c:       89 45 f4                mov    %eax,-0xc(%ebp)
 804874f:       53                      push   %ebx
 8048750:       31 db                   xor    %ebx,%ebx
 8048752:       6a 30                   push   $0x30
 8048754:       5b                      pop    %ebx
 8048755:       01 e3                   add    %esp,%ebx
 8048757:       e8 d1 ff ff ff          call   804872d <close@plt+0x10d>
 804875c:       8b 55 0c                mov    0xc(%ebp),%edx
 804875f:       50                      push   %eax
 8048760:       31 c0                   xor    %eax,%eax
 8048762:       6a 0c                   push   $0xc
 8048764:       58                      pop    %eax
 8048765:       01 d0                   add    %edx,%eax
 8048767:       50                      push   %eax
 8048768:       53                      push   %ebx
 8048769:       c3                      ret
 804876a:       b8 01 c7 45 f0          mov    $0xf045c701,%eax
 804876a:       b8 01 c7 45 f0          mov    $0xf045c701,%eax
 804876f:       fa                      cli
 8048770:       00 00                   add    %al,(%eax)
 8048772:       00 58 eb                add    %bl,-0x15(%eax)
 8048775:       27                      daa
 8048776:       8b 45 f4                mov    -0xc(%ebp),%eax
 8048779:       0f b6 00                movzbl (%eax),%eax
 804877c:       83 c0 01                add    $0x1,%eax
 804877f:       89 c2                   mov    %eax,%edx
 8048781:       8b 45 f4                mov    -0xc(%ebp),%eax
 8048784:       88 10                   mov    %dl,(%eax)
 8048786:       8b 45 f4                mov    -0xc(%ebp),%eax
 8048789:       0f b6 00                movzbl (%eax),%eax
 804878c:       8b 55 f0                mov    -0x10(%ebp),%edx
 804878f:       83 e2 2b                and    $0x2b,%edx
 8048792:       31 c2                   xor    %eax,%edx
 8048794:       8b 45 f4                mov    -0xc(%ebp),%eax
 8048797:       88 10                   mov    %dl,(%eax)
 8048799:       83 45 f4 01             addl   $0x1,-0xc(%ebp)
 804879d:       8b 45 f4                mov    -0xc(%ebp),%eax
 80487a0:       0f b6 00                movzbl (%eax),%eax
 80487a3:       84 c0                   test   %al,%al
 80487a5:       75 cf                   jne    8048776 <close@plt+0x156>
 80487a7:       c7 44 24 04 80 8c 04    movl   $0x8048c80,0x4(%esp)
 80487ae:       08
 80487af:       8b 45 08                mov    0x8(%ebp),%eax
 80487b2:       89 04 24                mov    %eax,(%esp)
 80487b5:       e8 46 fd ff ff          call   8048500 <strcmp@plt>
 80487ba:       85 c0                   test   %eax,%eax
 80487bc:       75 07                   jne    80487c5 <close@plt+0x1a5>
 80487be:       b8 01 00 00 00          mov    $0x1,%eax
 80487c3:       eb 05                   jmp    80487ca <close@plt+0x1aa>
 80487c5:       b8 00 00 00 00          mov    $0x0,%eax
 80487ca:       c9                      leave
 80487cb:       c3                      ret

(gdb) p/x 0x5c + 0x10
$3 = 0x6c

This code just adds 0x10 to 804875c and jumps to 804876c. compared to previous example it has a detour by calling a function
but the gist is it jumps to middle of instruction at
804876a:       b8 01 c7 45 f0          mov    $0xf045c701,%eax

The actual disassembly is as in prev blog starting at 804876c.
   0:    c7 45 f0 fa 00 00 00     movl   $0xfa,-0x10(%ebp)
   7:    58                       pop    %eax
   8:    eb 17                    jmp    0x21

Next is the loop doing the magic conversion of input and strcmp thereafter.  
 8048776:       8b 45 f4                mov    -0xc(%ebp),%eax
 8048779:       0f b6 00                movzbl (%eax),%eax
 804877c:       83 c0 01                add    $0x1,%eax
 804877f:       89 c2                   mov    %eax,%edx
 8048781:       8b 45 f4                mov    -0xc(%ebp),%eax
 8048784:       88 10                   mov    %dl,(%eax)
 8048786:       8b 45 f4                mov    -0xc(%ebp),%eax
 8048789:       0f b6 00                movzbl (%eax),%eax
 804878c:       8b 55 f0                mov    -0x10(%ebp),%edx
 804878f:       83 e2 2b                and    $0x2b,%edx
 8048792:       31 c2                   xor    %eax,%edx
 8048794:       8b 45 f4                mov    -0xc(%ebp),%eax
 8048797:       88 10                   mov    %dl,(%eax)
 8048799:       83 45 f4 01             addl   $0x1,-0xc(%ebp)
 804879d:       8b 45 f4                mov    -0xc(%ebp),%eax
 80487a0:       0f b6 00                movzbl (%eax),%eax
 80487a3:       84 c0                   test   %al,%al
 80487a5:       75 cf                   jne    8048776 <close@plt+0x156>

This is modified input = (input +1)  ^ 0x2a (where 0x2a is got from 0xfa & 0x2b).

 80487a7:       c7 44 24 04 80 8c 04    movl   $0x8048c80,0x4(%esp)
 80487ae:       08
 80487af:       8b 45 08                mov    0x8(%ebp),%eax
 80487b2:       89 04 24                mov    %eax,(%esp)
 80487b5:       e8 46 fd ff ff          call   8048500 <strcmp@plt>
 80487ba:       85 c0                   test   %eax,%eax
 80487bc:       75 07                   jne    80487c5 <close@plt+0x1a5>
 80487be:       b8 01 00 00 00          mov    $0x1,%eax
 80487c3:       eb 05                   jmp    80487ca <close@plt+0x1aa>
 80487c5:       b8 00 00 00 00          mov    $0x0,%eax
 80487ca:       c9                      leave
 80487cb:       c3                      ret

The modified input is getting strcmp with string at 0x8048c80. 
(gdb) x/s 0x8048c80
0x8048c80:     "@EHJ~@DZEL"

modified input == "@EHJ~@DZEL"

so input = (modified input ^ 0x2a)  - 1

seed@seed-desktop:~/projects/2$ python -c 'print "".join([chr((ord (k)^0x2A)-1) for k in "@EHJ~@DZEL"])'
ina_Simone

The first character of input is 'N'.
So the secret input is Nina_Simone.

seed@seed-desktop:~/projects/2$ ./reverse-challenge
Are you feeling lucky today? Nina_Simone         
[+] WooT! THE KEY IS: Nina_Simone
[+] If you want, now open a terminal and type:

echo "Nina_Simone" | nc 134.219.148.8 8080

Reversing a bonus challenge binary which appeared in coursera malware class.

The challenge is to crack the challenge by answering it right.

seed@seed-desktop:~/projects/2$ ./bonus_reverse-challenge
Are you feeling lucky today? 1
^C
[2]+  Stopped                 ./bonus_reverse-challenge

seed@seed-desktop:~/projects/2$ file ./bonus_reverse-challenge
./bonus_reverse-challenge: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, stripped

This is a stripped binary so cannot find main in objdump output. So the guess is since "Are you feeling lucky today?" is printed by
a call to printf with the string as an argument in the program. we need to find where the string is and where is getting loaded to stack
just before a call to printf, then we know that we are somewhere in code section and check what happens after that to our input.

(gdb) p/x 'A'
$1 = 0x41
(gdb) p/x 'r'
$2 = 0x72
(gdb)

"Are you feeling lucky today?" starts with 'A' and 'r' so we try to find 41 and 72 in objdump.

seed@seed-desktop:~/projects/2$ objdump -D ./bonus_reverse-challenge > obj
seed@seed-desktop:~/projects/2$ grep -n "41 72" obj
1018: 8048bfa:    00 41 72                 add    %al,0x72(%ecx)
(gdb) x/s 0x8048bfb
0x8048bfb:     "Are you feeling lucky today? "
searching 8048bfb to figuring who is loading it to stack in objdump gives.
 8048997:       b8 fb 8b 04 08          mov    $0x8048bfb,%eax
 804899c:       89 04 24                mov    %eax,(%esp)
 804899f:       e8 0c fb ff ff          call   80484b0 <printf@plt>
 80489a4:       a1 60 a0 04 08          mov    0x804a060,%eax
 80489a9:       89 04 24                mov    %eax,(%esp)
 80489ac:       e8 0f fb ff ff          call   80484c0 <fflush@plt>
 80489b1:       c7 44 24 08 ff 01 00    movl   $0x1ff,0x8(%esp)
 80489b8:       00
 80489b9:       8d 44 24 20             lea    0x20(%esp),%eax
 80489bd:       89 44 24 04             mov    %eax,0x4(%esp)
 80489c1:       c7 04 24 00 00 00 00    movl   $0x0,(%esp)
 80489c8:       e8 d3 fa ff ff          call   80484a0 <read@plt>
 80489cd:       8d 44 24 20             lea    0x20(%esp),%eax
 80489d1:       c7 44 24 1c ff ff ff    movl   $0xffffffff,0x1c(%esp)
 80489d8:       ff
 80489d9:       89 c2                   mov    %eax,%edx
 80489db:       b8 00 00 00 00          mov    $0x0,%eax
 80489e0:       8b 4c 24 1c             mov    0x1c(%esp),%ecx
 80489e4:       89 d7                   mov    %edx,%edi
 80489e6:       f2 ae                   repnz scas %es:(%edi),%al
 80489e8:       89 c8                   mov    %ecx,%eax
 80489ea:       f7 d0                   not    %eax
 80489ec:       83 e8 01                sub    $0x1,%eax
 80489ef:       89 84 24 28 02 00 00    mov    %eax,0x228(%esp)
 80489f6:       8b 84 24 28 02 00 00    mov    0x228(%esp),%eax
 80489fd:       83 e8 01                sub    $0x1,%eax
 8048a00:       0f b6 44 04 20          movzbl 0x20(%esp,%eax,1),%eax
 8048a05:       3c 0a                   cmp    $0xa,%al
 8048a07:       75 0f                   jne    8048a18 <close@plt+0x498>
 8048a09:       8b 84 24 28 02 00 00    mov    0x228(%esp),%eax
 8048a10:       83 e8 01                sub    $0x1,%eax
 8048a13:       c6 44 04 20 00          movb   $0x0,0x20(%esp,%eax,1)
 8048a18:       0f b6 44 24 20          movzbl 0x20(%esp),%eax
 8048a1d:       0f be c0                movsbl %al,%eax
 8048a20:       83 f8 42                cmp    $0x42,%eax
 8048a23:       74 17                   je     8048a3c <close@plt+0x4bc>
 8048a25:       83 f8 43                cmp    $0x43,%eax
 8048a28:       74 1f                   je     8048a49 <close@plt+0x4c9>
 8048a2a:       83 f8 41                cmp    $0x41,%eax
 8048a2d:       75 27                   jne    8048a56 <close@plt+0x4d6>
 8048a2f:       c7 84 24 2c 02 00 00    movl   $0x804872b,0x22c(%esp)
 8048a36:       2b 87 04 08
 8048a3a:       eb 1c                   jmp    8048a58 <close@plt+0x4d8>
 8048a3c:       c7 84 24 2c 02 00 00    movl   $0x8048644,0x22c(%esp)
 8048a43:       44 86 04 08
 8048a47:       eb 0f                   jmp    8048a58 <close@plt+0x4d8>
 8048a49:       c7 84 24 2c 02 00 00    movl   $0x80486ca,0x22c(%esp)
 8048a50:       ca 86 04 08
 8048a54:       eb 02                   jmp    8048a58 <close@plt+0x4d8>
 8048a56:       eb fe                   jmp    8048a56 <close@plt+0x4d6>
 8048a58:       0f b6 44 24 20          movzbl 0x20(%esp),%eax
 8048a5d:       0f be c0                movsbl %al,%eax
 8048a60:       83 e8 42                sub    $0x42,%eax
 8048a63:       89 84 24 24 02 00 00    mov    %eax,0x224(%esp)
 8048a6a:       8b 84 24 24 02 00 00    mov    0x224(%esp),%eax
 8048a71:       89 44 24 04             mov    %eax,0x4(%esp)
 8048a75:       8d 44 24 20             lea    0x20(%esp),%eax
 8048a79:       83 c0 01                add    $0x1,%eax
 8048a7c:       89 04 24                mov    %eax,(%esp)
 8048a7f:       8b 84 24 2c 02 00 00    mov    0x22c(%esp),%eax
 8048a86:       ff d0                   call   *%eax
 8048a88:       89 84 24 20 02 00 00    mov    %eax,0x220(%esp)
 8048a8f:       83 bc 24 20 02 00 00    cmpl   $0x0,0x220(%esp)
 8048a96:       00
 8048a97:       74 1a                   je     8048ab3 <close@plt+0x533>
 8048a99:       b8 19 8c 04 08          mov    $0x8048c19,%eax
 8048a9e:       8d 54 24 20             lea    0x20(%esp),%edx
 8048aa2:       83 c2 01                add    $0x1,%edx
 8048aa5:       89 54 24 04             mov    %edx,0x4(%esp)
 8048aa9:       89 04 24                mov    %eax,(%esp)
 8048aac:       e8 ff f9 ff ff          call   80484b0 <printf@plt>
 8048ab1:       eb 23                   jmp    8048ad6 <close@plt+0x556>
 8048ab3:       0f b6 44 24 20          movzbl 0x20(%esp),%eax
 8048ab8:       3c 42                   cmp    $0x42,%al

As you can see this is similar to reverse-ex:
printf("Are you feeling lucky today?");
fflush()
read(0,buf,511)
if (buf[n
n = strlen(buf);
if(buf[n-1] = '\n')
    buf[n-1] = 0;
   
switch[buf[0])   
    case 0x42:
        calls 0x8048644
        break;
    case 0x43:
        calls $0x80486ca
        break;
    case 0x41:
        calls 0x804872b
        break;
    default:
        loop
       
Let's test above analysis.

seed@seed-desktop:~/projects/2$ ./bonus_reverse-challenge
Are you feeling lucky today? A
[~] Maybe.
seed@seed-desktop:~/projects/2$ ./bonus_reverse-challenge
Are you feeling lucky today? B
[-] Nope.
seed@seed-desktop:~/projects/2$ ./bonus_reverse-challenge
Are you feeling lucky today? C
[~] Maybe.
seed@seed-desktop:~/projects/2$ ./bonus_reverse-challenge
Are you feeling lucky today? D
^C
[4]+  Stopped                 ./bonus_reverse-challenge

looks like some progress. Let's choose B route since it is different. Other's will lead to dead-end
but interesting stuff.
So jumping to 0x8048644 the 'B' related answer. This function gets called with two arguments (buf + 1) and (buf[0] - 0x42 = 0).

 8048644:       55                      push   %ebp
 8048645:       89 e5                   mov    %esp,%ebp
 8048647:       57                      push   %edi
 8048648:       56                      push   %esi
 8048649:       83 ec 10                sub    $0x10,%esp
 804864c:       8b 45 08                mov    0x8(%ebp),%eax
 804864f:       89 45 f4                mov    %eax,-0xc(%ebp)
 8048652:       8b 55 0c                mov    0xc(%ebp),%edx
 8048655:       50                      push   %eax
 8048656:       31 c0                   xor    %eax,%eax
 8048658:       68 64 86 04 08          push   $0x8048664
 804865d:       58                      pop    %eax
 804865e:       01 d0                   add    %edx,%eax
 8048660:       50                      push   %eax
 8048661:       c3                      ret

Here ret is popping 0x8048664 and jumping to it, Now instruction pointer is at 0x8048664.
 8048662:       b8 01 c7 45 f0          mov    $0xf045c701,%eax
 8048667:       fa                      cli
 8048668:       00 00                   add    %al,(%eax)
 804866a:       00 58 eb                add    %bl,-0x15(%eax)
 804866d:       17                      pop    %ss
 804866e:       8b 45 f4                mov    -0xc(%ebp),%eax
 8048671:       0f b6 00                movzbl (%eax),%eax
...
As you can 0x8048664 is middle of instruction at  0x8048662, so this means objdump disassembly for this piece of
code is bad, let's fix it to find the right instructions which get executed.

code jumps to 8048664 which is the middle of disassembled instruction at 8048662.
So we need to find to what extent the disassembly is bad and of-course the real
opcodes that will be executed.
So implemented a simple C code which converts hex to binary for the opcodes in hex
from address 8048664 for some bytes till the new disassembly (got from feeding the
binary output to objdump) matches the original disassembly.

seed@seed-desktop:~/projects/2$ cat x.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


unsigned char a[64] = {0xc7,0x45,0xf0,0xfa,0x00,0x00,0x00,0x58,
              0xeb,0x17,0x8b,0x45,0xf4,0x0f,0xb6,0x00,
              0x8b,0x55,0xf0,0x83,0xe2,0x2b,0x31,0xc2,
              0x8b,0x45,0xf4,0x88,0x10,0x83,0x45,0xf4,
              0x01,0x8b,0x45,0xf4,0x0f,0xb6,0x00,0x84,
              0xc0,0x75,0xdf,0x8b,0x45,0x08,0x89,0xc2,
              0xb8,0xc0,0x8b,0x04,0x08,0xb9,0x0f,0x00,
              0x00,0x00,0x89,0xd6,0x89,0xc7,0xf3,0xa6};
main()
{
int fd;
int ret;

fd = open("c", O_CREAT|O_WRONLY);
if (fd > 0) {
ret = write(fd,a, 64);
}
printf("%d %d\n", fd, ret);
}

seed@seed-desktop:~/projects/2$ gcc x.c
seed@seed-desktop:~/projects/2$ ./a.out
3 64
seed@seed-desktop:~/projects/2$ objdump -D -b binary -mi386 c

c:     file format binary


Disassembly of section .data:

00000000 <.data>:
   0:    c7 45 f0 fa 00 00 00     movl   $0xfa,-0x10(%ebp)
   7:    58                       pop    %eax
   8:    eb 17                    jmp    0x21
   a:    8b 45 f4                 mov    -0xc(%ebp),%eax
   d:    0f b6 00                 movzbl (%eax),%eax
  10:    8b 55 f0                 mov    -0x10(%ebp),%edx
  13:    83 e2 2b                 and    $0x2b,%edx
  16:    31 c2                    xor    %eax,%edx
  18:    8b 45 f4                 mov    -0xc(%ebp),%eax
  1b:    88 10                    mov    %dl,(%eax)
  1d:    83 45 f4 01              addl   $0x1,-0xc(%ebp)
  21:    8b 45 f4                 mov    -0xc(%ebp),%eax
  24:    0f b6 00                 movzbl (%eax),%eax
  27:    84 c0                    test   %al,%al
  29:    75 df                    jne    0xa
  2b:    8b 45 08                 mov    0x8(%ebp),%eax
  2e:    89 c2                    mov    %eax,%edx
  30:    b8 c0 8b 04 08           mov    $0x8048bc0,%eax
  35:    b9 0f 00 00 00           mov    $0xf,%ecx
  3a:    89 d6                    mov    %edx,%esi
  3c:    89 c7                    mov    %eax,%edi
  3e:    f3 a6                    repz cmpsb %es:(%edi),%ds:(%esi)

So only the hex bytes (\xc7\x45\xf0\x00\x00\x00\x58\xeb\x17) are the bad disassembled codes
otherwise everything remains the same.
 8048662:       b8 01 c7 45 f0          mov    $0xf045c701,%eax
 8048667:       fa                      cli
 8048668:       00 00                   add    %al,(%eax)
 804866a:       00 58 eb                add    %bl,-0x15(%eax)
 804866d:       17                      pop    %ss

 is equivalent to

    0:    c7 45 f0 fa 00 00 00     movl   $0xfa,-0x10(%ebp)
   7:    58                       pop    %eax
   8:    eb 17                    jmp    0x21

 The following remaining disassembled instructions are valid.
 804866e:       8b 45 f4                mov    -0xc(%ebp),%eax
 8048671:       0f b6 00                movzbl (%eax),%eax
 8048674:       8b 55 f0                mov    -0x10(%ebp),%edx <== 0xfa gets loaded here.
 8048677:       83 e2 2b                and    $0x2b,%edx
 804867a:       31 c2                   xor    %eax,%edx
 804867c:       8b 45 f4                mov    -0xc(%ebp),%eax
 804867f:       88 10                   mov    %dl,(%eax)
 8048681:       83 45 f4 01             addl   $0x1,-0xc(%ebp)
 8048685:       8b 45 f4                mov    -0xc(%ebp),%eax
 8048688:       0f b6 00                movzbl (%eax),%eax
 804868b:       84 c0                   test   %al,%al
 804868d:       75 df                   jne    804866e <close@plt+0xee>
...
So it jumps to 804868d which jumps back to 804866e. As you can see this piece of code
is xoring 0x2b with (buf contents bitwise AND with 0xFA) and storing it to buf contents till buf[blah] string reaches a 0 (NULL character).

 804868f:       8b 45 08                mov    0x8(%ebp),%eax
 8048692:       89 c2                   mov    %eax,%edx
 8048694:       b8 c0 8b 04 08          mov    $0x8048bc0,%eax
 8048699:       b9 0f 00 00 00          mov    $0xf,%ecx
 804869e:       89 d6                   mov    %edx,%esi
 80486a0:       89 c7                   mov    %eax,%edi
 80486a2:       f3 a6                   repz cmpsb %es:(%edi),%ds:(%esi)
 80486a4:       0f 97 c2                seta   %dl
 80486a7:       0f 92 c0                setb   %al
 80486aa:       89 d1                   mov    %edx,%ecx
 80486ac:       28 c1                   sub    %al,%cl
 80486ae:       89 c8                   mov    %ecx,%eax
 80486b0:       0f be c0                movsbl %al,%eax
 80486b3:       85 c0                   test   %eax,%eax
 80486b5:       75 07                   jne    80486be <close@plt+0x13e>
 80486b7:       b8 01 00 00 00          mov    $0x1,%eax            <== Success
 80486bc:       eb 05                   jmp    80486c3 <close@plt+0x143>
 80486be:       b8 00 00 00 00          mov    $0x0,%eax
 80486c3:       83 c4 10                add    $0x10,%esp
 80486c6:       5e                      pop    %esi
 80486c7:       5f                      pop    %edi
 80486c8:       5d                      pop    %ebp
 80486c9:       c3                      ret

 so modified input = (input ^ (0xfa & 0x2b)) = input ^ 0x2a.
(gdb) p/x 0xfa & 0x2b
$5 = 0x2a

The above code strcmp(modified input, $0x8048bc0)
(gdb) x/s  0x8048bc0
0x8048bc0:     "xKZl_^_XCY^CIE"

input ^ 0x2a =  "xKZl_^_XCY^CIE"
input ^ 0x2a ^ 0x2a = "xKZl_^_XCY^CIE" ^ 0x2a (xoring for all characters).
input = "xKZl_^_XCY^CIE" ^ 0x2a (xoring for all characters).

$ python -c 'print "".join([chr(ord(c)^0x2a) for c in "xKZl_^_XCY^CIE"])'
RapFuturistico

So the input is "BRapFuturistico".

seed@seed-desktop:~/projects/2$ ./bonus_reverse-challenge
Are you feeling lucky today? BRapFuturistico
[+] WooT!: xKZl_^_XCY^CIE

DONE...

[NOTE:]
Actual disassembly of the function for option 'B':
 8048644:       55                      push   %ebp
 8048645:       89 e5                   mov    %esp,%ebp
 8048647:       57                      push   %edi
 8048648:       56                      push   %esi
 8048649:       83 ec 10                sub    $0x10,%esp
 804864c:       8b 45 08                mov    0x8(%ebp),%eax
 804864f:       89 45 f4                mov    %eax,-0xc(%ebp)
 8048652:       8b 55 0c                mov    0xc(%ebp),%edx
 8048655:       50                      push   %eax
 8048656:       31 c0                   xor    %eax,%eax
 8048658:       68 64 86 04 08          push   $0x8048664
 804865d:       58                      pop    %eax
 804865e:       01 d0                   add    %edx,%eax
 8048660:       50                      push   %eax
 8048661:       c3                      ret

Replace following from
 8048662:       b8 01 c7 45 f0          mov    $0xf045c701,%eax
 8048667:       fa                      cli
 8048668:       00 00                   add    %al,(%eax)
 804866a:       00 58 eb                add    %bl,-0x15(%eax)
 804866d:       17                      pop    %ss
to
   0:    c7 45 f0 fa 00 00 00     movl   $0xfa,-0x10(%ebp)
   7:    58                       pop    %eax
   8:    eb 17                    jmp    0x21 (0x 8048685)

 804866e:       8b 45 f4                mov    -0xc(%ebp),%eax
 8048671:       0f b6 00                movzbl (%eax),%eax
 8048674:       8b 55 f0                mov    -0x10(%ebp),%edx
 8048677:       83 e2 2b                and    $0x2b,%edx
 804867a:       31 c2                   xor    %eax,%edx
 804867c:       8b 45 f4                mov    -0xc(%ebp),%eax
 804867f:       88 10                   mov    %dl,(%eax)
 8048681:       83 45 f4 01             addl   $0x1,-0xc(%ebp)
 8048685:       8b 45 f4                mov    -0xc(%ebp),%eax
 8048688:       0f b6 00                movzbl (%eax),%eax
 804868b:       84 c0                   test   %al,%al
 804868d:       75 df                   jne    804866e <close@plt+0xee>
 804868f:       8b 45 08                mov    0x8(%ebp),%eax
 8048692:       89 c2                   mov    %eax,%edx
 8048694:       b8 c0 8b 04 08          mov    $0x8048bc0,%eax
 8048699:       b9 0f 00 00 00          mov    $0xf,%ecx
 804869e:       89 d6                   mov    %edx,%esi
 80486a0:       89 c7                   mov    %eax,%edi
 80486a2:       f3 a6                   repz cmpsb %es:(%edi),%ds:(%esi)
 80486a4:       0f 97 c2                seta   %dl
 80486a7:       0f 92 c0                setb   %al
 80486aa:       89 d1                   mov    %edx,%ecx
 80486ac:       28 c1                   sub    %al,%cl
 80486ae:       89 c8                   mov    %ecx,%eax
 80486b0:       0f be c0                movsbl %al,%eax
 80486b3:       85 c0                   test   %eax,%eax
 80486b5:       75 07                   jne    80486be <close@plt+0x13e>
 80486b7:       b8 01 00 00 00          mov    $0x1,%eax
 80486bc:       eb 05                   jmp    80486c3 <close@plt+0x143>
 80486be:       b8 00 00 00 00          mov    $0x0,%eax
 80486c3:       83 c4 10                add    $0x10,%esp
 80486c6:       5e                      pop    %esi
 80486c7:       5f                      pop    %edi
 80486c8:       5d                      pop    %ebp
 80486c9:       c3                      ret

  

Saturday 1 November 2014

reversing example

coursera had a malware course, one of the class was to reverse engineer a binary and crack the key. I have tried to explain it here by taking baby steps using objdump in linux. The approach is trying to comeup with a pseudo code from binary. steps are objdump output, manual analysis, write pseudo code from the analysis and the finally the real code which was compiled to verify. Used gdb only for printing strings and converting hex to decimal. 

====== Example 1 =======

objdump
-------
In 1_objdump file search for main
08048394 <main>:
 8048394:       55                      push   %ebp
 8048395:       89 e5                   mov    %esp,%ebp
 8048397:       b8 7b 00 00 00          mov    $0x7b,%eax
 804839c:       5d                      pop    %ebp
 804839d:       c3                      ret
 804839e:       90                      nop
 804839f:       90                      nop

study
-----
 8048394:       55                      push   %ebp
save previous frame pointer on stack
 8048395:       89 e5                   mov    %esp,%ebp
Intialize the frame pointer to current stack pointer sp->bp.
 8048397:       b8 7b 00 00 00          mov    $0x7b,%eax
moving 0x7b value to eax register. 0x7b in decimal is
gdb ./a.out (using gdb for converting 123 to hex).)
(gdb) p/x 123
$1 = 0x7b
As you can see eax register is used to return values to the caller.

pseudocode
----------
main
    return 123;

code
----
#include <stdio.h>

int main(int argc, char **argv)
{
    return 123;
}

build
-----
gcc 1.c
objdump -d ./a.out > 1_objdump
====== Example 2 =======

080483c4 <main>:
 80483c4:       55                      push   %ebp
 80483c5:       89 e5                   mov    %esp,%ebp
 80483c7:       83 e4 f0                and    $0xfffffff0,%esp
 80483ca:       83 ec 10                sub    $0x10,%esp
 80483cd:       b8 b4 84 04 08          mov    $0x80484b4,%eax
 80483d2:       89 04 24                mov    %eax,(%esp)
 80483d5:       e8 1a ff ff ff          call   80482f4 <printf@plt>
 80483da:       b8 7b 00 00 00          mov    $0x7b,%eax
 80483df:       c9                      leave
 80483e0:       c3                      ret

Our 0x7b is still there, there is a call to function printf. so our string
"Hello World" should pushed on stack, so eax which looks like a pointer value
is pushed onto stack before calling printf. But objdump file doesn't contain
the address contents [0x80484b4].
objdump -D ./a.out > 1_objdump
 80484b4:       48                      dec    %eax
 80484b5:       65                      gs
 80484b6:       6c                      insb   (%dx),%es:(%edi)
 80484b7:       6c                      insb   (%dx),%es:(%edi)
 80484b8:       6f                      outsl  %ds:(%esi),(%dx)
 80484b9:       20 57 6f                and    %dl,0x6f(%edi)
 80484bc:       72 6c                   jb     804852a <__dso_handle+0x7a>
 80484be:       64                      fs

b ./a.out
(gdb) x/s 0x80484b4
0x80484b4 <__dso_handle+4>:     "Hello World"
(gdb) x/16xb 0x80484b4
0x80484b4 <__dso_handle+4>:    0x48    0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f
0x80484bc <__dso_handle+12>:    0x72    0x6c    0x64    0x00    0x01    0x1b    0x03    0x3b
(gdb) x/16cb 0x80484b4
0x80484b4 <__dso_handle+4>:    72 'H'    101 'e'    108 'l'    108 'l'    111 'o'    32 ' '    87 'W'    111 'o'
0x80484bc <__dso_handle+12>:    114 'r'    108 'l'    100 'd'    0 '\000'    1 '\001'    27 '\033'    3 '\003'    59 ';'

Ok, we have our "Hello world" pointer in stack before calling printf.

 80483c4:       55                      push   %ebp
 80483c5:       89 e5                   mov    %esp,%ebp
usual prologue
 80483c7:       83 e4 f0                and    $0xfffffff0,%esp
Aligning the stack to 16 bytes.
 80483ca:       83 ec 10                sub    $0x10,%esp
Allocating 16 bytes, only 4 bytes are needed to put arg to printf, adhering to
alignment of 16 bytes.
 80483cd:       b8 b4 84 04 08          mov    $0x80484b4,%eax
 80483d2:       89 04 24                mov    %eax,(%esp)
"Hello world" pointer is pushed to eax to contents on allocated stack.
 80483d5:       e8 1a ff ff ff          call   80482f4 <printf@plt>
 80483da:       b8 7b 00 00 00          mov    $0x7b,%eax
 80483df:       c9                      leave
 80483e0:       c3                      ret

pseudocode
----------
main
    printf "Hello World";
    return 123;
code
----
#include <stdio.h>

int main(int argc, char **argv)
{
        printf("Hello World");
        return 123;
}

build
-----
gcc 1.c
objdump -d ./a.out > 1_objdump
====== Example 3 =======
08048474 <main>:
 8048474:       55                      push   %ebp
 8048475:       89 e5                   mov    %esp,%ebp
 8048477:       83 e4 f0                and    $0xfffffff0,%esp
 804847a:       81 ec 20 02 00 00       sub    $0x220,%esp
 8048480:       b8 c4 85 04 08          mov    $0x80485c4,%eax
 8048485:       89 04 24                mov    %eax,(%esp)
 8048488:       e8 1b ff ff ff          call   80483a8 <printf@plt>
 804848d:       a1 a0 97 04 08          mov    0x80497a0,%eax
 8048492:       89 04 24                mov    %eax,(%esp)
 8048495:       e8 ee fe ff ff          call   8048388 <fflush@plt>
 804849a:       c7 44 24 08 ff 01 00    movl   $0x1ff,0x8(%esp)
 80484a1:       00
 80484a2:       8d 44 24 14             lea    0x14(%esp),%eax
 80484a6:       89 44 24 04             mov    %eax,0x4(%esp)
 80484aa:       c7 04 24 00 00 00 00    movl   $0x0,(%esp)
 80484b1:       e8 c2 fe ff ff          call   8048378 <read@plt>
 80484b6:       8d 44 24 14             lea    0x14(%esp),%eax
 80484ba:       89 04 24                mov    %eax,(%esp)
 80484bd:       e8 d6 fe ff ff          call   8048398 <strlen@plt>
 80484c2:       89 84 24 14 02 00 00    mov    %eax,0x214(%esp)
 80484c9:       8b 84 24 14 02 00 00    mov    0x214(%esp),%eax
 80484d0:       83 e8 01                sub    $0x1,%eax
 80484d3:       0f b6 44 04 14          movzbl 0x14(%esp,%eax,1),%eax
 80484d8:       3c 0a                   cmp    $0xa,%al
 80484da:       75 0f                   jne    80484eb <main+0x77>
 80484dc:       8b 84 24 14 02 00 00    mov    0x214(%esp),%eax
 80484e3:       83 e8 01                sub    $0x1,%eax
 80484e6:       c6 44 04 14 00          movb   $0x0,0x14(%esp,%eax,1)
 80484eb:       b8 7b 00 00 00          mov    $0x7b,%eax
 80484f0:       c9                      leave
 80484f1:       c3                      ret

study
-----
 8048474:       55                      push   %ebp
 8048475:       89 e5                   mov    %esp,%ebp
 8048477:       83 e4 f0                and    $0xfffffff0,%esp
usual

 804847a:       81 ec 20 02 00 00       sub    $0x220,%espa
(gdb) p 0x220
$1 = 544
Allocating 544 bytes on stack

 8048480:       b8 c4 85 04 08          mov    $0x80485c4,%eax
 8048485:       89 04 24                mov    %eax,(%esp)
 8048488:       e8 1b ff ff ff          call   80483a8 <printf@plt>
objdump -D ./a.out > 1_objdump
shows the contents of 0x80485c4.
(gdb) x/s 0x80485c4
0x80485c4 <__dso_handle+4>:     "Are you feeling lucky today? "
printf with one arg "Are you feeling lucky today? ".


 804848d:       a1 a0 97 04 08          mov    0x80497a0,%eax
 8048492:       89 04 24                mov    %eax,(%esp)
 8048495:       e8 ee fe ff ff          call   8048388 <fflush@plt>

man fflush

(gdb) x/s 0x80497a0
0x80497a0 <stdout@@GLIBC_2.0>:     ""
(gdb) p/x *0x80497a0
$6 = 0x0
so fflush is flusihing all open output streams. I think fflush(NULL).

 804849a:       c7 44 24 08 ff 01 00    movl   $0x1ff,0x8(%esp)
 80484a1:       00
 80484a2:       8d 44 24 14             lea    0x14(%esp),%eax
 80484a6:       89 44 24 04             mov    %eax,0x4(%esp)
 80484aa:       c7 04 24 00 00 00 00    movl   $0x0,(%esp)
 80484b1:       e8 c2 fe ff ff          call   8048378 <read@plt>

man 2 read
ssize_t read(int fd, void *buf, size_t count);
stack is 0x1ff (511), something in stack which is at 20 (0x14) bytes , 0
so args to read are fd = 0, buf, 511.
main() stack allocated is 544 bytes of which
...
something like buf of size 524 ...(there could be other local variables,
read call is only restricted to overwrite 511)
20
0
pointer to buf
511
...

 80484b6:       8d 44 24 14             lea    0x14(%esp),%eax
 80484ba:       89 04 24                mov    %eax,(%esp)
 80484bd:       e8 d6 fe ff ff          call   8048398 <strlen@plt>
 80484c2:       89 84 24 14 02 00 00    mov    %eax,0x214(%esp)

size_t strlen(const char *s);
so strlen(buf);
(gdb) p 0x214
$8 = 532

local variables of main are
(544 = 8,4 (var1),512 (buf),20(alignment, padding (4)))
main
    char buf[512]
    int var1
    char unknown[8]
   
    printf("Are you feeling lucky today? ");
    fflush(NULL);
   
    read(0, buf, 511);
    var1 = strlen(buf);
 80484d0:       83 e8 01                sub    $0x1,%eax
512 - 1 = 511
 80484d3:       0f b6 44 04 14          movzbl 0x14(%esp,%eax,1),%eax
displacement(%base, %index, scale) = displacement+%base+%index*scale.
since scale is 1 it is a char array.
buf[511]
 80484d8:       3c 0a                   cmp    $0xa,%al
(gdb) p/c 0xa
$10 = 10 '\n'
if (buf[511 == '\n')
 80484da:       75 0f                   jne    80484eb <main+0x77>
 80484dc:       8b 84 24 14 02 00 00    mov    0x214(%esp),%eax
 80484e3:       83 e8 01                sub    $0x1,%eax
 80484e6:       c6 44 04 14 00          movb   $0x0,0x14(%esp,%eax,1)
    buf[511] = 0;
 80484eb:       b8 7b 00 00 00          mov    $0x7b,%eax
 80484f0:       c9                      leave
 80484f1:       c3                      ret

pseudo code
main
    char buf[512]
    int var1
    char unknown[8]
   
    printf("Are you feeling lucky today? ");
    fflush(NULL);
   
    read(0, buf, 511);
    var1 = strlen(buf);

    if (buf[511 == '\n')
        buf[511] = 0;

    return 123

code
----
#include <stdio.h>
#include <string.h>

int main(int argc, char **argv)
{
        char buf[512];
        int n,ret;
        int (*f)(char *);

        printf("Are you feeling lucky today? ");
        fflush(stdout);

        (void)read(0, buf, sizeof(buf)-1);
        n = strlen(buf);
        if (buf[n-1] == '\n')
                buf[n-1] = 0;

        return 123;
}

====== Example 4 =======
080484ee <main>:
 80484ee:       55                      push   %ebp
 80484ef:       89 e5                   mov    %esp,%ebp
 80484f1:       83 e4 f0                and    $0xfffffff0,%esp
 80484f4:       81 ec 20 02 00 00       sub    $0x220,%esp
 80484fa:       b8 7c 86 04 08          mov    $0x804867c,%eax
 80484ff:       89 04 24                mov    %eax,(%esp)
 8048502:       e8 c1 fe ff ff          call   80483c8 <printf@plt>
 8048507:       a1 60 98 04 08          mov    0x8049860,%eax
 804850c:       89 04 24                mov    %eax,(%esp)
 804850f:       e8 94 fe ff ff          call   80483a8 <fflush@plt>
 8048514:       c7 44 24 08 ff 01 00    movl   $0x1ff,0x8(%esp)
 804851b:       00
 804851c:       8d 44 24 14             lea    0x14(%esp),%eax
 8048520:       89 44 24 04             mov    %eax,0x4(%esp)
 8048524:       c7 04 24 00 00 00 00    movl   $0x0,(%esp)
 804852b:       e8 68 fe ff ff          call   8048398 <read@plt>
 8048530:       8d 44 24 14             lea    0x14(%esp),%eax
 8048534:       89 04 24                mov    %eax,(%esp)
 8048537:       e8 7c fe ff ff          call   80483b8 <strlen@plt>
 804853c:       89 84 24 14 02 00 00    mov    %eax,0x214(%esp)
 8048543:       8b 84 24 14 02 00 00    mov    0x214(%esp),%eax
 804854a:       83 e8 01                sub    $0x1,%eax
 804854d:       0f b6 44 04 14          movzbl 0x14(%esp,%eax,1),%eax
 8048552:       3c 0a                   cmp    $0xa,%al
 8048554:       75 0f                   jne    8048565 <main+0x77>
 8048556:       8b 84 24 14 02 00 00    mov    0x214(%esp),%eax
 804855d:       83 e8 01                sub    $0x1,%eax
 8048560:       c6 44 04 14 00          movb   $0x0,0x14(%esp,%eax,1)
 8048565:       0f b6 44 24 14          movzbl 0x14(%esp),%eax
 804856a:       0f be c0                movsbl %al,%eax
 804856d:       83 f8 42                cmp    $0x42,%eax
 8048570:       74 17                   je     8048589 <main+0x9b>
 8048572:       83 f8 43                cmp    $0x43,%eax
 8048575:       74 21                   je     8048598 <main+0xaa>
 8048577:       83 f8 41                cmp    $0x41,%eax
 804857a:       75 29                   jne    80485a5 <main+0xb7>
 804857c:       c7 84 24 1c 02 00 00    movl   $0x80484a4,0x21c(%esp)
 8048583:       a4 84 04 08
 8048587:       eb 1e                   jmp    80485a7 <main+0xb9>
 8048589:       b8 9a 86 04 08          mov    $0x804869a,%eax
 804858e:       89 04 24                mov    %eax,(%esp)
 8048591:       e8 32 fe ff ff          call   80483c8 <printf@plt>
 8048596:       eb 0f                   jmp    80485a7 <main+0xb9>
 8048598:       c7 84 24 1c 02 00 00    movl   $0x80484d6,0x21c(%esp)
 804859f:       d6 84 04 08
 80485a3:       eb 02                   jmp    80485a7 <main+0xb9>
 80485a5:       eb fe                   jmp    80485a5 <main+0xb7>
 80485a7:       b8 7b 00 00 00          mov    $0x7b,%eax
 80485ac:       c9                      leave
 80485ad:       c3                      ret


rom 80484ee to 8048565 is
main
    char buf[512]
    int var1
    char unknown[8]
   
    printf("Are you feeling lucky today? ");
    fflush(NULL);
   
    read(0, buf, 511);
    var1 = strlen(buf);

    if (buf[511 == '\n')
        buf[511] = 0;

 8048565:       0f b6 44 24 14          movzbl 0x14(%esp),%eax
 804856a:       0f be c0                movsbl %al,%eax
 804856d:       83 f8 42                cmp    $0x42,%eax
 8048570:       74 17                   je     8048589 <main+0x9b>
if (buf[0] == 0x42)
(gdb) x/s 0x804869a
0x804869a <__dso_handle+42>:     "Hello"

    printf("Hello")

 8048572:       83 f8 43                cmp    $0x43,%eax
 8048575:       74 21                   je     8048598 <main+0xaa>
if (buf[0] == 0x43)
(gdb) x 0x80484d6
0x80484d6 <foobar>:    0x83e58955
    moving address of foobar to a local variable (function pointer).
 8048577:       83 f8 41                cmp    $0x41,%eax
 804857a:       75 29                   jne    80485a5 <main+0xb7>
 804857c:       c7 84 24 1c 02 00 00    movl   $0x80484a4,0x21c(%esp)
 8048583:       a4 84 04 08
 8048587:       eb 1e                   jmp    80485a7 <main+0xb9>
if (buf[0] == 0x41)
(gdb) x 0x80484a4
0x80484a4 <foo>:    0x83e58955
    moving address of foo to a local variable (function pointer).

 8048589:       b8 9a 86 04 08          mov    $0x804869a,%eax
 804858e:       89 04 24                mov    %eax,(%esp)
 8048591:       e8 32 fe ff ff          call   80483c8 <printf@plt>
// done with printf("Hello");
 8048596:       eb 0f                   jmp    80485a7 <main+0xb9>
 8048598:       c7 84 24 1c 02 00 00    movl   $0x80484d6,0x21c(%esp)
 804859f:       d6 84 04 08
 80485a3:       eb 02                   jmp    80485a7 <main+0xb9>
 80485a5:       eb fe                   jmp    80485a5 <main+0xb7>
Loo.....oop

switch (buf[0]) {
    case 0x41:
        var2 = &foo;
        break;
    case 0x42:
        printf("Hello");
        break;
    case 0x43:
        var2 = &foobar;
        break;
    default:
        loop here.
}
 80485a7:       b8 7b 00 00 00          mov    $0x7b,%eax
 80485ac:       c9                      leave
 80485ad:       c3                      ret

return 123;
====== Example 5 =======
08048577 <main>:
 8048577:       55                      push   %ebp
 8048578:       89 e5                   mov    %esp,%ebp
 804857a:       57                      push   %edi
 804857b:       83 e4 f0                and    $0xfffffff0,%esp
 804857e:       81 ec 30 02 00 00       sub    $0x230,%esp
 8048584:       b8 91 87 04 08          mov    $0x8048791,%eax
 8048589:       89 04 24                mov    %eax,(%esp)
 804858c:       e8 1f fe ff ff          call   80483b0 <printf@plt>
 8048591:       a1 40 a0 04 08          mov    0x804a040,%eax
 8048596:       89 04 24                mov    %eax,(%esp)
 8048599:       e8 22 fe ff ff          call   80483c0 <fflush@plt>
 804859e:       c7 44 24 08 ff 01 00    movl   $0x1ff,0x8(%esp)
 80485a5:       00
 80485a6:       8d 44 24 24             lea    0x24(%esp),%eax
 80485aa:       89 44 24 04             mov    %eax,0x4(%esp)
 80485ae:       c7 04 24 00 00 00 00    movl   $0x0,(%esp)
 80485b5:       e8 e6 fd ff ff          call   80483a0 <read@plt>
 80485ba:       8d 44 24 24             lea    0x24(%esp),%eax
 80485be:       c7 44 24 1c ff ff ff    movl   $0xffffffff,0x1c(%esp)
 80485c5:       ff
 80485c6:       89 c2                   mov    %eax,%edx
 80485c8:       b8 00 00 00 00          mov    $0x0,%eax
 80485cd:       8b 4c 24 1c             mov    0x1c(%esp),%ecx
 80485d1:       89 d7                   mov    %edx,%edi
 80485d3:       f2 ae                   repnz scas %es:(%edi),%al
 80485d5:       89 c8                   mov    %ecx,%eax
 80485d7:       f7 d0                   not    %eax
 80485d9:       83 e8 01                sub    $0x1,%eax
 80485dc:       89 84 24 28 02 00 00    mov    %eax,0x228(%esp)
 80485e3:       8b 84 24 28 02 00 00    mov    0x228(%esp),%eax
 80485ea:       83 e8 01                sub    $0x1,%eax
 80485ed:       0f b6 44 04 24          movzbl 0x24(%esp,%eax,1),%eax
 80485f2:       3c 0a                   cmp    $0xa,%al
 80485f4:       75 0f                   jne    8048605 <main+0x8e>
 80485f6:       8b 84 24 28 02 00 00    mov    0x228(%esp),%eax
 80485fd:       83 e8 01                sub    $0x1,%eax
 8048600:       c6 44 04 24 00          movb   $0x0,0x24(%esp,%eax,1)
 8048605:       0f b6 44 24 24          movzbl 0x24(%esp),%eax
 804860a:       0f be c0                movsbl %al,%eax
 804860d:       83 f8 42                cmp    $0x42,%eax
 8048610:       74 17                   je     8048629 <main+0xb2>
 8048612:       83 f8 43                cmp    $0x43,%eax
 8048615:       74 1f                   je     8048636 <main+0xbf>
 8048617:       83 f8 41                cmp    $0x41,%eax
 804861a:       75 27                   jne    8048643 <main+0xcc>
 804861c:       c7 84 24 2c 02 00 00    movl   $0x804852d,0x22c(%esp)
 8048623:       2d 85 04 08
 8048627:       eb 1c                   jmp    8048645 <main+0xce>
 8048629:       c7 84 24 2c 02 00 00    movl   $0x80484c4,0x22c(%esp)
 8048630:       c4 84 04 08
 8048634:       eb 0f                   jmp    8048645 <main+0xce>
 8048636:       c7 84 24 2c 02 00 00    movl   $0x804855f,0x22c(%esp)
 804863d:       5f 85 04 08
 8048641:       eb 02                   jmp    8048645 <main+0xce>
 8048643:       eb fe                   jmp    8048643 <main+0xcc>
 8048645:       8d 44 24 24             lea    0x24(%esp),%eax
 8048649:       83 c0 01                add    $0x1,%eax
 804864c:       89 04 24                mov    %eax,(%esp)
 804864f:       8b 84 24 2c 02 00 00    mov    0x22c(%esp),%eax
 8048656:       ff d0                   call   *%eax
 8048658:       89 84 24 24 02 00 00    mov    %eax,0x224(%esp)
 804865f:       83 bc 24 24 02 00 00    cmpl   $0x0,0x224(%esp)
 8048666:       00
 8048667:       74 1a                   je     8048683 <main+0x10c>
 8048669:       b8 af 87 04 08          mov    $0x80487af,%eax
 804866e:       8d 54 24 24             lea    0x24(%esp),%edx
 8048672:       83 c2 01                add    $0x1,%edx
 8048675:       89 54 24 04             mov    %edx,0x4(%esp)
 8048679:       89 04 24                mov    %eax,(%esp)
 804867c:       e8 2f fd ff ff          call   80483b0 <printf@plt>
 8048681:       eb 0c                   jmp    804868f <main+0x118>
 8048683:       c7 04 24 be 87 04 08    movl   $0x80487be,(%esp)
 804868a:       e8 41 fd ff ff          call   80483d0 <puts@plt>
 804868f:       8b 84 24 24 02 00 00    mov    0x224(%esp),%eax
 8048696:       89 04 24                mov    %eax,(%esp)
 8048699:       e8 52 fd ff ff          call   80483f0 <exit@plt>
 804869e:       90                      nop
 804869f:       90                      nop

from 8048577 to 8048645 is similar with minor changes in switch and local
variables.
allocated stack = 0x230 (560 = 36 padding, buffer 512, var1 4,var2 4,function pointer 4)
36 (var1, var2 and function pointer are 4 bytes they are aligned to 16 bytes
so 12*3 = 36 bytes).
buf[512] 0x24(%esp)
var1   
var2    0x224(%esp) NOTE: stack is gowing in reverse so this value is ret.
function pointer(fp)

(gdb) x 0x80484c4
0x80484c4 <checkkey>:     "U\211\345WV\203\354\020\213E\b\211E\364\353\024\213E\364\017\266"

switch(buf[0])
    case 0x41
        fp = &foo;
        break;
    case 0x42
        fp = &checkkey;
        break;
    case 0x43
        fp = &foobar;
        break;
    default:
        loop here

 8048649:       83 c0 01                add    $0x1,%eax
 804864c:       89 04 24                mov    %eax,(%esp)
    var2 = fp(buf+1);
    exit(ret);
puts at 804868a
(gdb) x/s 0x80487be
0x80487be:     "[-] Nope."

[chetan@chetan reverse]$ ./reverse-ex
Are you feeling lucky today? c
^C
[chetan@chetan reverse]$ ./reverse-ex
Are you feeling lucky today? A
foo
[-] Nope.
[chetan@chetan reverse]$ ./reverse-ex
Are you feeling lucky today? B
[-] Nope.
[chetan@chetan reverse]$ ./reverse-ex
Are you feeling lucky today? C
foo
[-] Nope.

So input with B calls checkkey(); 
080484c4 <checkkey>:
 80484c4:       55                      push   %ebp
 80484c5:       89 e5                   mov    %esp,%ebp
 80484c7:       57                      push   %edi
 80484c8:       56                      push   %esi
 80484c9:       83 ec 10                sub    $0x10,%esp
 80484cc:       8b 45 08                mov    0x8(%ebp),%eax
 80484cf:       89 45 f4                mov    %eax,-0xc(%ebp)
 80484d2:       eb 14                   jmp    80484e8 <checkkey+0x24>
char *p = buf[1];
 80484d4:       8b 45 f4                mov    -0xc(%ebp),%eax
 80484d7:       0f b6 00                movzbl (%eax),%eax
 80484da:       89 c2                   mov    %eax,%edx
 80484dc:       83 f2 2a                xor    $0x2a,%edx
 80484df:       8b 45 f4                mov    -0xc(%ebp),%eax
 80484e2:       88 10                   mov    %dl,(%eax)
*p = *p^42
 80484e4:       83 45 f4 01             addl   $0x1,-0xc(%ebp)
p++;
 80484e8:       8b 45 f4                mov    -0xc(%ebp),%eax
 80484eb:       0f b6 00                movzbl (%eax),%eax
 80484ee:       84 c0                   test   %al,%al
*p check in for loop
 80484f0:       75 e2                   jne    80484d4 <checkkey+0x10>

for (;*p ; p++)
    *p = *p ^ 0x2a; (0x2a = 42)

 80484f2:       8b 45 08                mov    0x8(%ebp),%eax
 80484f5:       89 c2                   mov    %eax,%edx
 80484f7:       b8 70 87 04 08          mov    $0x8048770,%eax
(gdb) x/s 0x8048770
0x8048770:     "KFFSE_XHKYOKXOHOFEDM^E_Y"

 80484fc:       b9 19 00 00 00          mov    $0x19,%ecx
 8048501:       89 d6                   mov    %edx,%esi
 8048503:       89 c7                   mov    %eax,%edi
 8048505:       f3 a6                   repz cmpsb %es:(%edi),%ds:(%esi)
 8048507:       0f 97 c2                seta   %dl
 804850a:       0f 92 c0                setb   %al
 804850d:       89 d1                   mov    %edx,%ecx
 804850f:       28 c1                   sub    %al,%cl
 8048511:       89 c8                   mov    %ecx,%eax
 8048513:       0f be c0                movsbl %al,%eax
 8048516:       85 c0                   test   %eax,%eax
strcmp()
 8048518:       75 07                   jne    8048521 <checkkey+0x5d>
 804851a:       b8 01 00 00 00          mov    $0x1,%eax
return 1 if match
 804851f:       eb 05                   jmp    8048526 <checkkey+0x62>
 8048521:       b8 00 00 00 00          mov    $0x0,%eax
 8048526:       83 c4 10                add    $0x10,%esp
 8048529:       5e                      pop    %esi
 804852a:       5f                      pop    %edi
 804852b:       5d                      pop    %ebp
 804852c:       c3                      ret

(Given input) ^ 42 = ("KFFSE_XHKYOKXOHOFEDM^E_Y") is the check in code
(Given input) ^ 42 ^ 42 = ("KFFSE_XHKYOKXOHOFEDM^E_Y") ^ 42
(Given input) = ("KFFSE_XHKYOKXOHOFEDM^E_Y") ^ 42

So to get the Given input
#include<stdio.h>
#include<string.h>

#define KEY "KFFSE_XHKYOKXOHOFEDM^E_Y"

main()
{
   char *p = KEY;   
   for (; *p; p++) {
      printf("%c",(*p) ^ 42);   
   }
   printf("\n");   
}
gcc above code
./a.out
allyourbasearebelongtous

[chetan@chetan reverse]$ ./reverse-ex
Are you feeling lucky today? Ballyourbasearebelongtous
[-] Nope.

Bug in the code
gcc -g reverse-ex.c
gdb ./a.out
(gdb) b checkkey
Breakpoint 1 at 0x804850a: file reverse-ex.c, line 13.
(gdb) r
Breakpoint 1, checkkey (
    key=0xbffff0b5 "allyourbasearebelongtous\n\377\277\265\306>")
    at reverse-ex.c:13
13       char *p = key;

There are junk characters read by read() call.
Fixing the read code (man read tells this)
from
   (void) read(0, buf, sizeof(buf)-1);
   n = strlen(buf);
to
   n = read(0, buf, sizeof(buf)-1);
   //n = strlen(buf);

checking through gdb
Breakpoint 1, checkkey (key=0xbffff0b5 "allyourbasearebelongtous")
    at ./reverse-ex.c:13
13       char *p = key;

[chetan@chetan reverse]$ ./a.out
Are you feeling lucky today? Ballyourbasearebelongtous
[+] WooT!: KFFSE_XHKYOKXOHOFEDM^E_Y

So the INPUT is Ballyourbasearebelongtous

code
---
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>

#define KEY "KFFSE_XHKYOKXOHOFEDM^E_Y"

int
checkkey(char *key)
{

   char *p = key;

   for (; *p; p++)
      *p ^= 42;

   if (!strcmp(key,KEY))
      return 1;
   return 0;
}

int
foo(char *data)
{
   printf("foo\n");
   return 0;
}

int
bar(char *data)
{
   printf("bar\n");
   return 0;
}
int
foobar(char *data)
{

   foo(data);
   return 0;
}

int
main(void)
{

   char buf[512];
   int n, ret;
   int (*f)(char *);

   //memset(buf, 0, sizeof(buf));

   printf("Are you feeling lucky today? ");
   fflush(stdout);

   n = read(0, buf, sizeof(buf)-1);
   //n = strlen(buf);
   if (buf[n-1] == '\n')
      buf[n-1] = 0;

   switch (buf[0]) {

      case 0x41:
         f = &foo;
         break;
      case 0x42:
         f = &checkkey;
         break;
      case 0x43:
         f = &foobar;
         break;
      default:
      loop:
         goto *&&loop;
   }

   ret = f(buf+1);
   if (ret)
      printf("[+] WooT!: %s\n", buf+1);
   else
      printf("[-] Nope.\n");

   exit(ret);
}