如何从 Dll 调用静态导入的函数?调用 dword ptr ds <> 不起作用

逆向工程 dll 聚乙烯 函数挂钩 我在 称呼
2021-07-01 03:34:15

免责声明:我对整个 RE 事情相对较新。所以我成功地将一些指令塞进了现有 DLL 的末尾并重定向了一个调用。

现在我实际上想在调用原始代码之前用函数参数做一些事情并尝试OutputDebugStringA它。

OutputDebugStringA 由我的 Dll 静态导入,因此我尝试执行以下操作:

call dword ptr ds:[<&OutputDebugStringA>]

这是我从 DLL 本身的用法中复制的指令。

所以这有效并被成功调用。但是,当我用这条指令修补 Dll 时,在下一次运行时地址无效,这会导致访问冲突和崩溃。(见图中红线)

在此处输入图片说明

为什么呢?相对于加载 Dll 的位置,函数的 IAT 条目不应该始终位于同一位置吗?

我该如何解决?

我需要复杂的技巧来找到我的模块的基地址吗?

或者是否有某种我愚蠢地不知道的相对远呼叫指令?

谢谢您的帮助。


我想我现在明白了。所以我不能确定 IAT 总是在同一个地址,甚至与 ds 段无关(这在我看来有点没用)。

但是,我可以确定 IAT 地址始终与我要运行的代码保持固定的相对数量。

所以我在 x86 下搜索了 PIC 技术,最终得到了到目前为止似乎工作正常的代码。

push ebp
mov ebp,esp
push eax
push ecx
push edx
push dword ptr ss:[ebp+C]
call <rcp-be-name.tmplbl>
pop ebx   ;@tmplbl
lea eax,dword ptr ds:[ebx+80F] ;the relative offset
call dword ptr ds:[eax-5] ;dunno why 5
pop edx
pop ecx
pop eax
push dword ptr ss:[ebp+C] ;the original arguments
push dword ptr ss:[ebp+8] ;  ...
call rcp-be-name.644A97D0 ;the original function
add esp,8
pop ebp
ret

非常感谢!

1个回答

看来您已经猜到了实际问题是什么 - 您的调用指令使用的是直接寻址而不是相对寻址。这意味着当 DLL 在两次执行之间更改它的位置时,您仍在尝试执行相同的绝对值,根据该地址中实际内容的内容,导致不同类型的错误。

专门针对您的问题 -0xFF 15是一个绝对的、接近的、4 字节的立即调用。0xFF用于绝对调用,而0x8E用于相对调用(如您在图像中看到的,在黄色突出显示的行)。

替换单个字节0xFF会将指令转换为相对指令,这意味着调用将是 to$+5e01d0e4而不是 to 0x5e01d0e4美元符号 ( $) 是“下一条指令的地址”的常规表示。

因为x86 CPU(以及许多其他CPU)的工作原理,更容易先前进到下一条指令,然后才进行任何EIP修改操作,从而使相关操作修改下一条指令EIP

用任何有符号整数替换最后四个字节将使调用指令将该数字(因此负数用于调用较小的地址值)添加到下一条指令的地址。例如,字节码FF 15 EA FF FF FF将被转换为一个 6 字节长的指令call $-6,创建一个call调用自身的指令,最终在堆栈溢出时出错。

一种比手动编辑指令字节代码更简单的方法是使用 olly 的 assemble 命令,并带有一个$符号来指示相关指令。