近期准备写个比较通用的脱壳机,其实现在很多具有一定通用性的脱壳机都是基于虚拟CPU的,跟虚拟机似的,个也不例外,但是由于它们仿真程度的不同,决定了它们解壳的能力,当然我是想把它做的解壳能力比较强,否则也没有必要写了......想在虚拟CPU上支持多线程,简单的多进程等特性,这样它的解壳能力应该是有点“猛”,不过,这都还处于假想阶段,深知要做成这个,技术门槛相当的高,超出了本人能力,不过还是抱着学习研究的态度,往下写吧,现在做人都讲究“无求”了......
基于虚拟CPU的解壳机效率肯定比较低,本人将尽量优化算法,使它能尽量的快......
程序特色:
1.纯C开发
2.自己写了内存适配器,坚决避免内存内碎片,有效遏制内存外碎片
3.充分利用程序局部性原理,仿真CPU具有cache功能
4.数据结构一般采用哈希表,红黑树,比较高效快速
5.为了高效脱壳,仿真CPU很多地方没有监听,导致有些脱壳方法比较笨,针对某壳特性,局部监听特定异常.
更新日志:
3月11号:
由于某原因,搬家至回龙观龙博一区,放弃linux内核研究,启动脱壳机项目
3月28日前:
完成x86机器码的识别
4月8号前:
大致写了虚拟 ring 3 x86 cpu代码,没有测试,体力活,没有技术含量
4月15日前:
修正虚拟CPU bug,基本调至能解UPX壳了,马马虎虎写了个dump模块,目前一调用,程序死了
4月23日前:
花了两天时间,调试dump模块,对“菜壳”通用的dump模块横空出世,花了两天时间模拟了SEH异常处理链,
开始支持异常处理(包括展开式SEH处理),优化了CPU指令解析系性能,核心部位全汇编实现
5月2号前:
具体细的也没有办法讲了,在调试壳的过程中,修正了不少bug,也为了脱一些壳,加入了不少新的特性,
最重要的是修正了dump模块一些bug,新增IAT表备份等功能,一个对“菜壳”比较通用的dump模块产生,
脱某壳时,发现程序执行过程中,切换堆栈到代码数据空间了,虚拟CPU刚设计的时候,为了效率,没有把堆栈
内存空间统一到“进程”空间,这里也统一它们了,并改了堆栈边界判定
脱petite的时候,利用堆栈代码执行技术,不过堆栈空间统一了,这个不是问题
脱petite的时候,仿真了FS段的局部功能,不光是SEH了
程序堆栈布局也再次调整了,有些壳利用系统load时压入的堆栈(程序启动代码压入的值,我们的PE load
没有程序启动功能,故需仿真之)
5月2号-3号:
脱petite v2.x,这款壳有点捍,用了可读内存写异常,单步异常,EIP=0异常,虚拟机新增了对这些异常的捕获,
另外,这款壳对IAT表的处理跟以前脱的壳不同,它自己分析的PE文件,这个不想模拟了,要模拟也简单,
因此这款脱目前脱出来还不可运行...感慨万千,这款脱搞得我要摇摇欲坠了
5月4号凌晨:
脱了winkript 1.0 和 pklite32 1.1,这两个壳很弱,没有什么说的
5月4号白天:
上午脱pepack 0.99 和 pepack 1.0,这款壳API调用采用jmp [x]方式,仿真了这个特性
下午脱pcshrinker 0.71,这款壳存在指令自修改现象,修正了指令自修改时,cache失效的一个bug,及时刷新cache指令集
下午晚上脱wwpack32 1.2 demo,这壳很弱,不过它用了SHLD指令,仿真CPU新增了对SHLD/SHRD指令的支持
5月5号上午:
昨天晚上发现脱upack v0.32时,PE load模块有重大bug,由于upack v0.32的PE头很乱,保存了很多
信息......昨天晚上研究了windows load过程,很有收获啊(http://bbs.pediy.com/showthread.php?t=43928)
上午修正了这个bug,upack v0.32被脱,这个壳注重的是压缩效果,没有什么其它特点
5月5号21:42前:
脱下upack v0.36,这里还是继续研究PE load模块,节的对齐问题
21:49脱下upack v0.37,这个壳跟upack v0.36一样
21:53脱下upack v0.38,这个壳跟upack v0.36一样
21:58脱下upack v0.39,这个壳跟upack v0.36一样
22:01脱下upack v0.399,这个壳跟upack v0.36一样
23:10脱下upack v0.23,修正CMPS,SCANS指令没有前缀却改写了ECX值的bug,脱法跟upack v0.32一样
5月6号:
1:36脱下rlpack Basic Edition v1.18,这个壳很简单,脱这个壳修正了dump新加节后,PE头大小非法,导致程序无法运行bug
1:45脱下rlpack Basic Edition v1.11
1:49脱下rlpack Basic Edition v1.12,脱法跟rlpack Basic Edition v1.11一样
1:54脱下rlpack Basic Edition v1.13,脱法跟rlpack Basic Edition v1.11一样
1:57脱下rlpack Basic Edition v1.14,脱法跟rlpack Basic Edition v1.11一样
2:00脱下rlpack Basic Edition v1.15,脱法跟rlpack Basic Edition v1.18一样
2:03脱下rlpack Basic Edition v1.16,脱法跟rlpack Basic Edition v1.18一样
2:42脱下rlpack Basic Edition v1.17,脱法跟rlpack Basic Edition v1.18一样
16:16脱下exe32pack v1.42,这款壳用了IsDebuggerPresent函数来检测是否被调试,并读取IsDebuggerPresent地址
第一个字节来判定是否0xcc,即是否在IsDebuggerPresent上下断点了,这里粗略仿真了API地址空间,这个壳还破坏了PE头,
这里引入了是否脱壳后采用原来PE头功能(这系列壳的低版本没有效验IsDebuggerPresent是否被下断点,应该也能搞定,
苦于没有找到加壳工具,无法验证设想),并修正了ADD(0x00)指令的一处bug,load模块也引入了多个Dll对应一个FirstThunk的处理方法
22:17脱下kbys v0.28,这款壳比较简单,不过它的VirtualFree通过retn来执行,这里仿真了这个属性在ret解析函数,
不过,其实应该在每个指令执行后,都要有这样的处理,但处于效率,且目前只有kbys这么用,就只在retn中这么干了
5月7号:
1:15脱了aspack系列余下的所有壳,均秒杀之
13:00脱了upx系列余下的壳,均秒杀之
22:18脱了fsg v1.0 v2.0,v2.0系统自动扫描到的IAT只是张函数地址表,各dll函数地址间没有0隔开,
于是又写了个dump,这个dump实现了新建IAT,让人失望,call/jmp访问系统无问题,但是一些通过其它指令
来访问系统的API没有办法工作了,貌似除了手工分析外,这个问题无法解决,唉,最后通过修改无效API地址为0,
解决这个问题
5月8号:
脱了morphine v1.3 v1.6,这两个壳,代码被解密出来,无法dump
5月9号:
脱了morphine v2.7,这个壳,由于TEB没有仿真,没有脱完,但是真实代码已经出来了,
从偏移nSizeBase开始扫描即可,无法dump
23:37脱了PECompact系列余下的壳,基本上秒杀
5月13号:
02:18脱了yoda's protector v1.02,这是个加密壳,6次SEH异常(5次是int3,1次访问0地址异常),
IsDebuggerPresent 3次,反softice等调试器,枚举进程列表来检测父进程信息(检测父进程是否为
EXPLORER.EXE),判定是否被调试,WaitForInputIdle来锁定输入设备,读取自身文件自效验等......
21:00脱了yoda's protector v1.03.2,这个壳比v1.02更加飙旱,BlockInput锁鼠标键盘,SetWindowLongA
锁任务栏,解密用win解密API
次日0:53脱了yoda's crypt v1.2 v1.3,修正自修改模块的一处bug,能脱yp脱yc没难度
5月14号:
22:20脱了EXE Stealth v2.75a v2.76,这个壳跟yc一个模样
22:54脱了EXE Stealth v2.72 v2.73 v2.74,脱法跟v2.75a一样
5月15号:
00:25脱了bjfnt v1.2,引入ESP定律脱壳,这壳没有特征好用,只能ESP定律了,无奈
00:30脱了bjfnt v1.3,脱法和bjfnt v1.2一样 (均存在导入表不对)
20:43脱了HidePE v1.1,只是加了几条指令骗下PEID,HidePE v1.0脱法一样
5月16号:
00:40脱下jdpack v1.01,修正PE load模块的一处bug,修正反汇编模块结束虚拟地址导致的一个与自修改相关bug
20:39脱了jdpack v2.0,对这个壳,只能说fk,对示例程序int3异常38万多次,OD无法调,估计这也是没有看到这个壳脱文的原因
20:48脱了jdpack v2.13,这个壳脱法跟jdpack v1.01一样
21:32脱了PEncrypt v3.1, so easy!
5月17号:
00:39脱了PEncrypt v4.0,这个壳没有啥特征,不好判定什么脱完了啊
20:03修正了脱PEncrypt4.0脱法,引入类似OEP识别技术来脱壳,并为popaf引入对单步异常的监听
20:25脱了Stone's PE Crypt v1.13, so easy!
5月18号:
20:48脱了telock v0.42
5月19号:
00:40前,加入反汇编模块专用内存,并设置上限,防止在执行某些程序的时候,内存过大问题
14:16脱了telock v0.51,加入IAT预处理,针对telock v0.51加密IAT情况
15:40脱了telock v0.60
18:15脱了telock v0.70,引入整数除0异常捕获
telock v0.80利用了自己分析kernel32.dll来导出函数,无法脱
23:49脱下ezip v1.0,仿真了SetFilePointer函数,修正了neg指令在标志位影响上的bug
5月20号
00:49脱下hmimys-packer v1.0, so easy!
1:24脱下jdprotect v0.9b, so easy! 仿真lstrcmp
16:44脱了lamecrypt,脱法跟ezip一样
19:11脱了UPolyX v0.51,脱法基本跟UPX一样
19:41脱StealthPE 1.01
21:01脱StealthPE 2.2
22:57脱depack
23:17脱涛涛压缩器(跟kbys一样)
5月21号
20:22脱了polyene 0.01
21:21脱了DragonArmour
21:44脱EP Protector v0.3,只是入口点混淆了下
23:09脱BeRoEXEPacker
00:01脱PackItBitch
5月23号
23:27脱了木马彩衣,这个只是个入口点篡改工具
5月26号
01:43优化反汇编模块完成
17:57优化CPU寻址系统完成
6月2号
01:24完成了PEID的功能(壳的准确快速识别),并修正了upx,aspack的脱壳方法,使之向壳识别不精确度靠拢,
即一种壳要尽量少的脱壳函数,这是因为壳识别到版本的不精确性决定的
6月5号
00:14当壳在脱壳过程中不动态导入IAT时,但壳用在脱壳中破坏函数名等信息,导致无法重建导入表,这里
写了个在脱壳前全备份导入表的模块,这样bjfnt系列壳导入表就完全没有问题了
6月6号
00:10,写了petite1.3导入表的情况处理模块,这个壳在脱壳过程中没有动态导入函数,而且复制了IAT供解壳后程序
用,写了针对这种情况的导入表重建模块
6月9号
17:25完成所有目前能脱壳的全自动化脱壳,从脱识别到调用对应函数脱壳,全自动化(这几天天气贼热,困)
15:36脱了mkfpack,很简单的一个压缩壳
6月11号
21:41脱下anti007 v2.5,仿真了加载系统dll功能,支持自己分析dll导出函数,这样一大批壳又可以被脱了
21:40脱下anti007 v2.6,LoadLibraryA("bqo.dll")敏感
6月12号
00:49脱下upack v3.5,仿真kernel32.dll基地自动发掘技术(通过EDX)
22:14脱下yzpack v1.1,仿真了另一种kernel32.dll基址自动发掘技术(通过TEB),修正pe load的函数导入bug
22:57脱下yzpack v1.2,仿真了cmovcc系列指令
23:20脱下yzpack v2.0beta, so easy!
23:47脱下spack_method1 v1.1, so easy!
6月13号
20:53脱下spack_method2 v1.1,用了int2e来反调试
21:19脱下spack_method1 v1.2,spack_method2 v1.2
21:22脱下spack_method1 v1.21,spack_method2 v1.21
21:29脱下spack v1.0
23:02脱下仙剑1001,脱法跟yc1.2一样
23:10脱下仙剑1000,脱法跟yc1.2一样
23:19脱下仙剑看雪测试版,脱法跟yc1.2一样
6月14号
00:36脱下仙剑1003,脱法跟yc1.2一样,仿真_lopen,这个壳在开始的时候用pf=1来跳,写了jpe解析函数,估计以后出问题在这里,要仿真PF?
22:03脱下xpal4(仙剑-旧的回忆4)
23:46脱下仙剑-凄凉雪,MD,它居然对每个API效验了前8个字节是否被0xcc
6月15号
00:39脱下仙剑-望海潮,它用lock cmpxchg8b eax来触发异常,这个指令是不能操作寄存器的
22:25处理了petite v2.2导入表加密,加密了,这样这个壳脱后可以运行了,hoho
6月16号
01:27处理了petite v2.3,这个壳脱后可以运行了
12:48脱下telock v0.80
12:49脱下telock v0.85,性质跟telock v0.80一样
15:07脱下telock v.90,性质跟telock v0.80一样,但是IAT加密方式已经不同了,加入对这个的处理代码
6月17号
00:55脱下telock v.92,仿真了用调试寄存器触发单步异常,MD,这个壳太强悍了
11:35脱下telock v.95,性质跟telock v.92一样,但是IAT加密方式不同,很强悍啊,写了用虚拟机执行IAT加密函数发掘API代码
11:49脱下telock v.96,性质跟telock v.95一样
11:57脱下telock v.98,性质跟telock v.95一样
17:34脱下telock v.99,性质跟telock v.95一样,不过先前版本CRC效验只从文件中读数据,这个壳还从load后程序中效验了,MD,导入模块时
我把dll名称改成小写了,MD,导致CRC效验不过,调得我要摇摇欲坠了
6月18号
00:56脱下mslrh0.31,MD,到处都是rdtsc,还有oep steal code,还原了被偷代码
20:42脱下mslrh0.32,MD,脱到了抽OEP处,被抽代码比较复杂,没有还原,dump后程序可以运行
20:55脱下[G!X]'s Protect(貌似mslrh0.2)
6月19号
23:47完成更严格的堆栈效验,完成编译器识别功能