前言:
之前学完PE结构导出表后,原以为只要是出现在导出名称表中的函数,就可以被其他程序调用。最近研究java的JNI实现,调用dll时也想证明这一点,随便去windows拽了一个dll,随便改了一个导出名称表的函数名,来给java调用,发现竟然不行。而后回到C,写了一个.exe调用这个dll的改之后的方法还是不行,GetProcAddress返回值为0。ollydbg跟汇编跟了好久才发现,问题出在GetProcAddress函数内部的LdrpNameToOrdinal方法。windows在使用这个函数在导出名称表中找函数名时,并非从上到下轮询,而是先比对名称表第一个方法,然后再对其余项进行二分法查找。
正文:
我们编写完一个dll源码,其导出方法由编译器自动安排在导出表中。比如导出了名称为aaa1,aaa2, aaa3, aaa4, aaa5, aaa6,bbb1, bbb2, bbb3, bbb4, bbb5, bbb6,ccc1, ccc2,ccc3,ccc4,ccc5,ccc6的18个方法。无论用.def文件的方式定义导出,还是用__declspec(dllexport)的方式导出,以及无论函数的定义先后、导出序号先后,在导出名称表中,这些函数名称都是按照严格的字母顺序并且大小写敏感的方式排列的: