/*
栈回溯目的:
已知函数B调用函数A,现欲得到函数B的地址,则可以inline hook A,在fake_funcA内部进行栈回溯,最终得到B的地址
*/
/*
使用OLLAYDBG跟踪~
本练习程序的
A函数地址:0x00401005 JMP TO 0x00401030真实的A函数地址
B函数地址:0x0040100A JMP TO 0x00401070真实的B函数地址
主函数地址:0x4010D0
*/
/*
追踪调用顺序如下:
首先从主函数F7到 0x004010EE 处 CALL functionB
进入函数B:
0x00401090处 CALL 函数A F7 跟进函数A
单步跟进到
.text:00401030 push ebp
.text:00401031 mov ebp, esp
.text:00401033 sub esp, 44h
查看寄存器和堆栈变化:
EBP = 0X0012FEB8 值为:0X0012FE18
则已知栈回溯代码:
mov edi,edi
push ebp
mov ebp, esp
//核心代码
mov eax,[ebp] eax=0X0012FE18
mov eax,[eax+4] eax=[0x0012fe1c]=0X004010fa
.text:004010F5 call j_funcB
.text:004010FA add esp, 0Ch
可以看到0X00401095在函数B内,是CALL B 指令之后的地址,也就是说,通过A就可以得到MAIN--- CALL B -----CALL A这个流程的CALL B 处的地址,再解析指令即得到B的地址
*/
/*
另外,使用Windbg进行 bp ExAllocatePoolWithTag
断下后,看ebp=b20ff374
kd> dd b20ff374
b20ff374 b20ff398 805c1d9c 00000001 00000050
b20ff384 f4636553 81f9cd68 821b32f0 00000000
kd> dd b20ff39c
b20ff39c 805c249a 81f9cd68 b20ff400 00000000
b20ff3ac 00000000 00000028 b20ff3e0 b20ff4c0
kd> u 805c249a
nt!ObCreateObject+0x12a:
805c249a 8bd8 mov ebx,eax
805c249c 85db test ebx,ebx
805c249e 0f8c57ffffff jl nt!ObCreateObject+0x8b (805c23fb)
805c24a4 8b7d14 mov edi,dword ptr [ebp+14h]
805c24a7 8b7528 mov esi,dword ptr [ebp+28h]
805c24aa 8d4718 lea eax,[edi+18h]
805c24ad 8906 mov dword ptr [esi],eax
805c24af f6470f10 test byte ptr [edi+0Fh],10h
进入到函数ObCreateObject的空间,再往上看可以发现
805c2495 e83af8ffff call nt!ObpAllocateObject (805c1cd4)
805c249a 8bd8 mov ebx,eax
也就是调用了ObpAllocateObject,跟进发现
ObpAllocateObject是调用了ExAllocatePoolWithTag的
这跟应用层的栈回溯结果是一样的!!!
*/
/*
得到 栈回溯返回的Addr是CALL B下一条指令的地址
Addr=Addr-5就是CALL B 处的地址
因为CALL的作用还有相对跳转jmp xxxx
在本程序中
.text:004010F5 call j_funcB
机器码是 E8 10FFFFFF,也就是说相对地址是FFFF10
我们得到相对地址 FFFF10+004010FA=0040100A
.text:0040100A jmp funcB
这里可能跟调用方式有关
得到的是jmp funcB的地址,而不是B的地址
得到0040100A的代码:
CallAddress=(ULONG)Addr-5;
JmpOffset=*(ULONG*)((PUCHAR)CallAddress+1);
FuncAddr=Addr+5+JmpOffset;
*/
栈回溯笔记
最新推荐文章于 2022-12-22 17:57:09 发布