终于到了分析用delphi语言编写的vmp保护接近最后一个版本了,delphi时代最后的狂欢了,我说的不知道有没有问题,但是我想表达的就是这个意思,这个版本可能是2.x的网上可以找到的最后一个版本了,代码结构相较于之前版本改动不算很大,所以说是最后的狂欢了,而支持分析vmp的插件貌似只支持到2.08,以后版本就不支持了,这也给后续版本的vmp,增加更加神秘的面纱了,然后他的下个版本就是3.0了,听说代码重构了,改用C++写了,我上一篇文章写的是vmp1.6的分析,他后面有1.7,1.8,等等,变化不大,我就不浪费时间了,OK,2.12.3这个版本正好取到承上启下的作用,等分析完这个版本就可以去分析3.0了,想想还是有点小兴奋,感觉像打怪升级,现在最新版本也3.9几,当然我这么说肯定要被大神们笑话了,有时候学习就是这样,给自己一点动力,方能事半功倍。
我们把VmProtect.2.12.3目录下的HelloASM.vmp1拖到OD里面,这个文件是用vmp编译过的,然后说下一些设置,首先选项这一栏我选择了最快速度,然后加密的字节,仍旧是程序入口的5个nop指令,生成的exe文件大小是12kb,就这大小而言还不算大,这边再补充一下上个文章中的一个知识点,因为后面需要用到,下面是1.64版本虚拟机入口执行时候的例子
我说一下上面的两个部分,第一部分是1.64demo版本虚拟机入口的部分代码,当EIP为004050FA时,这时候堆栈就是1.64demo版本第二部分的样子,这时ESP = 0019FF44,等下我们用来做对比,接着回到我们的现在的OD。
首先我们看下第一条指令,是一个jmp指令,和以前一样,
再往下看
上面这边已经不是push A , call B 了,在1.6版本这个A就是指加密了的伪代码地址,这个pushfd是占坑的作用,当执行到00405894的时候我们把当前8个寄存器和标志寄存器的值记录一下,如下所示
我们再往下看
00405A0C和00405A11这两处代码加上前面的代码,是不是和push A , call B 一样了呢。00405A2C和00405A2D两条指令组合等于啥也没干,垃圾指令。根据1.6版本的经验,后面的代码就把一堆寄存器入栈了
上面这些代码是不是跟我们前面提到的1.64版本中,从004050E6到004050FA 的代码干的事情一样,只是变得很不好分析了。其实我们可以不用去一个一个去跟踪上面的代码,我们只要在004050B2下个断点,运行到这边看下堆栈,和前面保存的寄存做个比较,就可以还原出他,原来的样子。以下就是执行到004050B2时,堆栈的样子,因为这边寄存器好几个值都是401000,我就保证他们每个都出现一次这样写,
上面的和1.64的对比了一下,基本上相同,这时候esp = 19ff3c,ebp = 0019FF40。为什么我在0019FF40后面注释push 0 ,而不是在0019FF44注释呢,我是根据004050C8的指令推断的,执行到这条指令ebp等于0019FF40,当然后面填充虚拟寄存器的时候也可以证明这一点。多出来没有注释的,现在还不知道干什么用,很有可能就是让伪代码执行的更复杂,我们再往下看
上面这些分析下来,和1.6,1.2版本相比并没有本质的变化。以上就是还没执行handler前的分析过程,下面开始就是分析handler的执行
以上第一条handler的执行过程,依旧是填充虚拟寄存器的handler,将19ff40上的值也就是0填充到了虚拟寄存,有变化的是,少了个 and al,0x3C 这个大家应该有印象吧,之前读取的伪代码有两个作用,一个是计算handler地址,另外一个作用就是解密出虚拟寄存器的偏移,这个版本因为[eax*4 + handler基址]算出的是加密后的handler,那么这个虚拟寄存器的偏移,就得另外存放在伪代码里面。使用了两个字节的伪代码,09和3C,虚拟寄存器的偏移是0x3C,对应前面的push 0。
我们再看下一条handler
以上handler的一些注意点,我们分析一下,00404867 上的这条指令,执行后,堆栈上19ff40的值变成AD7B4B1E,上一条handler就是将19ff40的值0,填充到虚拟寄存器,00404874上的这条指令相当于add esp,0x34。作用就是平衡前面的三个push 操作,所以可以将他们视作垃圾指令,同样00405522和00405525组合在一起也是没用的指令,接着我们在看下00405522和00405525组合,这两条指令有点迷惑性,分析之后这个跳转相当于jmp,jg指令要跳转需要满足esp比-0x4大,很显然这个条件永远满足,我们继续看00404158这个ja指令,从他开始往前找影响标志位的指令就是404148的这个比较指令,因为ebp和eax的值都是固定的,所以这个跳转指令相当于jmp,00404154这条指令也是平衡前面的入栈,所以他和前面的几条都是垃圾指令,这条handler总体分析下来总结就是,好像啥也不做,用了很多垃圾指令,和条件跳转干扰我们分析。
我们再看下一条handler
上面这条handler和前面一条handler都是干扰我们分析的,00405193这一条指令的ebp+4 = 0019FF40,就是我们前面填充虚拟寄存器的那个堆栈地址,既然他们是没有用的handler,那他们对应的伪代码是不是可以跳过,就是执行完第一条handler后回到执行40463e处的代码的时候我们把esi的值改为0040590D,这样不就是跳过了那两条handler了呢,我试过了不行,但是在1.2版本碰到干扰的伪代码可以直接修改跳过他,但是这边还是可以改的,还需要改ebp,我们知道第一条handler执行完,回到40463e处代码的时候,ebp = 0019FF44,接着执行第二条,第三条handler完后,回到40463e处代码的时候,ebp = 0019FF40,所以说直接修改esi的值就会出错,这也是作者故意给我们挖的坑,经过分析第二条handler迷惑性很强,又是在伪代码处读取数据,其实他就一个作用将ebp的值减去4,然后第三条handler可以直接跳过。
我们接着往下看第四条handler,也就是第一条执行的那个handler,使用了两个字节的伪代码,09和0C,虚拟寄存器的偏移是0C,从他填充到虚拟寄存器值的存放的位置判断这条也是用作混淆的。
我们接着往下看第五条handler,也就是第一条执行的那个handler,使用了两个字节的伪代码,09和0C,虚拟寄存器的偏移是0C,从他填充到虚拟寄存器值的存放的位置判断这条也是用作混淆的。
我们接着往下看第六条handler,也就是第一条执行的那个handler,使用了两个字节的伪代码,04和24,虚拟寄存器的偏移是24,对应前面的push ebp。
我们接着往下看第七条handler,也就是第一条执行的那个handler,使用了两个字节的伪代码,09和08,虚拟寄存器的偏移是08,对应前面的push ecx。
我们接着往下看第八条handler,也就是第一条执行的那个handler,使用了两个字节的伪代码,04和34,虚拟寄存器的偏移是34,对应前面的push edx。
我们接着往下看第九条handler,也就是第一条执行的那个handler,使用了两个字节的伪代码,04和28,虚拟寄存器的偏移是28,对应前面的push ebx。
我们接着往下看第十条handler,也就是第一条执行的那个handler,使用了两个字节的伪代码,72和00,虚拟寄存器的偏移是0,对应前面的push esi。
我们接着往下看第十一条handler,也就是第一条执行的那个handler,使用了两个字节的伪代码,09和10,虚拟寄存器的偏移是10,对应前面的push eax。
我们接着往下看第十二条handler,也就是第一条执行的那个handler,使用了两个字节的伪代码,04和04,虚拟寄存器的偏移是04,对应前面的push edi。
我们接着往下看第十三条handler,也就是第一条执行的那个handler,使用了两个字节的伪代码,09和14,虚拟寄存器的偏移是14,对应前面的push 重复。
我们接着往下看第十四条handler,也就是第一条执行的那个handler,使用了两个字节的伪代码,04和38,虚拟寄存器的偏移是38,对应前面的push eflag。
我们接着往下看第十五条handler,也就是第一条执行的那个handler,使用了两个字节的伪代码,09和2c,虚拟寄存器的偏移是2c,对应前面的85011D2F 。
我们接着往下看第十六条handler,也就是第一条执行的那个handler,使用了两个字节的伪代码,04和30,虚拟寄存器的偏移是30,对应前面的伪代码地址 。
执行到这边虚拟寄存器已经填充完毕。我们看下分布
这里我把数值替换成对应的寄存器
上面的这个位置表中根据之前分析1.2版本经验推断,混淆,未填充(可能不只这两种),这些位置的虚拟寄存器,可以当做变量随便使用,其他虚拟寄存器,只在模拟被vm的代码时候,用于保存计算结果。
我们接着看第十七条handler,使用了两个字节的伪代码,C4和38
所以上面这条handler也是用于混淆的handler了,没作用。
我们接着看第十八条handler,也就是第二条执行的那个handler,前面分析过了,执行之前ebp = 19ff70,执行完之后,ebp=19ff6c,将读取到的4字节存放到ebp中。对应5个字节伪代码0x1E,0x73,B6,0x1B,0x46。
我们接着看第十九条handler,这边我就不把对应的代码全部贴出来了,前面分析过后,基本上哪些是垃圾指令,都能够一眼看出来了,这里就做一些分析记录就行了,这条handler执行之后,[0019FF68] = FFFFFEFF, ebp = 0019FF68 , 对应的3字节伪代码,0x23,0xff,0xfe。esi = 00405931。
我们接着看第二十条handler,这条handler执行之后,[0019FF68] = FFFFFEFF, ebp = 0019FF68 , 对应的3字节伪代码,0x23,0xff,0xfe。esi = 00405931。
我们接着看第二十一条handler,这条handler执行之后,[0019FF64] = 0x246, ebp = 0019FF64, 对应的2字节伪代码,0x10,0x38。esi = 00405933。这条是混淆用的
我们接着看第二十二条handler,这条handler执行之后,[0019FF60] = 0x0019FF64, ebp = 0019FF60, 对应的1字节伪代码,0x4e。esi = 00405934。还看不出来干什么的
我们接着看第二十三条handler,这条handler执行之后,[0019FF60] = 0x246, ebp = 0019FF60, 对应的1字节伪代码,0x42。esi = 00405935。这条也是混淆用的,分析到这边,发现前面全是搞混淆的,这边以后我加快分析,就不每一条执行的handler都记录了。
伪代码地址405936 对应的handler,将某个值填充到偏移为18的虚拟寄存器,我们前面做了个表格,知道这个虚拟寄存器是未填充的,所以我们可以大胆判断,这条也是混淆用的。
伪代码地址405939 对应的handler,这边很有意思,将虚拟标志寄存器的值0x246,存放到偏移为0x2c的那个虚拟寄存器,这边应该是虚拟寄存器位置互换,位于偏移为0x38的标志虚拟寄存器就解放了,后面有多次对其进行垃圾数据的写入 。
伪代码地址40593D 对应的handler,开始计算esi的值,这里是读取伪代码的值, 期间还会多次读取伪代码的数据进行各种解密计算,其中穿插有很多干扰的handler,和一些其他的环节,这边我就不一一分析,计算过程了。
伪代码地址40597B 对应的handler,这条将偏移为0x3c的那个虚拟寄存器值 0 ,存放到0x19ff6c,
我们再看下一条handler,这条将偏移为0x8的那个虚拟寄存器值0x0401000,存放到0x19ff68,
我们再看下一条handler,这条将偏移为0x4的那个虚拟寄存器值0x0401000,存放到0x19ff64,
我们再看下一条handler,这条将偏移为0x0的那个虚拟寄存器值0x0401000,存放到0x19ff60,
我们再看下一条handler,这条将偏移为0x2c的那个虚拟寄存器值0x00000246,存放到0x0019FF5C,
我们再看下一条handler,这条将偏移为0x10的那个虚拟寄存器值0x0019FFCC,存放到0x0019FF58,
我们再看下一条handler,这条将偏移为0x4的那个虚拟寄存器值0x0401000,存放到0x0019FF54,
我们再看下一条handler,这条将偏移为0x28的那个虚拟寄存器值0x0037C000存放到0x0019FF50
(这边解释一下,这个为什么和刚开始执行时候的ebx不一样,因为每次运行程序断在入口点的时候ebx都不一样,由于我调试的时候重新运行了程序)
我们再看下一条handler,这条将偏移为0x24的那个虚拟寄存器值0x0019FF80,存放到0x0019FF4C
我们再看下一条handler,这条将偏移为0x8的那个虚拟寄存器值0x00401000,存放到0x0019FF48
我们再看下一条handler,这条将偏移为0x14的那个虚拟寄存器值0x00401000,存放到0x0019FF44
我们再看下一条handler,这条将偏移为0xC的那个虚拟寄存器值0xAD7B4B1E,存放到0x0019FF40
我们总结一下上面的这几条虚拟寄存器值吐出到ebp指向的堆栈操作,前面因为我命名的时候是根据他们的值命名的,但是发现有好几个寄存器值都是一样的,其实这边应该把他们的值先设置成不同的比较好一点,都分析到这里了,只能硬着头皮继续分析,一些虚拟寄存器名字可能会有张冠李戴的错误,遇到这个不用管它。
我们再看下一条handler,这一条是条读取指令执行完,[19ff3c] = 5284B4E2,我们再看下一条,这一条加法指令执行完,[19ff40] = 0,我们再看下一条,这一条就是对偏移为0x34的那个虚拟寄存器写入00000257,这是个标志寄存器的值,所以这里正好印证前面的分析。
我们再看下一条,这条将偏移为0x3c的那个虚拟寄存器值0x0,存放到0x19ff3c,
我们再看下一条,这条将偏移为0x38的那个虚拟寄存器值0x00405899,这个0x00405899就是我们前面讲的经过多次解密计算后的将要改写esi值的值,这里偏移为0x38的那个虚拟寄存器保存了这个值,再存放到0x19ff38,等待使用。
我们再看下一条handler,这条handler对应的伪代码地址0x40599f,我们全面分析一下,
上面这一条handler执行完,esi变为0x00405899。
我们接着看下一条handler,这条是将偏移为0x28的那个虚拟寄存器(对应ebx)值改为0。
我们接着看下一条handler,这条是从伪代码读取4字节的数据AD7B4B1E。我们接着看伪代码地址为4058A3的handler,这里是将AD7B4B1E存放在偏移为0x1c的那个虚拟寄存器中,
我们接着看下一条handler,这条handler是将0019FF44的值00401000,存放到偏移为0xC的那个虚拟寄存器,我们前面推导出,0019FF44保存的是偏移为0x14的那个虚拟寄存器(对应edx),这边应该也是虚拟寄存器位置互换了,
我们接着看下一条handler,这条handler是将0019FF48的值00401000,存放到偏移为0x10的那个虚拟寄存器,我们前面推导出,0019FF48保存的是偏移为0x8的那个虚拟寄存器(对应ecx),这边应该也是虚拟寄存器位置互换了
我们接着看下一条handler,这条handler是将0019FF4C的值0019FF80,存放到偏移为0x18的那个虚拟寄存器,我们前面推导出,0019FF4C保存的是偏移为0x24的那个虚拟寄存器(对应ebp),这边应该也是虚拟寄存器位置互换了
我们接着看下一条handler,这条handler是将0019FF50的值003AE000,存放到偏移为0x14的那个虚拟寄存器,我们前面推导出,0019FF50保存的是偏移为0x28的那个虚拟寄存器(对应ebx),这边应该也是虚拟寄存器位置互换了
我们接着看下一条handler,这条handler是将0019FF54的值0401000,存放到偏移为0x0的那个虚拟寄存器,我们前面推导出,0019FF54保存的是偏移为0x4的那个虚拟寄存器(对应edi),这边应该也是虚拟寄存器位置互换了
我们接着看伪代码地址为4058CD对应的handler,这条handler是将0019FF58的值0019FFCC,存放到偏移为0x24的那个虚拟寄存器,我们前面推导出,0019FF58保存的是偏移为0x10的那个虚拟寄存器(对应eax),这边应该也是虚拟寄存器位置互换了,这边要说一下这条handler执行前,前面执行了好多干扰handler,所做的事情完全一样但是就是没有意义。
我们接着看下一条handler,这条handler是将0019FF5C的值0x246,存放到偏移为0x34的那个虚拟寄存器,我们前面推导出,0019FF5C保存的是偏移为0x2C的那个虚拟寄存器(对应新eflag),这边应该也是虚拟寄存器位置互换了,这里我解释一下这个eflag,他本来的偏移是0x38,后来有换到0x2C,这次又换到了0x34,挺有意思的。从执行伪代码地址40597B开始,虚拟寄存器的值相当于拷贝了一份到堆栈上,所以可以随便去互换各个虚拟寄存器的位置。
我们接着看下一条handler,这条handler是将0019FF60的值0401000,存放到偏移为0x30的那个虚拟寄存器,我们前面推导出,0019FF60保存的是偏移为0x0的那个虚拟寄存器(对应esi),这边应该也是虚拟寄存器位置互换了
我们接着看下一条handler,这条handler是将0019FF64的值0401000,存放到偏移为0x8的那个虚拟寄存器,我们前面推导出,0019FF64保存的是偏移为0x4的那个虚拟寄存器(对应edi),这边应该也是虚拟寄存器位置互换了
我们接着看下一条handler,这条handler是将0019FF68的值0401000,存放到偏移为0x20的那个虚拟寄存器,我们前面推导出,0019FF68保存的是偏移为0x8的那个虚拟寄存器(对应ecx),这边应该也是虚拟寄存器位置互换了
我们接着看下一条handler,这条handler是将0019FF6C的值0,存放到偏移为0x3C的那个虚拟寄存器,我们前面推导出,0019FF6C保存的是偏移为0x3C的那个虚拟寄存器(对应重定位0)。
我们接着看下一条handler,这条handler是将0019FF70的值0x246,存放到偏移为0x4的那个虚拟寄存器, 我们前面知道,0x246就是虚拟标志寄存器的值。
我们接着看伪代码地址为4058e9对应的handler,这条handler是从伪代码中读取4个字节的值401005,这个值使我们虚拟机返回的地址。
到这里我们可以更新一下虚拟寄存器的表格了,我是根据前面分析,和他的值去猜测的,可能会有矛盾的地方,直接忽略就行,如下所示
我们再看下一条handler,这条将偏移为0x4的那个虚拟寄存器(对应eflag)值0x0246,存放到0x0019FF6C。
我们再看下一条handler,这条将偏移为0xC的那个虚拟寄存器(对应edx)值0x00401000,存放到0x0019FF68。
我们再看下一条handler,这条将偏移为0x8的那个虚拟寄存器值0x00401000,存放到0x0019FF64。
我们再看下一条handler,这条将偏移为0x24的那个虚拟寄存器(对应eax)值0x0019FFCC,存放到0x0019FF60。
我们再看下一条handler,这条将偏移为0x30的那个虚拟寄存器(对应esi)值0x00401000,存放到0019FF5C。
我们再看下一条handler,这条将偏移为0x14的那个虚拟寄存器(对应ebx)值0x00228000,存放到0019FF58。
我们再看下一条handler,这条将偏移为0x38的那个虚拟寄存器值0x461BFFD3,存放到0019FF54。
我们再看下一条handler,这条将偏移为0x10的那个虚拟寄存器(对应ecx)值0x00401000,存放到0019FF50。
我们再看下一条handler,这条将偏移为0x18的那个虚拟寄存器(对应ebp)值0x0019FF80,存放到0019FF4C。
我们再看下一条handler,这条将偏移为0x18的那个虚拟寄存器(对应ebp)值0x0019FF80,存放到0019FF4C。
我们再看下一条handler,这条将偏移为0x0的那个虚拟寄存器(对应edi)值0x00401000,存放到0019FF48。
我们再看下一条handler,这条将偏移为0x1C的那个虚拟寄存器值0xAD7B4B1E,存放到0019FF44。
以上分析中,除了ecx,edx,esi,edi,这四个寄存器的值刚开始都为401000,命名的时候比较混乱以为,其他寄存器的值在虚拟寄存器上都和他们在入口点的值一样。这也是我分析到这边坚持下去的原因吧。
这边就是把虚拟寄存器全部吐到堆栈上了,等待从堆栈弹到各个真是寄存器中。
我们再看下一条handler,
最后我们给堆栈标一下对应寄存器的位置。
总结,2.12.3版本和1.6版本相比确实困难了不少,比较有意思的是在一个流程块里面虚拟寄存器,就已经进行了位置互换,我分析1.6之前的只在每个流程块里不一样。还有就是分析到中间的那个修改esi的值用了加密,而最后离开虚拟机的,那个返回值却连加密都没有,直接放在伪代码上面,在分析的1.6版本之前都是有加密的,还有修改和读取虚拟寄存器对应的伪代码,本来只要一个字节就行,现在还拆分成了两个字节,等等。这些的改变,使编写一款分析插件相较于之前的版本难度和工作量增加了不少,但是总体的运行框架没有变,这也是我可以根据分析之前的版本,预测出每一步都是干什么,本来还想去分析它的反调试整个执行流程,但是之前1.6版本已经分析过了,我想再分析,可能看不出什么新意吧,那就显得很枯燥,没意思了,那下一篇分析就直接进入3.0时代了,想想都觉得兴奋。
004050E6 |$ 56 push esi
004050E7 |. 53 push ebx
004050E8 |. 50 push eax
004050E9 |. 53 push ebx
004050EA |. 51 push ecx
004050EB |. 9C pushfd
004050EC |. 52 push edx
004050ED |. 57 push edi
004050EE |. 55 push ebp
004050EF |. 68 00000000 push 0x0
004050F4 |. 8B7424 2C mov esi,dword ptr ss:[esp+0x2C]
004050F8 |. 89E5 mov ebp,esp
004050FA |. 81EC C0000000 sub esp,0xC0
004050E6 |$ 56 push esi
004050E7 |. 53 push ebx
004050E8 |. 50 push eax
004050E9 |. 53 push ebx
004050EA |. 51 push ecx
004050EB |. 9C pushfd
004050EC |. 52 push edx
004050ED |. 57 push edi
004050EE |. 55 push ebp
004050EF |. 68 00000000 push 0x0
004050F4 |. 8B7424 2C mov esi,dword ptr ss:[esp+0x2C]
004050F8 |. 89E5 mov ebp,esp
004050FA |. 81EC C0000000 sub esp,0xC0
0019FF44 00000000 ;1 push 0x0
0019FF48 0019FF80 ;2 push ebp
0019FF4C 00401000 ;3 push edi
0019FF50 00401000 ;4 push edx
0019FF54 00000246 ;5 pusfd
0019FF58 00401000 ;6 push ecx
0019FF5C 003C9000 ;7 push ebx
0019FF60 0019FFCC ;8 push eax
0019FF64 003C9000 ;9 push ebx
0019FF68 00401000 ;10 push esi
0019FF6C 0040578C ;前面执行的CALL压入的返回地址
0019FF70 00405790 ;伪代码地址
0019FF44 00000000 ;1 push 0x0
0019FF48 0019FF80 ;2 push ebp
0019FF4C 00401000 ;3 push edi
0019FF50 00401000 ;4 push edx
0019FF54 00000246 ;5 pusfd
0019FF58 00401000 ;6 push ecx
0019FF5C 003C9000 ;7 push ebx
0019FF60 0019FFCC ;8 push eax
0019FF64 003C9000 ;9 push ebx
0019FF68 00401000 ;10 push esi
0019FF6C 0040578C ;前面执行的CALL压入的返回地址
0019FF70 00405790 ;伪代码地址
00401000 > $- E9 8E480000 jmp HelloASM.00405893
00401000 > $- E9 8E480000 jmp HelloASM.00405893
00405893 9C pushfd
00405894 E9 73010000 jmp HelloASM.00405A0C
00405893 9C pushfd
00405894 E9 73010000 jmp HelloASM.00405A0C
EAX 0019FFCC
ECX 00401000
EDX 00401000
EBX 00228000
ESP 0019FF70
EBP 0019FF80
ESI 00401000
EDI 00401000
Eflag 00000246
EAX 0019FFCC
ECX 00401000
EDX 00401000
EBX 00228000
ESP 0019FF70
EBP 0019FF80
ESI 00401000
EDI 00401000
Eflag 00000246
00405A0C E8 00000000 call HelloASM.00405A11
00405A11 C74424 04 05594>mov dword ptr ss:[esp+0x4], 00405905
00405A19 882C24 mov byte ptr ss:[esp],ch;垃圾指令
00405A1C 66:C70424 EE70 mov word ptr ss:[esp],0x70EE;垃圾指令
00405A22 880424 mov byte ptr ss:[esp],al;垃圾指令
00405A25 C70424 2F1D0185 mov dword ptr ss:[esp],0x85011D2F;垃圾指令
00405A2C 9C pushfd
00405A2D 8D6424 04 lea esp,dword ptr ss:[esp+0x4]
00405A31 ^ E9 C1E9FFFF jmp HelloASM.004043F7
00405A0C E8 00000000 call HelloASM.00405A11
00405A11 C74424 04 05594>mov dword ptr ss:[esp+0x4], 00405905
00405A19 882C24 mov byte ptr ss:[esp],ch;垃圾指令
00405A1C 66:C70424 EE70 mov word ptr ss:[esp],0x70EE;垃圾指令
00405A22 880424 mov byte ptr ss:[esp],al;垃圾指令
00405A25 C70424 2F1D0185 mov dword ptr ss:[esp],0x85011D2F;垃圾指令
00405A2C 9C pushfd
00405A2D 8D6424 04 lea esp,dword ptr ss:[esp+0x4]
00405A31 ^ E9 C1E9FFFF jmp HelloASM.004043F7
004043F7 60 pushad
004043F8 9C pushfd
004043F9 885C24 04 mov byte ptr ss:[esp+0x4],bl
004043FD FF7424 14 push dword ptr ss:[esp+0x14];push ebx
00404401 f3:9c rep pushfd;pushfd
00404403 8F4424 24 pop dword ptr ss:[esp+0x24]
00404407 9C pushfd
00404408 C60424 2B mov byte ptr ss:[esp],0x2B
0040440C 9C pushfd
0040440D 9C pushfd
0040440E 8D6424 30 lea esp,dword ptr ss:[esp+0x30]
00404412 E9 C1110000 jmp HelloASM.004055D8
004043F7 60 pushad
004043F8 9C pushfd
004043F9 885C24 04 mov byte ptr ss:[esp+0x4],bl
004043FD FF7424 14 push dword ptr ss:[esp+0x14];push ebx
00404401 f3:9c rep pushfd;pushfd
00404403 8F4424 24 pop dword ptr ss:[esp+0x24]
00404407 9C pushfd
00404408 C60424 2B mov byte ptr ss:[esp],0x2B
0040440C 9C pushfd
0040440D 9C pushfd
0040440E 8D6424 30 lea esp,dword ptr ss:[esp+0x30]
00404412 E9 C1110000 jmp HelloASM.004055D8
004055D8 66:81FF 79E0 cmp di,0xE079
004055DD 51 push ecx
004055DE 60 pushad
004055DF 895424 1C mov dword ptr ss:[esp+0x1C],edx
004055E3 C0E1 05 shl cl,0x5
004055E6 8D8E 7B0A5051 lea ecx,dword ptr ds:[esi+0x51500A7B]
004055EC 894424 18 mov dword ptr ss:[esp+0x18],eax
004055F0 80C1 C2 add cl,0xC2
004055F3 E8 4EFAFFFF call HelloASM.00405046
004055D8 66:81FF 79E0 cmp di,0xE079
004055DD 51 push ecx
004055DE 60 pushad
004055DF 895424 1C mov dword ptr ss:[esp+0x1C],edx
004055E3 C0E1 05 shl cl,0x5
004055E6 8D8E 7B0A5051 lea ecx,dword ptr ds:[esi+0x51500A7B]
004055EC 894424 18 mov dword ptr ss:[esp+0x18],eax
004055F0 80C1 C2 add cl,0xC2
004055F3 E8 4EFAFFFF call HelloASM.00405046
00405046 877C24 18 xchg dword ptr ss:[esp+0x18],edi
0040504A F6D0 not al
0040504C 0FB6C9 movzx ecx,cl
0040504F 895C24 14 mov dword ptr ss:[esp+0x14],ebx
00405053 66:09F7 or di,si
00405056 84F1 test cl,dh
00405058 897424 10 mov dword ptr ss:[esp+0x10],esi
0040505C 66:F7D7 not di
0040505F 66:D3D7 rcl di,cl
00405062 897424 0C mov dword ptr ss:[esp+0xC],esi
00405066 66:C1C7 03 rol di,0x3
0040506A 66:C1FF 05 sar di,0x5
0040506E 66:0FBAF1 0F btr cx,0xF
00405073 20F1 and cl,dh
00405075 876C24 08 xchg dword ptr ss:[esp+0x8],ebp
00405079 66:39F7 cmp di,si
0040507C FF35 164C4000 push dword ptr ds:[0x404C16]
00405082 8F4424 04 pop dword ptr ss:[esp+0x4]
00405086 66:D1C6 rol si,1
00405089 50 push eax
0040508A 66:0FACC7 02 shrd di,ax,0x2
0040508F C74424 04 00000>mov dword ptr ss:[esp+0x4],0x0;重定位有关系的
00405097 66:0FC1FE xadd si,di
0040509B 8B7424 34 mov esi,dword ptr ss:[esp+0x34];esi赋值
0040509F 66:0FA5C5 shld bp,ax,cl
004050A3 66:0FADCF shrd di,cx,cl
004050A7 66:29E5 sub bp,sp
004050AA 8D6C24 04 lea ebp,dword ptr ss:[esp+0x4]
004050AE 66:C1D7 03 rcl di,0x3
004050B2 81EC BC000000 sub esp,0xBC;开辟堆栈
00405046 877C24 18 xchg dword ptr ss:[esp+0x18],edi
0040504A F6D0 not al
0040504C 0FB6C9 movzx ecx,cl
0040504F 895C24 14 mov dword ptr ss:[esp+0x14],ebx
00405053 66:09F7 or di,si
00405056 84F1 test cl,dh
00405058 897424 10 mov dword ptr ss:[esp+0x10],esi
0040505C 66:F7D7 not di
0040505F 66:D3D7 rcl di,cl
00405062 897424 0C mov dword ptr ss:[esp+0xC],esi
00405066 66:C1C7 03 rol di,0x3
0040506A 66:C1FF 05 sar di,0x5
0040506E 66:0FBAF1 0F btr cx,0xF
00405073 20F1 and cl,dh
00405075 876C24 08 xchg dword ptr ss:[esp+0x8],ebp
00405079 66:39F7 cmp di,si
0040507C FF35 164C4000 push dword ptr ds:[0x404C16]
00405082 8F4424 04 pop dword ptr ss:[esp+0x4]
00405086 66:D1C6 rol si,1
00405089 50 push eax
0040508A 66:0FACC7 02 shrd di,ax,0x2
0040508F C74424 04 00000>mov dword ptr ss:[esp+0x4],0x0;重定位有关系的
00405097 66:0FC1FE xadd si,di
0040509B 8B7424 34 mov esi,dword ptr ss:[esp+0x34];esi赋值
0040509F 66:0FA5C5 shld bp,ax,cl
004050A3 66:0FADCF shrd di,cx,cl
004050A7 66:29E5 sub bp,sp
004050AA 8D6C24 04 lea ebp,dword ptr ss:[esp+0x4]
004050AE 66:C1D7 03 rcl di,0x3
004050B2 81EC BC000000 sub esp,0xBC;开辟堆栈
0019FF3C 0019FF33 ;
0019FF40 00000000 ;push 0
0019FF44 00000000 ;
0019FF48 0019FF80 ;push ebp
0019FF4C 00401000 ;push ecx
0019FF50 00401000 ;push edx
0019FF54 00228000 ;push ebx
0019FF58 00401000 ;push esi
0019FF5C 0019FFCC ;push eax
0019FF60 00401000 ;push edi
0019FF64 00401000 ;push 重复
0019FF68 00000246 ;pushfd
0019FF6C 85011D2F ;前面执行的CALL压入的返回地址的堆栈位置
0019FF70 00405905 ;伪代码地址
0019FF3C 0019FF33 ;
0019FF40 00000000 ;push 0
0019FF44 00000000 ;
0019FF48 0019FF80 ;push ebp
0019FF4C 00401000 ;push ecx
0019FF50 00401000 ;push edx
0019FF54 00228000 ;push ebx
0019FF58 00401000 ;push esi
0019FF5C 0019FFCC ;push eax
0019FF60 00401000 ;push edi
0019FF64 00401000 ;push 重复
0019FF68 00000246 ;pushfd
0019FF6C 85011D2F ;前面执行的CALL压入的返回地址的堆栈位置
0019FF70 00405905 ;伪代码地址
004050B2 81EC BC000000 sub esp,0xBC;开辟堆栈
004050B8 66:0FBAF9 07 btc cx,0x7
004050BD D2D8 rcr al,cl
004050BF 89E7 mov edi,esp;edi存放虚拟寄存器基地址
004050C1 D2E0 shl al,cl
004050C3 66:0FBDC9 bsr cx,cx
004050C7 F5 cmc
004050C8 0375 00 add esi,dword ptr ss:[ebp];重定位有关系的
004050B2 81EC BC000000 sub esp,0xBC;开辟堆栈
004050B8 66:0FBAF9 07 btc cx,0x7
004050BD D2D8 rcr al,cl
004050BF 89E7 mov edi,esp;edi存放虚拟寄存器基地址
004050C1 D2E0 shl al,cl
004050C3 66:0FBDC9 bsr cx,cx
004050C7 F5 cmc
004050C8 0375 00 add esi,dword ptr ss:[ebp];重定位有关系的
0040463E 8A06 mov al,byte ptr ds:[esi];取出伪代码
00404640 66:0FACC9 02 shrd cx,cx,0x2
00404645 F6D1 not cl
00404647 D2E9 shr cl,cl
00404649 0FB6C0 movzx eax,al
0040464C 80F1 55 xor cl,0x55
0040464F 8B0C85 1A4C4000 mov ecx,dword ptr ds:[eax*4+0x404C1A];计算handler地址,不过此时还是加密的
00404656 E9 81050000 jmp HelloASM.00404BDC
0040463E 8A06 mov al,byte ptr ds:[esi];取出伪代码
00404640 66:0FACC9 02 shrd cx,cx,0x2
00404645 F6D1 not cl
00404647 D2E9 shr cl,cl
00404649 0FB6C0 movzx eax,al
0040464C 80F1 55 xor cl,0x55
0040464F 8B0C85 1A4C4000 mov ecx,dword ptr ds:[eax*4+0x404C1A];计算handler地址,不过此时还是加密的
00404656 E9 81050000 jmp HelloASM.00404BDC
00404BDC 83EE FF sub esi,-0x1;等效于inc esi
00404BDC 83EE FF sub esi,-0x1;等效于inc esi
00404BF7 81F1 CE66B527 xor ecx,0x27B566CE;解密
00404BF7 81F1 CE66B527 xor ecx,0x27B566CE;解密
00404C02 894C24 24 mov dword ptr ss:[esp+0x24],ecx;handler地址存放到堆栈
00404C06 C60424 0E mov byte ptr ss:[esp],0xE
00404C0A FF7424 24 push dword ptr ss:[esp+0x24]; handler地址入栈
00404C0E C2 2800 retn 0x28 ;转到handler执行
00404C02 894C24 24 mov dword ptr ss:[esp+0x24],ecx;handler地址存放到堆栈
00404C06 C60424 0E mov byte ptr ss:[esp],0xE
00404C0A FF7424 24 push dword ptr ss:[esp+0x24]; handler地址入栈
00404C0E C2 2800 retn 0x28 ;转到handler执行
00404125 F5 cmc
00404126 0FC0C2 xadd dl,al
00404129 66:29CA sub dx,cx
0040412C 66:0FBDD3 bsr dx,bx
00404130 8A06 mov al,byte ptr ds:[esi];取出虚拟寄存器偏移
00404132 66:81C2 F096 add dx,0x96F0
00404137 8B55 00 mov edx,dword ptr ss:[ebp];将先前入栈的寄存器给edx
0040413A F5 cmc
0040413B E8 13010000 call HelloASM.00404253
00404125 F5 cmc
00404126 0FC0C2 xadd dl,al
00404129 66:29CA sub dx,cx
0040412C 66:0FBDD3 bsr dx,bx
00404130 8A06 mov al,byte ptr ds:[esi];取出虚拟寄存器偏移
00404132 66:81C2 F096 add dx,0x96F0
00404137 8B55 00 mov edx,dword ptr ss:[ebp];将先前入栈的寄存器给edx
0040413A F5 cmc
0040413B E8 13010000 call HelloASM.00404253
00404253 8D76 01 lea esi,dword ptr ds:[esi+0x1];等效于inc esi
00404256 84FF test bh,bh
00404258 83C5 04 add ebp,0x4
0040425B 9C pushfd
0040425C 60 pushad
0040425D 891438 mov dword ptr ds:[eax+edi],edx;填充虚拟寄存器的值
00404260 FF7424 08 push dword ptr ss:[esp+0x8]
00404264 68 58E5DA5D push 0x5DDAE558
00404269 9C pushfd
0040426A 8D6424 34 lea esp,dword ptr ss:[esp+0x34]
0040426E E9 580E0000 jmp HelloASM.004050CB
00404253 8D76 01 lea esi,dword ptr ds:[esi+0x1];等效于inc esi
00404256 84FF test bh,bh
00404258 83C5 04 add ebp,0x4
0040425B 9C pushfd
0040425C 60 pushad
0040425D 891438 mov dword ptr ds:[eax+edi],edx;填充虚拟寄存器的值
00404260 FF7424 08 push dword ptr ss:[esp+0x8]
00404264 68 58E5DA5D push 0x5DDAE558
00404269 9C pushfd
0040426A 8D6424 34 lea esp,dword ptr ss:[esp+0x34]
0040426E E9 580E0000 jmp HelloASM.004050CB
004050CB 20E8 and al,ch
004050CD E8 6BF5FFFF call HelloASM.0040463D;继续循环读取伪代码执行
[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!
最后于 2025-10-4 00:26
被阿强编辑
,原因: