获取程序真正的起始执行地址

Posted muzicangcang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了获取程序真正的起始执行地址相关的知识,希望对你有一定的参考价值。

摘要

最近在使用vs2010编写shellcode的时候,在将编写好的shellcode保存为二进制格式的。那么引出一个问题,我刚开始的时候直接: 取地址符 + 函数名 的方式来获取函数的首地址。当时在使用shellcode的时候,程序一直崩溃,经过分析发现shellcode前面的一些代码并不是我们所需要的代码,而是一条jmp指令+一系列的CC指令,再经过对原本编写shellcode的程序进行逆向,对比分析后得出结论:&取地址符 获取的函数地址并非真正的起始地址。

 

分析过程

下面我将会使用一个最简单的例子来记录和说明。

环境:win7 64位操作系统 + vs2010.

代码如下:

void function(){

    MessageBox(0, "", "", 0);

    return ;

}

int main(){

    void *p = (void *)&function;

    printf("function的ì?地ì?址?¤:êo%x", p);

    getchar();

    return 0;

}

打开od对我们生成的程序, 定位到main函数:

技术分享图片

当执行完:lea rax, qword ptr ds:[function]这条汇编指令(相当于执行完:void *p = (void *)&function;)后,此时rax = 0x000000013F7F100A。

技术分享图片

接下来我们在定位到rax执向的地址:000000013F7F100A。

技术分享图片

可以看出,rax指向的是一条跳转指令的地址,并非是function函数的真正执行地址。

 

获取函数真正地址

那么问题来了,我们要怎么获取我们需要的函数的真正的地址呢?我们进行进一步的分析。首先明确跳转指令jmp是由:E9 + 4字节的偏移(相对本条指令结束),那么接下来我们就可以很容易地确定函数的真正执行地址了。其代码如下:

void *p = (void *)&function;

int offset = *(unsigned int *)((char*)p + 1);

void *rfadr = (void*)((char*)p + 5 + offset);

其结果如下:

技术分享图片

运行完 lea rax,qword ptr ds:[rcx+rax+5] | ;rax:function 这条指令后,rax = 0x000000013F501020,我们转移到rax指向的地址:

技术分享图片

这次获取的地址是我们真正想要的函数地址。

 

总结

经过对这个小例子的分析,我不仅仅知道了所谓的对函数名取地址的操作并非直接获取函数的真正的起始地址,更是让我在从发现shellcode执行崩溃,到逆向分析shellcode,再到找出、确认问题产生的原因,最后到给出真正的解决方法,这整个过程中收获良多。

 

 

2018-04-04 21:02:02

 

以上是关于获取程序真正的起始执行地址的主要内容,如果未能解决你的问题,请参考以下文章

UISplitViewController 应该是root,那么如何将真正的起始视图“推”到顶部?

JSP 获取访问者真正的IP地址

汇编:获取段地址的问题

如何获得真正的硬件 MAC 地址 [关闭]

可执行程序的入口点在那里?(强化概念:程序真正的入口是mainCRTstartup)

ssd1306高地址起始为啥是0x10