如何使用程序集,机器代码将字符串地址推送到堆栈

时间:2011-01-02 02:38:20

标签: assembly executable code-injection dll-injection

我正在更改minesweeper.exe,以便了解代码注入的工作原理。简单地说,我希望扫雷在开始之前显示一个消息框。因此,我在可执行文件中找到一个“洞穴”,然后定义要在消息框中显示的字符串并调用消息框。另外,当然,我必须更改可执行文件的模块入口点的值,并首先将其指向我的附加代码,然后继续自己的代码。 所以我在山洞里做的事情;

"hello starbuck",0

push 0 //arg4 of MessageBoxW function
push the address of my string //arg3, must be title
push the address of my string //arg2, must be the message
push 0  //arg1
call MessageBoxW
...

现在,由于可执行文件中代码的内存地址每次加载到内存中时都会更改,因此,为了调用MessageBoxW函数,我给出了导入地址表中定义MessageBoxW的地址的偏移量。例如,如果IAT中的 address1 定义了MessageBoxW,而call MessageBoxW之后的指令位于 address2 而不是写call MessageBoxW,我写call address2 - address1

所以我的问题是,如何将字符串的地址推送到堆栈? 例如,如果我通过ollydbg进行这些更改,我会提供“hello starbuck”的直接地址进行推送并且它可以工作。但是在重新加载可执行文件或在ollydbg之外启动它之后,它自然会失败,因为直接地址会发生变化。

提前致谢, Yigit。

编辑:现在出现这个问题是因为每次打开exe时,模块入口点的高位字都会改变。所以,为了看看其他字符串是如何被推送到堆栈的,我这样做了:

我在代码中找到了“Destroy Canvas”字符串。它位于地址:00403E44。并且在地址0042878E处,存在指令PUSH 00403E44(68 44 3E 40 00),这意味着指向字符串的指针被推送到堆栈。然后我在UltraEdit中打开了exe,找到了相应的地址,即00027D8E。在那里,它写的是“68 44 3E 00 01”,而不是“68 44 3E 40 00”。现在它意味着当OllyDbg加载exe时,它会更新这些代码; 00 01至40 00.我看了其他字符串,他们的推送说明也是如此。所以我想如果我在UltraEdit中写“68 DA 9A 00 01”而不是“68 DA 9A 40 00”来推送字符串,它也会被更新。但事实并非如此。当我在此之后打开OllyDbg中的exe时,要推送的地址仍为“01009ADA”。

所以我认为必须有一些东西来组织这些“更新代码”程序。也许它与重定位表有关,我不知道。

您是否认为我可能会将此问为另一个问题?

3 个答案:

答案 0 :(得分:0)

如果字符串嵌入在EXE中,则该字符串的偏移量不应更改。它是作为资源加载还是动态分配或者是什么?如果是后者之一,那么你需要推动动态创建的地址。但是静态字符串应始终使用相同的偏移地址加载。

答案 1 :(得分:0)

您的解决方案:

您添加的字符串应为UTF-16。

对于字符串“Hello”,您应该写“H.e.l.l.o”,点为00h。确保在此字符串的末尾至少有00h00h00h(3 X 0) 还要确保当你使用dword ptr []来调用msgbox时 CALL DWORD PTR DS:[10010B8]

详情:

在程序结束时,靠近LoadLibrary字符串(不是unicode),在UTF-16中添加字符串,即每个ASCII字符用00h分隔,unicode字符串终止至少00h00h(00h用点表示)在ollydbg的转储窗口中

在程序的入口点你可能有这个:

01003E21 PUSH 70
01003E23 PUSH winmine_.01001390
01003E28 CALL winmine_.0100400C

双击PUSH 70线将其替换为JMP 01004A5F :(不要写“winmine _”。)

01003E21 JMP winmine_.01004A5F
01003E26 NOP
01003E27 NOP
01003E28 CALL winmine_.0100400C

在01004A5F,你注入你的代码:

01004A5F PUSH 0
01004A61 PUSH winmine_.01004A5F
01004A66 PUSH winmine_.01004A5F
01004A6B PUSH 0
01004A6D CALL DWORD PTR[010010B8] ;msgbox

并添加在入口点添加跳转时删除的原始代码,然后跳回正常的程序执行:

01004A72 PUSH 70
01004A74 PUSH winmine_.01001390
01004A79 JMP winmine_.01003E28

要查找MessageBoxW的地址,请按CTRL + N,您将获得已注册函数的有序列表。

对于字符串,它看起来像这样:

01004A58 UNICODE "Hello",0

享受。

原帖: 当您在exe中注入字符串时,在OllyDbg中尝试右键单击反汇编窗口并搜索 - >所有引用文本字符串。 在那里你应该能够找到你的字符串及其地址。

以下是您应该仔细阅读的2篇文章:

http://osix.net/modules/article/?id=633

在本文的第2部分中,将解释如何使用您自己的消息替换exe中的现有(未使用)字符串以及如何使用自定义函数调用它。

http://osix.net/modules/article/?id=758

在本文的第2部分中,有关于文本部分和字符串以及如何引用它们的说明。

这应该会给你很多信息来开始反转Windows应用程序。

作为逆转Windows游戏的奖励教程: http://osix.net/modules/article/?id=723(freecell)

答案 2 :(得分:0)

我认为您需要首先将地址发送到AX然后再推送

mov ax,OFFSET string1  ;or use LEA ax,string1
push ax

因此,要创建MessageBox,您需要执行以下操作:

mov ax,16            ;16 = Critical Icon (for example)
push ax
lea dx,title
push dx
lea dx,text
push dx
mov ax,0              ;0 is like NULL for the window's handle
push ax
call MesssageBox...