assembly 如何从机器代码调用Windows .DLL(API)函数?

zy1mlcev  于 7个月前  发布在  Windows
关注(0)|答案(1)|浏览(94)

我最近一直在做很多低级编码,想尝试完全用机器码编写一个程序,以进一步提高我的知识(从x64汇编翻译下来,并将其添加到PE文件的正确部分)。
我遇到的唯一问题是,我在Windows上,我必须使用Win API而不是系统调用来拥有任何我可以与之交互的东西,比如窗口,甚至只是标准输出,很明显,关于如何从机器代码调用.DLL函数的指导并不多。我假设这可能是由操作系统使用PE文件中的某些字段完成的,而不是实际上由编译器完成的。有人有任何信息吗?在这个?

k0pti3hp

k0pti3hp1#

我在这里的实际例子:https://github.com/joshudson/dossuperfloppy/blob/660586f2bb3d660d8154b0cb6857562dc4892bcf/postntfs.asm#L374 32位和64位之间的差异很小,这仍然是一个很好的例子,说明.idata部分应该是什么样子。
您需要发出.idata部分(是的,它可以与另一个部分组合;但内容需要在那里.)
在PE头中,第二个RVA指针指向导入目录,而第13个指针指向导入地址表(稍后详细介绍)。
导入表中的每个条目由五个dword组成。第一个dword是指向此dll开始的IA表中位置的RVA。第二个和第三个在最简单的情况下为零。第四个是指向DLL名称的ASCIIZ字符串的RVA(不,您不能导入Unicode名称中的DLL),第五个是输入地址转换表的RVA,该表以五个零双字的条目结束。(我不知道为什么它以这种方式结束,而不是在头中使用size参数;注意RVA表中的size包括终止条目。)导入表必须是双字对齐的。
导入地址表由导入名称表中的机器字(dword表示32位,qword表示64位)RVA指针组成。零将停止处理此特定导入DLL。此表必须与机器字对齐。
导入名称表由包含单词提示(如果图像尚未绑定,则0是提示值的最佳选择)的条目组成,后跟一个ASCIIZ字符串,该字符串给出要导入的符号的名称。名称表中的每个条目必须进行单词对齐。如果名称表中的条目未进行单词对齐,则会导致特别令人困惑的错误。
在磁盘映像中,导入地址转换(IAT)表是导入地址表的副本。在加载过程中,它会被指向实际导入符号的指针覆盖。因此,.idata部分被声明为可写。
使用导入符号的最简单方法是发出一条call [rel iat-offset]指令。由于您打算在机器代码中执行此操作,因此发出的指令被编码为FF 15,后跟一个little-endiand dword,该dword是(六字节)指令和导入地址转换表中的条目(如RAM中加载的;注意,这很可能不是图像中的距离)。
相对虚拟地址。一个指针,其基址是内存中映像的加载地址。

相关问题