吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 6658|回复: 23
收起左侧

[原创] 脱壳之简单加密壳

  [复制链接]
Nattevak 发表于 2021-12-22 18:38
本帖最后由 Nattevak 于 2021-12-22 19:29 编辑

一、简单分析与解密
脱壳最重要的三步:找原始OEP,转存文件,修复文件
压缩壳按照这三步就可以完成脱壳,而加密壳因为对PE文件的信息进行了加密处理,找到OEP只是刚开始,还需要将加密之后的代码、数据进行还原才能够完成脱壳
注:遇到未知壳最通用的办法还是单步跟踪,将程序载入OD,到达OEP

1.找OEP
先看代码段,查看IAT调用的opcode, 是FF15还是FF25, FF15就是VS程序,FF25就是宝蓝
公司的程序。

1.1

1.1


再看链接器版本,6.0,可以确定是VC6.0

1.2

1.2


所以调试程序,设置api断点GetVersion和GetSystemTimeAsFileTime,等断到主模块调用时栈回溯,找到OEP

1.3

1.3

1.4

1.4


往上找一下就能找到OEP

1.5

1.5


2.进入CALL简单分析一下,一堆花指令,简单NOP大法一下

2.1

2.1

2.2

2.2


由于JMP都是往下跳,没有跳到其他地方,这部分的代码都是向下运行,故将JMP都NOP掉,化简代码部分

2.3

2.3


最终化简代码
[Asm] 纯文本查看 复制代码
032B000A    B8 5B00E260     MOV EAX,0x60E2005B    ;加密的值
032B0012    35 15151515     XOR EAX,0x15151515     ;还原IAT函数
032B001A    50              PUSH EAX              ;将函数压入堆栈
032B001F    C3              RETN                  ;返回真正的IAT函数

3.因为此处的IAT都已经加密了,所以我们需要进行解密
选中地址并在数据窗口中跟随

3.1

3.1



因为此处IAT是动态的获取一个地址再填充进去的,所以我们下一个硬件写入断点

3.2

3.2


程序断下,我们发现有一个eax赋值给[edi]的操作,查看一下eax和edi

3.3

3.3

3.4

3.4


分析上段代码,发现并没有对EAX的操作,都是对EAX指向内容的操作,所以EAX应该来源于VirtualAlloc的返回值

3.5

3.5


再向上分析,找到了GetProcAddress

3.6

3.6


4.解密IAT
①NOP很多代码,保留未知操作部分与填充IAT部分即可

4.1

4.1

[Asm] 纯文本查看 复制代码
004385B9    FF15 CC924300   CALL DWORD PTR DS:[0x4392CC]
004385BF    90              NOP
004385C0    90              NOP
004385C1    90              NOP
004385C2    90              NOP
004385C3    90              NOP
004385C4    90              NOP
004385C5    90              NOP
004385C6    90              NOP
004385C7    90              NOP
004385C8    90              NOP
004385C9    90              NOP
004385CA    90              NOP
004385CB    90              NOP
004385CC    90              NOP
004385CD    90              NOP
004385CE    90              NOP
004385CF    90              NOP
004385D0    90              NOP
004385D1    90              NOP
004385D2    90              NOP
004385D3    90              NOP
004385D4    90              NOP
004385D5    90              NOP
004385D6    90              NOP
004385D7    90              NOP
004385D8    90              NOP                                      ; 拷贝16字节到xmm0
004385D9    90              NOP
004385DA    90              NOP
004385DB    90              NOP
004385DC    90              NOP
004385DD    8B55 CC         MOV EDX,DWORD PTR SS:[EBP-0x34]
004385E0    90              NOP                                      ; 填充16个字节到[eax]
004385E1    90              NOP
004385E2    90              NOP
004385E3    90              NOP
004385E4    90              NOP                                      ; 拷贝16字节到xmm0
004385E5    90              NOP
004385E6    90              NOP
004385E7    90              NOP
004385E8    90              NOP
004385E9    90              NOP                                      ; 填充16个字节到[eax+0x10]
004385EA    90              NOP
004385EB    90              NOP
004385EC    90              NOP
004385ED    90              NOP
004385EE    8907            MOV DWORD PTR DS:[EDI],EAX               ; 填充IAT

②NOP异或部分,直接填充IAT

4.2

4.2

[Asm] 纯文本查看 复制代码
修改
004385C8      8907        MOV DWORD PTR DS:[EDI],EAX
004385CA      90          NOP
004385CB      90          NOP
004385CC      90          NOP
修改
004385EE      90          NOP                                      ; 填充IAT
004385EF      90          NOP

③手工填充IAT
在获取IAT和填充IAT的位置分别下断点

4.3

4.3


程序运行之后,手工将未加密的IAT复制到加密填充的位置

4.4

4.4

4.5

4.5

4.6

4.6


成功手工修复一个地址

4.7

4.7


④使用通用脚本修复IAT,原理与③相同

4.8

4.8

[Asm] 纯文本查看 复制代码
// 1.定义变量
MOV dwOEP,00409486
MOV dwGetAPI,004385BF
MOV dwWriteIAT,004385F0 

// 2. 清除环境
BC    // 清除所有软件断点
BPHWC // 清除所有硬件断点
BPMC  // 清除内存断点

// 3. 设置断点
BPHWS dwOEP, "x" //当执行到此地址时产生中断.
BPHWS dwGetAPI, "x" //当执行到此地址时产生中断.
BPHWS dwWriteIAT, "x" //当执行到此地址时产生中断.

// 4. 循环
LOOP0:
  RUN // F9  
  CMP dwGetAPI,eip  
  JNZ CASE1  
  MOV dwTMP,eax
  JMP LOOP0
CASE1:
  CMP dwWriteIAT,eip    
  JNZ CASE2
  MOV [edi],dwTMP
  JMP LOOP0
CASE2:
  CMP dwOEP,eip  
  JNZ LOOP0  
  MSG "已到达OEP"

脚本运行完成后务必ESC一下!!

⑤使用特定脚本修复IAT,原理与②相同

附

[Asm] 纯文本查看 复制代码
// 1.定义变量
MOV dwOEP,00409486
MOV dwPatch1,004385C8 
MOV dwPatch2,004385EE 

// 2. 清除环境
BC    // 清除所有软件断点
BPHWC // 清除所有硬件断点
BPMC  // 清除内存断点

// 3. 设置断点
BPHWS dwOEP, "x" //当执行到此地址时产生中断.
BPHWS dwPatch1, "x" //当执行到此地址时产生中断.

// 4. 循环
LOOP0:
  RUN // F9  
  CMP dwPatch1,eip  
  JNZ CASE1  
  FILL dwPatch1,5,90           //NOP 5个字节    
  ASM dwPatch1,"MOV DWORD PTR DS:[EDI],EAX" //将当前指令修改为 MOV DWORD PTR DS:[EDI],EAX
  FILL dwPatch2,2,90    
  BPHWC dwPatch1
  JMP LOOP0
CASE1:
  CMP dwOEP,eip  
  JNZ LOOP0  
  MSG "OEP已到达"

5.DUMP完成脱壳

5.1

5.1



二.单步跟踪分析
先回到程序入口点,看第一个CALL,00438456处调用了004383A0,观察发现并没有入栈操作,故没有参数,而调用完后,返回值EAX没有被使用,可知这个CALL没有参数也没有返回值,所以这个CALL在C语言中的函数原型应为void fun(void),进入这个CALL,大致查看其功能,发现有对FS寄存器的操作代码

二.1

二.1

二.2

二.2


访问FS寄存器一般是访问线程TEB以及PEB结构体,再加上获取kernel32基址的话需要访问PEB结构体中的模块链表。继续向下分析,发现有函数名称的字符串注释,包括LoadLibraryA、GetModuleHandleA、VirtualProyect等函数名,再查看调用call和全局变量的值,发现均为0,所以当执行到访问全局变量和调用时已经初始化了。

二.3

二.3


所以可以推测出此函数就是初始化函数地址的函数
单步步过483A0这个CALL,查看CALL内的全局变量,观察初始化后的值,可以看到初始化了一些函数地址

二.4

二.4


在438040地址内存中存放的是400000,即映像基址

二.5

二.5


在438044地址内存中存放的是1000,即代码RVA

二.6

二.6


继续向下分析,发现两处VirtualProtect的调用,观察两处调用的参数

二.7

二.7


第一处VirtualProtect修改的地址是401000,即代码段基址,修改的属性为可读可写可执行,故猜测下面会有写入代码的操作,而第二次VirtualProtect调用之前,只有CALL 438290 ,猜测其中有修改代码段的代码

二.8

二.8


先查看一下代码段代码

二 .9

二 .9


单步步过这个CALL,发现代码段被修改了,恢复为正常代码

二.10

二.10


故猜测这个CALL内部应该是执行了解密代码段的操作,回车进去简单分析一下
可以很明显的发现与0x15的异或操作,故此处CALL的功能就是解密代码段

二.11

二.11


继续分析第二处VirtualProtect,修改的属性为可读可执行,故此处是恢复代码段的内存属性

二.12

二.12


再向下分析,是信息框的弹出以及对信息框返回值的判断,发现CALL 4384E0再信息框确定之后才会执行源程序代码

二.13

二.13


在MessageBoxA下面的代码,除了条件判断就是一个CALL一个JMP,还是退出进程的函数,而且本程序的映像基址是400000,不需要重定位,剩下的只有修复IAT了
而CALL后面的JMP多半就是跳转到原始OEP的,看一下JMP的地址,为409486,查看409486,一看就知道是VC6.0或者易语言的程序入口

二.14

二.14

二.15

二.15


再查看一下这个地址所在的区段,是第一个区段,基本上就能确定是原始OEP

二.16

二.16


后面就仍是对IAT的分析了,上文已写出分析过程,故不再赘述。

加密IAT的大致逻辑:
       1.在局部变量中保存了一段shellcode代码
       2.使用GetProcAddress获取函数地址,加密处理,保存到局部变量中
       3.申请内存,将局部变量准备好的代码拷贝到申请的内存中
       4.将申请内存的首地址填充到IAT
破解加密IAT的方法就是将未加密的函数地址填充到IAT即可


免费评分

参与人数 6威望 +1 吾爱币 +25 热心值 +4 收起 理由
Hmily + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
Caesar + 1 我很赞同!
18053317345 + 1 我很赞同!
邓振振 + 1 + 1 用心讨论,共获提升!
ywlYWL + 1 + 1 秀儿,是你吗?
Vardven + 1 + 1 热心回复!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

邓振振 发表于 2021-12-22 20:19
本帖最后由 邓振振 于 2021-12-22 20:29 编辑

大佬,你好。下载了坛子的The Enigma Protector

主要搞.net的,写了个winform。用The Enigma Protector 加密了,大佬有兴趣帮忙看看The Enigma Protector 这个软件的加壳强度怎么样吗

「WindowsFormsTest.exe」 链接:https://www.aliyundrive.com/s/yBaHRuVM7Ba
邓振振 发表于 2021-12-22 20:54
落红护花 发表于 2021-12-22 20:44
enigma秒破,dump就行

感谢,我想问一下你知道有没有支持.net core加密的软件,加密后的可以在linux运行。准备买dnguard旗舰版,但是加密的程序只能在win上运行。找了好久没找到适合的。
du2009 发表于 2021-12-22 20:24
落红护花 发表于 2021-12-22 20:44
邓振振 发表于 2021-12-22 20:19
大佬,你好。下载了坛子的The Enigma Protector

主要搞.net的,写了个winform。用The Enigma Protector ...

enigma秒破,dump就行
落红护花 发表于 2021-12-22 21:29
邓振振 发表于 2021-12-22 20:54
感谢,我想问一下你知道有没有支持.net core加密的软件,加密后的可以在linux运行。准备买dnguard旗舰版 ...

winlicense试试,忘了是不是有Linux支持,我一直用的是这个
落红护花 发表于 2021-12-22 21:32
邓振振 发表于 2021-12-22 20:54
感谢,我想问一下你知道有没有支持.net core加密的软件,加密后的可以在linux运行。准备买dnguard旗舰版 ...

还有那个dnguard只有一年服务吧
DreamMaker 发表于 2021-12-22 23:20
学习了,谢谢分享。
17798 发表于 2021-12-22 23:23
小白看不懂系列
icjhao 发表于 2021-12-23 06:33
很专业,收藏起来慢慢学习
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-12-23 19:19

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表