能力值:
( LV12,RANK:210 )
|
-
-
2 楼
啥都不说了。
by序号的时候hook table有点小问题。。。
|
能力值:
( LV12,RANK:210 )
|
-
-
3 楼
不知道怎么写文档。 从没写过。。
挺简单的一个壳。
1:
首先, 在最后petite追加的sfx节中, 把自己的后续处理代码, 以及原来的压缩
的节都解出来, 这里他一共用了2个算法。
0压缩 是zlib库的inflate, 应该是113版的, 因为压缩代码中可以看到这个版本号,
根据代码的对比也知道是113版的, 网上流行的是123的最新版, 所以用123的
www.zlib.net, 其实他是有点修改, 关键在于inflateblock函数中,
他没有case 1的fix table, 而是case 1是原来2的dynamic table,
所以改了一下, 另, 他是一个raw stream, 所以需要在inflateInit2调用的bitwidth中
填写-15。
1~9压缩是aplib的一种变形, 为什么这么说呢, 因为几个关键子, d00, 500, 80太熟了。
但是他有另几种比较值, 而且比aplib要简单, 但有雏形, 包括getbit以及getrepeat等
还有, 他每次src->dest的时候, 都需要xor一下当时的留下size.
算法都比较简单, 就不多说.
所以: 注定有2个stub, 所以: 需要定义2中偏移量.
2:
所有的节都解出来了后, 就构造一个异常, 跑到程序开始设置的seh去执行,
也就是第一次解出来的SMC代码. 这里, 需要修复下e8e9, 还有一个操作, 就是padding zero.
其实: 这里能知道原来的节的信息, 包括为了section align所需要的0都有,
但是我这并没优化, 因为一般样本, 这样效率不高. 除非评委改了.. 说远了.
e8e9的修复是壳经常用的手段, 因为跳的地方相对与自己的地方这个查值一般比较小.
有助于后面的压缩. 其实还包括f0这样的长跳. 代码很段. 自己看原代码吧.
再次构造一个jmp eax(eax=0)的seh, 去执行3. 同时把sfx给清楚.
把自己拷贝一点自己给原来的入口, 以给以后做变换.
3:
这里给代码进行自效验. 包括pe头的, 包括smc的. 同时需要
得到xorkey, 这个就是把smc的代码的某些字节进行一下hash,
那个fs:12, fs:2c(没记错的话), 其实就是一个0和一个1起作用. 估计是反虚拟机的..
然后不停的xor那个buf然后循环移位, 每次移动前都把自己最低位置上
这个算出来的xorkey, 跟原来的entrypoint的旁边的16个字节xor后, 这样
如果没出问题, entrypoint就是一个e9.... jmp xxxxxxxx(记错maigc x)
恢复导入表, 始终没看到重定位的信息.. 不知道他怎么敢加dll....
导入表的位置,函数名字位置跟原来没变, 只是把原来的5*4一条的导入表信息用一个4字的
firstthunk代替了.直接的dllname被拷贝到pe头去了. 因为5*4比4大嘛, 所以他敢这么放.
我这简单的把他放回去.. 0000 0000 0000 pe头的名 原来的thunk.
然后2次循环, 一次是dll的, 一次是函数的, 把函数的thunk填对就ok了。
值得注意的是name和序号是不一样的, 如果是序好, 那么不走流程x.
名字就要走流程x
流程x: 每次走的时候, 每次计数值都减1, 看是否比0大, 如果没有, 那么就hook掉这个api,
并且把hook后的地址的地方&7做下一次计数值, 计数值的初史值需要从exe中读,
可能是0,1等...
最后, 把入口magic x跟api数量进行变换.
如果hook了, 就 x = ror(x-2,3) 否则就x = ror(x-1,3)
这样能算出入口来,
修正pe头, entrypoint, imagesize, 取掉最后一个节, 然后dump就完了.
看下原代码就什么都清楚了.
这里没有idb, 所以很多东西都是凭记忆写的, 难免有失误, 见谅.
|
能力值:
(RANK:570 )
|
-
-
4 楼
第8个崩溃了
其他都可以脱,但是只有第一个脱了之后能运行
样本序号 执行结果 原始大小 解压大小
1 pass 20,480 20,480
2 fail
3 fail
4 fail
5 fail
6 fail
7 fail
8 fail
name 起始时间 结束时间 做题时间 脱壳成功文件数 解压比例 提交次数
jjnet 2007-9-2 12:00 2007-9-6 11:34 5734 1 1 2
得分13.74481446
|