因此,我正在调试该过程,其中包含许多反调试技术,而且我遇到了一些我不知道如何绕过的新事物。

动态更改代码会导致异常发生,并且该过程会
,因此无法设置INT 3断点。调试过程的方法仅是使用Hardware Breakpoints。内存CheckSum符合预期。如果我更改了内存中的一个字节,则CheckSum不会与预期的一样,因此该过程将崩溃。这实际上非常简单,并在代码中这样完成:JE short的十六进制值为0x74 0x0B,我想将其更改为JMP short,即0xEB 0x0B。当我这样做时,程序将崩溃。
我使用Memory breakpoints在代码的不同位置发现了程序崩溃的位置,然后我发现该函数执行CheckSum(它读取所有内存)。但是现在我发现还有另一个现有的功能,它可能做类似的事情!导致程序崩溃。

但是这一次,当我在已更改的JE到JMP上放置一个Memory breakpoint时,它永远不会在断点处停止。

所以这是我的第一个问题,我遇到的另一个问题是我怀疑我的一个功能与更改代码时的崩溃有关,但是当我在上面设置了Hardware breakpoint时,它没有中断。我肯定知道该函数正在被调用并且代码肯定会运行。所以我以为自己可能要确保我的Memory & Hardware breakpoints不能正常工作,并且需要某种反调试机制。

我读了一点,发现了关于GetThreadContext的情况,就我而言致电Wow64GetThreadContext。它接收一个包含大多数寄存器的上下文结构。上下文结构如下所示:

CMP EAX,EDX                  ; Compare CheckSum
JE __GoodCode                  ; jmp must be taken
CALL <CrashProgram>
__GoodCode: 
XOR EAX,EAX
...


-https://msdn.microsoft.com/zh-cn/library/windows/desktop/ms679284(v=vs.85).aspx

第一个参数是我的Hardware breakpoints,我可以看到它们显然,但似乎并没有对他们的价值观有所帮助。所以我不认为这会导致崩溃的功能。每当调用它时,它看起来都更像是调试代码。此外,永远不会定期调用此功能-仅在程序崩溃后。

现在还有ReadProcessMemory,我读到它可能由于某种原因而绕过我的Memory breakpoints。我在该函数上设置了日志记录断点,但似乎从未读取到与更改后的函数接近的Page(大小为0x1000),是的,我也检查了它正在读取的大小。
尽管经常调用此函数

我也听说过ZwProtectVirtualMemory函数可以更改内存区域的属性,以便Memory breakpoint'exceptions'不会发生,调试器也不会接收它们。该函数正在被调出,但是我不确定内存中的用法是什么,或者与我相关的参数是什么。

我还有其他可能丢失的东西吗?

我正在阅读的文章对我有很大帮助,但并没有帮助我找出导致崩溃的原因:
http://waleedassar.blogspot.in/2012/11/defeating-memory-breakpoints.html


我已经更改了这个问题的措词。希望现在更清楚

评论

您是更改磁盘上的字节还是仅更改内存中的字节?该程序可能正在读取其可执行文件。另外,某些程序尝试检测它们是否正在调试器中运行。您是否安装了Stealth插件?如果您不打补丁,该程序是否可以在Ollydbg上运行?也许程序检测到内存断点。如果您不打补丁但设置了内存断点,该程序是否可以工作?

您可能对此链接感兴趣。

@GuntramBlohm我仅在内存中动态更改了字节。不在磁盘上。我使用的是Stealth插件,程序会检查其是否已调试。该程序在Olly中的Stealth插件上运行良好,我可以使用硬件断点(正常断点添加Int 3)进行调试。

在第二个链接的末尾,他们说:“ N.B。ReadProcessMemory还被用作在不触发硬件断点的情况下读取内存的一种隐秘方式。”我假设ReadProcessMemory使用内核环0模式复制内存,因此它避免了适用于用户模式的页面限制。检查ReadProcessMemory是否在某处被调用很容易。

@GuntramBlohm,哇,ReadProcessMemory确实发生了!我从没想过这个API会绕过olly的内存断点。我以为我发现在新线程崩溃之前就已调用此API。.我记录了对ReadProcessMemory的所有调用,第二个参数pBaseAddress从未接近我更改过的内存..它一定是其他东西或我想念什么吗?

#1 楼

某些可能性(在许多可能性中):

1.
程序可能会调用SetThreadContextZwContinue使用新的上下文设置所有寄存器。
如果DRx寄存器被重置,则您的硬件断点将被删除。

2.
程序将使用参数ZwSetInformationThread0x11)调用ThreadHideFromDebugger。如果线程是从调试器中隐藏的,则断点异常将不会被调试器捕获,而是会传递给程序(如果未处理的话),它将崩溃。