00:00
啊,那这一节课呢,咱们是反调式专题的第三节啊,我们继续来写这个反调试啊,我们首先创业的一个项目啊。嗯。包括一些我们今天可能会用到的文件啊,呃,我们Windows API相关的啊,Windows啊,这个输入输出啊,输出据流啊,然后还有这个呃,Victor啊,然后一个数据结构啊,然后这个是操作这个进程线程的一个快照相关我们需要用到的,接着呢,我们给它写一个主函数啊,In the。
01:25
让他在结束之前暂停一下,然后我们还需要这个还是需要来多线程的检测啊,所以说我们在上边呢,还是要给它启动一个线程啊,它会返回一个线成句柄a three。A great thread。
02:04
F12进去啊,找一下它函数原型啊,这好像第三个参数刚才也写多了。下一个是参数啊,然后其他的呢,也都写闹啊,现场ID我们也不需要啊,都给它闹掉就完事了啊,这好像写多了一个啊。诶啊,写错地方了。好,接着我们等待他一下,For先购等待我们现场的返回啊,那一般情况下它应该是回不来了啊,我们直接给他一个永久等待啊负一好,那么接下来呢,我们就开始实现它的这个反调式啊,那今天的反调式呢,我们基本上呢,都是依赖于环境的啊,那首先呢,我们来写一个依赖于什么,依赖于进程的,因为你这种类似于调试器的东西,你起来之后啊,它肯定是有一个进程在的啊,那么这个时候呢,我们就可以通过什么,通过它的这个进程的一个相关信息啊叭,如这个啊,它的名字啊,就可以判断它了啊,当然了,你可以说啊,我改一个加尔达的竞争名啊,这种也是可以的啊,但是呢,就是如果他在没有改的情况下呢,我们是可以通过他的竞争名啊,对他进行一个。
03:47
获取。首先呢,我们要获取它的进程呢,我们有多种方式啊,那现在我们使用的方式呢,主要是使用它的进程快照。
04:15
我们要这个获取的是进程相关的啊,所以是这个TH32CS NP process啊,那后边的是进程ID啊,没有这个搜索进程的时候不需要填,我们填个零或者now啊,接下来呢,我们用一个if啊,来判断一下它返回的这个句柄是否这个是有问题的。啊,如果是有问题的呢,我们就直接给他return一个false。如果不是的情况下呢,我们就继续找啊,我们去找他进程里的这个第一个进程信息,如果这块不太懂的呢,可以去领取咱们window系统编程的这个回放啊,里边是有的。
05:16
两个参数,第一个参数是快照句柄,第二个参数是你一个结构,这个结构呢,就是一个叫做这个price n32的这么一个结构,给它触化一下他的size。出发完事之后啊,把它地址啊传入其中,如果如果成功的情况下,我们直接通过外循环判断它返回的是不是为针啊,为true啊,如果为true的情况下呢,我们就进入到循环内部。
06:01
如果进入到循环内部了,我们就可以进行一个对比啊,首先啊对比一下啊,如果说它是一个这个ask编码的,那么这种情况下我们就用str啊CP来对比,如果它是一个的编码的,你就调用WCSP来对比,它还有一个版本是T叉版本的,就是自适应啊,那个有一个这个T叉版本的对比函数啊,那个是一个红啊,实际上就是根据环境来判断使用这个还是这个,那现在呢,我们是一个呃,是一个这个多字符的形式啊,那我们就用它SRCP来进行对比啊,首先对比我们啊PE32里边有一个成员叫做这个我们这个东西,我们进程啊这个32UG点进行一个对比,如果说啊对比完事之后啊,这个函数啊,它如果说是等于零的情况下,那么才是相等的啊,所以说判断它是不是等于零,如果等于零了,我们调用一个。
07:02
弹窗mabox啊,或者mabo a啊,然后来进行一个弹窗。检测到调试器。啊,现在呢,我们就已经可以点检测到它的调试器啊,如果到这儿了,就是检测到它调试器了,然后弹个窗,弹窗之后呢,我们在这儿啊,给它一个处啊返回,如果说没有找到啊,不是本个进程,我们可以让他继续向下找。如果都没有找到的情况下,到最后呢,你可以把它的这个句柄啊给它关掉。
08:08
嗯,HS这个呢,如果说找到找到了,你也可以给他关一下啊,这因为他要返回了嘛,然后呢,这如果没找到的情况下,你就return一个false。这个失败了,就不用那什么了啊,好大概就这样,然后呢,我们给它来在这里边进行一个调用啊,直接写一个外循环啊,直接判断它。嗯。其实我直接来一个死循环就可以了,处一下,然后呢,我们就调用它一下,然后接着呢,就让他暂停一下再运行啊,暂停1000毫秒啊,然后现在呢,我们就可以来给它这个运行起来。啊,检测到调试器啊,点击确定,然后等一秒,它还会再检测一次啊,因为我们这个东西开着呢,我们现在把它关掉,然后我们点确定啊,然后我们等一下。
09:09
也可以看到啊,它就没有弹出了,对不对啊,所以说呢,这个就是可以检测啊,没有问题,那我们还有呢,就是其他方式啊,其他方式比如说我们还可以检测它的窗口啊,但是窗口这个东西呢,我推荐两种,我我有两种方式啊,大家推荐第二种,那首先我们来检测一下啊,这个是。这个是安bug啊,那我再给他改个名。这儿呢,我们其实是可以直接啊用一个这个if啊来判断一下什么find window find的window这个API呢,它主要就是来查找窗口的啊,然后它一共有两个参数,这两个参数呢,第一个呢是你窗口类,第二个窗口名啊,那你如果不知道的情况下呢,你可以通过我们的这个加来找,就是我们studio上面有个工具,工具里有一个加加啊点开。
10:04
点开SP加加之后呢,它有这么一个窗口啊,这有一个望远镜,你点开,点开之后把这个东西拖啊,拖到它的顶层窗口上,然后你就可以看到啊,它现在是什么东西啊,标题是一个菜单debug啊,它的类是一个这个呃,QT5啊,然后q window icon啊这么一个东西啊,然后你如果在底下它还有其他的东西啊,你比如说啊他这个。它底下窗口啊,都是不同的这个类名啊。啊,标题变了啊,你可以看到没标题啊,有的有标题,有的没有标题啊,你比如这个这个呢,它的标题就是一个这个状态栏看到了吧啊但是这种呢,它都是它这类都是属于QT的,所以说我们谈类名的话,传类名的情况下呢,很容易就重复了,所以呢,我们只能还是什么呢,以这个啊窗口名啊作为什么作为一个这个标题啊,作为一个传传入,那现在呢,我们就给它传这个第二个参数啊,一个窗口名,那么第一个参数呢,你就可以给他传一个now啊告诉我们不去寻找它,然后寻找第二个啊然后呢,它这个返回的呢,实际上是返回的一个这个句柄啊,那我们可以来给他判断一下,是不是等于这个不等于闹好,然后呢,我们就如果是不等于闹的情况下,我们就给他来这个检测到调试器啊。
11:19
然后一个处,那现在呢,我们就可以来这个位置给它进行一个调用啊,那现在呢,我们来直接运行。啊,你可以看到现在检测到了,确定,然后等一会儿又检测到了,那我们把这个关掉。关掉之后再点一下。啊,它就没了啊,这样是确实是可以检测到的,但是它是有问题的啊,为什么说它是有问题的呢?因为我们如果说啊,打开这个我们的这个调试器啊,你看调试器我们先打开了,打开之后啊,我们这个位置现在的标题是叉32D bug这么个问题,但是如果说啊,你把这个任意一个进程拖进去。可以看到啊,它的标题就变了啊,我们把它拖上来啊,你看一下它的标题现在是这么长一串。
12:05
它主要内容是你要调你调试的这个啊,它的这个进程名啊,然后它的进程ID啊,你当前所属的模块啊,当前所属的线程啊,最后是一个叉bug。啊,那所以说呢,我们使用这种方式呢,那就不太科学了啊,因为你找到之后你会发现啊,我这儿有可能找不到,因为我们对比的是精确字符,对不对啊,所以说呢,它有可能会找不到,那怎么办呢?那我们就可以来使用另一种方式来寻找它的窗口啊,那首先呢,我们还是要什么,还是要便利他所有的这个顶层窗口啊。我们啊传入一个微啊,接受他所有便利到的窗口,或者说窗口句柄啊,不能说窗口,要说窗口句柄。
13:11
那么首先呢,我们对这个victor呢,进行一个清空啊,一个clear清空之后呢,我们现在呢,先找到一个第一个句柄。Get top温啊,然后传个零,找到第一个顶层句柄,找到之后啊,我们现在呢,进行外表循环啊,判断到底有没有找到它,如果找到它的情况下,我们现在来判断它是不是顶层窗口啊,怎么判断呢?判断他有没有父亲啊,顶层是没有父亲的啊,所以说呢,我们如果说找到父亲说明什么,说明就不是口。判断啊,如果等于等于零啊,那么这种情况下,它就是没有父亲,没有父亲呢说明是顶层,如果是顶层呢,现在呢,我们调用我们的victoror啊,然后直接一个push back啊给它存到最后把我们的这个当前的这个窗口句柄啊给它传进去,传进去之后呢,接下来我们就要接下来找下一个窗口啊,那接着下一个窗口呢,还是怎么样通过一个API来进行获取,我们直接啊get window啊get window呢,首先呢,我们把这个我们的句柄啊传进去,当前的句柄传进去,然后找怎么找它的下一个句柄呢?这里头有一个红啊就其W啊,然后HWND啊N也就是下一个啊,我是不是写写错了WND啊好,现在啊我们就找到了下一个啊,如果说啊全都编辑完之后,我们return什么啊,Return一个啊,Victor。
14:44
啊,Size啊,Size如果说是大于零的情况下啊,那说明它就是啊,这是一个表达式,好,那么接下来我们有了这个东西之后呢,我们现在呢,来写下一种这个调反调式的方法啊,就是一个布尔行啊,然后antit debug啊第二种。
15:03
012啊,实际上是第今天第三种,然后我现在呢,首先呢,定义一个。对它呢,进行一个实例化啊,把它里边的东西呢,设置成句柄类型,好,然后呢,我们开始便利啊。传入我们victor好,传入微之后呢,接下来呢,我们要这个存储啊,存储它的一个什么呢?存储它的一个内容啊,也就是它一个标题名啊,那我们可以来直接啊申请什么,申请一个数组啊。这应该叫进程名啊,或者说进程窗口名。
16:01
我们给他初始化一下吧,省着一会用麦set了,我们直接初始化啊,初始化之后呢,我们现在呢,还要还要来这个对它进行一个便利,我们这个呢,使用一个新特性啊,就是类似于我们Python的那种for均衡方式啊。也就是那种for each for each。一个一个进行取出啊,然后呢,我们现在呢,呃,获取一下我们的窗口标题啊,这块呢,我们其实可以获取到很多很多的东西啊,比如它的进程名啊,它的这个进程ID啊,模块名啊,什么乱七八糟东西,其实我们都可以通过一定的方法来进行获取,但是我们今天的不搞那么复杂,我们直接来获取一下他的这个窗口名。没点关注的点点关注啊,然后呢,每周六周日晚上八点都有直播啊。
17:01
好,然后呢,我们现在呢,来给它这个进行一下获取啊,这块呢,我们只要调用一个API get window test啊就可以了。好,它的参数呢,首先第一啊,第一个啊,我们要传入的呢,就是我们的这个句柄。第二个呢,就是这个我们要存储到哪啊,把这个获取到的名字啊,那我们刚才声明了一个变量啊,就填到这儿,接下来呢,是它的一个大小啊,那我们就是一个mi。这样就行了。好,然后接下来呢,我们就来判断一下啊判断,因为我们现在呢,它的标题啊,有可能是这么一长串啊,所以我们要在其中找到我们想要找的东西,我们这里头呢,有几种思路啊,比如说我们可以获取到自己的这个竞ID,然后进行进争ID的判断啊,可以判断一下它是不是当天有没有这个这个模块啊,NT为有线主线程,这个或者没自己的进程是可以啊,但是呢,我们现在呢,就来找他最简单的东西,就是这个叉2BUG啊。
18:11
那参照2B如何去找呢?我们这里呢,调用一个STSTR的一个指令啊,一个库函数,它呢主要是在串里判断有没有存在另一个串,我们首先呢,第一个参数呢,就是啊,你这个东西刚才获取到在哪了啊,这个window name window name呢,我们刚才获取到这了啊,那接下来呢,我们的第二个参数就是什么?第二个参数就是我们刚才要找的这个东西啊,这里边任何一个东西其实找到都可以不用啊,我们现在来传一个叉三二的bug,然后呢,它的返回值呢,我们判断一下,如果说不等于now啊,如果不等于now的情况下呢,就是找到了,然后呢,我们就写一个啊检测到调试器,然后直接return一个处啊这样就行了啊,这样就OK了,接着呢,我们现在呢,就来这个在下一次循环之前啊,我们最好呢是对它呢进行一个清空啊,就是memory set啊,对它这个存储进行一下清空,防止它有上一次遗留的内容啊没有覆盖掉。
19:10
啊,这样就可以了,然后我们现在呢,对它呢进行一下调用。啊,有一个处啊没问题,在这儿进行调用,调用完事之后啊,我们现在呢来运行啊。你可以看到啊,也检测到了,对不对。即使它的标题名变了啊,也检测到了,我们点击确定,等一会儿啊,它还是检测到,我们把它关掉啊,确定关掉。关掉之后。它就没了,没了之后呢,我们等一会儿啊,然后呢,我们把它重新启动起来,诶你看又检测到了,又检测到之后呢,我现在呢,把我的这个调试器里边贴拖一个这个进程,然后它标题名,标题名现在变了啊,标题名变了之后,我们等一会儿,诶你看还是检测到,所以说呢,这种形式呢,就不怕它怎么样拖出东西之后,它的这个名字啊,是这个有这个变化的了啊,会这个比较这个准确啊,那这个呢,就是咱们今天要讲的这个三种检测方式啊,然后大家有没有什么问题啊,有问题的可以问一下啊,没问题呢,咱们就今天的技术部分就到这了。
20:14
啊,没点关注的点点关注啊,然后有需要回放的呢,可以联系咱们老板进行获取啊。
我来说两句