01.About Programming /12.Default knowledge
StackFrame 을 이용한 stack Back Trace
JamesK78
2009. 9. 3. 15:13
함수 호출로 인한 스택 구성시,
처음에, 이전의 EBP 레지스터 값을 스택에 저장한다.
이를 이용해 현재의 EBP + 0x4 에서 함수의 Return Address 를 찾을 수 있다.
이 방법을 반복하여, 함수 콜 관계를 확인할 수 있다.
예제 )
결과
처음에, 이전의 EBP 레지스터 값을 스택에 저장한다.
이를 이용해 현재의 EBP + 0x4 에서 함수의 Return Address 를 찾을 수 있다.
이 방법을 반복하여, 함수 콜 관계를 확인할 수 있다.
예제 )
void __fastcall WhoCallMe()
{
PVOID pEBP;
PVOID pStackFrame;
DWORD dwReturnAddr;
DWORD dwArgs[3];
CHAR sMsg[512];
{
PVOID pEBP;
PVOID pStackFrame;
DWORD dwReturnAddr;
DWORD dwArgs[3];
CHAR sMsg[512];
//__asm mov eax, [ebp+4]
//__asm mov dword ptr [dwReturnAddr], eax
//__asm mov dword ptr [dwReturnAddr], eax
__asm mov pEBP, ebp
do{
pStackFrame = pEBP;
pEBP = (PVOID)*(PDWORD)(pEBP);
dwReturnAddr = *(PDWORD)((DWORD)pStackFrame +4);
dwArgs[0] = *(PDWORD)((DWORD)pStackFrame +8);
dwArgs[1] = *(PDWORD)((DWORD)pStackFrame +12);
dwArgs[2] = *(PDWORD)((DWORD)pStackFrame +16);
do{
pStackFrame = pEBP;
pEBP = (PVOID)*(PDWORD)(pEBP);
dwReturnAddr = *(PDWORD)((DWORD)pStackFrame +4);
dwArgs[0] = *(PDWORD)((DWORD)pStackFrame +8);
dwArgs[1] = *(PDWORD)((DWORD)pStackFrame +12);
dwArgs[2] = *(PDWORD)((DWORD)pStackFrame +16);
sprintf(sMsg, "[DBG] StackPtr:0x%08x CallAddr:0x%08x Args[0]:%08x Args[1]:%08x Args[2]:%08x\n",
pEBP, dwReturnAddr, dwArgs[0], dwArgs[1], dwArgs[2]);
OutputDebugString(sMsg);
pEBP, dwReturnAddr, dwArgs[0], dwArgs[1], dwArgs[2]);
OutputDebugString(sMsg);
}while(dwReturnAddr != 0);
}
}
void fnC(void *a, void *b, void *c)
{
WhoCallMe();
return;
}
{
WhoCallMe();
return;
}
void fnB(char a, char b)
{
fnC((PUCHAR)1, (PUCHAR)2, (PUCHAR)3);
return;
}
{
fnC((PUCHAR)1, (PUCHAR)2, (PUCHAR)3);
return;
}
BOOL fnA(int a)
{
fnB('1', '2');
return 0;
}
{
fnB('1', '2');
return 0;
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
fnA(1);
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
fnA(1);
return 0;
}
}
결과
[2416] [DBG] StackPtr:0x0012ff04 CallAddr:0x004010aa Args[0]:0012ff18 Args[1]:004010ba Args[2]:00000001
[2416] [DBG] StackPtr:0x0012ff18 CallAddr:0x004010ba Args[0]:00000001 Args[1]:00000002 Args[2]:00000003
[2416] [DBG] StackPtr:0x0012ff28 CallAddr:0x004010cb Args[0]:00000031 Args[1]:00000032 Args[2]:0012ff34
[2416] [DBG] StackPtr:0x0012ff34 CallAddr:0x004010dc Args[0]:00000001 Args[1]:0012ffc0 Args[2]:00401205
[2416] [DBG] StackPtr:0x0012ffc0 CallAddr:0x00401205 Args[0]:00400000 Args[1]:00000000 Args[2]:00142426
[2416] [DBG] StackPtr:0x0012fff0 CallAddr:0x7c816ff7 Args[0]:00360033 Args[1]:00340037 Args[2]:7ffd8000
[2416] [DBG] StackPtr:0x00000000 CallAddr:0x00000000 Args[0]:00401137 Args[1]:00000000 Args[2]:78746341
[2416] [DBG] StackPtr:0x0012ff18 CallAddr:0x004010ba Args[0]:00000001 Args[1]:00000002 Args[2]:00000003
[2416] [DBG] StackPtr:0x0012ff28 CallAddr:0x004010cb Args[0]:00000031 Args[1]:00000032 Args[2]:0012ff34
[2416] [DBG] StackPtr:0x0012ff34 CallAddr:0x004010dc Args[0]:00000001 Args[1]:0012ffc0 Args[2]:00401205
[2416] [DBG] StackPtr:0x0012ffc0 CallAddr:0x00401205 Args[0]:00400000 Args[1]:00000000 Args[2]:00142426
[2416] [DBG] StackPtr:0x0012fff0 CallAddr:0x7c816ff7 Args[0]:00360033 Args[1]:00340037 Args[2]:7ffd8000
[2416] [DBG] StackPtr:0x00000000 CallAddr:0x00000000 Args[0]:00401137 Args[1]:00000000 Args[2]:78746341