S表示是否栈指针
P表示是否是调用返回地址
H是否堆指针
E是否可执行代码
Address Value S P E H
-------------------------
0012FF7C 0012FF7C 1 0 0 0
0012FF80 004011F5 0 0 1 0
发现调用栈
TraceStack:004010D0 ip_ptr:004010D0 offset:-293
函数部分代码:
51 68 D0 70 40 00 8D 44
24 04 68 C8 70 40 00 68
B4 70 40 00 89 44 24 0C
E8 13 01 00 00 68 98 70
0012FF84 004012E5 0 0 1 0
发现调用栈
TraceStack:004010D0 ip_ptr:004011F0 offset:-245
函数部分代码:
E8 DB FE FF FF 33 C0 C3
90 90 90 90 90 90 90 90
53 56 BE 08 71 40 00 57
56 E8 4B 01 00 00 8B F8
0012FF88 00000001 0 0 0 0
0012FF8C 00381010 0 0 0 1
0012FF90 00381068 0 0 0 1
0012FF94 00241FE4 0 0 0 1
0012FF98 0012F7BC 1 0 0 0
0012FF9C 7FFDB000 0 0 0 0
0012FFA0 00000006 0 0 0 0
0012FFA4 F0A8ED04 0 0 0 0
0012FFA8 0012FF94 1 0 0 0
0012FFAC 865F204C 0 0 0 0
0012FFB0 0012FFE0 1 1 0 0
0012FFB4 00402878 0 0 1 0
0012FFB8 004060B0 0 0 1 0
0012FFBC 00000000 0 0 0 0
0012FFC0 0012FFF0 1 1 0 0
0012FFC4 7C817077 0 0 0 0
0012FFC8 00241FE4 0 0 0 1
0012FFCC 0012F7BC 1 0 0 0
0012FFD0 7FFDB000 0 0 0 0
0012FFD4 80545C7D 0 0 0 0
0012FFD8 0012FFC8 1 0 0 0
0012FFDC 856C7020 0 0 0 0
0012FFE0 FFFFFFFF 0 0 0 0
0012FFE4 7C839AD8 0 0 0 0
0012FFE8 7C817080 0 0 0 0
0012FFEC 00000000 0 0 0 0
0012FFF0 00000000 0 0 0 0
0012FFF4 00000000 0 0 0 0
0012FFF8 00401231 0 0 1 0
0012FFFC 00000000 0 0 0 0
-------------------------
当E=TRUE 且 *(unsigned char *)(Value-5)==0xE8 则 Value是调用栈 意思是如果此指针(Value)指向可执行代码,且所指向的位置Value-5个字节是CALL指令,
则Value是一个上层函数调用自己的的返回地址
找到当前函数的返回地址后, 我们在继续向上寻找上一个函数被调用后返回的地址,直到0012FFFF(栈底)
如何得到当前函数的代码?
unsigned char * ip_ptr=Value; 另ip_ptr=调用栈Value的值
ip_ptr-=5;
//
得到call指令首地址,属于假设,为了保证绝对是调用指令,需要判断第一个字符是否是0xEB
if
(*ip_ptr==0xE8)
//
如果是相对CALL指令则
{
ip_ptr++;
int offset = *(int *)ip_ptr; 首先得CALL的偏移地址
ip_ptr+=4;
//
跳过当前指令再+
ip_ptr+=offset;
//
计算出绝对地址
//dump
(ip_ptr,n)
//
显示当前函数16进制码
}
//
实现代码
int main(int argc, char* argv[]);
bool IsStackPointer(unsigned int p)
{
return
( p>=0x00030000 && p<0x0012FFFF );
}
bool IsExeCode(unsigned int p)
{
return
( p>=0x00400000 && p<0x005FFFFF );
}
bool IsHeapPointer(unsigned int p)
{
return
( (p>=0x00130000 && p<0x003FFFFF ) || (p>=0x00600000 && p<0x0FFFFFFF) );
}
void dump_mem(unsigned char * start, int len)
{
int i;
if
(start == NULL)
return
;
for
(i=0;i<len;i++)
{
printf
(
"%02X "
,start[i]);
if
(i%8==7)
printf
(
"\n"
);
}
printf
(
"\n"
);
}
//
获取调用自己的函数
void TraceStack()
{
unsigned int *p;
p=(unsigned int *)&p;
printf
(
"%-8s %-8s S P E H\n"
,
"Address"
,
"Value"
);
printf
(
"-------------------------\n"
);
while
((unsigned int)p<0x0012FFFF)
{
//if
( IsStackPointer(*p) && IsStackPointer(*p)?((unsigned int )p<*p):0)
{
printf
(
"%08X %08X %d %d %d %d\n"
, p,*p, IsStackPointer(*p) , IsStackPointer(*p)?((unsigned int )p<*p):0 , IsExeCode(*p), IsHeapPointer(*p));
}
if
(IsExeCode(*p))
{
unsigned char *ip_ptr=(unsigned char *)(*p);
ip_ptr-=5;
if
(*ip_ptr==0xE8)
{
printf
(
"发现调用栈\n"
,*ip_ptr);
ip_ptr++;
int offset=*(int *)ip_ptr;
ip_ptr+=4;
ip_ptr+=offset;
printf
(
"TraceStack:%08X ip_ptr:%08X offset:%d\n函数部分代码:\n"
, TraceStack, ip_ptr, offset);
dump_mem(ip_ptr,32);
}
}
p++;
}
printf
(
"-------------------------\n"
);
}
int main(int argc, char* argv[])
{
TraceStack();
return
0;
}