有点背景;我试图将自己的代码注入旧游戏SimTower中,其最终目标是以与OpenRCT2创建时相同的方式对其进行反向工程。我在注入自己的DLL并将main方法更改为我自己的DLL时遇到了一些麻烦(如本文中https://bwrsandman.wordpress.com/2014/12/27/first-steps-to-reverse- engineering-an-executable /),但我想我找到了另一种方法。

SimTower要做的第一件事就是从WAVEMIXINIT运行WAVMIX16.DLL。据我所知,如果返回值为0,它将显示一个对话框并禁用声音。



我现在的计划是简单地创建一个人造wavmix16将会(暂时)始终从该函数返回0的dll。这应该可以让我获得一个入口点来运行我自己的代码,并开始游戏。 ,并且可以看到该调用即将传入我的函数中,因为如果我取消注释while循环,该程序将被卡在其中。转到我的返回语句。

(Windows XP)



这是被调用的DDL函数的程序集。我有点不确定为什么除了wavmix16.dllmov(例如retf吗?)之外还有更多的东西,但是我对此很陌生,所以也许这很正常。 />
这是原始DLL函数的汇编:



非常感谢任何帮助,谢谢!

评论

您是否检查了是否使用了正确的参数和调用约定?这似乎是清理错误。

据我所知。查看wavemix库的头文件,我可以看到该函数定义为HANDLE WINAPI WaveMixInit(void);。 HANDLE被定义为我在代码中以相同方式定义的空指针。 WINAPI,如果我理解本文的正确之处与我的__far __pascal相同...我将添加原始DLL中的反编译函数,看看是否可以发现任何差异...

对我来说,似乎我的函数在返回之前将2个值压入堆栈,而原始DLL在返回之前将6个值压入并弹出4个值(再次保留2个),这对我来说意味着调用约定应该相同。 ..

WINAPI应该解析为__stdcall(在现代系统上)。在另一个节点上,您的函数不会还原原始的bp和sp。真的很奇怪的约定

因此,由于没有发现任何输出16位代码的现代系统,因此我正在使用古老的编译器来编译16位DLL :)我正在遵循DigitalMars的本指南并使用其编译器

#1 楼

您的伪函数未将堆栈固定在该函数的结尾处。根据调用约定,它的末尾应该具有

pop ds
pop bp
dec bp




假设函数中的堆栈指针具有1000h的值(在CS:IP已被压入堆栈以进行远端调用之后)。然后,您将拥有原始函数

; sp = 1000h
mox ax, ds     
...
push bp        ; sp = 0ffeh
mov bp, sp     ; bp = 0ffeh
...
lea sp, [bp-2] ; sp = 0ffch
pop ds         ; sp = 0ffeh
pop bp         ; sp = 1000h
retf



要使问题中使用的编译器,Digital Mars编译器dmc.exe,在生成以下指令时从far函数返回时,传递标志-Wm,该标志将“生成INC BP / DEC BP标记远堆栈帧”。

评论


关于inc bp / dec bp:blogs.msdn.microsoft.com/oldnewthing/20110316-00/?p = 11203

–伊戈尔·斯科钦斯基♦
17年11月8日12:44



谢谢!我在函数中添加了xor ax,ax,pop ds,pop bp,dec bp,retf作为内联汇编,它解决了!

– LinusUnnebäck
17年11月8日在16:55

话虽如此,如果有人可以指出正确的方向,让DigitalMars编译器dmc.exe输出正确的指令,我将非常高兴:)

– LinusUnnebäck
17年11月8日在17:03

我找到了!标志-Wm将使dmc“ Generate INC BP / DEC BP标记远堆栈帧”。将此添加到答案中以确保完整性。最好在其他编译器中添加如何执行此操作:)

– LinusUnnebäck
17年11月8日在19:56