00:00
好,然后呢,今天呢,咱们继续来讲这个反调试啊,这是咱们反调式课程的第四天啊,然后今天呢,咱们来讲一下这个如何利用异常来进行反调试啊呃,那我们先写一个最简单的一个异常的方式啊,那这种方式呢,是基于我们的异常的,哎,这个东西呢,具体呢,是怎么用的呢?我们一会再说,我们先给它写一下。首先啊,我们给他加一个异常处理,然后呢,给它加一个处理啊,刚才这是保护端啊,现在呢加一个处理。好,那么现在呢,我们直接啊MP啊来给他看一下他的这个说明啊。我们在Windows下啊,比较常用的异常呢,包含两种,一种呢是异常啊,一种呢是什么?一种是异常啊,那我们种属呃,我们这种异呢,大家以看一首呢内呢,它是一个保护啊,它是一个你需要保护的代码,也就是说呢,你把你这个可能会触发异常的啊,可能会触发异常。
01:24
触发。异常的代码放到啊这里啊,那剩下的这是什么东西呢?这个是你的这个位置上是你处理的方法啊,底下是什么?底下是异常处理代码,那么这个处理的方法是指的什么东西呢?啊,我们来看一下啊,它这个说明里呢啊。他这个说明不是啊,这不是这个是我们另一个啊,那我们给他在这上边摁一下F1啊,看看它是不是能转过去啊。啊,这回就对了啊,你可以看到这有三个方向啊,三个方向啊,你可以看到这有这个对它的一个说明,首先呢,这个东西呢是什么?是这个我们微软啊Microsoft对这个C和下加语言的一种扩展,因为什么?因为下家里也有一种这个呃异常处理,但是下家里那种异常处理是什么啊,是你要自己抛,抛完之后呢再自己处理啊,你不抛呢,就没有办法,但是eh是什么呢?
02:23
Eh呢,是在踹后边的这个保护节里边啊,然后呢,它就是干嘛呢,自动啊,自动进行这个捕捉,捕捉之后呢,把什么把异常引到我们的这个啊处理段里啊,但是我们处理段的处理方法呢,是需要我们自己来进行一个指定的啊,你可以看到啊,它后边呢,是异常处理程序啊,你要指定你要采取的操作啊,具体呢,有这么几种啊,首先呢,我们在这个位置上可以看到有这么三个红,这三个红呢,实际上就代表着什么呀,代表着我们这个异常处理的这个三种形式啊,第一种呢,就是异常已经没了啊,你从这个触发异常的位置上啊,继续执行啊,比如说我现在呢,在踹里边有异常啊,我这啊进到我这边来啊,如果说我这个括号里放的是这个红,那么在这块之后我们再回去啊,继续执行就行了啊,那第二种什么东西啊,第二种呢,它是一个无法识别的异常,继续向上搜索啊,这个我们的这个处理程序啊。
03:14
因为我们的S是这个,就是呢,这个当S对战里离你最近的那个处理程序,如果离你最近的那个异常处理程序没办法处理呢,它其实是可以向上啊,继续干嘛,继续去寻找新的啊,直到能处理,如果说找到最后也没有能处理的方法,那么它就崩掉啊,就这么一个形式啊,那第三种呢,就是异常可以识别啊,我们把它呢,通过这个处理块啊,把这个控制权处理到异常处理程序,然后呢,在处理块之后进行执行,也就是什么呢?比如说我在这里啊触发了一个异常,然后呢,我根据我的这个处理方法进入到我异常处理代码,这然后呢,在这个位置上啊,我们处理完事之后呢,在下一行啊开始继续执行啊,这是几种方式啊,不同的方式,那我们现在呢,我们要处理的这这种方式呢,就是什么呢?就是利用它这种方式啊,进行一个处理啊,因为大家也知道啊,调试器这种东西,它是可以干嘛呢,它是可以接收到异常的啊,那我们利用它这个特性啊,我们选择第三种。
04:15
异常已经识别了啊,然后呢,直接在后面去找,哎哎,我们这么着啊,然后呢,就是这种,为什么选这种呢?因为这种呢,它不会回到TRY这里啊,继续去执行TRY这个代码,那我们触发异常的方式呢,我们可以啊选一些这个比较常见的都可以啊,但是这呢,我选一个INT3。啊,为什么选择in特三呢?因为INT3这个东西调试器是要自己处理掉的啊,因为你抛出一个INT3 int3的一个异常,那INT3这个异常呢,相当于什么东西啊,首首先啊,Int这种东西啊,INT3实际上就是中断啊中断,但是INT3这种中断的比较特殊啊,它相当于什么?相当于一个在硬版表写了一个0SCC,那这个东西是什么呢?实际上就是调试器啊实现软件断点的方法啊,那你调试器一共三种断点嘛,一种就是我们这个软件断点啊,那一种呢是什么一种呢是内存断点,还有一种什么一种呢,是这个硬件断点啊,它大致上就分这么三种,其他的都是用这种东西来组合的,比如说什么条件断点啊什么的,那你软件断点呢,实际上就是什么,就是这个IN3啊,就是IN3啊,那内存断点呢,是什么是内存权限啊,那硬内存访问权限啊,然后呢,这个硬件断点呢,是这个DR音器啊,硬件断点进器。
05:36
啊,那我们现在用的呢,就是INT3啊,进行一个触发啊,所以说呢,我们在这写了一个INT3呢,它如果说在非调试器的情况下啊,就是说我们没有一个调试器挂在上面,那么这个时候他会干什么,它会进入到我们这个位置哈,进行一个代码的一个处理,那么我们在这儿呢,可以干一件事就是什么?就是我们直接啊给他来一个这个return啊,Return一个false啊,为什么在这可以return一个false啊,因为你只要是进到这来,那说明什么?
06:03
只要是啊,代码执行到尺处就说明啊没有调试器对异常啊进行接收处理。啊,因为如果你调试器把这个INT3 int3这个异常给接收掉的情况下,它其实是跑不到这边的啊,跑到这边的,所以说呢,你如果走到这边,他肯定是什么,它肯定是没有调试器这种状态啊,所以说false就行了,那如果说你走到后边来了呢,走到后边来呢,说明什么呀,说明我们调试器啊,把这个异常接收掉了啊,它就干嘛呢,没有出现异常,没有异常的情况下,串里边的代码呢,就不会执行到我们的处理框里边,那么这种情况下,它就会直接执行到后面,那执行到后面说明什么呢?我们直接return一个处啊,肯定不会打空啊,就这么一回事,那么现在呢,我们可以把这个NT这个debug啊放到我们的这个这里啊,来进行一个执行啊,比如说我直接啊进行一个if啊判断一下。
07:00
好,那如果说啊,我们啊这个给他,比如说我现在在里边写点东西啊。嗯,我想想啊,我先。我我给他取个反吧,我然后呢,进来之后,那说明它是一个正常的执行啊,我们使用一个stout啊,然后就说啊。这是啊,一次普普通通的。执行过程啊,这是一次普通的执行过程啊。好,那如果进到这儿之后呢,我们可以让他停啊停这个1000毫秒啊,这是正常的执行,然后呢,我们可以直接调用一下这个continue,调用continue呢,它就跳出本次循环,那不会一直跳出循环啊,跳出本次循环了啊,然后呢,如果说啊,那没有啊没有这种情况下,它就会干嘛呢?往底下走,往底下走呢,我们就可以判断啊,它大致上呢,是干嘛呢,是被调试了啊,大致上是这么一回事啊,那现在呢,比如说我现在呢,使用这个啊来进行一下运行。
08:22
诶,你看它会直接啊在这断下来,为什么呀,因为我们的这个VS它也是一种调试器啊,它没有接受这个东西,没有处理,那这个时候呢,我可以干嘛呢?我可以让它啊在这种普通的形式下啊,来直接进行一个运行,诶你看这是一次普普通通的执行过程啊,就这样就行了,然后没点关注的点点关注啊,有需要这个领取回放的咨询课程的等等的都可以直接联系咱们老板啊,然后呢,我们这个在双11期间啊,如果报名的话是有这个活动的啊,可以联系老板进行咨询啊。好,然后呢,我们现在呢,就来给他啊,把调试器附加上,比如说我用这个沙32.debug啊,我进行一个附加啊,然后直接附加上边,附加上面之后呢,它就暂停了啊,诶没有暂停啊,我看看啊。
09:06
等一下啊,暂停了好了,暂停之后呢,我们把它放开之后啊,放开。你看被调试了。然后它又会异常暂停,然后又会异常暂停,又会异常暂停啊之所以会这样呢,是因为我们在每一次循环的时候啊,它都会进一次里边啊,然后进到里边之后都会触发一次IN3的异异常异常啊然后呢,它的左下角有一个第一次异常于什么什么位置上,你可以看到啊这啊它写的是什么8000003啊,也就是异常的是一个什么呀,一个print print啊啊没点关注,点点关注啊,然后呢,每周六周日啊都有直播啊,然后呢,我们现在呢,再来说一个问题,如果大家在做这个实验的时候发现啊,他一直是普普通通的这个执行过程没有发现被调试,它是因为什么?这个是一个选项的问题,你在选项这啊,如果说他有一个事件有返回编啊,不是有异常啊,异常这里呢,如果你的异常处理者是什么,是调试器就没问题,如果你把它发挥到被调试对象了,我们再试一试啊,我们让他继续跑。
10:09
啊,这个线程是一直在的啊,我们应该重新给它附加一下啊,我们直接给他重重重新运行啊。诶。不对啊,理论上是应该是没有问题的,我看一下啊。我给它重启一下啊。好像我这个记错了啊,但不重要,反正它也被检测到了,好,然后呢,我们继续啊,来实现它的下一种方法啊,我们这种方法呢,是基于INT3的啊,它这个比较草率啊,我们还可以给它进一步加深它的利用方式啊,我们首先啊来一个这个第二个。
11:12
第四个应该说啊,这是我跟上节课一起写的,昨天的代码写在上边啊好,那现在呢,我们再来写一种啊,这种呢就是什么啊,就是我们可以利用close handle啊来进行一件事啊close handle这种函数啊,大家都知道,它是关注关闭一个句柄啊,关闭一个句。啊,但是这个函数呢,它有一个特殊的这个点,就是什么呢?就是如果说你在正常的情况下啊,关闭一个这个关闭一个无效句柄啊,是没有任何问题的啊,是没有任何问题的啊因为什么?因为它直接就放过去了,它只会造成一个这个返回一个false,但是如果说啊,如果说你是在调试的环境下啊,你调了这个close handle啊,然后呢,这个写了一个什么呢?释放了一个无效的这个句柄,它就会触发异常,这是有区别的啊。
12:04
非调试。状态下返回bos啊,返回bos调试状态下触发异常啊,所以说呢,这个东西呢,也可以用我们的这个TRY和还有这个TRY和这个处理函数啊来进行处理,比如说我们先给它反写一个TRY啊,写完TRY之后呢,我们在TRY里边呢,给它实现一个close handle啊,比如说我们现在呢,来写一个这个close handle。然后呢,我们随便给他来一下强转。强转成这个憨豆类型啊,我们随便想转一个值啊,你愿意多少多少。12341234啊没错啊好,那我现在就关这个纸啊,然后呢,如果说啊,嗯,等一下他出了什么。
13:07
啊,我忘写括号了啊,要把这个强转内容写在括号里啊,没点关注点点关注啊,然后呢,我们来看一下啊,我们现在呢,已经把它关关闭了啊,如果说它是在非调试状态下啊,它是不会出现什么问题的啊,我现在呢来给他写一下啊,写一下异常处理,异常处理呢,我们还是使用的刚才的这个处理方式啊,让他啊,让他这个执行之后啊在后边执行,那如果说到这个位置上了啊,我们就直接干什么,我们直接一个处。因为什么?因为只有在调试的状态下,它才会触发异常,才会进到我们的异常处理块里头,所以说呢,我们返回一个数,否则呢,我们什么一个false啊就OK了,那么这种情况下呢,我们来给它重新生成一下。啊,右键打开所在路径啊,然后呢,我们点开点开它啊,首先呢,你看啊,现在呢,诶不对,这个这个不对啊,这个我忘记给它替换什么啊,替换那个线上会调理的函数了啊好,现在就对了啊,然后我们重新运行。
14:15
好,现在运行运行之后呢,我现在使用我的这个调试器啊,打开我的调试器,然后呢,把调试器啊对它呢进行一下附加。附加之后呢,现在呢,我们等一下啊等一下。嗯。等一下啊,我再观察一下啊四。哎。这什么问题,我去。我看一下啊。
15:41
我把它改一下啊,我把它。我把它改到这儿啊,我看它是不是有调用的啊。
16:39
哎,奇怪了。啊,应该是这个数不发不触发异常啊,那我换一个啊,哎,这回我再运行一下啊。继续,哎,这就异常了吗?啊,刚才是那个数不行啊,我想起来那个八个F它不异常。
17:01
好,那我们重新给它运行一下啊。好,现在你可以看到它是普通的一个执行啊,然后呢,我们来给它附加一下。走。诶。他有异常了呀,他为什么没打印出来。等一下啊,他异常啊,异常被接收了啊,所以说呢,他应该是这样的,还是选项的问题啊,他这个两头堵。
18:07
这不科学。你这肯定是会触发异常的,触发完异常之后。对,他直接就崩了,崩完之后被调试啊,看一下啊,我们直接用VS,它肯定是已经是被调试了,但是为什么我们X6D bug没有显示出来啊,这是一个奇怪的点啊,我重新试一下。
19:35
诶,奇怪了。按照VS调试的肯定是没有问题的,这东西异常了,走走走走走。它是正常的,然后使用调试器,它有问题,我先给它编辑成64位版本看一下啊。
20:09
啊,这有一个需要注释掉。哎,这下就可以了啊,看到没,这下就可以了,应该是刚才那个调试器被我设置了什么,然后把这个异常忽略掉了。啊,这回是检测到了啊,用64位版本它就检测到了。好,然后我们再来写一个啊,这个是使用一个close handle的方式啊,那实际上还有一种方式啊,也是类似的方法,但是呢,就没有close handle这么方便,就是我们可以使用那个叫做nt close啊,Nt close使用方法呢,和它类似,但是呢,因为它是NTDLDL导出的啊,然后呢,我们现在呢,要使用它的情况下,不能直接用。
21:21
啊,就是这个close啊,可以看到是没有的啊,也是未文档未文档化的,那我们要用它呢,是要使用这种函数人的形式啊,首先我们type。API行。Fn nt close啊这这样这样用的啊,然后它的参数呢,是一个handle。接着呢,我们现在呢,就可以来这个获取它一下,首先我们要加载这个NTDRDR到我们的这个模块模块里啊。
22:03
我们使用library啊,把我们的这个NDDL加载进来。加载进来之后呢,我们判断一下啊。判断一下他是不是不为闹。如果为闹的情况下,Return false。啊不对,应该是等于等于到啊,然后false好,然后获取完事之后呢,我们现在来获取这个函数啊,就是使用这个pd close啊这个函数针。等于啊对它呢进行一个强转啊,因为我们get p address它的返回啊不兼容啊,所以说呢,要进行强转。好强转完事之后呢,我们现在呢,就可以来给他啊抽烟啊传入第一个啊,就是模块的一个句柄,第二个呢,就是我们的这个名字。
23:14
好判断一下啊,他是不是呃是不是为闹啊,如果为闹就for,如果不闹的情况下呢,继续往下走啊来,我们现在呢,就可以调用它了啊,首先啊,还是一个TRYTRY里边的内容其实和close这个handle是一样的啊,我们直接调用这个png close,然后呢,在close里啊,给它关闭一个啊,关闭一个比如说我们上面这种句柄。关闭一个句柄啊,关闭完事之后啊,如果说啊,我们进入到了他的异常处理里。就说明被调试了,否则呢,就是没有被调试好,现在呢,我们可以来啊,把它用一下。
24:11
我们直接运行。好,它异常了,异常之后走啊被调试了走走走,因为什么,因为在VS里啊,那如果说是我们正常运行呢。啊,在这个64位版啊,64位版啊,我们直接啊运行啊,你可以看它就是一个呃,打印一个普普通通的执行过程啊,那这时候呢,如果我们用X64D bug啊对其进行附加。走你看啊,就显示什么显示被调试了啊,这说明什么,这说明啊,我们现在啊,已经啊反调试啊,已经察觉到它了啊,没点关注的点点关注啊,每周六周日啊,晚上都有这个直播啊,有需要领取课程啊之类的啊,有咨询的可以联系咱们老板进行咨询啊好,那这是呢,咱们今天的这个第二种啊,那然后还有一种方式啊,还有一种方式,那这两个呢,其实都是直接去关闭它啊,那还有一种方式呢,就不跟他们不太一样了啊,但是也是基于异常的一种方式。
25:13
首先呢,我们来搞一个这个。搞一个内核对象,这个内容对象呢,你可以任选啊。啊。呃,安全属性填个到,然后这个呢,我们填一个继承force。然后名字啊,名字我们随便填啊,然后呢,我们判断一下它是不是有效。
26:06
如果有效的情况下啊,我们对其啊进行一个设置啊,Set set。Handle啊。好,第一个参数呢,我们设置一下啊,就是它啊,你要设置的内核对象是谁啊,也就是个handle是谁,然后第二个呢,就是啊你要设置的属性啊,那它的属性呢,其实有很多种啊,我们现在直接F1啊,到这个函数的一个说明里来进行看一下啊,微点关注的点点关注啊,咱们每周六周日都有直播,我们可以看到啊,它这个里边有一个这个mask,还有一个flex啊,这个里边呢都可以有什么都可以有两个宏啊,那第一个宏呢,是如果设置这个标志啊,那么创建的就可以继承这个对象,句柄这个呢是什么?这个如果设置第二个标志,那么啊调用这个close handle函数就不会关闭对个对象对句柄,那我们选择第二个啊,然后你可以看到第二个和第三个,它的这个值要求是相同的常量啊,也就是把一个红填两遍就行了。
27:14
好填完之后呢,我们现在呢,就可以来继续啊进行这个操作,首先我们来一个TRY。菜里边呢,我们在这儿啊,调用一下这个close handle啊来进行关闭它的句柄,但是呢,因为我们刚才的设置,所以说呢,它并不会成功。下一步,SCEPT。在这边啊,Return false好,如果进入到这啊,就说明什么被调试了啊,因为什么,因为我们这个啊并没有成功啊,我们现在呢,来直接调用它啊,我们运行。
28:06
你可以看到啊,直接就察觉到被调试了,然后呢,我们现在呢,来正常运行一下试试。你可以看到啊,就是一次普通的执行过程,那如果说我们用调试器附加呢。可以看到啊,也是被调试的啊,然后这个呢,就是我们的这个今天的这个几种反调试方式啊,但是呢,我们不管是哪一种,它其实本质上呢,都是基于异常的,而且呢,这几种方式呢,其实基本上也是基种基于同一种模式下的,就是触发一个异常啊,然后根据他能不能接收到啊,来进行这个回馈啊,你比如说如果是我这个特三这边的,那就是如果说啊,他到这儿了,那就说明什么啊,就说我接到异常了,那就没有问题,那这边的是什么呢?这边的如果说我没接到异常啊,那么这种情况下啊,才是这个啊被调呃,没接到异常呃,常才是正常的,如果接到异常就是被调试的啊,就是这样的,因为close handle和这个n close啊,它们俩本质上而言呢,是只有在调试状态下才会触发异常啊,关闭时效句柄的情况下,那你像这个呢,其实本质上调用的还是close handle,但是只是因为呢,我们在前面这呢,设置了一下这个handle的一个信息啊,所以说呢,导致呢它才会出现这种状况。
29:31
好,有没有什么问题,如果没有什么问题呢,今天的技术部分呢就OK了。
我来说两句