我正在尝试替换静态值:

MOV DWORD PTR SS:[EBP-30],4c


用来自特定地址的值:

MOV DWORD PTR SS:[EBP-30],400400 // MOV DWORD PTR SS:[EBP-30],OFFSET 400400


但是SS:[EBP-30]的值未设置为0x400400的值。

我是新手,但我认为这可以工作:

MOV DWORD PTR SS:[EBP-30],DWORD PTR DS:[400400]


但是我想不是因为ollydbg给出了一个错误。

0x400400中的值是int 10064 00 00 00。为什么不起作用?我有什么选择?

我也在考虑做类似的事情:

MOV ECX,DWORD PTR DS:[400400]
MOV DWORD PTR SS:[EBP-30],ECX


但是我不知道如何在ollydbg中添加新的指令我也担心会更改所有地址。

#1 楼

让我们将其分开。我将跳过一些您可能已经了解的内容,但是如果某些内容不清楚,我们可能需要扩展此内容。


MOV DWORD PTR SS:[EBP-30], 400400
MOV DWORD PTR SS:[EBP-30],DWORD PTR DS:[400400]

语法有点古怪,但是我们可以理解,您想用两个编码MOV内存操作数。
让我们看一些文档
参考:https://www.felixcloutier.com/x86/MOV.html
对于MOV来说,没有可能接受m32,m32的编码。使用m32被理解为32位指针。
情况并非如此,但不幸的是。
参考:https://stackoverflow.com/a/33799523/10279341
如果您关心为什么,这是一个很好的答案,但这只是补充性阅读,对这种情况并不重要。

因此,如果我们要使用x86将内存复制到内存中,请参见: :https://stackoverflow.com/a/1299094/10279341
普遍接受的解决方案是将寄存器用作临时值存储。
请注意,我们需要保存寄存器的状态正在使用else,我们可能会意外更改程序状态。

MOV ECX,DWORD PTR DS:[400400]
MOV DWORD PTR SS:[EBP-30],ECX

所以,这是对的。但是我们需要事先保存ECX,以防其他用途。
0x00000000: 51                  push ecx
0x00000001: 8b 0d 00 04 40 00   mov ecx, dword ptr [0x400400]
0x00000007: 89 4d e2            mov dword ptr [ebp - 0x1e], ecx
0x0000000a: 59                  pop ecx

您应该这样做。我们通过将ECX压入堆栈来保存它。将地址0x400400的值加载到ECX中。然后将ECX的值写入到[EBP-0x1E]的内存中,然后将ECX恢复为其先前的值。

那么我们如何将其修补到二进制映像中呢?
上面的程序集是11字节长度,我们的目标是更改指令
0: c7 45 e2 4c 00 00 00 mov DWORD PTR [ebp-0x1e],0x4c
我们看到的是7个字节长。
我们可以使用“代码洞穴”获得这4个字节。我们会将执行重定向到未使用的内存中,执行代码,然后跳回。
参考:https://www.codeproject.com/Articles/20240/The-Beginners-Guide-to-Codecaves
简而言之,我们正在寻找在exe映像内分配/映射的“空白空间”,最好在.text部分中,但在任何情况下均不被程序使用。由于Windows PE中的SectionAlignment默认为4096,几乎所有可执行映像中都会出现这种情况。
最简单的实现方法是在我们尝试修改的同一内存区域中找到未使用的字节。 >在此处显示了使用ollydbg查找/应用代码洞穴的基本方法:
https://medium.com/@vysec.private/backdoor-101-f318110e1fcb

找到合适的方法之后为我们的洞穴存储,在shellcode中打补丁:
0x00000000: 51                  push ecx
0x00000001: 8b 0d 00 04 40 00   mov ecx, dword ptr [0x400400]
0x00000007: 89 4d e2            mov dword ptr [ebp - 0x1e], ecx
0x0000000a: 59                  pop ecx

,使用ollydbg的汇编程序。
然后将mov DWORD PTR [ebp-0x1e],0x4c的原始指令更改为JMP x,其中x是您的shellcode地址,在同一模块/映像中。
如果需要,可以用0x90(NOP)覆盖其余的指令字节。这样我们最终得到:
c7 45 e2 4c 00 00 00-原始指令
e9 xx xx xx xx 90 90-JMP rel32加上2个NOP
x86 JMP的参考:https://c9x.me/x86/html/file_module_x86_id_147.html将pop ecx之后的
返回到我们的代码中,然后进行汇编:JMP y
其中ymov DWORD PTR [ebp-0x1e],0x4c之后的指令的地址。退出代码陷阱时,您最终应该跳过NOP指令,这就是为什么我说它们是可选的。

摘要,


组装我们的shellcode,记下正确的x86 ASM并保留程序状态。


如果没有足够的空间来内嵌指令,请识别代码漏洞。


应用代码凹腔并组合两个JMP指令,以将执行(1)重定向到代码凹腔,(2)从原始代码重定向到下一条指令。



评论


我要读取的值只有1-100是否重要?例如该值最大为100。因此从技术上讲,我可以将其读取为单个字节。

– majidarif
18-09-27在17:45

除非更改值周围的字节,否则没有关系。例如0x400401、0x400402,包含不属于该值的其他值。 dword ptr [0x400400]将从0x400400开始读取4个字节(小端)。如果将其更改为字节ptr,它将仅读取一个字节。

–阿比盖尔
18/09/27在18:59

#2 楼

内存到内存MOV不存在。您可以尝试以下操作:

    MOV eax, DWORD PTR DS : [400400]
    MOV DWORD PTR SS : [EBP - 30], eax


请还检查绝对数字是否在汇编器中解释为十六进制值。

评论


我实际上是在想这个,但是我如何在ollydbg中做到这一点?我不确定如何添加新的说明行,它可能会更改所有地址吗?

– majidarif
18-09-27在14:39

如果您打算修补现有代码,并且修补程序比替换的代码需要更多的字节,则必须确保不再需要额外空间中的代码,或者可以将jmp插入(即修补)到一个可用的内存位置,重新插入“销毁”的代码,然后将jmp返回到原始代码,可以像修补程序之前那样继续进行。关于Olly,我不知道答案,因为我通常在Ida工作。

–乔什
18-09-27在15:01

谢谢。不幸的是,尽管我认为我明白你的意思。我真的很陌生,不知道该怎么做。当您对空闲内存位置说JMP时。我是否用JMP替换当前指令,然后使用JMP来返回那些指令?但是,我该怎么做呢?以及如何找到可用内存?

– majidarif
18-09-27在15:09

我认为你做对了。从技术上讲,您的操作方式取决于。尝试精通您的工具。一种可能性是创建机器码(通常不是手工,而是从汇编器创建),然后将其修补到exe文件中,然后在调试器中对其进行测试。通常最棘手的部分是找到一个足够大的免费内存位置,例如,不要引入新的错误。依赖于绝对内存地址(尝试了解“ ASLR”的含义)等。不存在标准配方。

–乔什
18-09-27在16:08