// gcc -o rtld rtld.c -fPIC -pie
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <dlfcn.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);
}
void get_shell() {
system("/bin/sh");
}
int main()
{
long addr;
long value;
initialize();
printf("stdout: %p\n", stdout);
printf("addr: ");
scanf("%ld", &addr);
printf("value: ");
scanf("%ld", &value);
*(long *)addr = value;
return 0;
}
GOT Overwrite가 가능하다.
stdout 라이브러리 주소를 출력해 줘서 libc base 주소를 구할 수 있고 임의의 주소를 덮는 취약점이 존재한다.
get_shell 함수가 존재하지만 PIE가 있어서 어떻게 사용해야 할지 모르겠다...
ld base 주소를 구하고 _dl_rtld_lock_recursive 함수 값을 덮으면 get_shell로 덮어보자
remote 환경이 16.04 버전이라 도커로 하자!
stdout 라이브러리 주소를 이용해 libc_base 주소를 구했다.
이제 libc와 ld offset은 항상 같기 때문에 gdb로 offset을 구해보자.
[그림 1-4] 참고하면 ld가 libc 보다 높은 주소에 있는걸 알 수 있다.
offset은 0x3ca000이다.
ld base 주소를 구했다!
_dl_rtld_lock_recursive는 _rtld_global + 3848 위치에 존재한다.
[그림 2-1]처럼 dl_rtld_lock_recursive 주소를 구할 수 있다.
PIE가 enabled 되어있는데 get_shell 주소를 구할 방법을 못 찾겠어서 one_gadget 사용으로 방법을 바꿨다.
local에서는 shell이 실행되었다.
성공!
remote에서는 shell이 될 때가 있고 안될 때가 있는데
실행될 때마다 one_gadget 조건을 만족할 때가 있고 안될 때가 있어서 그런 거 같다. -> 내 생각
최종 익스 코드
알 게 된점
1. 눈에 보이는 코드가 안되면 다른 방법도 생각하자...
'Dreamhack - pwnable' 카테고리의 다른 글
send_sig (0) | 2023.03.15 |
---|---|
Sigreturn-Oriented Progamming (0) | 2023.03.14 |
environ (0) | 2023.03.06 |
master_canary (1) | 2023.02.15 |
seccomp (0) | 2023.02.13 |