virut感染文件恢复算法

接上一篇:virut文件感染算法
上一篇是在我阅读完virut感染代码后立刻写的, 然后这几天我在写恢复算法, 今天差不多完成了, 写的同时, 发现有的地方我理解地不准确. 例如, 当直接修改oep而不通过hook点1来跳转到病毒代码时, 是没有那两句c6 05/ c7 05的, 此时就通过计算来得到oep值, 也就是我源代码中的backvalue1和backvalue2.

源代码VS2017解决方案
链接:https://pan.baidu.com/s/1vN6Y99U0XY-UIqECh4rVmw
提取码:thl0
使用时禁用spectrum缓解, x86编译调试.

凌乱的代码:
https://github.com/baosj0/virutfix

恢复算法的考虑就是:
1. 直接修改OEP到 OEP节尾, 或尾节病毒代码
判断方式为, 判断OEP是否在 oep节末尾-filealignment, oep节末尾之间;
判断OEP是否在尾节.
2. 通过HOOK1点, 跳转到OEP节尾或尾节代码.
如果前面OEP不存在修改, 那么说明采用了HOOK点的方式. 此时需要判断是否存在OEP节尾病毒代码. 判断的依据为OEP节的vsize是否等于rsize. 如果是, 那么说明有OEP节尾病毒代码.
3. 经过前面, 可以得到CodeEntry1_RVA(OEP节节尾病毒代码入口), 和CodeEntry2_RVA(尾节病毒代码入口). 先解析OEP节的那四个跳转, 得到外层加密方式, 密钥, 以及最终第四条跳跳到尾节CodeEntry2_RVA的值. 用密钥对尾节代码进行解密.
4. 解析尾节的跳转, 得到最终bodybase_RVA. 解析的过程中, 保存backvalue1和backvalue2的值, 这两个值相加, 就是hook点1的VA或者OEP的VA.
5. 得到最终bodybase_RVA后, 解密bodybase_RVA+53c开始的blockdescriptor数据.
之所以能解密, 是因为这个加密算法有漏洞:

                   mov     ecx, 3D34h
loc_1B1051:       
                   xor     [eax], dl 
                   imul    edx, 0Dh
                   inc     eax
                   dec     ecx
                   xchg    dh, dl
                   jnz     loc_1B1051
                   retn

edx中dx有个随机数key[0,ffff]

这个算法有漏洞, 只需要知道加密前后的数据, 就可以直接得到key并解密.

方法是:

词语: db_base_x_after, db_base_x_before db代表一个字节, x代表base+x处, after代表加密后数据, before代表加密前数据.
dh:dl表示2个字节, dh为高字节,dl为低字节.

key1 = db_base_0_after ^ db_base_0_before = db_base_0_before ^ key1 ^ db_base_0_before = key1^ (db_base_0_before ^ db_base_0_before) = key1也就是第一次加密时的dl

对(dh:key1) * 0xd 的结果, dh2:dl2, 显然dl2是由key1*0d决定的, 而经过xchg dh, dl之后, dl2就变成了dh, 此时再结合下面的key2, 那么edx中的dx就是 dl2:key2 那么key实际上就得到了.

key2 = db_base_1_after ^ db_base_1_before

同时为了避免浪费计算, 可以在需要解密的数据的前2个字节拿数据, 算出key后就可以直接用于解密, 不需要再循环N次得到对应位置的key. 拿的数据必须是代码, 因为是代码才确定before是什么值.

我代码中采用了+53c-3开始的 00 c3 这两个字节. 通过+53c-3和+53c-2位置, 我可以算出+53c-1位置时用的整个dx, 之后自然就顺利进行下去了.

_
6. 解密之后, 寻找before_size为0x3d34, 0x3eb0的块, 我这儿找了之前文章之外的第二个变种. 因为我之前文章中的样本, 我只有那一个变种, 没法测试我写的恢复程序的所有功能. 找到这个块之后, 通过CodeEntry2_RVA - after_offset得到尾节基地址CodeEntry2_base_RVA
7. 如果本程序中有hook点1, 那么通过寻找before_offset包括0x173的块, 然后通过CodeEntry2_base_RVA + after_offset, 找到代码对应位置后解析代码, 得到c6 05/c7 05的那两条指令中的有用的参数, 利用这参数, 恢复HOOK点1的原来数据.
8. 如果本程序中没有hook点1, 那么说明就是直接修改OEP来跳转到病毒代码的, 此时就利用backvalue1+backvalue2-imagebase, 就可以得到OEP的值.
9. 之后清除病毒数据, 清除标记, 设置区段表, 设置文件大小等…

代码中, 我用了capstone来反汇编代码, 主要我用的功能就是得到当前指针处的指令字节数, 这样避免EB XX 瞎几把跳.

另外, 还有其他的做法:
例如, 通过遍历跳转,找到跳转目的地址最小的那个, 然后就将其作为垃圾代码的起始地址, 删除之后的所有病毒代码.
再例如, 我可以不需要解密blockdescript来获取那两条恢复指令所在块的地址, 而直接在我解析CodeEntry2_RVA那个循环时, 直接去寻找那两条恢复指令, 更快更简单. 那为什么我一定要解密内层呢?? 主要是因为之前写sality, sality那东西解密后, 里面有许多有用的数据… 然后还有点强迫症, 不解密我就浑身不舒服.
还有, 这边的样本有两种, 因为我之前文章中, 只有那变种就一个, 而且属于有HOOK点1, 没OEP节节尾病毒代码的那种, 这样我很多功能就不能测试. 于是我去virusshare上以win32.virut.ce为关键字搜索, 找到了另一批变种, 看了代码之后发现非常类似, 基本是一样的. 除了bodysize和+20标记的值… 有了这批变种, 我就能测试我的功能了…

我的修复日志: 下面列的样本都在sampledir之中.

修复文件079e270fa5de4e0e664082aebafe1e25b7c85b34a26b6e965f509c991a3ae3ba
确认为变种1
入口点在最后一个区段
用于计算回跳点的值1:59410a
用于计算回跳点的值2:ffffa216
尾节最终block块RVA为19013b
重新设置PE头中的OEP为18e320
将尾区段的VSize减小5000 RSize减小4400
将PE头的SizeOfImage减小5000 将文件大小减小4400


修复文件1cfa01b2915612ec6e9c3a2f409e3c7e45c11ed35bd37e16196d548b6f5982b9
确认为变种1
入口节节尾有病毒代码
入口点没被更改,进行hook点1搜索
HOOK点1跳到了OEP节尾: hook点1 5503d 入口点节尾7442f
尾节块大小为429c
 入口节尾病毒使用的寄存器为ebx
OEP节尾病毒使用的加密算法为加法, 密钥为2bf54783
尾节病毒代码入口点为f4152
用于计算回跳点的值1:4f4157
用于计算回跳点的值2:fff60ee6
尾节最终block块RVA为f4250
包含那两条恢复指令的病毒代码块RVA为f8270
在45503d处恢复一个字节值为ff
在45503e处恢复四个字节值为47524c15
将尾区段的VSize减小5000 RSize减小5000
将PE头的SizeOfImage减小5000 将文件大小减小5000
将OEP区段表的VSize减小c82
将OEP区段的raddr: 7437e处的c82字节清0


修复文件393f5d5988c7ea6e0d1e26a83c07fe72d81b6ae10995f105e6a32a8775600c4b
确认为变种1
入口点在最后一个区段
用于计算回跳点的值1:4f2102
用于计算回跳点的值2:ffff0efe
尾节最终block块RVA为f231a
重新设置PE头中的OEP为e3000
将尾区段的VSize减小5000 RSize减小5000
将PE头的SizeOfImage减小5000 将文件大小减小5000


修复文件4d4a0d26f9a1fe970ba5e592c6563d66102d5a981408f0759ad681be20184c22
确认为变种1
入口点在最后一个区段
用于计算回跳点的值1:5f0065
用于计算回跳点的值2:ffffb41b
尾节最终block块RVA为1f01d0
重新设置PE头中的OEP为1eb480
将尾区段的VSize减小5000 RSize减小4400
将PE头的SizeOfImage减小5000 将文件大小减小4400


修复文件55bc06b12f53c7c54f6fba9a6b169eff51adb0075408420f8f7aedc1a6dba61b
确认为变种1
入口点没被更改,进行hook点1搜索
HOOK点1跳到了尾节: hook点10 入口点节尾b9fc9
用于计算回跳点的值1:4b9fce
用于计算回跳点的值2:fff47054
尾节最终block块RVA为b60e2
包含那两条恢复指令的病毒代码块RVA为ba051
在401022处恢复四个字节值为8bee3e8
在401026处恢复一个字节值为0
将尾区段的VSize减小5000 RSize减小4400
将PE头的SizeOfImage减小5000 将文件大小减小4400


修复文件5744b82f4425c056873ecde3d41bf55cbaf87caff8196d57eee1316704e7e9b6
确认为变种1
入口节节尾有病毒代码
入口点没被更改,进行hook点1搜索
HOOK点1跳到了OEP节尾: hook点1 1df95 入口点节尾3380b
尾节块大小为4264
 入口节尾病毒使用的寄存器为ebx
OEP节尾病毒使用的加密算法为加法, 密钥为cfa125a1
尾节病毒代码入口点为5610b
用于计算回跳点的值1:456110
用于计算回跳点的值2:fffc7e85
尾节最终block块RVA为5206f
包含那两条恢复指令的病毒代码块RVA为5201a
在41df95处恢复四个字节值为125c4e8
在41df99处恢复一个字节值为0
将尾区段的VSize减小5000 RSize减小5000
将PE头的SizeOfImage减小5000 将文件大小减小5000
将OEP区段表的VSize减小be0
将OEP区段的raddr: 33420处的be0字节清0


修复文件b01ba13ea0c4410316aa6df384f3a117a0cc7e959e8d53237299eaa233e0d445
确认为变种1
入口节节尾有病毒代码
入口点没被更改,进行hook点1搜索
HOOK点1跳到了OEP节尾: hook点1 17ac 入口点节尾c6c8
尾节块大小为4298
 入口节尾病毒使用的寄存器为ecx
OEP节尾病毒使用的加密算法为加法, 密钥为b764da8
尾节病毒代码入口点为14185
用于计算回跳点的值1:414196
用于计算回跳点的值2:fffed616
尾节最终block块RVA为143b2
包含那两条恢复指令的病毒代码块RVA为18271
在4017ac处恢复一个字节值为ff
在4017ad处恢复四个字节值为40d04415
将尾区段的VSize减小5000 RSize减小5000
将PE头的SizeOfImage减小5000 将文件大小减小5000
将OEP区段表的VSize减小ac0
将OEP区段的raddr: c540处的ac0字节清0


修复文件ba5cacb73cbdd2065beee4b108f061572228e83d279baebdb24d4cf8ed834235
确认为变种1
入口节节尾有病毒代码
入口点没被更改,进行hook点1搜索
HOOK点1跳到了OEP节尾: hook点1 54e7 入口点节尾6704
尾节块大小为42ac
 入口节尾病毒使用的寄存器为eax
OEP节尾病毒使用的加密算法为加法, 密钥为23e606b1
尾节病毒代码入口点为2108c
用于计算回跳点的值1:421091
用于计算回跳点的值2:fffe4456
尾节最终block块RVA为21265
包含那两条恢复指令的病毒代码块RVA为25239
在4054e7处恢复一个字节值为ff
在4054e8处恢复四个字节值为40706415
将尾区段的VSize减小5000 RSize减小5000
将PE头的SizeOfImage减小5000 将文件大小减小5000
将OEP区段表的VSize减小a14
将OEP区段的raddr: 65ec处的a14字节清0


修复文件Virut.exe1
确认为变种1
入口点没被更改,进行hook点1搜索
HOOK点1跳到了尾节: hook点10 入口点节尾37c14
用于计算回跳点的值1:1037c1e
用于计算回跳点的值2:fffcf5e8
尾节最终block块RVA为37d8a
包含那两条恢复指令的病毒代码块RVA为37caa
在1007206处恢复四个字节值为110c15ff
在100720a处恢复一个字节值为0
将尾区段的VSize减小16400 RSize减小15200
将PE头的SizeOfImage减小16400 将文件大小减小15200
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值