吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4692|回复: 12
收起左侧

[原创] 初探反调试程序

  [复制链接]
镇北看雪 发表于 2020-3-10 18:29
本帖最后由 镇北看雪 于 2020-7-24 19:37 编辑

反调试:顾名思义就是程序编写者采用一些手段防止程序被调试,从而达到防破解的目的。
———————————————————————————————————————————————————
在破解程序之前我们先来了解一下 线程环境块TEB进程环境块PEB

  • 线程环境块:在线程创建初始化时系统用一块内存来保存线程的一些重要信息,这块内存就是线程环境块TEB(FS : 0指向这块内存)
  • 进程环境块:保存进程的一些重要信息的内存块,这块内存就是进程环境块PEB

  • 我们下面分析一下有关线程环境块所包含的一些重要信息(只是开头一部分其余部分我们不关心)
TEB:

0x00      ExceptionList:      
0x04      StackBase:         
0x08      StackLimit:           
0x0c      SubSystemTib:         
0x10     FiberData:            
0x14     ArbitraryUserPointer:
0x18     Self:                                                       ;其指向TEB结构,其指向其自身0x00处
0x1c      EnvironmentPointer:   
0x20     ClientId:            
0x28     RpcHandle:            
0x2c     Tls Storage:         
0x30    PEB Address:                                        ;其保存进程信息块PEB的地址

  • 我们再来分析一下有关进程环境块所包含的一些重要信息(同样只是开头一部分)
PEB:
0x00     InheritedAddressSpace;
0x01     ReadImageFileExecOptions;
0x02     BeingDebugged;                                 ;其标志程序是否被调试

注意PEB的BeingDebugged字段的值如果为0则标志程序没有被调试,所以可以利用检测PEB的BeingDebugged字段来检测程序是否被调试!

—————————————————————————————————————————————————————
下面我们来分析此程序:

我们先运行一下程序,输入伪码发现没反应。
O8PT$`@LWF_{IV0A7S`CB[6.png

接着我们打开od载入程序。
在程序入口点其调用了一个SetUnhandledExceptionFilter()函数,这个函数时设置一个顶级异常处理回调函数(我们不管它)
E6LFFNNJB4WVAN[3O)MTO~V.png


我们运行程序输入伪码后程序停了下来。观察堆栈原来是调用了DebugBreak()此函数功能相当于int3断点
CFNAF3%`F_9U3({10VL6APK.png
接下来我们在反汇编窗口观察此函数调用处(在堆栈处右击反汇编跟随)。
我们看到DebugBreak()函数返回后会跳向执行结束进程函数ExitProcess( ),我们往上看如何能让其跳过此处代码
我们发现其在调用了IsDebuggerPresent( )函数后如果返回值为0则会跳过此处代码,不会结束进程。

B_LCH2NK]UK_`M[)%7}RM]U.png

我们跟进IsDebuggerPresent( )发现其代码就三行:
  • 其先读取fs : [0x30]处的值给eax(fs : [0]处存放的是TEB线程环境块,fs : [0x30]为PEB进程环境块的地址所以eax此时为PEB进程环境块的地址)
  • 接着其又把[eax + 0x2]的值给eax后返回(eax为PEB的地址,[ eax + 2]就是PEB结构中用来检测是否在被调试的字段BeingDebugged的值)
ZF[QS64MNW6~4G$L`V~Q6ZA.png
[Asm] 纯文本查看 复制代码
mov eax,dword ptr fs:[0x30]
movzx eax,byte ptr ds:[eax+0x2]retn

所以实际上IsDebuggerPresent()函数就是通过检测PEB的BeingDebugged字段来判断程序是否正在被调试。

我们在IsDebugPresent( )下断点,重新运行程序输入伪码后程序停在此处。
我们可以通过直接修改此函数返回值,或者通过改变进程环境块PEB的BeingDebugged字段的值来绕过IsDebuggerPresent()函数的检测,从而使其不调用ExitProcess函数结束进程。(实际上很多插件打补丁的原理就是第二种方法)


  • 下面我们采用第二种方法:

  • 通过fs:0指向TEB

      OV_)$U`F1YD]}MH9J{X`ULL.png
  • 而TEB偏移0x30处为PEB的地址

$U)~U~YDTBIIFO1AHAQ%3~5.png
  • 然后在数据窗口我们搜索此地址,此地址向后偏移2个字节就为PEB的BeingDebugged字段。我们发现此时其值为1,说明此时程序正在被调试直接修改其值为0即可

OCCMM6USJS2]@%4G)CGOY_J.png
因为我们修改了其值为0,此时IsDebuggerPresent函数就会认为程序没有被调试,返回值就为0

MLS5H6F{O2QCQ{ZD$O883@K.png ——————————————————————————————————————————————————————————————
我们F9执行发现其发生异常程序停了下来,观察发现原来是程序试图向地址0处写数据,从而发生了内存读写异常 HQU5M)Y]ENTQ9TF70$NCS3X.png



此时可以按shift + f7忽略此异常,而我们发现忽略此异常后程序会终止运行(这应该是程序设计者故意为之,不可能是程序的bug

这时我们想起来了在程序入口处其调用了SetUnhandledExceptionFilter( )函数,
_________________________________________________________________________________________________________________________________________________________
下面的分析涉及到windows的异常处理如果不了解windows的异常处理就很难理解)。
因为当程序产生一个异常时,首先会被系统内核捕捉然后系统内核会判断当前是否有调试器调试,有的话把异常交给调试器。如果没有调试器或者调试器处理不了此异常的话,异常会被分发给SEH链上的各个异常处理回调函数依次处理,这些回调函数的地址是通过一个链表存储。通过遍历这个链表从而调用各个异常处理回调函数。如果异常被某个回调函数正常处理了就继续从产生异常的代码处继续往下执行。如果一直遍历到链表的最后一个异常回调函数之前都没能够处理此异常的话,此异常就会交给最后一个默认的异常处理程序处理
  • 而最后一个异常处理回调函数在调用前会先调用UnhandledExceptionFilter( )过滤函数,
  • 此函数又会调用ZwQueryInformationProcess( )函数先判断是否有调试器存在,有的话会直接返回进行异常的二次分发(一般就是会结束进程)。
  • 如果ZwQueryInformationProcess()函数没有检测到调试器的存在的话其将会调用默认异常处理回调函数。而一般默认异常处理回调函数是默认的终止程序的函数

但是windows提供一个函数来对UnhandledExceptionFilter( )过滤函数进行干预从而修改其返回值让其正常返回,而不执行默认的异常回调函数终止程序。此函数就是SetUnhandledExceptionFilter( ),此函数具有唯一的参数就是设置用来干预UnhandledExceptionFilter( )过滤函数的回调函数的地址,UnhandledExceptionFilter( )会在内部调用这个函数。(一般称这个函数为顶级异常处理回调函数,我认为这么称是不准确的。因为真正的顶级异常处理函数是默认的异常回调函数,此函数应该称为顶级过滤干预函数

  • 所以我们刚刚之所以按了shift + F7后程序退出了就是因为UnhandledExceptionFilter( )调用了ZwQueryInformationProcess( )检测到了程序正在被调试,所以我们在程序入口通过SetUnhandledExceptionFilter( )设置的顶级过滤干预函数没有被执行,进行异常的二次分发,最后结束程序。
  • 而我们在一开始直接运行程序因为没有检测到调试器,所以异常会被顶级异常处理回调函数处理,程序不会崩溃结束。


所以我们要想让其调用顶级过滤干预函数UnhandledExceptionFilter( )的返回值进行干预,从而继续让程序往下执行的话我们应该改变ZwQueryInformationProcess( )函数的Buffer参数,因为函数返回后其为0值表示没有检测到调试器,这样其就可以调用顶级过滤干预函数

—————————————————————————————————————————————————————
由程序开头处的SetUnhandledExceptionFilter( )我们知道其设置的顶级异常处理回调函数地址为00401108



我们在00401108地址处下断点,然后我们再在ZwQueryInformationProcess( )处下断点。运行程序重新运行程序,然后按前面的方法过掉IsDebuggerPresent函数的检测后,程序会停在发生异常处。然后我们shift + f7忽略异常后,程序会停在ZwQueryInformationProcess( )函数处。
X}LPY@FN4T8}E0C{@SOA8PK.png
在数据窗口搜索Buffer参数,当函数返回后其值为0表示无调试器,返回值为FFFFFFFF则表示有调试器。我们ctry + F9执行到返回后再改变其值为0。
TJF~)N`@((9JY}U}NSM6$`8.png
此时认为其没有检测到调试器,所以会调用我们SetUnhandledExceptionFilter( )设置的那个顶级过滤干预函数
其地址为00401108,运行程序后,程序果然停在了此地址处。
7PLC12O4LL)ZZNUO_NG(@6V.png
接着往下分析发现其会弹出一个在执行一个跳转后弹出一个消息框
是不是注册正确的消息框呢?我们更改跳转后,继续执行

}A8_LAPD6EX}{QN~{4I@SXS.png
弹出了注册成功消息框!
所以上方跳转为关键跳转,和关键算法
注册算法我就不分析了,主要是了解他的反调试和异常处理部分!
D$]R8SGUXFH${T3YKP~3J76.png



最后补充一下有关StrongOD插件的使用。
  • 选择Normal可以实现绕过IsDebuggerProcess函数的检测

)`O0}1`]U[KEY6_H%{@{`2D.png

如果发现内存访问异常等一些异常无法使程序停止运行,有可能是你的OD在调试设置中忽略了该异常
在破解本程序时为了让其在内存写入异常时断下,应该把忽略非法访问内存去除。
这样在向0地址写入数据时就会断下,需要按shift+F7才能忽略


T_[J4DV1_I83}}U@$MEZP.png
如果设置了之后异常还不能断下,可能是你的某个插件设置里忽略某些异常。
  • 如StrongOD的此选项就可以忽略某些异常

M0{RMFIAXW2R@J{MBJJDEDU.png
程序链接:
[Asm] 纯文本查看 复制代码
链接:[url=https://pan.baidu.com/s/1gUEeudQ3H2hEbVhLTIWNGw]https://pan.baidu.com/s/1gUEeudQ3H2hEbVhLTIWNGw[/url] 
提取码:xurl 



最近在学win32汇编,所以我用MASM32写了一个保护方法类似的程序,有兴趣的可以玩玩
链接:https://www.52pojie.cn/thread-1130363-1-1.html

免费评分

参与人数 7威望 +2 吾爱币 +12 热心值 +7 收起 理由
little3388 + 1 + 1 用心讨论,共获提升!
woshihaoren + 1 + 1 谢谢@Thanks!
Poner + 2 + 8 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
古月不傲 + 1 + 1 我很赞同!
565266718 + 1 + 1 谢谢@Thanks!
夕雪 + 1 我很赞同!
davidhee + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| 镇北看雪 发表于 2020-3-13 12:06
夕雪 发表于 2020-3-13 10:43
很厉害 我也遇到了利用异常来反调试的   找了很多异常资料来分析 都还是看不懂  看了你这篇之后 豁然开朗了 ...

我也是看了好多资料才搞懂
夕雪 发表于 2020-3-13 10:43
很厉害 我也遇到了利用异常来反调试的   找了很多异常资料来分析 都还是看不懂  看了你这篇之后 豁然开朗了
Hou 发表于 2020-3-10 19:04
后面没怎么看明白,是利用异常处理捕获调试器吗,想看看样本
rsice 发表于 2020-3-10 19:40
能否把程序发上来让我们呢依葫芦画瓢操练一遍
aikoz88 发表于 2020-3-11 10:20
多点这类帖子就好了
学士天下 发表于 2020-3-11 11:24
谢谢分享,受益匪浅!!!
fjh322 发表于 2020-3-13 22:00

太专业了,看不懂。
xpz84 发表于 2020-3-13 23:39
学习了,正在找这反面的资料。
Lumine 发表于 2022-10-14 12:59
先收藏了,虽然还没有学到但是以后肯定会用到的
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-26 17:13

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表