简单的栈回溯Trackback文件简析.docx

上传人:b****0 文档编号:700853 上传时间:2022-10-12 格式:DOCX 页数:15 大小:668.89KB
下载 相关 举报
简单的栈回溯Trackback文件简析.docx_第1页
第1页 / 共15页
简单的栈回溯Trackback文件简析.docx_第2页
第2页 / 共15页
简单的栈回溯Trackback文件简析.docx_第3页
第3页 / 共15页
简单的栈回溯Trackback文件简析.docx_第4页
第4页 / 共15页
简单的栈回溯Trackback文件简析.docx_第5页
第5页 / 共15页
点击查看更多>>
下载资源
资源描述

简单的栈回溯Trackback文件简析.docx

《简单的栈回溯Trackback文件简析.docx》由会员分享,可在线阅读,更多相关《简单的栈回溯Trackback文件简析.docx(15页珍藏版)》请在冰豆网上搜索。

简单的栈回溯Trackback文件简析.docx

简单的栈回溯Trackback文件简析

简单的栈回溯&简单的栈回溯欺骗--简单分析

1.#include   

2.#include   

3.#include   

4.  

5.#pragma warning(disable:

 4311 4312 4313)  

6.  

7.int fake_ebp_1, fake_ebp_2;  

8.  

9.void __stdcall _StackTrace(int StackBase, int ebp, int esp)  

10.{  

11.        int limit = 30, retaddr, calladdr;  

12.        printf("ebp      ret      call\n");  

13.        while ((ebp > esp) && (ebp < StackBase) && (limit--))   

14.        {  

15.            retaddr = *(int *)(ebp + 4);  

16.            calladdr = 0;  

17.            __try   

18.            {  

19.                if (*(unsigned char *)(retaddr - 5) == 0xe8)   

20.                {     

21.                    calladdr = *(int *)(retaddr - 4) + retaddr;  

22.                }  

23.            } __except (EXCEPTION_EXECUTE_HANDLER) {}  

24.            printf("%08x %08x %08x\n", ebp, retaddr, calladdr);  

25.            ebp = *(int *)ebp;  

26.        }  

27.        printf("trace completed.\n");  

28.}  

29.  

30.__declspec(naked) void __stdcall StackTrace()  

31.{  

32.        // iceboy's stack trace  

33.        __asm {  

34.            push esp  

35.            push ebp  

36.            push fs:

[0x4]        //; StackBase  

37.            call _StackTrace  

38.            retn  

39.        }  

40.}  

41.  

42.void b(int, int)  

43.{  

44.        StackTrace();  

45.}  

46.  

47.void a(int, int, int)  

48.{  

49.        b(0, 0);  

50.}  

51.  

52.int search_call(int fn1, int fn2)  

53.{  

54.    while (true)   

55.    {  

56.        if (*(unsigned char *)(fn1++) == 0xe8)    

57.        {                                         

58.            if ((*(int *)fn1 + fn1 + 4) == fn2)  

59.            {                                                                     

60.                 return fn1 + 4;                      

61.            }  

62.        }  

63.    }  

64.}  

65.  

66.// fake call  

67.__declspec(naked) void __stdcall d(int, int)  

68.{  

69.    __asm {  

70.        push fake_ebp_1  

71.        push ebp  

72.        mov ebp, esp  

73.        push fake_ebp_2  

74.        push ebp  

75.        mov ebp, esp  

76.        call StackTrace  

77.        pop esp  

78.        pop ebp  

79.        pop eax  

80.        retn 8  

81.    }  

82.}  

83.  

84.// fake call & hide self  

85.__declspec(naked) void __stdcall e(int, int)  

86.{  

87.    __asm {  

88.        push ebp  

89.        mov ebp, [ebp]  

90.        push 0  

91.        push 0  

92.        call d  

93.        pop ebp  

94.        retn 8  

95.    }  

96.}  

97.  

98.void c(int, int, bool hideself)  

99.{  

100.        if (!

hideself)   

101.        {  

102.            d(0, 0);  

103.        } else   

104.        {  

105.            e(0, 0);  

106.        }  

107.}  

108.  

109.int main()  

110.{  

111.        fake_ebp_1 = search_call((int)main, (int)a);  

112.        fake_ebp_2 = search_call((int)a, (int)b);  

113.  

114.  

115.        printf("address of function a:

    0x%08x\n", a);  

116.        printf("address of function b:

    0x%08x\n", b);  

117.        printf("address of function c:

    0x%08x\n", c);  

118.        printf("address of function main:

 0x%08x\n", main);  

119.  

120.        printf("\ntest 1:

 standard call\n");  

121.        a(0, 0, 0);  

122.  

123.        printf("\ntest 2:

 fake call\n");  

124.        c(0, 0, false);  

125.  

126.        printf("\ntest 3:

 fake call & hide self\n");  

127.        c(0, 0, true);  

128.  

129.        printf("\npress any key to continue...");  

130.        _getch();  

131.        printf("\n");  

132.        return 0;  

133.}  

在我的机器上输出如下:

我们就顺着程序来一步一 步分析,需要什么知识点时就说明什么知识点。

首先

1.fake_ebp_1 = search_call((int)main, (int)a);  

2.fake_ebp_2 = search_call((int)a, (int)b);  

search_call的代码如下:

1.int search_call(int fn1, int fn2)  

2.{  

3.    while (true)   

4.    {  

5.        if (*(unsigned char *)(fn1++) == 0xe8)    

6.        {                                         

7.            if ((*(int *)fn1 + fn1 + 4) == fn2)  

8.            {                                                                     

9.                 return fn1 + 4;                      

10.            }  

11.        }  

12.    }  

13.} 

14.首先要知道的是x86平台call指令有很多种,有e8call,ff15call,还有regcall.对于e8call,我们可以计算出call的地址,也就是被调函数首地址,其它的call就困难了许多.那么e8call具体是如何计算机被调函数的首地址的呢?

15.e8是call的指令机器码,这点大家都很清楚。

e8后面的四字节机器码是此时指令指针(EIP)的值与目的地址(被调函数首地址)的差值,也即两地址间的相对偏移。

指令指针在这里可以叫做返回地址,意思就是从被调函数返回后应执行的第一条指令的地址。

16.明白了这些,就很容易计算出目的地址(被调函数首地址):

 目的地址= 返回地址+ 相对偏移 举个例子吧:

17.0045F761   > \8B8D D8000000 MOV ECX,DWORD PTR SS:

[EBP+D8]  

18.0045F767   .  53            PUSH EBX       

19.0045F768   .  03CA          ADD ECX,EDX    

20.0045F76A   .  51            P

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 自然科学 > 物理

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1