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

问题描述 投票:0回答:1

我最近做了很多低级编码,想尝试完全用机器代码编写一个程序来加深我的知识(从 x64 汇编向下翻译,并将其添加到 PE 文件的正确部分)

我遇到的唯一问题是我在 Windows 上,我必须使用 win API 而不是系统调用来拥有任何我可以交互的东西,比如窗口,甚至只是标准输出,显然没有很多关于的指南如何从机器代码调用 .DLL 函数。我假设它可能是由操作系统使用 PE 文件中的某些字段完成的,而不是实际上由编译器完成的。有谁有这方面的资料吗

windows assembly dll x86-64 machine-code
1个回答
0
投票

我的实际示例在这里:https://github.com/joshudson/dossuperfloppy/blob/660586f2bb3d660d8154b0cb6857562dc4892bcf/postntfs.asm#L374就导入符号而言,32位和64位之间的差异很小。

您需要发出

.idata
部分(是的,它可以与另一个部分组合;但内容需要在那里......)

在PE头中,第二个RVA指针指向导入目录,而第13个指针则指向导入地址表(稍后会详细介绍)。

导入表中的每个条目由五个双字组成。第一个双字是该 dll 启动的 IA 表中位置的 RVA。在最简单的情况下,第二个和第三个将为零。第四个是 DLL 名称的 ASCIIZ 字符串的 RVA(不,您不能以 unicode 名称导入 dll),第五个是导入地址转换表的 RVA。该表以五个零双字条目结束。 (为什么它以这种方式结束,而不是使用标头中的大小参数,我不知道;请注意,RVA 表中的大小包括终止条目。)导入表必须双字对齐。

导入地址表由指向导入名称表的机器字(32 位为 dword,64 位为 qword)RVA 指针组成。零会停止对该特定导入的 DLL 的处理。该表必须机器字对齐。

导入名称表由包含单词提示的条目组成(如果图像尚未绑定,则提示值的最佳选择为 0),后跟给出要导入的符号名称的 ASCIIZ 字符串。名称表中的每个条目必须字对齐。未能对名称表中的条目进行单词对齐会导致特别令人困惑的错误。

在磁盘映像中,导入地址转换 (IAT) 表是导入地址表的副本。在加载期间,它会被指向实际导入符号的指针覆盖。因此,

.idata
部分被声明为可写。

使用导入符号的最简单方法是发出

call [rel iat-offset]
指令。由于您专注于在机器代码中执行此操作的痛苦,因此要发出的指令被编码为 FF 15 后跟一个小尾数双字,它是(六字节)指令末尾与中条目之间的字节数导入地址转换表(在 RAM 中加载;请注意,这很可能不是图像中的距离)。

RVA:相对虚拟地址。一个指针,其基址是图像在内存中的加载地址。

© www.soinside.com 2019 - 2024. All rights reserved.