实现dll劫持:
首先我们需要使用到工具:AheadLIB,这个工具可以帮我们生成dll文件的cpp代码。
什么是dll劫持,就是利用程序运行时会通过搜索名字来运行dll文件的方式,自己生成一个同名的dll文件,并且放在程序的同目录下,从而使程序会使用我们自己生成的dll文件,当然程序仍会使用系统的dll文件,因为我们自己生成的dll文件有系统dll文件的入口,否则我们就需要将系统的dll文件的代码全部生成,那样工作量会非常大,所以dll劫持的意思就是先加载我们的同名dll文件然后继续运行系统的dll文件。
然后开始尝试dll劫持,打开AheadLib工具,将我们想要劫持的dll文件拖入其中,然后直接生成代码
这样就生成成功了。然后我们再创建一个dll工程,打开vs,创建一个动态链接库(dll),然后将我们的生成的cpp文件拖入项目文件中,然后再将其在源文件中打开,然后右键我们的项目重新生成,找到dllmain函数,因为dllmain是程序的入口,所以我们可以将我们想要添加的代码放入dllmain函数中,比如我们可以添加一个弹窗来证实我们成功实现dll劫持。
编译链接,找到我们生成的dll文件,放入我们想要dll劫持的exe的同一级目录中就可以了。
一个加了壳的程序如何搜索字符串:
如何在加有壳的exe中搜索字符串,将一个加了upx壳的程序拖入od后,发现搜索字符串什么都搜不出来,我们先让程序运行起来,然后进入M窗口,找到我们的代码节的开始,然后ctrl g转到代码节的开始位置,在搜索就能搜索到想要搜索的字符串了。
如何过掉程序的crc检测:
1、干掉crc进程:
假如一个程序加了crc检测,那么我们如何在调试的时候下断点,可以在T窗口中查看我们的进程,找到最活跃的(我也不知道为什么要找最活跃的,可能是因为crc检测运算量比较大?),直接将其挂起,就好了。
2、干掉crc函数的判断
这个方法其实很不靠谱,我们得找到函数的关键跳,然后通过修改标志寄存器来影响关键跳的状态,假如函数很复杂的话,就会很难找到关键跳转。
什么是硬件断点
首先我们需要知道内存断点的原理是将相应位置的指令修改为int 3来实现的,那么硬件断点是什么呢?硬件断点是通过设置CPU相应硬件寄存器来阻止程序继续运行的。内存断点是修改的程序代码,所以可以设置很多个,但很容易被检测出来,如上面的crc检测,而内存断点一般只可以设置几个,因为硬件寄存器数量有限,但是很难被检测出来。
易语言字符串比较的必经之地:test edx,3
以及易语言中字符串比较的特征代码:
调试寄存器:
如上图,当我们将Dr7设置成0x405时,传到Get函数里却为5,为什么呢?NCK老师给我们展示了一下intel白皮书中关于调试寄存器的介绍,
如上图,DR7寄存器中,有很多位,实际上数值是以二进制的形式储存在这么多位中,比如5就是101,占了后三位,而我们前面将其设置成了405,也就是10000000101,可是在运行的时候,cpu并不会管前面的位数,实际上只关了后面的几位,所以会显示成5。
DR0到DR7寄存器分别是什么意思呢?
DR0到DR3时地址寄存器,我的猜测是就是存放地址的,DR4没什么用,DR7很重要,直接决定DR0设置的地址受否生效,DR6则决定DR0里面设置的断点是什么类型的,比如说是一个字节的访问断点,两个自己的执行断点。
然后DR7中的L0,L1,L2,L3,分别与DR0,DR1,DR2,DR3寄存器相对应其中的断点是否生效。
G0,G1,G2,G3与上面的一样,只是L0等等再执行过断点以后cpu会自动将其清除,而G0等等则不会自动清除。
好了那么我们再来学习一下如何通过代码实现绕过crc检测,昨天我们学习过了如何获取线程的上下文,所以我们可以通过修改调试寄存器的值从而去自动判断并且下硬件断点,从而绕过crc检测。如上图,通过SetThreadContext函数去设置调试寄存器的值。另外代码中的DLL_PROCESS_ATTACH是什么意思呢?上网搜了一下了解一下吧。
DLL_PROCESS_ATTACH通知
当DLL被初次映射到进程的地址空间中时,系统将调用该DLL的DllMain函数,给它传递参数fdwReason的值DLL_PROCESS_ATTACH。只有当DLL的文件映像初次被映射时,才会出现这种情况。如果线程在后来为已经映射到进程的地址空间中的DLL调用LoadLibrary(Ex)函数,那么操作系统只是递增DLL的使用计数,它并不再次用DLL_PROCESS_ATTACH的值来调用DLL的DllMain函数。
当处理DLL_PROCESS_ATTACH时,DLL应该执行DLL中的函数要求的任何与进程相关的初始化。例如,DLL可能包含需要使用它们自己的堆栈(在进程的地址空间中创建)的函数。通过在处理DLL_PROCESS_ATTACH通知时调用HeapCreate函数,该DLL的DllMain函数就能够创建这个堆栈。已经创建的堆栈的句柄可以保存在DLL函数有权访问的一个全局变量中。
最后写一下自己对于壳的理解,壳就是保护pe 文件的,比如vm壳,vm是保护代码,壳是保护程序。(欢迎大佬指正)