您最喜欢的反调试技巧是什么?

发布于 2024-07-13 19:30:45 字数 596 浏览 5 评论 0原文

在我以前的雇主中,我们使用了第三方组件,它基本上只是一个 DLL 和一个头文件。 该特定模块处理 Win32 中的打印。 然而,制造该组件的公司破产了,所以我无法报告我发现的错误。

所以我决定自己修复这个错误并启动调试器。 我很惊讶地发现反调试代码几乎无处不在,通常的 IsDebuggerPresent,但引起我注意的是:

    ; some twiddling with xor 
    ; and data, result in eax 
    jmp eax 
    mov eax, 0x310fac09 
    ; rest of code here 

乍一看,我只是跳过了被调用两次的例程,然后事情简直发疯了。 过了一会儿,我意识到位旋转结果总是相同的,即 jmp eax 总是直接跳到 mov eax, 0x310fac09 指令。 我剖析了这些字节,发现了 0f31,即 rdtsc 指令,用于测量 DLL 中某些调用之间所花费的时间。

所以我的问题是:你最喜欢的反调试技巧是什么?

At my previous employer we used a third party component which basically was just a DLL and a header file. That particular module handled printing in Win32. However, the company that made the component went bankcrupt so I couldn't report a bug I'd found.

So I decided to fix the bug myself and launched the debugger. I was surprised to find anti-debugging code almost everywhere, the usual IsDebuggerPresent, but the thing that caught my attention was this:

    ; some twiddling with xor 
    ; and data, result in eax 
    jmp eax 
    mov eax, 0x310fac09 
    ; rest of code here 

At the first glance I just stepped over the routine which was called twice, then things just went bananas. After a while I realized that the bit twiddling result was always the same, i.e. the jmp eax always jumped right into the mov eax, 0x310fac09 instruction.
I dissected the bytes and there it was, 0f31, the rdtsc instruction which was used to measure the time spent between some calls in the DLL.

So my question to SO is: What is your favourite anti-debugging trick?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

小猫一只 2024-07-20 19:30:46

我最喜欢的技巧是为不起眼的微处理器编写一个简单的指令模拟器。

然后,复制保护和一些核心功能将为微处理器进行编译(GCC 在这里很有帮助),并作为二进制 blob 链接到程序中。

这背后的想法是,普通 x86 代码中不存在复制保护,因此无法反汇编。 您也不能删除整个模拟器,因为这会删除程序的核心功能。

破解程序的唯一机会是对微处理器仿真器的功能进行逆向工程。

我使用 MIPS32 进行仿真,因为它非常容易仿真(只需要 500 行简单的 C 代码)。 为了让事情变得更加模糊,我没有使用原始的 MIPS32 操作码。 相反,每个操作码都与其自己的地址进行异或运算。

复制保护的二进制文件看起来像垃圾数据。

强烈推荐! 花了 6 个多月的时间才出现破解(这是一个游戏项目)。

My favorite trick is to write a simple instruction emulator for an obscure microprocessor.

The copy protection and some of the core functionality will then compiled for the microprocessor (GCC is a great help here) and linked into the program as a binary blob.

The idea behind this is, that the copy protection does not exist in ordinary x86 code and as such cannot be disassembled. You cannot remove the entire emulator either because this would remove core functionality from the program.

The only chance to hack the program is to reverse engineer what the microprocessor emulator does.

I've used MIPS32 for emulation because it was so easy to emulate (it took just 500 lines of simple C-code). To make things even more obscure I didn't used the raw MIPS32 opcodes. Instead each opcode was xor'ed with it's own address.

The binary of the copy protection looked like garbage-data.

Highly recommended! It took more than 6 month before a crack came out (it was for a game-project).

素手挽清风 2024-07-20 19:30:46

我是许多 RCE 社区的成员,也曾参与过黑客攻击和攻击。 开裂。 从我的时代起,我就意识到这种脆弱的技巧通常是不稳定且徒劳的。 大多数通用反调试技巧都是特定于操作系统的,根本不“可移植”。

在上述示例中,您可能使用内联汇编和 naked 函数 __declspec,在 x64 架构上编译时,MSVC 不支持这两种功能。 当然,仍然有一些方法可以实现上述技巧,但是任何已经逆行足够长的时间的人都能够在几分钟内发现并击败这个技巧。

因此,一般来说,我建议除了利用 IsDebuggerPresent API 进行检测之外,不要使用反调试技巧。 相反,我建议您编写存根和/或虚拟机代码。 我编写了自己的虚拟机,并且多年来一直在对其进行改进,我可以诚实地说,这是迄今为止我在保护代码方面做出的最佳决定。

I've been a member of many RCE communities and have had my fair share of hacking & cracking. From my time I've realized that such flimsy tricks are usually volatile and rather futile. Most of the generic anti-debugging tricks are OS specific and not 'portable' at all.

In the aforementioned example, you're presumably using inline assembly and a naked function __declspec, both which are not supported by MSVC when compiling on the x64 architecture. There are of course still ways to implement the aforementioned trick but anybody who has been reversing for long enough will be able to spot and defeat that trick in a matter of minutes.

So generally I'd suggest against using anti-debugging tricks outside of utilizing the IsDebuggerPresent API for detection. Instead, I'd suggest you code a stub and/or a virtual machine. I coded my own virtual machine and have been improving on it for many years now and I can honestly say that it has been by far the best decision I've made in regards to protecting my code so far.

筱果果 2024-07-20 19:30:46

分离出一个子进程,该子进程作为调试器附加到父进程上。 修改关键变量。 保持子进程驻留并将调试器内存操作用作某些关键操作的 IPC 的奖励点。

在我的系统上,您无法将两个调试器附加到同一进程。

这个的好处是除非他们试图篡改东西,否则不会有任何破坏。

Spin off a child process that attaches to parent as a debugger & modifies key variables. Bonus points for keeping the child process resident and using the debugger memory operations as a kind of IPC for certain key operations.

On my system, you can't attach two debuggers to the same process.

Nice thing about this one is unless they try to tamper w/ things nothing breaks.

还不是爱你 2024-07-20 19:30:46

引用未初始化的内存! (以及其他黑魔法/伏都教......)

这是一本非常酷的读物:
http://spareclockcycles.org/ 2012/02/14/stack-necromancy-通过-raise-the-dead击败-debuggers/

Reference uninitialized memory! (And other black magic/vodoo...)

This is a very cool read:
http://spareclockcycles.org/2012/02/14/stack-necromancy-defeating-debuggers-by-raising-the-dead/

等风来 2024-07-20 19:30:46

最现代的混淆方法似乎是虚拟机。

您基本上获取目标代码的一部分,并将其转换为您自己的字节码格式。 然后添加一个小型虚拟机来运行此代码。 正确调试此代码的唯一方法是为虚拟机的指令格式编写模拟器或反汇编程序。 当然,您还需要考虑性能。 太多的字节码会让你的程序运行得比本机代码慢。

大多数旧技巧现在都没用了:

  • Isdebuggerpresent :非常蹩脚且易于修补
  • 其他调试器/断点检测
  • Ring0 东西:用户不喜欢安装驱动程序,你实际上可能会破坏他们系统上的某些东西等。
  • 每个人都知道的其他琐碎的东西,或者这会使你的软件不稳定。 请记住,即使破解使您的程序不稳定但它仍然可以工作,这种不稳定将归咎于您。

如果您确实想自己编写 VM 解决方案(有很好的程序出售),请不要仅使用一种指令格式。 使其具有多态性,以便可以使代码的不同部分具有不同的格式。 这样,仅编写一个模拟器/反汇编器就不会破坏您的所有代码。 例如,一些人提供的 MIPS 解决方案似乎很容易被破解,因为 MIPS 指令格式有很好的文档记录,并且像 IDA 这样的分析工具已经可以反汇编代码。

IDA 支持的指令格式列表专业反汇编程序

The most modern obfuscation method seems to be the virtual machine.

You basically take some part of your object code, and convert it to your own bytecode format. Then you add a small virtual machine to run this code. Only way to properly debug this code will be to code an emulator or disassembler for your VM's instruction format. Of course you need to think of performance too. Too much bytecode will make your program run slower than native code.

Most old tricks are useless now:

  • Isdebuggerpresent : very lame and easy to patch
  • Other debugger/breakpoint detections
  • Ring0 stuff : users don't like to install drivers, you might actually break something on their system etc.
  • Other trivial stuff that everybody knows, or that makes your software unstable. remember that even if a crack makes your program unstable but it still works, this unstability will be blamed on you.

If you really want to code the VM solution yourself (there are good programs for sale), don't use just one instruction format. Make it polymorphic, so that you can have different parts of the code have different format. This way all your code can't be broken by writing just one emulator/disassembler. For example MIPS solution some people offered seems to be easily broken because MIPS instruction format is well documented and analysis tools like IDA can already disassemble the code.

List of instruction formats supported by IDA pro disassembler

清风挽心 2024-07-20 19:30:46

我更希望人们编写的软件是可靠的、可靠的并且能够实现其广告宣传的功能。 他们还以合理的价格和合理的许可证出售它。

我知道我浪费了太多时间与那些拥有复杂许可方案的供应商打交道,这些方案只会给客户和供应商带来问题。 我始终建议避开这些供应商。 在核电厂工作时,我们被迫使用某些供应商的产品,因此被迫必须处理他们的许可计划。 我希望有一种方法可以收回我个人浪费在处理他们为我们提供工作许可产品的失败尝试上的时间。 这似乎是一件小事,但对于那些为了自己的利益而变得太狡猾的人来说,这似乎是一件困难的事情。

I would prefer that people write software that is solid, reliable and does what it is advertised to do. That they also sell it for a reasonable price with a reasonable license.

I know that I have wasted way too much time dealing with vendors that have complicated licensing schemes that only cause problems for the customers and the vendors. It is always my recommendation to avoid those vendors. Working at a nuclear power plant we are forced to use certain vendors products and thus are forced to have to deal with their licensing schemes. I wish there was a way to get back the time that I have personally wasted dealing with their failed attempts to give us a working licensed product. It seems like a small thing to ask, but yet it seems to be a difficult thing for people that get too tricky for their own good.

不忘初心 2024-07-20 19:30:46

我赞同虚拟机的建议。 我实现了一个 MIPS I 模拟器,它(现在)可以执行使用 mipsel-elf-gcc 生成的二进制文件。 添加代码/数据加密功能(AES 或您选择的任何其他算法)、自模拟能力(这样您就可以拥有嵌套模拟器),您就拥有了一个非常好的代码混淆器。

选择 MIPS I 的好处是 1) 易于实现,2) 我可以用 C 语言编写代码,在桌面上进行调试,完成后只需针对 MIPS 进行交叉编译。 无需调试自定义操作码或为自定义虚拟机手动编写代码。

I second the virtual machine suggestion. I implemented a MIPS I simulator that (now) can execute binaries generated with mipsel-elf-gcc. Add to that code/data encryption capabilities (AES or with any other algorithm of your choice), the ability of self-simulation (so you can have nested simulators) and you have a pretty good code obfuscator.

The nice feature of choosing MIPS I is that 1) it's easy to implement, 2) I can write code in C, debug it on my desktop and just cross-compile it for MIPS when it's done. No need to debug custom opcodes or manually write code for a custom VM..

妳是的陽光 2024-07-20 19:30:46

我个人最喜欢的是 Amiga,它有一个协处理器(Blitter)独立于处理器进行大量数据传输; 该芯片将被指示清除所有内存,并通过定时器 IRQ 复位。

当您连接 Action Replay 卡带时,停止 CPU 意味着 Blitter 将继续清除内存。

My personal favourite was on the Amiga, where there is a coprocessor (the Blitter) doing large data transfers independent from the processor; this chip would be instructed to clear all memory, and reset from a timer IRQ.

When you attached an Action Replay cartridge, stopping the CPU would mean that the Blitter would continue clearing the memory.

冰之心 2024-07-20 19:30:46

我最喜欢的是在看似合法但真正隐藏实际指令的中间计算跳转。 无论如何,人类很容易检测到它们,但自动化工具常常会把事情搞砸。

另外,替换堆栈上的返回地址也会浪费时间。

Calculated jumps in the middle of a legitimate looking but really hiding an actual instruction instructions are my favorite. They are pretty easy to detect for humans anyway, but automated tools often mess it up.

Also replacing a return address on the stack makes a good time waster.

使用 nop 通过调试器删除程序集是一个有用的技巧。 当然,把代码放回去要困难得多!

Using nop to remove assembly via the debugger is a useful trick. Of course, putting the code back is a lot harder!!!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文