学习一下基础的软件脱壳,之后慢慢更新

upx

type

upx属于比较经典的压缩壳,支持大多数操作系统运行文件,可以使压缩过的可执行文件体积缩小50%-70% ;

文件位压缩后的运行方式便是在压缩文件的开始加入解压缩的代码,所以程序在运行完解压缩代码之后,程序的代码实际上就与压缩前一致了,而这也是我们可以手动调试脱壳的前提。

pack

先下载 upx

od 查看文件在upx 之前的内存情况,从开始处,信息比较清楚

未加壳

未加壳

命令行调用upx 给文件加壳 ./upx.exe filename.exe

再次查看文件情况,当然也可以使用IDA。

加壳

加壳

unpack

  1. upx自带脱壳命令,加个-d 就是脱壳模式
  2. 手动脱壳

文件起始有个pushad将所有寄存器的值入栈,之后从加壳后的文件起始处按f8单步往后走,发现不久后就开始了反复循环

1
2
3
4
5
6
7
8
9
10
004079D0   > /8A06          mov al,byte ptr ds:[esi]
004079D2 . |46 inc esi ; upxpacke.00407006
004079D3 . |8807 mov byte ptr ds:[edi],al
004079D5 . |47 inc edi ; upxpacke.00401002
004079D6 > |01DB add ebx,ebx
004079D8 . |75 07 jnz short upxpacke.004079E1
004079DA > |8B1E mov ebx,dword ptr ds:[esi]
004079DC . |83EE FC sub esi,-0x4
004079DF . |11DB adc ebx,ebx
004079E1 >^\72 ED jb short upxpacke.004079D0

可以看到大概意思就是在疯狂复制esi地址的数据到 edi地址处

而我们只需要找到之后的popad就可以了,所以右键->serch for->command 或直接 ctrl+F 寻找popad ,不过这里需要去掉entire block的勾选,否则会找到起始地址之前的popad,找到之后f2下断点,f9直接运行到这里

之后继续单步,一个小循环之后,跳转到一个地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
00407B66   .  61            popad
00407B67 . 8D4424 80 lea eax,dword ptr ss:[esp-0x80]
00407B6B > 6A 00 push 0x0
00407B6D . 39C4 cmp esp,eax
00407B6F .^ 75 FA jnz short upxpacke.00407B6B
00407B71 . 83EC 80 sub esp,-0x80
00407B74 .- E9 C897FFFF jmp upxpacke.00401341


00401341 E8 83040000 call upxpacke.004017C9
00401346 ^ E9 B3FDFFFF jmp upxpacke.004010FE
0040134B 8BFF mov edi,edi ; upxpacke.<ModuleEntryPoint>
0040134D 55 push ebp
0040134E 8BEC mov ebp,esp
00401350 81EC 28030000 sub esp,0x328

到达该地址后,可以看到有个call函数,此时就可以使用od 的插件OllyDump将文件脱壳,需要注意的是重建输入表一般会选择方式二,其他的可以根据情况来定,这次保持默认就可以了

ollydump

ollydump

打开输出的脱壳的文件,找到最初始的地方,发现与脱壳前一样,也就是说脱壳成功

脱壳效果

脱壳效果

aspack

type

专门针对win32程序的压缩软件,整体原理与upx差不多所以方法实际上是可以通用的。

unpack

aspack popad不容易找到,所以可以使用其他的办法来

这里可以确定0x401000是程序本身的初始位置,只是在没有解包之前,这里还无法反汇编。

我们这里使用硬件断点(硬件断点不通过0xCC/int 3h/中断程序运行并向调试器发送报告,而是通过写入DR寄存器来实现;其支持更复杂的中断,但是只能设置四个),在0x401000处设置一个硬件断点,f9运行,程序到0x401000处停止执行,此时应该已经解包完成,如果没有显示的话按ctrl+A, 使得OD重新分析代码即可