#include < stdio.h >
void function1()
{
printf("Victory\n");
}
void function2()
{
printf("Failed\n");
}
int main(int argc, char **argv)
{
function2();
}
Compile the program
gcc ./vuln.c -m32 -ggdb -o vuln
Test the program and watch the output. It know outputs failed but the goal is to binary patch it so function1 is executed and Victory is printed to the screen.
$ ./vuln
Failed
I used nm to find what memory address function1 is located in the binary as the output shows it's at address 0x0804841d
$ nm ./vuln
0804a020 B __bss_start
0804a020 b completed.6591
0804a018 D __data_start
0804a018 W data_start
08048360 t deregister_tm_clones
080483d0 t __do_global_dtors_aux
08049f0c t __do_global_dtors_aux_fini_array_entry
0804a01c D __dso_handle
08049f14 d _DYNAMIC
0804a020 D _edata
0804a024 B _end
080484d4 T _fini
080484e8 R _fp_hw
080483f0 t frame_dummy
08049f08 t __frame_dummy_init_array_entry
08048628 r __FRAME_END__
0804841d T function1
08048431 T function2
0804a000 d _GLOBAL_OFFSET_TABLE_
w __gmon_start__
080482b0 T _init
08049f0c t __init_array_end
08049f08 t __init_array_start
080484ec R _IO_stdin_used
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
08049f10 d __JCR_END__
08049f10 d __JCR_LIST__
w _Jv_RegisterClasses
080484d0 T __libc_csu_fini
08048460 T __libc_csu_init
U __libc_start_main@@GLIBC_2.0
08048445 T main
U puts@@GLIBC_2.0
08048390 t register_tm_clones
08048320 T _start
0804a020 D __TMC_END__
08048350 T __x86.get_pc_thunk.bx
Fire up radare in write mode and disassemble main
$ r2 -w ./vuln
-- This should be documented, since it's not that obvious
[0x08048320]> pdf @ main
Cannot find function at 0x08048445
[0x08048320]> pd @ main
;-- sym.main:
0x08048445 55 push ebp
0x08048446 89e5 ebp = esp
0x08048448 83e4f0 esp &= 0xfffffff0
0x0804844b e8e1ffffff call sym.function2
0x08048431(unk) ; sym.function2
0x08048450 c9
0x08048451 c3
0x08048452 6690
0x08048454 6690
0x08048456 6690
0x08048458 6690
0x0804845a 6690
0x0804845c 6690
0x0804845e 6690
;-- sym.__libc_csu_init:
0x08048460 55 push ebp
0x08048461 57 push edi
0x08048462 31ff edi = 0
0x08048464 56 push esi
0x08048465 53 push ebx
0x08048466 e8e5feffff call sym.__x86.get_pc_thunk.bx
0x08048350(unk, unk, unk, unk) ; sym.__x86.get_pc_thunk.bx
0x0804846b 81c3951b0000 ebx += 0x1b95
0x08048471 83ec1c esp -= 0x1c
0x08048474 8b6c2430 ebp = [esp+0x30]
0x08048478 8db30cffffff esi = [ebx-0xf4]
0x0804847e e82dfeffff call sym._init
0x080482b0() ; sym._init
0x08048483 8d8308ffffff eax = [ebx-0xf8]
0x08048489 29c6 esi -= eax
0x0804848b c1fe02 sar esi,0x2
0x0804848e 85f6 cmp esi, esi
┌─< 0x08048490 7427 je 0x80484b9
│ 0x08048492 8db600000000 esi = [esi]
┌──> 0x08048498 8b442438 eax = [esp+0x38]
││ 0x0804849c 892c24 [esp] = ebp
││ 0x0804849f 89442408 [esp+0x8] = eax
││ 0x080484a3 8b442434 eax = [esp+0x34]
││ 0x080484a7 89442404 [esp+0x4] = eax
││ 0x080484ab ff94bb08fff. call dword [ebx+edi*4-0xf8]
││ 0x080483ba() ; sym.register_tm_clones
││ 0x080484b2 83c701 edi += 0x1
││ 0x080484b5 39f7 cmp edi, esi
└──< 0x080484b7 75df jne 0x8048498
└─> 0x080484b9 83c41c esp += 0x1c
0x080484bc 5b pop ebx
0x080484bd 5e pop esi
0x080484be 5f pop edi
0x080484bf 5d pop ebp
0x080484c0 c3
┌───< 0x080484c1 eb0d goto sym.__libc_csu_fini
│ 0x080484c3 90
│ 0x080484c4 90
│ 0x080484c5 90
│ 0x080484c6 90
│ 0x080484c7 90
│ 0x080484c8 90
│ 0x080484c9 90
│ 0x080484ca 90
│ 0x080484cb 90
│ 0x080484cc 90
│ 0x080484cd 90
│ 0x080484ce 90
│ 0x080484cf 90
;-- sym.__libc_csu_fini:
└───> 0x080484d0 f3c3 repe ret
;-- section_end..text:
0x080484d2 0000 [eax] += al
;-- section..fini:
0x080484d4 53 push ebx ; [13] va=0x080484d4 pa=0x000004d4 sz=20 vsz=20 rwx=-r-x .fini
0x080484d5 83ec08 esp -= 0x8
0x080484d8 e873feffff call sym.__x86.get_pc_thunk.bx
0x08048350(unk) ; sym.__x86.get_pc_thunk.bx
0x080484dd 81c3231b0000 ebx += 0x1b23
0x080484e3 83c408 esp += 0x8
0x080484e6 5b pop ebx
0x080484e7 c3
;-- section..rodata:
0x080484e8 hex length=4 delta=0
0300 0000 ....
;-- sym._IO_stdin_used:
0x080484ec hex length=4 delta=0
0100 0200 ....
;-- str.Victory:
0x080484f0 .string "Victory" ; len=8
;-- str.Failed:
0x080484f8 .string "Failed" ; len=7
;-- section_end..rodata:
0x080484ff 0001 eax += [eax]
0x08048501 1b03 sbb eax,[ebx]
0x08048503 3b38 cmp edi, [eax]
0x08048505 0000 [eax] += al
0x08048507 0006 [esi] += al
0x08048509 0000 [eax] += al
0x0804850b 00e0 al += ah
0x0804850d fd
0x080485d7 0038 [eax] += bh
0x080485d9 0000 [eax] += al
0x080485db 00a000000080 [eax-0x80000000] += ah
0x080485eb 088502410e0c [ebp+0xc0e4102] |= al
0x080485f1 8703 xchg [ebx],eax
0x080485f3 43 inc ebx
0x080485f4 0e push cs
0x080485f5 108604410e14 adc [esi+0x140e4104],al
0x080485fb 83054e0e300. dword [0x2300e4e] += 0x48
0x08048602 0e push cs
0x08048603 1441 adc al,0x41
0x08048605 c3
0x08048606 0e push cs
0x08048607 1041c6 adc [ecx-0x3a],al
0x0804860a 0e push cs
0x0804860b 0c41 al |= 0x41
Note this row in the output "0x0804844b e8e1ffffff call sym.function2" it's the row we want to patch to call function1 instead.
Use s command to move to 0x0804844b offset in the binary.
[0x08048320]> s 0x0804844b
Now use wa to write assembler instruction to call our function2 memory address.
[0x0804844b]> wa call 0x0804841d
Written 5 bytes (call 0x0804841d) = wx e8f8000000
$ ./vuln
Victory
Wow that was easy radare2 is awesome :-)