특정 프로세스에서 호출되는 Child process 개체를 확인하고 싶을 때 Windbg 를 사용하여 이를 추적하는 방법에 대해서 아래와 같이 정리하였습니다. 단순히 자식 프로세스를 확인하기 위한 방법이라면 Process Explorer 를 사용할 수도 있지만 Child Process 호출 단계가 복잡하거나 Child Process 생성에 문제가 있을 때, 단계별로 추적할 때 활용할 수 있을 듯 합니다.
[시나리오]
cmd.exe 프로세스를 실행한 후 notepad.exe 를 실행할 때, 실행되는 단계를 Windbg 로 확인함
[확인절차]
1. cmd.exe 실행
2. windbg 실행 - Attach to process... - cmd.exe 선택
-- createprocess 함수 찾기
0:001> x *kernel32!*createprocess*
00000000`77a9b980 kernel32!BasepCreateProcessParameters = <no type information>
00000000`77a9c830 kernel32!BasepConstructSxsCreateProcessMessage = <no type information>
00000000`77ae1890 kernel32!NtVdm64CreateProcessInternalW = <no type information>
00000000`77a9a600 kernel32!CreateProcessInternalW = <no type information>
00000000`77a9cbd0 kernel32!BasepReleaseSxsCreateProcessUtilityStruct = <no type information>
00000000`77b17a60 kernel32!CreateProcessInternalA = <no type information>
00000000`77b18730 kernel32!CreateProcessA = <no type information>
00000000`77a8b3d0 kernel32!CreateProcessAsUserW = <no type information>
00000000`77b1cd18 kernel32!_imp_RtlCreateProcessParametersEx = <no type information>
00000000`77a9e7b0 kernel32!CreateProcessW = <no type information>
00000000`77a81720 kernel32!BasepSxsCreateProcessCsrMessage = <no type information>
-- 해당 함수가 호출될 때, break point 설정
0:001> bp 77b17a60
0:001> bp 77b18730
0:001> bp 77a8b3d0
0:001> bp 77a9e7b0
0:001> bl
0 e 00000000`77b17a60 0001 (0001) 0:**** kernel32!CreateProcessInternalA
1 e 00000000`77b18730 0001 (0001) 0:**** kernel32!CreateProcessA
2 e 00000000`77a8b3d0 0001 (0001) 0:**** kernel32!CreateProcessAsUserW
3 e 00000000`77a9e7b0 0001 (0001) 0:**** kernel32!CreateProcessW
-- cmd.exe 실행 제어권 넘겨준 뒤, cmd.exe 에서 notepad.exe 실행
0:001> g
Breakpoint 3 hit
kernel32!CreateProcessW:
00000000`77a9e7b0 4883ec68 sub rsp,68h
-- break point 설정에 의해 제어권이 다시 디버거로 넘어오고 콜 스택을 확인해 보면 CreateProcessW 함수 확인
0:000> kbL
RetAddr : Args to Child : Call Site
00000000`49f64e97 : 00000000`00000000 00000000`000e65a0 00000000`000e65a0 00000000`00000001 : kernel32!CreateProcessW
00000000`49f6178f : 00000000`00000000 00000000`00000000 00000000`000e65a0 00000000`00000001 : cmd!ExecPgm+0x307
00000000`49f61832 : 00000000`00000004 00000000`000ebbb0 00000000`000e6580 00000000`00000000 : cmd!ECWork+0xb8
00000000`49f618b3 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`000ebbb0 : cmd!ExtCom+0x4a
00000000`49f62982 : 00000000`00000004 00000000`000ebbb0 00000000`00000001 00000000`00000000 : cmd!FindFixAndRun+0x10f
00000000`49f68768 : 00000000`00000002 00000000`00000002 00000000`00000002 00000000`00000002 : cmd!Dispatch+0x192
00000000`49f69756 : 00000000`00000000 00000000`00000000 00000000`49f889a8 00000000`00000001 : cmd!main+0x454
00000000`77a9f56d : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : cmd!LUAGetUserType+0x315
00000000`77cd3021 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : kernel32!BaseThreadInitThunk+0xd
00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x1d
-- 해당 함수에서 호출한 프로세스 이름 확인
0:000> du 000e65a0
00000000`000e65a0 "notepad"
0:001> x *kernel32!*createprocess*
00000000`77a9b980 kernel32!BasepCreateProcessParameters = <no type information>
00000000`77a9c830 kernel32!BasepConstructSxsCreateProcessMessage = <no type information>
00000000`77ae1890 kernel32!NtVdm64CreateProcessInternalW = <no type information>
00000000`77a9a600 kernel32!CreateProcessInternalW = <no type information>
00000000`77a9cbd0 kernel32!BasepReleaseSxsCreateProcessUtilityStruct = <no type information>
00000000`77b17a60 kernel32!CreateProcessInternalA = <no type information>
00000000`77b18730 kernel32!CreateProcessA = <no type information>
00000000`77a8b3d0 kernel32!CreateProcessAsUserW = <no type information>
00000000`77b1cd18 kernel32!_imp_RtlCreateProcessParametersEx = <no type information>
00000000`77a9e7b0 kernel32!CreateProcessW = <no type information>
00000000`77a81720 kernel32!BasepSxsCreateProcessCsrMessage = <no type information>
-- 해당 함수가 호출될 때, break point 설정
0:001> bp 77b17a60
0:001> bp 77b18730
0:001> bp 77a8b3d0
0:001> bp 77a9e7b0
0:001> bl
0 e 00000000`77b17a60 0001 (0001) 0:**** kernel32!CreateProcessInternalA
1 e 00000000`77b18730 0001 (0001) 0:**** kernel32!CreateProcessA
2 e 00000000`77a8b3d0 0001 (0001) 0:**** kernel32!CreateProcessAsUserW
3 e 00000000`77a9e7b0 0001 (0001) 0:**** kernel32!CreateProcessW
-- cmd.exe 실행 제어권 넘겨준 뒤, cmd.exe 에서 notepad.exe 실행
0:001> g
Breakpoint 3 hit
kernel32!CreateProcessW:
00000000`77a9e7b0 4883ec68 sub rsp,68h
-- break point 설정에 의해 제어권이 다시 디버거로 넘어오고 콜 스택을 확인해 보면 CreateProcessW 함수 확인
0:000> kbL
RetAddr : Args to Child : Call Site
00000000`49f64e97 : 00000000`00000000 00000000`000e65a0 00000000`000e65a0 00000000`00000001 : kernel32!CreateProcessW
00000000`49f6178f : 00000000`00000000 00000000`00000000 00000000`000e65a0 00000000`00000001 : cmd!ExecPgm+0x307
00000000`49f61832 : 00000000`00000004 00000000`000ebbb0 00000000`000e6580 00000000`00000000 : cmd!ECWork+0xb8
00000000`49f618b3 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`000ebbb0 : cmd!ExtCom+0x4a
00000000`49f62982 : 00000000`00000004 00000000`000ebbb0 00000000`00000001 00000000`00000000 : cmd!FindFixAndRun+0x10f
00000000`49f68768 : 00000000`00000002 00000000`00000002 00000000`00000002 00000000`00000002 : cmd!Dispatch+0x192
00000000`49f69756 : 00000000`00000000 00000000`00000000 00000000`49f889a8 00000000`00000001 : cmd!main+0x454
00000000`77a9f56d : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : cmd!LUAGetUserType+0x315
00000000`77cd3021 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : kernel32!BaseThreadInitThunk+0xd
00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x1d
-- 해당 함수에서 호출한 프로세스 이름 확인
0:000> du 000e65a0
00000000`000e65a0 "notepad"
[참고자료]
WinDbg - Break Point 설정 방법
http://laigo.kr/338
작성자 : Lai Go / 작성일자 : 2010.12.28