求助 把一文件脱壳

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了求助 把一文件脱壳相关的知识,希望对你有一定的参考价值。

匿名提取文件连接 http://pickup.mofile.com/7257419383802528
或登录Mofile,使用提取码 7257419383802528 提取文件

扩展冰城_.rar 154K

软件和工具用了N多.还是研究不明白

脱完后请打包 EMAIL 至 dandan7610@vip.hl.cn

查收完毕送积分.绝对
能下吧? 我刚传上去啊

加QQ也可以.急啊 QQ:7210258

步骤1 检测壳

壳的概念:
所谓“壳”就是专门压缩的工具。
这里的压缩并不是我们平时使用的RAR、ZIP这些工具的压缩,壳的压缩指的是针对exe、com、和dll等程序文件进行压缩,在程序中加入一段如同保护层的代码,使原程序文件代码失去本来面目,从而保护程序不被非法修改和反编译,这段如同保护层的代码,与自然界动植物的壳在功能上有很多相似的地方,所以我们就形象地称之为程序的壳。

壳的作用:
1.保护程序不被非法修改和反编译。
2.对程序专门进行压缩,以减小文件大小,方便传播和储存。

壳和压缩软件的压缩的区别是
压缩软件只能够压缩程序
而经过壳压缩后的exe、com和dll等程序文件可以跟正常的程序一样运行

下面来介绍一个检测壳的软件
PEID v0.92
这个软件可以检测出 450种壳
新版中增加病毒扫描功能,是目前各类查壳工具中,性能最强的。
另外还可识别出EXE文件是用什么语言编写的VC++、Delphi、VB或Delphi等。
支持文件夹批量扫描

我们用PEID对easymail.exe进行扫描
找到壳的类型了
UPX 0.89.6 - 1.02 / 1.05 - 1.24 -> Markus & Laszlo
说明是UPX的壳
下面进行

步骤2 脱壳
对一个加了壳的程序,去除其中无关的干扰信息和保护限制,把他的壳脱去,解除伪装,还原软件本来的面目。这个过程就叫做脱壳。
脱壳成功的标志
脱壳后的文件正常运行,功能没有损耗。
还有一般脱壳后的文件长度都会大于原文件的长度。
即使同一个文件,采用不同的脱壳软件进行脱壳,由于脱壳软件的机理不通,脱出来的文件大小也不尽相同。

关于脱壳有手动脱壳和自动脱壳
自动脱壳就是用专门的脱壳机脱 很简单 按几下就 OK了
手动脱壳相对自动脱壳 需要的技术含量微高 这里不多说了

UPX是一种很老而且强大的壳 不过它的脱壳机随处就能找到
UPX本身程序就可以通过
UPX 文件名 -d
来解压缩 不过这些需要的 命令符中输入
优点方便快捷 缺点DOS界面
为了让大家省去麻烦的操作 就产生了一种叫 UPX SHELL的外壳软件

UPX SHELL v3.09
UPX 外壳程序!
目的让UPX的脱壳加壳傻瓜化

注:如果程序没有加壳 那么我们就可以省去第二步的脱壳了,直接对软件进行分析了。

脱完后 我们进行

步骤3
运行程序
尝试注册
获取注册相关信息

通过尝试注册 我们发现一个关键的字符串

“序列号输入错误”

步骤4
反汇编

反汇编一般用到的软件 都是 W32Dasm
W32dasm对于新手 易于上手 操作简单
W32Dasm有很多版本 这里我推荐使用 W32Dasm 无极版

我们现在反汇编WebEasyMail的程序文件easymail.exe

然后看看能不能找到刚才的字符串

步骤5
通过eXeScope这个软件来查看未能在w32dasm中正确显示的字符串信息

eXeScope v6.50
更改字体,更改菜单,更改对话框的排列,重写可执行文件的资源,包括(EXE,DLL,OCX)等。是方便强大的汉化工具,可以直接修改用 VC++ 及 DELPHI 编制的程序的资源,包括菜单、对话框、字符串表等
新版可以直接查看 加壳文件的资源

我们打开eXeScope
找到如下字串符

122,"序列号输入错误 "
123,"恭喜您成为WebEasyMail正式用户中的一员! "
124,注册成功
125,失败

重点是122

步骤6
再次返回 w32dasm

* Possible Reference to String Resource ID=00122: "?鲹e?"

但是双击后
提示说找不到这个字串符
不是没有 是因为 "?鲹e?"是乱码 w32dasm对于中文显示不是太好
毕竟不是国产软件

先把今天会用到的汇编基本指令跟大家解释一下

mov a,b ;把b的值赋给a,使a=b
call :调用子程序 ,子程序以ret结为
ret :返回主程序
je或jz :若相等则跳转
jne或jnz :若不相等则跳转
push xx:xx 压栈
pop xx:xx 出栈

栈,就是那些由编译器在需要的时候分配,在不需要的时候自动清楚的变量的存储区。里面的变量通常是局部变量、函数参数等。

我们搜索
Possible Reference to String Resource ID=00122
因为对E文支持很好
我们来到了

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00406F17(C) //跳转来自 406F17
|

* Possible Reference to String Resource ID=00125: "1%"
|
:004070DD 6A7D push 0000007D
:004070DF 8D4C2410 lea ecx, dword ptr [esp+10]
:004070E3 E8F75A1200 call 0052CBDF

* Possible Reference to String Resource ID=00122: "?鲹e?"
|
:004070E8 6A7A push 0000007A
:004070EA 8D4C2408 lea ecx, dword ptr [esp+08]
:004070EE E8EC5A1200 call 0052CBDF

我们来到

:00406F01 8B876C080000 mov eax, dword ptr [edi+0000086C]这里是对
:00406F07 8B4C2408 mov ecx, dword ptr [esp+08]
:00406F0B 50 push eax//这两个eax和ecx入栈就比较让我们怀疑了
:00406F0C 51 push ecx//产生注册码
:00406F0D E8AE381100 call 0051A7C0//这CALL里对注册位应该会有设置
:00406F12 83C40C add esp, 0000000C
:00406F15 85C0 test eax, eax// 检测注册位
:00406F17 0F85C0010000 jne 004070DD //不存在注册位 就会跳到4070DD就会出现那个错误的字串符了

我们记住406F01这个地址

接着进行下一步

步骤7
这一步我们进行的是调试

用到的软件是ollydbg

好了我们找到了 注册码0012AF04 00FD4A10 ASCII "04893e058f9c1c9fb16764c3b86f78e6"

但是这个并不是我们的主要目的

我们还要做出属于自己的注册机

相信这个是很多人梦寐以求的事情

步骤8
制作注册机

注册机我们需要的是一个KEYMAKE的软件
因为2.0是演示版而且停止更新了
所以我们用1.73版

做一个内存注册机 需要下面几个资料

中断地址:406F0C
中断次数:1
第一字节:51
指令长度:1

好了 一个完美的注册机 就产生了
还不赶快发给你的朋友 炫耀一下
保证让他迷糊死 佩服得你要死
其实最后还有几个步骤
就是撰写破文
不过大家都是新手 这个步骤 就去了吧

不知不觉说了这么多废话 希望能对大家有些作用
如果有什么不懂 不理解的事情 请联系我 或者到论坛发贴
QQ:9595859
MSN:kcarhc@163.com
今天的课程就到这里 大家赶快去动手实践吧~!

--------------------------------------------------------------------------------

-- 作者:admin
-- 发布时间:2005-10-11 11:13:00

-- 实战查壳脱壳制作破解注册机最详细的教程

大家好,我是kcarhc
今天8月1日了 刚从医院回来 正好凌晨
这期的课程做晚了 这里给大家道个歉
8月1日 如果我没记错
是建军节
既然是建军节 也要象征性的弄些东西来
为了建军节 这期我选择打击黑暗势力--黑社会

那么今天的主题就是
-----------
迎接建军节,铲除黑社会
-----------
首先介绍软件

黑社会2.0
[功能简介]:
1 五大必备功能
远程屏幕; 完全控制; 文件传送; Telnet; 远程关机
2 提供IP反弹定位功能
可以通过静态IP动态域名,网页文件的方式反弹通知IP.
3 集成vidc客户端
内网的朋友想用自动上线功能,可以实现了
4 本软件集成了常用攻击工具(如OpenTelnet OpenTftp等)
通过IPC拷贝,而且带有标准的拷贝进度,全球首次面世;
opentelnet就不介绍了,相信大家都知道;
opentftp为本软件独创,可以远程开启tftp服务;
5 本软件集成的极速端口扫描器(扫描速度世界领先)
最开始我用的扫描器是大名鼎鼎的SuperScan3.0,感觉速度很慢;
后来改用SSPort1.0 扫描速度有了明显的提高.
经过速度对比,本软件扫描速度比SSPort快 1/3 ,是SuperScan的N倍!!!
我的机器是 赛扬700+256M内存,一般扫描速度为180台/秒;
一些号称可以达到1000台/秒的扫描器在本机上试验只有120台/秒.
--------------------
准备工作:

安装黑社会
--------------------
步骤一 查壳

Peid v0.92
ASPack 2.12 -> Alexey Solodovnikov、
--------------------
步骤二 脱壳

手动脱壳

快速脱掉ASPACK所有版本的方法

的OEP关键点在下面

0048D3AF 61 POPAD
0048D3B0 75 08 JNZ SHORT 黑社会.0048D3BA
0048D3B2 B8 01000000 MOV EAX,1
0048D3B7 C2 0C00 RETN 0C//402c4a
0048D3BA 68 00000000 PUSH 0

402ca4就是我们要找的OEP

自动脱壳

AspackDie v1.41

这是一个小小的 PE 文件解压缩器 (EXE, DLL, ...) 她可以解压缩
自 Aspack 2000 以后的任何 Aspack 版本. 包括:

- Aspack 2000
- Aspack 2001
- Aspack 2.1
- Aspack 2.11
- Aspack 2.11c/d
- Aspack 2.12
- Aspack 2.12a/b
- 一些未知的版本

-------------------
步骤三 试运行程序 发现突破点

看到关键字符串
“注册码错误!”
-------------------
步骤四 W32DASM 寻找突破点

用w32dasm载入已经脱壳的程序
字符串察看
未发现 字符串 而是发现一堆乱码
大家于是一定想到了第一节的办法

用EXESCOPE
-------------------
步骤四 察找 字符串

打开eXeScope 并载入 但是发现 都没有字符串
这项
为啥呢?大家一定会疑问
一般用eXeScope查不到
我们将开始
-------------------
步骤五 查询软件的编译类型

Peid v0.92
Microsoft Visual Basic 5.0 / 6.0
--------------------
步骤六 采用GetVBRes v0.51 对付VB程序

GetVBRes v0.51 一个非常好的VB汉化工具

对于VB程序 我们用专门汉化用的GetVBRes v0.51来对付它
也许有人不理解 为啥用汉化工具呢
其实eXeScope也属于汉化工具
GetVBRes载入黑社会
发现没有乱码了
看到的全是完整的字符
我们找到了
注册码错误!
这个字符串
接着为了能搞到程序关键点地址
我们把“注册码错误!”
改成111111
为啥改成111111因为111111111
保存修改
---------------------
步骤六 用W32Dasm载入修改后的文件
发现字符串中有111111
那个就是我们修改的 原来是“注册码错误!”

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004792EF(C)
|
:00479474 B904000280 mov ecx, 80020004
:00479479 B80A000000 mov eax, 0000000A
:0047947E 894D9C mov dword ptr [ebp-64], ecx
:00479481 894DAC mov dword ptr [ebp-54], ecx
:00479484 894DBC mov dword ptr [ebp-44], ecx
:00479487 8D5584 lea edx, dword ptr [ebp-7C]
:0047948A 8D4DC4 lea ecx, dword ptr [ebp-3C]
:0047948D 894594 mov dword ptr [ebp-6C], eax
:00479490 8945A4 mov dword ptr [ebp-5C], eax
:00479493 8945B4 mov dword ptr [ebp-4C], eax

* Possible StringData Ref from Code Obj ->"1111111" //刚才我们看到的注册吗错误的哦
|
:00479496 C7458C98194100 mov [ebp-74], 00411998
:0047949D C7458408000000 mov [ebp-7C], 00000008

发现跳转来自到4792EF
安照习惯 我们来到4792EF后 接着向前看
看到一个跳到这里的那个地址
这里是40928C

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00479278(C)
|
:0047928C 8B55E4 mov edx, dword ptr [ebp-1C]

* Reference T MSVBVM60.__vbaStrMove, Ord:0000h
|
:0047928F 8B3578124000 mov esi, dword ptr [00401278]
:00479295 8D4DE0 lea ecx, dword ptr [ebp-20]
:00479298 895DE4 mov dword ptr [ebp-1C], ebx
:0047929B FFD6 call esi
:0047929D 8B4DE8 mov ecx, dword ptr [ebp-18]
:004792A0 6A01 push 00000001
:004792A2 8D55E0 lea edx, dword ptr [ebp-20]
:004792A5 51 push ecx
:004792A6 52 push edx
:004792A7 E8440F0000 call 0047A1F0
:004792AC 8BD0 mov edx, eax
:004792AE 8D4DDC lea ecx, dword ptr [ebp-24]
:004792B1 FFD6 call esi
:004792B3 50 push eax
:004792B4 53 push ebx

* Reference T MSVBVM60.__vbaInStr, Ord:0000h
|
:004792B5 FF15E8114000 Call dword ptr [004011E8]
:004792BB 8BF0 mov esi, eax
:004792BD 8D45E8 lea eax, dword ptr [ebp-18]
:004792C0 F7DE neg esi
:004792C2 8D4DDC lea ecx, dword ptr [ebp-24]
:004792C5 50 push eax
:004792C6 1BF6 sbb esi, esi
:004792C8 8D55E0 lea edx, dword ptr [ebp-20]
:004792CB 51 push ecx
:004792CC 52 push edx
:004792CD F7DE neg esi
:004792CF 6A03 push 00000003
:004792D1 F7DE neg esi

* Reference T MSVBVM60.__vbaFreeStrList, Ord:0000h
|
:004792D3 FF150C124000 Call dword ptr [0040120C]
:004792D9 8D45D4 lea eax, dword ptr [ebp-2C]
:004792DC 8D4DD8 lea ecx, dword ptr [ebp-28]
:004792DF 50 push eax
:004792E0 51 push ecx
:004792E1 6A02 push 00000002

* Reference T MSVBVM60.__vbaFreeObjList, Ord:0000h
|
:004792E3 FF1548104000 Call dword ptr [00401048]
:004792E9 83C41C add esp, 0000001C
:004792EC 663BF3 cmp si, bx
:004792EF 0F847F010000 je 00479474

我们在
004792AC看到下面这些
EAX=0015A47C, (UNICODE "1000464401458371268751252821609291844811465000")
EDX=00000000

怀疑EAX为的
1000464401458371268751252821609291844811465000
为注册码
------------------
步骤七 用不确定正确的注册 尝试注册


1000464401458371268751252821609291844811465000
这个注册后
我们发现 注册成功
------------------
步骤八 制做注册机

Keymake v1.73

中断地址:4792AC
中断次数:1
第一字节:8B
指令长度:2
------------------
步骤九 发布注册机

找一个网站比如黑基或者你的朋友之间
------------------
步骤十 休息

黑社会终于干掉了
现在去找你的男朋友或者女朋友
老公或者老婆
找个地方聊聊天 放松放松
告诉他们 你刚刚把黑社会 摆平了
一定很有趣的
------------------
课程结束
------------------
有事情大家可以去论坛
不过你如果性子急
或者嫌我回复的速度慢
我建议你直接联系我
只要我在 基本可以马上给你解答
不在可以留言
我的两个联系方式
QQ:9595859
MSN:kcarhc@163.com
最后 说一个事
我的女朋友最近生病了
所以才导致这期的课程 这么晚才做出来
希望大家能理解我
我还希望大家能祝福她早日康复
不然的话
你们见到我的日子可能会少了
甚至可能会消失在你们眼前
好了不说了 今天就是到此OVER吧
---------- kcarhc
2004年8月1日 凌晨 沈阳

--------------------------------------------------------------------------------

-- 作者:admin
-- 发布时间:2005-10-11 16:42:00

-- 使用OllyDbg快速脱壳

作者:KU-凌 
目标:采用ASPACK、UPX加壳的NOTEPAD.EXE
工具:OllyDbg 1.09英文版、DUMP插件、PEditor
系统:Win98SE
关键词: 脱壳、OllyDbg、OD、DUMP、PUSHAD、POPAD

预备知识
  大多数壳都有一个共同的特点。在壳准备开始解压时都要执行PUSHAD,当壳解压
完时都要调用POPAD。到底PUSHAD和POPAD是什么干什么用的呢?其实PUSHAD是用来将
所有普通寄存器顺序进栈的指令,POPAD是所有普通寄存器顺序出栈指令。POPAD的出
栈顺序和PUSHAD相反。壳为了保护寄存器,便在解压前将所有寄存器进栈保护起来,
当解压完成后又将寄存器出栈,恢复其原貌,并将IP设置为原程序的OEP。这样我们就可以通过这个特点快速脱掉多种软件的壳。

ASPACK篇
  先用ASPACK将NOTEPAD.EXE加壳。用OllyDbg(以下简称OD)载入。看见光标停在
壳的入口处。
0040D001 > 60       PUSHAD ;壳的入口。准备开始解压,保护寄存器
0040D002  E8 03000000  CALL  NOTEPAD.0040D00A
……
我们不管它,直接向下翻页找POPAD指令。在40D3AF处找到POPAD
……
0040D3AF  61       POPAD ;解压完成,恢复寄存器
0040D3B0  75 08     JNZ  SHORT NOTEPAD.0040D3BA
0040D3B2  B8 01000000  MOV  EAX, 1
0040D3B7  C2 0C00    RETN  0C
0040D3BA  68 CC104000  PUSH  NOTEPAD.004010CC ;返回到原程序OEP处
0040D3BF  C3       RETN
……
选定40D3AF这一行,F4运行到此处。在这里说明壳已经完成解压工作。并且返回到原
程序的入口处。F8单步到4010CC,这里便是原程序的OEP。用DUMP插件直接DUMP出来就可以了(在DUMP时注意将入口点改为10CC,即4010CC-400000=10CC,400000是映象基地址)。文件大小是77059字节,用PEditor重建PE头便可以了。未压缩的文件大小是53248字节,脱壳后的文件大小是60930字节。

UPX篇
  用UPX将NOTEPAD.EXE加壳,然后用OD载入。停在PUSHAD处,用脱ASPACK同样的方
法,向下翻页找POPAD。
……
0040E9FE  61       POPAD
0040E9FF - E9 C826FFFF  JMP  NOTEPAD.004010CC
……
下面的JMP就是跳转到程序的OEP处。F4到40E9FF处,F8单步一下,来到OEP处,DUMP出来。DUMP文件的大小是65536字节,直接就可以运行。为了完美,用PEditor重建PE头。那么脱壳后的文件大小是60293字节。

后记
  用上面说的方法,很多种壳都可以快速的手动脱掉。如果你没有OD的DUMP插件,
可以到新论坛的下载区找。如果实在没有,也可以直接停在OEP处用PEDump来DUMP。很久没有写东西了。这一篇是写给初学者练手的。其实壳也是软件,再怎么复杂都有可能被脱下来。祝你好运。
  另外,转载时请保持本文的完整。

--------------------------------------------------------------------------------

-- 作者:admin
-- 发布时间:2005-10-11 17:10:00

-- 用Ollydbg手脱EncryptPE V1.2003.5.18加壳的DLL

有兄弟让看看EncryptPE加壳的DLL,我说新版的就不行了,搞不定的。后来看是EncryptPE V1.2003.5.18旧版加壳的,应该用的是老王老师发布的免费版。呵呵,所以脱了一下,顺便记录过程。
大家可以自己用EncryptPE V1.2003.5.18免费版加个EdrLib.dll看看。

—————————————————————————————————
一、避开IAT加密

设置Ollydbg忽略所有的异常选项。用IsDebug 1.4插件去掉Ollydbg的调试器标志。
添加“同时忽略0EEDFADE、C0000008、009B25C、00953D74”异常。

代码:--------------------------------------------------------------------------------
00877000 60 pushad//进入OD后停在这
00877001 9C pushfd
00877002 64:FF35 00000000 push dword ptr fs:[0]
00877009 E8 79010000 call EdrLib.00877187
--------------------------------------------------------------------------------

下断:BP IsDebuggerPresent 断下后取消断点
现在我们Ctrl+G:711A0000
为何用这个地址?因为V12003518.EPE是相同的。呵呵,钻了个旧版的空子。

其实可以再BP GetProcAddress,根据返回地址来判断。如果返回地址是711XXXXX,说明这是V12003518.EPE的调用,就可以取消断点Ctrl+F9返回了。具体情况以堆栈的返回地址为准。

现在Ctrl+S 在“整个区段”搜索命令序列:

代码:--------------------------------------------------------------------------------
mov eax,edi
mov edx,dword ptr ss:[ebp-8]
mov dword ptr ds:[eax],edx
xor eax,eax
--------------------------------------------------------------------------------

找到在711A339F处,我们在711A339F处下个 硬件执行 断点。
现在我们关闭Ollydbg,重新载入这个dll,直接Shift+F9运行,中断在711A339F处

代码:--------------------------------------------------------------------------------
711A339F 8BC7 mov eax,edi
711A33A1 8B55 F8 mov edx,dword ptr ss:[ebp-8]
//改为: mov edx,dword ptr ss:[ebp-4] ★ 正确函数写入
711A33A4 8910 mov dword ptr ds:[eax],edx
711A33A6 33C0 xor eax,eax
711A33A8 5A pop edx
711A33A9 59 pop ecx
711A33AA 59 pop ecx
711A33AB 64:8910 mov dword ptr fs:[eax],edx
711A33AE EB 0A jmp short V1200351.711A33BA
--------------------------------------------------------------------------------

把711A33A1处修改好之后,取消以前下的711A339F处的断点。
再Ctrl+S搜索命令序列:

代码:--------------------------------------------------------------------------------
add ebx,4
mov eax,dword ptr ss:[ebp-4C]
add eax,4
--------------------------------------------------------------------------------

找到在711A43C2处,我们在下面xor eax,eax的711A4401下断。Shift+F9运行

代码:--------------------------------------------------------------------------------
711A43C2 83C3 04 add ebx,4
711A43C5 8B45 B4 mov eax,dword ptr ss:[ebp-4C]
711A43C8 83C0 04 add eax,4
711A43CB 8945 B4 mov dword ptr ss:[ebp-4C],eax
711A43CE 8B03 mov eax,dword ptr ds:[ebx]
711A43D0 85C0 test eax,eax
711A43D2 0F87 39FDFFFF ja V1200351.711A4111
711A43D8 A1 74C71B71 mov eax,dword ptr ds:[711BC774]
711A43DD 8038 00 cmp byte ptr ds:[eax],0
711A43E0 75 1F jnz short V1200351.711A4401
711A43E2 8B45 C4 mov eax,dword ptr ss:[ebp-3C]
711A43E5 83C0 14 add eax,14
711A43E8 8945 C4 mov dword ptr ss:[ebp-3C],eax
711A43EB 8B45 C4 mov eax,dword ptr ss:[ebp-3C]
711A43EE 8378 0C 00 cmp dword ptr ds:[eax+C],0
711A43F2 76 0D jbe short V1200351.711A4401
711A43F4 8B45 C4 mov eax,dword ptr ss:[ebp-3C]
711A43F7 8378 10 00 cmp dword ptr ds:[eax+10],0
711A43FB 0F87 38FCFFFF ja V1200351.711A4039//循环处理IAT
711A4401 33C0 xor eax,eax//此处下断! ★
--------------------------------------------------------------------------------

当我们中断在711A4401处时IAT已经处理完毕,此时就可以用ImportREC得到正确的输入表了。
因为EncryptPE后面有自校验,所以我们返回711A33A1处,点右键->撤销选择,恢复原来的代码。

—————————————————————————————————
二、得到重定位表信息、获得OEP

Ctrl+S 在“整个区段”搜索命令序列:

代码:--------------------------------------------------------------------------------
mov edx,dword ptr ss:[ebp-24]
sub edx,dword ptr ds:[eax+34]
mov
参考技术A 加壳和脱壳,简单说就是软件的加密和解密!

最早提出“壳”这个概念的,据我所知,应该是当年推出脱壳软件 RCOPY 3 的作者熊焰先生。在几年前的 DOS 时代,“壳”一般都是指磁盘加密软件的段加密程序,可能是那时侯的加密软件还刚起步不久吧,所以大多数的加密软件(加壳软件)所生成的“成品”在“壳”和需要加密的程序之间总有一条比较明显的“分界线”。有经验的人可以在跟踪软件的运行以后找出这条分界线来,至于这样有什么用这个问题,就不用我多说了。但毕竟在当时,甚至现在这样的人也不是很多,所以当 RCOPY3 这个可以很容易就找出“分界线”,并可以方便的去掉“壳”的软件推出以后,立即就受到了很多人的注意。老实说,这个我当年在《电脑》杂志看到广告,在广州电脑城看到标着999元的软件,在当时来说,的确是有很多全新的构思,单内存生成 EXE 可执行文件这项,就应该是世界首创了。但它的思路在程序的表现上我认为还有很多可以改进的地方(虽然后来出现了可以加强其功力的 RO97),这个想法也在后来和作者的面谈中得到了证实。在这以后,同类型的软件想雨后春笋一般冒出来,记得住名字的就有: UNKEY、MSCOPY、UNALL .... 等等,但很多的软件都把磁盘解密当成了主攻方向,忽略了其它方面,当然这也为以后的“密界克星”“解密机器”等软件打下了基础,这另外的分支就不多祥谈了,相信机龄大一点的朋友都应该看过当时的广告了。

解密(脱壳)技术的进步促进、推动了当时的加密(加壳)技术的发展。LOCK95和 BITLOK 等所谓的“壳中带籽”加密程序纷纷出笼,真是各出奇谋,把小小的软盘也折腾的够辛苦的了。正在国内的加壳软件和脱壳软件较量得正火红的时候,国外的“壳”类软件早已经发展到像 LZEXE 之类的压缩壳了。这类软件说穿了其实就是一个标准的加壳软件,它把 EXE 文件压缩了以后,再在文件上加上一层在软件被执行的时候自动把文件解压缩的“壳”来达到压缩 EXE 文件的目的。接着,这类软件也越来越多, PKEXE、AINEXE、UCEXE 和后来被很多人认识的 WWPACK 都属于这类软件,但奇怪的是,当时我看不到一个国产的同类软件。

过了一段时间,可能是国外淘汰了磁盘加密转向使用软件序列号的加密方法吧,保护 EXE 文件不被动态跟踪和静态反编译就显得非常重要了。所以专门实现这样功能的加壳程序便诞生了。 MESS 、CRACKSTOP、HACKSTOP、TRAP、UPS 等等都是比较有名气的本类软件代表,当然,还有到现在还是数一数二的,由台湾同胞所写的 FSE 。其实以我的观点来看,这样的软件才能算是正宗的加壳软件。

在以上这些加壳软件的不断升级较劲中,很多软件都把比较“极端”技术用了上去,因为在这个时候 DOS 已经可以说是给众高手们玩弄在股掌之间了,什么保护模式、反 SICE 、逆指令等等。相对来说,在那段时间里发表的很多国外脱壳程序,根本就不能对付这么多的加壳大军,什么 UPC、TEU 等等都纷纷成为必防的对象,成绩比较理想的就只有 CUP386 了,反观国内,这段时间里也没了这方面的“矛盾斗争”。加壳软件门挥军直捣各处要岗重地,直到在我国遇到了 TR 这个铜墙铁壁以后,才纷纷败下阵来各谋对策,但这已经是一年多以后的事情了。我常想,如果 TR 能早两年“出生”的话,成就肯定比现在大得多,甚至盖过 SICE 也有可能。TR 发表的时候 WIN95 的流行已经成为事实,DOS 还有多少的空间,大家心里都清楚。但话又说回来, TR 的确是个好软件,比起当年的 RCOPY3 有过之而无不及,同时也证明了我们中国的 CRACK 实力(虽然有点过时)。这个时候,前面提到过的 FSE 凭着强劲的实力也渐渐的浮出了水面,独领风骚。其时已经是 1997 年年底了,我也走完了学生“旅程”。工作后在CFIDO 的 CRACK 区认识了 Ding-Boy ,不久 CRACK 区关了,我从此迷上了 INTERNET,并于98年6月建起了一个专门介绍“壳”的站台: http://topage.126.com ;;,放上了我所收集的所有“壳”类软件。在这段时间里,各种“壳”类软件也在不段的升级换代,但都没什么太大的进展,差不多就是 TR 和众加壳软件的版本数字之争而已。
1998年8月,一个名为 UNSEC (揭秘)的脱壳软件发表了,它号称可以脱掉98年8月以前发表的所有壳。我测试之后,觉得并没传闻中的那么厉害,特别是兼容性更是令我不想再碰它。 Ding-Boy 给这个软件的作者提了很多建议,但寄去的 EMIAL 有如泥牛入海,可能是一怒之下吧,不久 Ding-Boy 的 BW (冲击波)就诞生了。这个使用内存一次定位生成 EXE 文件(后来放弃了)的脱壳软件,在我的站台公开后,得到了很多朋友们的肯定。要知道,从RCOPY 3 开始,绝大部分的脱壳软件都是要两次运行目标程序来确定 EXE 的重定位数据的。BW 的这一特点虽然有兼容性的问题,但也树立了自己的风格、特色。经过几个月的改善, BW 升级到了 2.0 版本,这个版本的推出可以说是 BW 的转折点,因为它已经是一个成熟、稳定脱壳软件了,它可以对付当时(现在)大多数的壳,包括当时最新的 FSE 0.6 等。更重要的是这个版本把选择壳的和软件“分界线”这个最令新手头疼的步骤简化到不能再简化的地步,使更多的朋友接受了它。另外,能加强 BW 功力的 CI 模式也是其它脱壳软件没有的东西。最近,BW 发表了最新的 2.5 BETA2 版本,增强了一些方面的功能,因它竟然可以脱掉号称最厉害的磁盘加密工具 LOCKKING 2.0 的加密壳,因而进一步奠定了它在“脱壳界”的地位。说到最新,就不能不提 GTR、LTR、EDUMP、ADUMP、UPS、UPX、APACK 这几个国外的好软件了,它们每个都有自己的特色,可以说都是当今各类“壳”中的最新代表了。(这些软件和详细介绍请到我的主页查阅)

由于 WINDOWS 3.1 只是基于 DOS 下的一个图形外壳,所以在这个平台下的“壳”类软件很少,见过的就只有像 PACKWIN 等几个有限的压缩工具,终难成气候。

可能是 MICROSOFT 保留了 WIN95 的很多技术上的秘密吧,所以即便是 WIN95 已经推出了 3 年多的时间,也没见过在其上面运行的“壳”类软件。直到 98 年的中期,这样的软件才迟迟的出现,而这个时候 WIN98 也发表了有一段日子了。应该是有 DOS 下的经验吧,这类的软件不发表由自可,一发表就一大批地的冲了出来。先是加壳类的软件如: BJFNT、PELOCKNT 等,它们的出现,使暴露了 3 年多的 WIN95 下的 PE 格式 EXE 文件得到了很好的保护。大家都应该知道现在很多 WIN95 下的软件都是用注册码的方法来区分、确定合法与非法用户的吧,有了这类加壳软件,这种注册方法的安全性提高了不少,如果大家也有自己编的 WIN95 程序,就一定要多留意一下本类软件了。接着出现的就是压缩软件了,因为 WIN95 下运行的 EXE 文件“体积”一般都比较大,所以它的实用价值比起 DOS 下的压缩软件要大很多,这类的软件也很多,早些时候的 VBOX、PEPACK、PETITE 和最近才发表的 ASPACK、UPX 都是其中的佼佼者。在 DOS 下很流行的压缩软件 WWPACK 的作者也推出了对应 WIN95 版本的 WWPACK32,由于性能并不是十分的突出,所以用的人也不太多。由于压缩软件其实也是间接给软件加了壳,所以用它们来处理 EXE 也是很多软件作者喜欢做的事情,最近新发表的很多软件里都可以看到这些加壳、加压缩软件的名字了。有加壳就一定会有脱壳的,在 WIN95 下当然也不例外,但由于编这类软件比编加壳软件要难得多,所以到目前为止,我认为就只有 PROCDUMP 这个软件能称为通用脱壳软件了,它可以对付现在大多数的加壳、压缩软件所加的壳,的确是一个难得的精品。其它的脱壳软件多是专门针对某某加壳软件而编,虽然针对性强、效果好,但收集麻烦,而且这样的脱壳软件也不多。前些时候 TR 作者也顺应潮流发表了 TR 的 WIN95 版本: TRW ,由现在的版本来看可以对付的壳还不多,有待改进。

BW 的作者 Ding-Boy 最新发表了一个 WIN95 的 EXE 加壳软件 DBPE 。虽然它还不太成熟,但它可以为软件加上使用日期限制这个功能是其它加壳软件所没有的,或者以后的加壳软件真的会是像他说的那样可以:加壳和压缩并重、并施;随意加使用日期;加上注册码;加软件狗(磁盘)保护;加硬件序列号判别

可以去下个暴力破解软件~~
参考技术B 恩,脱好了,给你发过去了,刚发的,你查收一下吧,别忘了给我再追加50分啊~~本回答被提问者采纳 参考技术C 汗,你这文件用来干啥子的哦 扩展冰城_.exe(貌似WG的样子)
ASProtect 2.1x SKE -> Alexey Solodovnikov
这种壳不懂哈,路过的
参考技术D 现在你的这个文件下载下来了吗?
哥们,好像没有下载的选项

Android 逆向整体加固脱壳 ( DEX 优化流程分析 | dvmDexFileOpenPartial | dexFileParse | 脱壳点 | 获取 dex 文件在内存中的首地址 )(代码片

前言


上一篇博客 【Android 逆向】整体加固脱壳 ( DEX 优化流程分析 | DexPrepare.cpp 中 dvmContinueOptimizati() 函数分析 ) 中 , 分析了 DexPrepare.cppdvmContinueOptimizati() 方法 , 在其中调用了 rewriteDex() 方法 , 重写 DEX 文件 ;

本篇博客继续分析 DexPrepare.cpprewriteDex() 方法 ;





一、DexPrepare.cpp 中 rewriteDex() 方法分析



第一个参数 u1* addr 是加载到内存中的 dex 文件的首地址 ;

第二个参数 int len 是内存中的 dex 文件的字节长度 ;

static bool rewriteDex(u1* addr, int len, bool doVerify, bool doOpt,
    DexClassLookup** ppClassLookup, DvmDex** ppDvmDex)

dvmDexFileOpenPartial 函数是 脱壳点 函数 , 通过该函数定位脱壳点 , 然后进行脱壳操作 ;

	/*
	 * 既然可以直接读取DEX文件,那么创建一个DexFile结构
	 * 为了它。
	 */
    if (dvmDexFileOpenPartial(addr, len, &pDvmDex) != 0) 
        ALOGE("Unable to create DexFile");
        goto bail;
    

DexPrepare.cpp 中 rewriteDex() 方法源码 :

/*
 * 对内存映射的DEX文件执行就地重写。
 * 
 * 如果这是从短期子进程(dexopt)调用的,我们可以
 * 疯狂地加载类和分配内存。当天气好的时候
 * 调用以准备字节数组中提供的类,我们可能需要
 * 要保守一点。
 * 
 * 如果“ppClassLookup”为非空,则为指向新分配的
 * DexClassLookup将在成功时返回。
 * 
 * 如果“ppDvmDex”为非空,则将创建新分配的DvmDex结构
 * 成功返回。
 */
static bool rewriteDex(u1* addr, int len, bool doVerify, bool doOpt,
    DexClassLookup** ppClassLookup, DvmDex** ppDvmDex)

    DexClassLookup* pClassLookup = NULL;
    u8 prepWhen, loadWhen, verifyOptWhen;
    DvmDex* pDvmDex = NULL;
    bool result = false;
    const char* msgStr = "???";

    /* 如果索引的字节顺序错误,请立即交换它 */
    if (dexSwapAndVerify(addr, len) != 0)
        goto bail;

	/*
	 * 既然可以直接读取DEX文件,那么创建一个DexFile结构
	 * 为了它。
	 */
    if (dvmDexFileOpenPartial(addr, len, &pDvmDex) != 0) 
        ALOGE("Unable to create DexFile");
        goto bail;
    

	/*
	 * 创建类查找表。这最终将被追加
	 * 直到最后。奥德克斯。
	 * 
	 * 我们从DexFile创建一个临时链接,以便
	 * 类加载,如下所示。
	 */
    pClassLookup = dexCreateClassLookup(pDvmDex->pDexFile);
    if (pClassLookup == NULL)
        goto bail;
    pDvmDex->pDexFile->pClassLookup = pClassLookup;

	/*
	 * 如果我们不打算验证或优化这些类,
	 * 加载它们没有任何价值,所以尽早退出。
	 */
    if (!doVerify && !doOpt) 
        result = true;
        goto bail;
    

    prepWhen = dvmGetRelativeTimeUsec();

	/*
	 * 加载在此DEX文件中找到的所有类。如果它们无法加载
	 * 由于某些原因,它们不会得到验证(这是应该的)。
	 */
    if (!loadAllClasses(pDvmDex))
        goto bail;
    loadWhen = dvmGetRelativeTimeUsec();

	/*
	 * 创建字节码优化器使用的数据结构。
	 * 我们需要在几个类中查找方法,因此这可能会导致
	 * 一点类加载。我们通常在VM初始化期间执行此操作,但是
	 * 对于dexopt on core。jar操作的顺序变得有点棘手,
	 * 所以我们把它推迟到这里。
	 */
    if (!dvmCreateInlineSubsTable())
        goto bail;

	/*
	 * 验证并优化DEX文件(命令行)中的所有类
	 * (如果允许的话)。
	 * 
	 * 这是最大的努力,所以dexopt真的没有办法
	 * 在这一点上失败。
	 */
    verifyAndOptimizeClasses(pDvmDex->pDexFile, doVerify, doOpt);
    verifyOptWhen = dvmGetRelativeTimeUsec();

    if (doVerify && doOpt)
        msgStr = "verify+opt";
    else if (doVerify)
        msgStr = "verify";
    else if (doOpt)
        msgStr = "opt";
    ALOGD("DexOpt: load %dms, %s %dms, %d bytes",
        (int) (loadWhen - prepWhen) / 1000,
        msgStr,
        (int) (verifyOptWhen - loadWhen) / 1000,
        gDvm.pBootLoaderAlloc->curOffset);

    result = true;

bail:
    /*
     * 成功后,归还来电者要求的物品。
     */

    if (pDvmDex != NULL) 
        /* break link between the two */
        pDvmDex->pDexFile->pClassLookup = NULL;
    

    if (ppDvmDex == NULL || !result) 
        dvmDexFileFree(pDvmDex);
     else 
        *ppDvmDex = pDvmDex;
    

    if (ppClassLookup == NULL || !result) 
        free(pClassLookup);
     else 
        *ppClassLookup = pClassLookup;
    

    return result;

源码路径 : /dalvik/vm/analysis/DexPrepare.cpp





二、DvmDex.cpp 中 dvmDexFileOpenPartial() 方法分析 ( 脱壳点 )



该函数中的 参数 const void* addr 是 dex 文件在内存中的起始地址 ;

在调用的 dexFileParse 函数中 , 也可以获取到 dex 文件在内存中的首地址 ;


DvmDex.cpp 中 dvmDexFileOpenPartial() 方法源码 :

/*
 * 为“部分”DEX创建DexFile结构。这是一个在
 * 被优化的过程。优化标头未完成
 * 我们没有任何辅助数据表,所以我们必须这样做
 * 初始化过程略有不同。
 * 
 * 错误时返回非零。
 */
int dvmDexFileOpenPartial(const void* addr, int len, DvmDex** ppDvmDex)

    DvmDex* pDvmDex;
    DexFile* pDexFile;
    int parseFlags = kDexParseDefault;
    int result = -1;

    /* -- 文件不完整,尚未计算新校验和
    if (gDvm.verifyDexChecksum)
        parseFlags |= kDexParseVerifyChecksum;
    */

    pDexFile = dexFileParse((u1*)addr, len, parseFlags);
    if (pDexFile == NULL) 
        ALOGE("DEX parse failed");
        goto bail;
    
    pDvmDex = allocateAuxStructures(pDexFile);
    if (pDvmDex == NULL) 
        dexFileFree(pDexFile);
        goto bail;
    

    pDvmDex->isMappedReadOnly = false;
    *ppDvmDex = pDvmDex;
    result = 0;

bail:
    return result;

源码路径 : /dalvik/vm/DvmDex.cpp





三、DexFile.cpp 中 dexFileParse() 方法分析 ( 脱壳点 )



/*
 * 解析优化或未优化的。存储在内存中的dex文件。这是
 * 在字节排序和结构对齐修复后调用。
 * 
 * 成功后,返回新分配的文件。
 */
DexFile* dexFileParse(const u1* data, size_t length, int flags)

    DexFile* pDexFile = NULL;
    const DexHeader* pHeader;
    const u1* magic;
    int result = -1;

    if (length < sizeof(DexHeader)) 
        ALOGE("too short to be a valid .dex");
        goto bail;      /* bad file format */
    

    pDexFile = (DexFile*) malloc(sizeof(DexFile));
    if (pDexFile == NULL)
        goto bail;      /* alloc failure */
    memset(pDexFile, 0, sizeof(DexFile));

    /*
     * Peel off the optimized header.
     */
    if (memcmp(data, DEX_OPT_MAGIC, 4) == 0) 
        magic = data;
        if (memcmp(magic+4, DEX_OPT_MAGIC_VERS, 4) != 0) 
            ALOGE("bad opt version (0x%02x %02x %02x %02x)",
                 magic[4], magic[5], magic[6], magic[7]);
            goto bail;
        

        pDexFile->pOptHeader = (const DexOptHeader*) data;
        ALOGV("Good opt header, DEX offset is %d, flags=0x%02x",
            pDexFile->pOptHeader->dexOffset, pDexFile->pOptHeader->flags);

        /* parse the optimized dex file tables */
        if (!dexParseOptData(data, length, pDexFile))
            goto bail;

        /* ignore the opt header and appended data from here on out */
        data += pDexFile->pOptHeader->dexOffset;
        length -= pDexFile->pOptHeader->dexOffset;
        if (pDexFile->pOptHeader->dexLength > length) 
            ALOGE("File truncated? stored len=%d, rem len=%d",
                pDexFile->pOptHeader->dexLength, (int) length);
            goto bail;
        
        length = pDexFile->pOptHeader->dexLength;
    

    dexFileSetupBasicPointers(pDexFile, data);
    pHeader = pDexFile->pHeader;

    if (!dexHasValidMagic(pHeader)) 
        goto bail;
    

	/*
	 * 验证校验和。这相当快,但确实需要
	 * 触摸DEX文件中的每个字节。基本校验和在
	 * 字节交换和索引优化。
	 */
    if (flags & kDexParseVerifyChecksum) 
        u4 adler = dexComputeChecksum(pHeader);
        if (adler != pHeader->checksum) 
            ALOGE("ERROR: bad checksum (%08x vs %08x)",
                adler, pHeader->checksum);
            if (!(flags & kDexParseContinueOnError))
                goto bail;
         else 
            ALOGV("+++ adler32 checksum (%08x) verified", adler);
        

        const DexOptHeader* pOptHeader = pDexFile->pOptHeader;
        if (pOptHeader != NULL) 
            adler = dexComputeOptChecksum(pOptHeader);
            if (adler != pOptHeader->checksum) 
                ALOGE("ERROR: bad opt checksum (%08x vs %08x)",
                    adler, pOptHeader->checksum);
                if (!(flags & kDexParseContinueOnError))
                    goto bail;
             else 
                ALOGV("+++ adler32 opt checksum (%08x) verified", adler);
            
        
    

	/*
	 * 验证SHA-1摘要。(通常我们不想这样做--
	 * 摘要用于唯一标识原始DEX文件,以及
	 * 无法在索引被字节交换后计算以进行验证
	 * (并进行了优化。)
	 */
    if (kVerifySignature) 
        unsigned char sha1Digest[kSHA1DigestLen];
        const int nonSum = sizeof(pHeader->magic) + sizeof(pHeader->checksum) +
                            kSHA1DigestLen;

        dexComputeSHA1Digest(data + nonSum, length - nonSum, sha1Digest);
        if (memcmp(sha1Digest, pHeader->signature, kSHA1DigestLen) != 0) 
            char tmpBuf1[kSHA1DigestOutputLen];
            char tmpBuf2[kSHA1DigestOutputLen];
            ALOGE("ERROR: bad SHA1 digest (%s vs %s)",
                dexSHA1DigestToStr(sha1Digest, tmpBuf1),
                dexSHA1DigestToStr(pHeader->signature, tmpBuf2));
            if (!(flags & kDexParseContinueOnError))
                goto bail;
         else 
            ALOGV("+++ sha1 digest verified");
        
    

    if (pHeader->fileSize != length) 
        ALOGE("ERROR: stored file size (%d) != expected (%d)",
            (int) pHeader->fileSize, (int) length);
        if (!(flags & kDexParseContinueOnError))
            goto bail;
    

    if (pHeader->classDefsSize == 0) 
        ALOGE("ERROR: DEX file has no classes in it, failing");
        goto bail;
    

    /*
     * Success!
     */
    result = 0;

bail:
    if (result != 0 && pDexFile != NULL) 
        dexFileFree(pDexFile);
        pDexFile = NULL;
    
    return pDexFile;

源码路径 : /dalvik/libdex/DexFile.cpp

以上是关于求助 把一文件脱壳的主要内容,如果未能解决你的问题,请参考以下文章

如何对.EXE文件进行脱壳?

知道怎么给文件脱壳吗?谢谢

如何实现upx的脱壳(请详细说明步骤和软件)?

万能脱壳工具怎么用

Android 逆向ART 脱壳 ( DexClassLoader 脱壳 | exec_utils.cc 中执行 Dex 编译为 Oat 文件的 Exec 和 ExecAndReturnC函数 )(代

Android 逆向整体加固脱壳 ( DEX 优化流程分析 | dvmDexFileOpenPartial | dexFileParse | 脱壳点 | 获取 dex 文件在内存中的首地址 )(代码片