BORLAND DELPHI DLL
确实是ASPACK壳,我不放脱好的文件了,只把脱的过程简单说一下,献给初学者。DLL脱壳与EXE不同的地方就在于重定位表,而ASPACK这个压缩壳,对重定位的处理比较简,学习时容易一些。
首先用OD载入,CTRL+S,输入 push 0和retn这两条指令(这是ASPACK的特征,更多壳的资料,参考:
http://www.openrce.org/reference_library/packer_database),到来这里:
0097A3AF 61 POPAD
0097A3B0 75 08 JNZ SHORT Aspappg.0097A3BA
0097A3B2 B8 01000000 MOV EAX, 1
0097A3B7 C2 0C00 RETN 0C
0097A3BA 68 00000000 PUSH 0 ; 这里的0会被修改成程序的OEP地址
0097A3BF C3 RETN ; 这个retn就是跳向OEP的
在retn这一行F4一下,再F7,就到了程序的OEP:
00921E90 55 PUSH EBP
00921E91 8BEC MOV EBP, ESP
00921E93 83C4 C4 ADD ESP, -3C
00921E96 B8 80199200 MOV EAX, Aspappg.00921980
00921E9B E8 3053F5FF CALL Aspappg.008771D0
00921EA0 33C9 XOR ECX, ECX
00921EA2 B2 01 MOV DL, 1
00921EA4 A1 EC318E00 MOV EAX, DWORD PTR DS:[8E31EC]
00921EA9 E8 7A91F7FF CALL Aspappg.0089B028
00921EAE 8B15 0CB69300 MOV EDX, DWORD PTR DS:[93B60C] ; Aspappg.00940900
00921EB4 8902 MOV DWORD PTR DS:[EDX], EAX
00921EB6 E8 452AF5FF CALL Aspappg.00874900
观察一下:
00921E96 B8 80199200 MOV EAX, Aspappg.00921980
这条指令中就包含一个绝对地址,也就是说这里就会重定位。
我们下内存断点 hw 921e97,然后CTRL+F2重新载入程序,F9运行,程序第一次被断在了这里:
0097A170 3E:03BD 2204000>ADD EDI, DWORD PTR DS:[EBP+422]
0097A177 8BB5 52010000 MOV ESI, DWORD PTR SS:[EBP+152]
0097A17D C1F9 02 SAR ECX, 2
0097A180 F3:A5 REP MOVS DWORD PTR ES:[EDI], DWORD P>; 第一次断在这里
输入命令d 921797,看到数值是4b1980,还没有被重定位,再F9,第二次断在了这里:
0097A23E 66:8B1E MOV BX, WORD PTR DS:[ESI]
0097A241 81E3 FF0F0000 AND EBX, 0FFF
0097A247 01141F ADD DWORD PTR DS:[EDI+EBX], EDX
0097A24A EB 00 JMP SHORT Aspappg.0097A24C ; 第二次断在这里
熟悉的人一眼就看出这正是处理重定位表的地方,即使不熟悉,看一下 921797这个地址,就会发现它已经被重定位了。
这个完整的循环是这样的:
0097A209 66:8B1E MOV BX, WORD PTR DS:[ESI]
0097A20C C1EB 0C SHR EBX, 0C
0097A20F 83FB 01 CMP EBX, 1 ; 判断重定位项类型
0097A212 74 0C JE SHORT Aspappg.0097A220 ; 1是HIGH
0097A214 83FB 02 CMP EBX, 2
0097A217 74 16 JE SHORT Aspappg.0097A22F ; 2是LOW
0097A219 83FB 03 CMP EBX, 3
0097A21C 74 20 JE SHORT Aspappg.0097A23E ; 3是HIGHLOW
0097A21E EB 2C JMP SHORT Aspappg.0097A24C
0097A220 66:8B1E MOV BX, WORD PTR DS:[ESI]
0097A223 81E3 FF0F0000 AND EBX, 0FFF
0097A229 66:01041F ADD WORD PTR DS:[EDI+EBX], AX ; 这里处理HIGH
0097A22D EB 1D JMP SHORT Aspappg.0097A24C
0097A22F 66:8B1E MOV BX, WORD PTR DS:[ESI]
0097A232 81E3 FF0F0000 AND EBX, 0FFF
0097A238 66:01141F ADD WORD PTR DS:[EDI+EBX], DX ; 这里处理LOW
0097A23C EB 0E JMP SHORT Aspappg.0097A24C
0097A23E 66:8B1E MOV BX, WORD PTR DS:[ESI]
0097A241 81E3 FF0F0000 AND EBX, 0FFF
0097A247 01141F ADD DWORD PTR DS:[EDI+EBX], EDX ; 这里处理HIGHLOW
0097A24A EB 00 JMP SHORT Aspappg.0097A24C ; 第二次断在这里
0097A24C 66:830E FF OR WORD PTR DS:[ESI], 0FFFF ; 将用过的重定位表的内容抹掉
0097A250 83C6 02 ADD ESI, 2
0097A253 ^ E2 B4 LOOPD SHORT Aspappg.0097A209
0097A255 ^ EB 9A JMP SHORT Aspappg.0097A1F1
对重定位表的处理,看我注释就明白了。为了脱壳,我们要对这里进行一些处理。
先删除原来的内存断点,而在97A209处下执行断点:he 97a209,然后再一次CTRL+F2重来,F9运行,程序被断下。
断下后,删除断点,我们把代码中处理重定位三条的ADD指令全部NOP掉,并把壳用来“抹去”重定位数据的那条OR指令也NOP掉。
剩下的事就是运行到OEP,然后DUMP映像,修正重定位表目录的偏移和大小,重建输入表,就完成了。
脱壳后的DLL可以regsvr32注册成功,也可以用OD调试。