Microsoft MVP성태의 닷넷 이야기
디버깅 기술: 125. WinDbg로 EXE의 EntryPoint에서 BP 거는 방법 [링크 복사], [링크+제목 복사],
조회: 20804
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 
(연관된 글이 1개 있습니다.)
(시리즈 글이 9개 있습니다.)
디버깅 기술: 11. (Managed) Main Method에 Break Point 걸기
; https://www.sysnet.pe.kr/2/0/469

디버깅 기술: 11.1. (Managed) Main Method에 Break Point 걸기 - 내용 보강
; https://www.sysnet.pe.kr/2/0/470

디버깅 기술: 35. windbg - 분석 예: 시작하자마자 비정상 종료하는 프로세스 - NullReferenceException
; https://www.sysnet.pe.kr/2/0/996

디버깅 기술: 37. .NET 4.0 응용 프로그램의 Main 함수에 BreakPoint 걸기
; https://www.sysnet.pe.kr/2/0/1021

디버깅 기술: 59. NT 서비스가 시작하자마자 디버거를 연결시키는 방법 (1)
; https://www.sysnet.pe.kr/2/0/1586

디버깅 기술: 60. NT 서비스가 시작하자마자 디버거를 연결시키는 방법 (2)
; https://www.sysnet.pe.kr/2/0/1587

디버깅 기술: 61. NT 서비스 시작 단계에서 닷넷 메서드에 BP를 걸어 디버깅하는 방법
; https://www.sysnet.pe.kr/2/0/1598

디버깅 기술: 100. windbg - .NET 4.0 응용 프로그램의 Main 메서드에 Breakpoint 걸기
; https://www.sysnet.pe.kr/2/0/11322

디버깅 기술: 125. WinDbg로 EXE의 EntryPoint에서 BP 거는 방법
; https://www.sysnet.pe.kr/2/0/11859




WinDbg로 EXE의 EntryPoint에서 BP 거는 방법

지난 글에서,

EXE를 LoadLibrary로 로딩해 PE 헤더에 있는 EntryPoint를 직접 호출하는 방법
; https://www.sysnet.pe.kr/2/0/11858

2가지 유형의 EntryPoint를 갖는 EXE를 만들었습니다.

  1. 콘솔 프로그램: 사용자 main 함수
  2. 콘솔 프로그램: mainCRTStartup 또는 wmainCRTStartup

우선, windbg로 첫 번째 유형의 EXE 프로그램을 "Open Executable (Ctrl + E)" 메뉴로 로드해 보면 다음과 같이 나옵니다.

Microsoft (R) Windows Debugger Version 10.0.17763.132 X86
Copyright (c) Microsoft Corporation. All rights reserved.

CommandLine: c:\temp\ConsoleApplication1\Debug\exe_entry.exe

************* Path validation summary **************
Response                         Time (ms)     Location
Deferred                                       SRV*e:\Symbols*http://msdl.microsoft.com/download/symbols
Symbol search path is: SRV*e:\Symbols*http://msdl.microsoft.com/download/symbols
Executable search path is: 
ModLoad: 00840000 00859000   exe_entry.exe
ModLoad: 77560000 776fc000   ntdll.dll
ModLoad: 74c50000 74d30000   C:\WINDOWS\SysWOW64\KERNEL32.DLL
ModLoad: 759b0000 75baa000   C:\WINDOWS\SysWOW64\KERNELBASE.dll
(4f5c.730): Break instruction exception - code 80000003 (first chance)
eax=00000000 ebx=002ef000 ecx=cf060000 edx=00000000 esi=00432ea0 edi=775737ec
eip=7760f126 esp=001df5b8 ebp=001df5e4 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
ntdll!LdrpDoDebuggerBreak+0x2b:
7760f126 cc              int     3

그러니까, 운영체제의 ntdll Loader 단계부터 디버깅이 시작되는데 EntryPoint는 이후 한참(?) 후에 나오게 됩니다. 그 시점까지 진행하는 방법은 AddressOfEntryPoint를 이용해 BP를 걸면 됩니다.

이를 위해 PE 헤더를 분석해주는 도구로 AddressOfEntryPoint의 값을 구하고, 현재 EXE 모듈이 로드된 주소를 찾아서 더하면 됩니다. 모듈의 로딩 주소는 windbg의 lm 명령어로 구할 수 있으므로,

0:000> lm
start    end        module name
00840000 00859000   exe_entry   (deferred)             
74c50000 74d30000   KERNEL32   (deferred)             
759b0000 75baa000   KERNELBASE   (deferred)             
77560000 776fc000   ntdll      (pdb symbols)          e:\symbols\wntdll.pdb\06265607D3AAB293F80811D978F5F5B31\wntdll.pdb

AddressOfEntryPoint의 값이 110f라고 구해졌다면 다음과 같이 EntryPoint 주소를 구할 수 있습니다.

0:000> ? 00840000 + 1100f
Evaluate expression: 8720399 = 0085100f

따라서 이 주소에 BP를 걸고,

0:000> bp  0085100f
*** WARNING: Unable to verify checksum for exe_entry.exe

0:000> bl
     0 e Disable Clear  0085100f     0001 (0001)  0:**** exe_entry!ILT+10(_main)

g 키를 눌러 실행을 계속하면 우리가 원하던 EntryPoint에서 실행이 멈추는 것을 확인할 수 있습니다.

0:000> g
Breakpoint 0 hit
eax=001dfb60 ebx=002ef000 ecx=0085100f edx=0085100f esi=0085100f edi=0085100f
eip=0085100f esp=001dfb08 ebp=001dfb14 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
exe_entry!ILT+10(_main):
0085100f e93c000000      jmp     exe_entry!main (00851050)

(Windows 10의 경우) 이 시점에서 콜 스택은 다음과 같습니다.

exe_entry!ILT+10(_main)
ntdll!__RtlUserThreadStart+0x2f
ntdll!_RtlUserThreadStart+0x1b

결국 EntryPoint의 호출은 ntdll!__RtlUserThreadStart에서,

ntdll!__RtlUserThreadStart:
775c65fe 6a30            push    30h
775c6600 6840926677      push    offset ntdll!QueryRegistryValue+0x10da (77669240)
775c6605 e84add0100      call    ntdll!_SEH_prolog4 (775e4354)
775c660a 8bf9            mov     edi,ecx
775c660c 8365fc00        and     dword ptr [ebp-4],0
775c6610 8b351c096877    mov     esi,dword ptr [ntdll!Kernel32ThreadInitThunkFunction (7768091c)]
775c6616 52              push    edx
775c6617 85f6            test    esi,esi
775c6619 0f844ac90300    je      ntdll!__RtlUserThreadStart+0x3c96b (77602f69)
775c661f 8bce            mov     ecx,esi
775c6621 ff15e0416877    call    dword ptr [ntdll!__guard_check_icall_fptr (776841e0)]
775c6627 8bd7            mov     edx,edi
775c6629 33c9            xor     ecx,ecx
775c662b ffd6            call    esi

위의 call esi로 인해 발생하며 이때의 esi 값이 바로 0085100f입니다.




위의 경우에는 사용자가 작성한 main 함수를 EntryPoint로 지정한 EXE였기 때문에 마지막 call stack에 exe_entry!main이 나왔습니다. CRT가 연결된 EXE라면 EntryPoint의 주소는 mainCRTStartup 또는 wmainCRTStartup이 됩니다.

확인 방법 역시 위에서 설명한 것과 동일하지만 이번에는 다른 방법으로 접근해 보겠습니다. ^^

How to get to entry point with windbg
; https://stackoverflow.com/questions/13387691/how-to-get-to-entry-point-with-windbg

그렇습니다. windbg가 제공하는 가상 레지스터인 $exentry 값을 사용하면 되는 것입니다. 따라서 lm 명령이나 AddressOfEntryPoint 값을 알아낼 필요도 없이 곧바로 BP를 걸 수 있습니다.

0:000> bp $exentry
*** WARNING: Unable to verify checksum for exe_dll_entry.exe

0:000> bl
     0 e Disable Clear  002313c0     0001 (0001)  0:**** exe_dll_entry!ILT+955(_mainCRTStartup)

0:000> g
Breakpoint 0 hit
eax=006ffa8c ebx=00434000 ecx=002313c0 edx=002313c0 esi=002313c0 edi=002313c0
eip=002313c0 esp=006ffa34 ebp=006ffa40 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
exe_dll_entry!ILT+955(_mainCRTStartup):
002313c0 e92b1b0000      jmp     exe_dll_entry!mainCRTStartup (00232ef0)

보는 바와 같이 진입 지점의 함수가 "exe_dll_entry!mainCRTStartup"라고 나옵니다.




지난 글에서, EXE 모듈을 윈도우 운영체제로 하여금 DLL로써 다루도록 Characteristics에 IMAGE_FILE_DLL 속성을 부여할 수 있다고 했는데요. 재미있게도, windbg의 경우 IMAGE_FILE_DLL 속성이 부여된 EXE를 로드하는 경우 다음과 같은 오류를 발생시키며 디버깅 진입에 실패합니다.

Could not create process 'c:\temp\ConsoleApplication1\Debug\exe_dll_entry.exe', Win32 error 0n193

%1 is not a valid Win32 application.

따라서 windbg로 로드하려면 다시 IMAGE_FILE_DLL을 제거해야만 합니다.




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 4/4/2019]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




... 91  92  93  94  95  96  97  98  99  100  101  102  103  104  [105]  ...
NoWriterDateCnt.TitleFile(s)
11300정성태9/10/201721183.NET Framework: 681. dotnet.exe - run, exec, build, restore, publish 차이점 [3]
11299정성태9/9/201719851개발 환경 구성: 330. Hyper-V VM의 Internal Network를 Private 유형으로 만드는 방법
11298정성태9/8/201723156VC++: 119. EnumProcesses / EnumProcessModules API 사용 시 주의점 [1]
11297정성태9/8/201719829디버깅 기술: 96. windbg - 풀 덤프에 포함된 모든 닷넷 모듈을 파일로 저장하는 방법
11296정성태9/8/201722938웹: 36. Edge - "이 웹 사이트는 이전 기술에서 실행되며 Internet Explorer에서만 작동합니다." 끄는 방법
11295정성태9/7/201720430디버깅 기술: 95. Windbg - .foreach 사용법
11294정성태9/4/201720093개발 환경 구성: 329. 마이크로소프트의 CoreCLR 프로파일러 예제 빌드 방법 [1]
11293정성태9/4/201720703개발 환경 구성: 328. Visual Studio(devenv.exe)를 배치 파일(.bat)을 통해 실행하는 방법
11292정성태9/4/201718887오류 유형: 419. Cannot connect to WMI provider - Invalid class [0x80041010]
11291정성태9/3/201720712개발 환경 구성: 327. 아파치 서버 2.4를 위한 mod_aspdotnet 마이그레이션
11290정성태9/3/201723972개발 환경 구성: 326. 아파치 서버에서 ASP.NET을 실행하는 mod_aspdotnet 모듈 [2]
11289정성태9/3/201721628개발 환경 구성: 325. GAC에 어셈블리 등록을 위해 gacutil.exe을 사용하는 경우 주의 사항
11288정성태9/3/201718436개발 환경 구성: 324. 윈도우용 XAMPP의 아파치 서버 구성 방법
11287정성태9/1/201727596.NET Framework: 680. C# - 작업자(Worker) 스레드와 UI 스레드 [11]
11286정성태8/28/201715015기타: 67. App Privacy Policy
11285정성태8/28/201723517.NET Framework: 679. C# - 개인 키 보안의 SFTP를 이용한 파일 업로드파일 다운로드1
11284정성태8/27/201721539.NET Framework: 678. 데스크톱 윈도우 응용 프로그램에서 UWP 라이브러리를 이용한 비디오 장치 열람하는 방법 [1]파일 다운로드1
11283정성태8/27/201717313오류 유형: 418. CSS3117: @font-face failed cross-origin request. Resource access is restricted.
11282정성태8/26/201719758Math: 22. 행렬로 바라보는 피보나치 수열
11281정성태8/26/201721593.NET Framework: 677. Visual Studio 2017 - NuGet 패키지를 직접 참조하는 PackageReference 지원 [2]
11280정성태8/24/201718590디버깅 기술: 94. windbg - 풀 덤프에 포함된 모든 모듈을 파일로 저장하는 방법
11279정성태8/23/201730186.NET Framework: 676. C# Thread가 Running 상태인지 아는 방법
11278정성태8/23/201718434오류 유형: 417. TFS - Warning - Unable to refresh ... because you have a pending edit. [1]
11277정성태8/23/201719673오류 유형: 416. msbuild - error MSB4062: The "TransformXml" task could not be loaded from the assembly
11276정성태8/23/201723921.NET Framework: 675. C# - (파일) 확장자와 연결된 실행 파일 경로 찾기 [2]파일 다운로드1
11275정성태8/23/201732950개발 환경 구성: 323. Visual Studio 설치 없이 빌드 환경 구성 - Visual Studio 2017용 Build Tools [1]
... 91  92  93  94  95  96  97  98  99  100  101  102  103  104  [105]  ...