如何得到一个函数的基址和大小?
一个可执行文件(exe、dll等)中用到的函数有外部导入的,也有自定义的,当这个可执行文件执行起来时,我如何得到所有函数(外部导入和自定义)在内存中的基址和大小?或者能够对该可执行文件静态分析得到函数基址和大小(如IDA)?
如对于外部导入的函数CreateFileA,我可以通过GetProcAddress得到基址,但却没办法得到函数的大小。自定义函数基址和大小都不知道了?
使用IDA可以得到,效果如图:
但如何在自己的代码中实现呢?
[解决办法]
基址可以通过导入/导出表获得,对于大小,我觉得那就要分析汇编代码了,遇到C3(汇编是retn),就是返回,因此可以计算大小,不过要忽略比如push C3(68 c3000000)这类的数据代码。
[解决办法]
楼上检测retn的方法不行啦,一个函数有可能有多个出口,这样做就错了阿.
到现在还没有找到如何计算函数大小的准确方法,看来不了解PE格式是不可能的了
还有,不要说把两个函数放在一起计算,那样是不行的,编译器不保证代码中的函数相邻实际二进制代码就相邻
[解决办法]
函数这个概念在编译成二进制以后就没有了。
代码在执行的时候,哪有什么函数? 完全就是顺序执行下去的执行指令。
你在代码里面写一个函数,意思就是说,编译器最终生成的二进制指令里面, 这个地方需要保存现场,寄存器压栈。
函数的退出,那么编译器就生成了寄存器出栈和恢复现场,还原到进入函数时候的状态。
在二进制指令的层次上,只能通过这些特征结合代码流程来判断一个函数的进入和退出。
因为编译器一般是不允许乱goto的,所以一般都能够分析得出
但在汇编里面完全可以乱goto,所以有些软件就是通过混入一些乱goto的花指令,来让IDA反汇编工具分析不出来它的函数流程结构。
[解决办法]
获取外部导入的函数可将EXE加载到内存中通过PE格式的Import表来查找。
关于获取函数长度的方法,可通过反汇编引擎从函数开头开始反汇编,遇到C3、C2(ret)这类指令时可当作函数结束(不一定),此时获取累加的指令长度。