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);
}

No comments:

Post a Comment