Hi there.
Today I was asking myself if I still remember some low level programming like assembly and some nice stuff I played when I was a 16 years old kid. I don’t remember that much but I decided to do a quick test to see if I’m able to pick up something from the middle of my brain. Actually some minutes on google helped a bit to refresh my memory.
I wrote this simple post to teach you how to edit a binary file (or create a very very simple crack).
We’re gonna do this using PHP and some tools that you can find on your linux box.
1) First let’s compile our example using C. Create a file hello-world.c with the following content:
#include <stdio.h>
void main() {
int password = 9;
if (password == 8) {
printf("Congratulations \n");
} else {
printf("Try again \n");
}
}
2) To compile try this:
gcc -o hello-world hello-world.c
Now that we have a binary file on our folder, we can run it using this: ./hello-world
Try again
Our goal is change the binary file in order to show the word “Congratulations”. First, let’s take a look on the binary file.
3) Poke around inside the binary file using the following command:
objdump -d hello-world > dump.txt
Your dump.txt must look like this:
hello-world: file format elf64-x86-64
Disassembly of section .init:
00000000004003e0 <_init>:
4003e0: 48 83 ec 08 sub $0x8,%rsp
4003e4: 48 8b 05 0d 0c 20 00 mov 0x200c0d(%rip),%rax # 600ff8 <_DYNAMIC+0x1d0>
4003eb: 48 85 c0 test %rax,%rax
4003ee: 74 05 je 4003f5 <_init+0x15>
4003f0: e8 3b 00 00 00 callq 400430 <__gmon_start__@plt>
4003f5: 48 83 c4 08 add $0x8,%rsp
4003f9: c3 retq
Disassembly of section .plt:
0000000000400400 <puts@plt-0x10>:
400400: ff 35 02 0c 20 00 pushq 0x200c02(%rip) # 601008 <_GLOBAL_OFFSET_TABLE_+0x8>
400406: ff 25 04 0c 20 00 jmpq *0x200c04(%rip) # 601010 <_GLOBAL_OFFSET_TABLE_+0x10>
40040c: 0f 1f 40 00 nopl 0x0(%rax)
0000000000400410 <puts@plt>:
400410: ff 25 02 0c 20 00 jmpq *0x200c02(%rip) # 601018 <_GLOBAL_OFFSET_TABLE_+0x18>
400416: 68 00 00 00 00 pushq $0x0
40041b: e9 e0 ff ff ff jmpq 400400 <_init+0x20>
0000000000400420 <__libc_start_main@plt>:
400420: ff 25 fa 0b 20 00 jmpq *0x200bfa(%rip) # 601020 <_GLOBAL_OFFSET_TABLE_+0x20>
400426: 68 01 00 00 00 pushq $0x1
40042b: e9 d0 ff ff ff jmpq 400400 <_init+0x20>
0000000000400430 <__gmon_start__@plt>:
400430: ff 25 f2 0b 20 00 jmpq *0x200bf2(%rip) # 601028 <_GLOBAL_OFFSET_TABLE_+0x28>
400436: 68 02 00 00 00 pushq $0x2
40043b: e9 c0 ff ff ff jmpq 400400 <_init+0x20>
Disassembly of section .text:
0000000000400440 <_start>:
400440: 31 ed xor %ebp,%ebp
400442: 49 89 d1 mov %rdx,%r9
400445: 5e pop %rsi
400446: 48 89 e2 mov %rsp,%rdx
400449: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp
40044d: 50 push %rax
40044e: 54 push %rsp
40044f: 49 c7 c0 d0 05 40 00 mov $0x4005d0,%r8
400456: 48 c7 c1 60 05 40 00 mov $0x400560,%rcx
40045d: 48 c7 c7 2d 05 40 00 mov $0x40052d,%rdi
400464: e8 b7 ff ff ff callq 400420 <__libc_start_main@plt>
400469: f4 hlt
40046a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
0000000000400470 <deregister_tm_clones>:
400470: b8 47 10 60 00 mov $0x601047,%eax
400475: 55 push %rbp
400476: 48 2d 40 10 60 00 sub $0x601040,%rax
40047c: 48 83 f8 0e cmp $0xe,%rax
400480: 48 89 e5 mov %rsp,%rbp
400483: 77 02 ja 400487 <deregister_tm_clones+0x17>
400485: 5d pop %rbp
400486: c3 retq
400487: b8 00 00 00 00 mov $0x0,%eax
40048c: 48 85 c0 test %rax,%rax
40048f: 74 f4 je 400485 <deregister_tm_clones+0x15>
400491: 5d pop %rbp
400492: bf 40 10 60 00 mov $0x601040,%edi
400497: ff e0 jmpq *%rax
400499: 0f 1f 80 00 00 00 00 nopl 0x0(%rax)
00000000004004a0 <register_tm_clones>:
4004a0: b8 40 10 60 00 mov $0x601040,%eax
4004a5: 55 push %rbp
4004a6: 48 2d 40 10 60 00 sub $0x601040,%rax
4004ac: 48 c1 f8 03 sar $0x3,%rax
4004b0: 48 89 e5 mov %rsp,%rbp
4004b3: 48 89 c2 mov %rax,%rdx
4004b6: 48 c1 ea 3f shr $0x3f,%rdx
4004ba: 48 01 d0 add %rdx,%rax
4004bd: 48 d1 f8 sar %rax
4004c0: 75 02 jne 4004c4 <register_tm_clones+0x24>
4004c2: 5d pop %rbp
4004c3: c3 retq
4004c4: ba 00 00 00 00 mov $0x0,%edx
4004c9: 48 85 d2 test %rdx,%rdx
4004cc: 74 f4 je 4004c2 <register_tm_clones+0x22>
4004ce: 5d pop %rbp
4004cf: 48 89 c6 mov %rax,%rsi
4004d2: bf 40 10 60 00 mov $0x601040,%edi
4004d7: ff e2 jmpq *%rdx
4004d9: 0f 1f 80 00 00 00 00 nopl 0x0(%rax)
00000000004004e0 <__do_global_dtors_aux>:
4004e0: 80 3d 59 0b 20 00 00 cmpb $0x0,0x200b59(%rip) # 601040 <__TMC_END__>
4004e7: 75 11 jne 4004fa <__do_global_dtors_aux+0x1a>
4004e9: 55 push %rbp
4004ea: 48 89 e5 mov %rsp,%rbp
4004ed: e8 7e ff ff ff callq 400470 <deregister_tm_clones>
4004f2: 5d pop %rbp
4004f3: c6 05 46 0b 20 00 01 movb $0x1,0x200b46(%rip) # 601040 <__TMC_END__>
4004fa: f3 c3 repz retq
4004fc: 0f 1f 40 00 nopl 0x0(%rax)
0000000000400500 <frame_dummy>:
400500: 48 83 3d 18 09 20 00 cmpq $0x0,0x200918(%rip) # 600e20 <__JCR_END__>
400507: 00
400508: 74 1e je 400528 <frame_dummy+0x28>
40050a: b8 00 00 00 00 mov $0x0,%eax
40050f: 48 85 c0 test %rax,%rax
400512: 74 14 je 400528 <frame_dummy+0x28>
400514: 55 push %rbp
400515: bf 20 0e 60 00 mov $0x600e20,%edi
40051a: 48 89 e5 mov %rsp,%rbp
40051d: ff d0 callq *%rax
40051f: 5d pop %rbp
400520: e9 7b ff ff ff jmpq 4004a0 <register_tm_clones>
400525: 0f 1f 00 nopl (%rax)
400528: e9 73 ff ff ff jmpq 4004a0 <register_tm_clones>
000000000040052d <main>:
40052d: 55 push %rbp
40052e: 48 89 e5 mov %rsp,%rbp
400531: 48 83 ec 10 sub $0x10,%rsp
400535: c7 45 fc 09 00 00 00 movl $0x9,-0x4(%rbp)
40053c: 83 7d fc 08 cmpl $0x8,-0x4(%rbp)
400540: 75 0c jne 40054e <main+0x21>
400542: bf e4 05 40 00 mov $0x4005e4,%edi
400547: e8 c4 fe ff ff callq 400410 <puts@plt>
40054c: eb 0a jmp 400558 <main+0x2b>
40054e: bf f5 05 40 00 mov $0x4005f5,%edi
400553: e8 b8 fe ff ff callq 400410 <puts@plt>
400558: c9 leaveq
400559: c3 retq
40055a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
0000000000400560 <__libc_csu_init>:
400560: 41 57 push %r15
400562: 41 89 ff mov %edi,%r15d
400565: 41 56 push %r14
400567: 49 89 f6 mov %rsi,%r14
40056a: 41 55 push %r13
40056c: 49 89 d5 mov %rdx,%r13
40056f: 41 54 push %r12
400571: 4c 8d 25 98 08 20 00 lea 0x200898(%rip),%r12 # 600e10 <__frame_dummy_init_array_entry>
400578: 55 push %rbp
400579: 48 8d 2d 98 08 20 00 lea 0x200898(%rip),%rbp # 600e18 <__init_array_end>
400580: 53 push %rbx
400581: 4c 29 e5 sub %r12,%rbp
400584: 31 db xor %ebx,%ebx
400586: 48 c1 fd 03 sar $0x3,%rbp
40058a: 48 83 ec 08 sub $0x8,%rsp
40058e: e8 4d fe ff ff callq 4003e0 <_init>
400593: 48 85 ed test %rbp,%rbp
400596: 74 1e je 4005b6 <__libc_csu_init+0x56>
400598: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1)
40059f: 00
4005a0: 4c 89 ea mov %r13,%rdx
4005a3: 4c 89 f6 mov %r14,%rsi
4005a6: 44 89 ff mov %r15d,%edi
4005a9: 41 ff 14 dc callq *(%r12,%rbx,8)
4005ad: 48 83 c3 01 add $0x1,%rbx
4005b1: 48 39 eb cmp %rbp,%rbx
4005b4: 75 ea jne 4005a0 <__libc_csu_init+0x40>
4005b6: 48 83 c4 08 add $0x8,%rsp
4005ba: 5b pop %rbx
4005bb: 5d pop %rbp
4005bc: 41 5c pop %r12
4005be: 41 5d pop %r13
4005c0: 41 5e pop %r14
4005c2: 41 5f pop %r15
4005c4: c3 retq
4005c5: 66 66 2e 0f 1f 84 00 data32 nopw %cs:0x0(%rax,%rax,1)
4005cc: 00 00 00 00
00000000004005d0 <__libc_csu_fini>:
4005d0: f3 c3 repz retq
Disassembly of section .fini:
00000000004005d4 <_fini>:
4005d4: 48 83 ec 08 sub $0x8,%rsp
4005d8: 48 83 c4 08 add $0x8,%rsp
4005dc: c3 retq
5) Let’s take a look on the block that is really important to us:
000000000040052d <main>:
40052d: 55 push %rbp
40052e: 48 89 e5 mov %rsp,%rbp
400531: 48 83 ec 10 sub $0x10,%rsp
400535: c7 45 fc 09 00 00 00 movl $0x9,-0x4(%rbp)
40053c: 83 7d fc 08 cmpl $0x8,-0x4(%rbp)
400540: 75 0c jne 40054e <main+0x21>
400542: bf e4 05 40 00 mov $0x4005e4,%edi
400547: e8 c4 fe ff ff callq 400410 <puts@plt>
40054c: eb 0a jmp 400558 <main+0x2b>
40054e: bf f5 05 40 00 mov $0x4005f5,%edi
400553: e8 b8 fe ff ff callq 400410 <puts@plt>
400558: c9 leaveq
400559: c3 retq
40055a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
Now, let’s zoom in at the line that defines the value 9 to our password variable:
400535: c7 45 fc 09 00 00 00 movl $0x9,-0x4(%rbp)
Since we know the source code, if we change the number 9 to 8 we’re gonna crack the binary. So, let’s find it opening using xxd to see our binary on hexadecimal format:
cat hello-world | xxd | grep 'fc 09'
0000530: e548 83ec 10c7 45fc 0900 0000 837d fc08 .H....E......}..**
There we go! We found the sequence of the hexadecimal bytes responsable to define the number 9.
So, since we know the memory address (0x530) let’s use PHP to change the value of those bytes. But first let’s explain something:
As you can see, the hexadecimal 0x530 is the address that contains 32 bytes, but which byte do we have to set our pointer to write the new password? To figure out which address, let’s split the 32 bytes in groups:
0000530: e548 83ec 10c7 45fc 0900 0000 837d fc08
Byte 00 is: e5
Byte 01 is: 48
Byte 02 is: 83
Byte 03 is: ec
Byte 04 is: 10
Byte 05 is: c7
Byte 06 is: 45
Byte 07 is: fc
Byte 08 is: 09 --> There we go! 0x530 + 0x08 = 0x538
Byte 09 is: 00 -> wait.. why is this byte zero?
Byte 10 is: 00 -> what?
Byte 11 is: 00 -> wtf???
Did you notice the sequence of zeros after 09? Do you have an idea why? Oh well, remember that one integer in PHP have 4 bytes? of “memory space”? There we go my friend, let’s change 4 bytes then.
<?php
$fp = fopen("hello-world", "r+");
fseek($fp, 0x538);
$content = fread($fp, 4);
// echo $content;
$unpack = unpack("N*", $content);
foreach($unpack as $byte) {
// echo dechex($byte). " \n";
}
fseek($fp, 0x538);
$pack = pack("N*", 0x8000000);
fwrite($fp, $pack);
$unpack = unpack("N*", $pack);
foreach($unpack as $byte) {
// echo dechex($byte). " \n";
}
fclose($fp);
I added some extra code here because I was learning how to edit the file. Basically fseek sets the pointer to the address we want to change. After that, fwrite does the trick and as you can see our before and after binary must look like this:
Before:
cat hello-world | xxd | grep 'fc 09'
0000530: e548 83ec 10c7 45fc 0900 0000 837d fc08 .H....E......}..**
After:
cat hello-world | xxd | grep 'fc 08'
0000530: e548 83ec 10c7 45fc 0800 0000 837d fc08 .H....E......}..
The final test:
./hello-world
Congratulations
That’s it for today. I hope you enjoyed.
Rodolfo
<< All Posts
How to Install MySQL Server (MariaDB) on OpenBSD