Kill Safengine Shadow Dll(附源码)

                                        Kill Safengine Shadow Dll(OD插件)

 

/**************************************
/* 作者:半斤八兩
/* 博客:http://cnblogs.com/bjblcracked
/* 日期:2013-06-21  01:01
/**************************************

 

只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!

 

  端午回来在宿舍无聊上网,有一网友问se的shadow怎么绕过.之前就想研究的,正好刚放假回来无聊,就下载了个最新版 2.2.0.0 版本的加了一个壳看看 :)

 

0x1. 分析如何下断?

0x2. 分析如何shadow system function?

0x3. 分析为何要alloc memory 2次, 多此一举?

0x4. 分析用哪种方法处理shadow最好?

 

 

 

0x1. 分析如何下断?

  得第一次分析SE的时候,无论怎样下断都下不下来.后面就下到了可能是shadow了.于是就想到一个最麻烦,但又最管用的方法,搜索特征码. 比如函数 User32.MessageBoxA 就把Msg头部,的特征码复制下来,到OD的内存窗口里面去搜索.这样就能下断了.虽然方法很管用.但是,如果我们要下的断点很多的话,那样就会显得相当麻烦.下面我们来分析看看她是如何shadow的.

 

加壳时 [反内联API挂钩] 勾上即可 :)

 

0x2. 分析如何shadow system function?

  规则,首先OD载入.然后我们想一下,他shadow 无非就是重载 或者重写.我们先以作者是重载的思路来分析看看:)

重载常规的手段大概就两种. 

 

1. 1种是读取system32 下的 DLL.

2. 另一种就是读取已加载的模块内存.

 

我们先试试第1种,读取 system32 的DLL,那么我们首先就是想到了 file 的那几个操作函数.

Createfile readfile. 等.

这里可能有的同学会问了,我们本身就是处理shadow的. 那file的这几个操作函数会不会是也已经shadow了?

答案是 还没有. 因为我们刚OD载入.他的程序还没来的及处理呢.所以 file 操作的这几个函数,他还是用的原始的系统函数.这点大家可以放心.

 

下面我们先对 createfilea/w readfile 下断. F9运行.

 

断下回显:

 

1 0012F604   0049C938  /CALL to CreateFileW from Shadow.0049C936
2 0012F608   0012FC54  |FileName = "C:\Windows\System32\ntdll.dll"
3 0012F60C   80000000  |Access = GENERIC_READ
4 0012F610   00000001  |ShareMode = FILE_SHARE_READ
5 0012F614   00000000  |pSecurity = NULL
6 0012F618   00000003  |Mode = OPEN_EXISTING
7 0012F61C   00000080  |Attributes = NORMAL
8 0012F620   00000000  \hTemplateFile = NULL

 

 

 

(为了方便,我们就以user32.messagebox 为例子讲解.)

 

Createfilew 断下来了,第一个参数显示

"C:\Windows\System32\ntdll.dll"

我们不管它,继续 F9 运行.

 

断下回显:

 

1 0012FC28   00465FA9  /CALL to CreateFileW
2 0012FC2C   0012FC54  |FileName = "C:\Windows\System32\ntdll.dll"
3 0012FC30   80000000  |Access = GENERIC_READ
4 0012FC34   00000001  |ShareMode = FILE_SHARE_READ
5 0012FC38   00000000  |pSecurity = NULL
6 0012FC3C   00000003  |Mode = OPEN_EXISTING
7 0012FC40   00000080  |Attributes = NORMAL
8 0012FC44   00000000  \hTemplateFile = NULL

 

 

 

 

我们看见SE调用两次.先不管它,继续运行.

 

断下回显:

 

1 0012FC30   00465FC7  /CALL to ReadFile from Shadow.00465FC2
2 0012FC34   000000A4  |hFile = 000000A4 (window)
3 0012FC38   01480020  |Buffer = 01480020
4 0012FC3C   0013AD40  |BytesToRead = 13AD40 (1289536.)
5 0012FC40   0012FE5C  |pBytesRead = 0012FE5C
6 0012FC44   00000000  \pOverlapped = NULL

 

 

 

 

Readfile 断下来了,第三个参数是 文件大小我们去系统文件夹下看一下 user32.dll 有多大.?

 

User32 大小

792 KB (811,520 字节)

 

现在断下来的大小 13AD40 (1289536.) ntdll.dll .我们不用管它.继续运行.

直到是 user32的大小的时候,才停下.

 

在经过读取了 ntdll.dll kernelbase.dll kernel32.dll ,现在终于在user32.dll 下断下来了.

 

断下回显:

1 0012FBE8   0182D53F  /CALL to ReadFile from 0182D53A
2 0012FBEC   000000A4  |hFile = 000000A4 (window)
3 0012FBF0   01370020  |Buffer = 01370020
4 0012FBF4   000C6200  |BytesToRead = C6200 (811520.)
5 0012FBF8   0012FE5C  |pBytesRead = 0012FE5C
6 0012FBFC   00000000  \pOverlapped = NULL

 

 

 

 

我们让他把文件读取出来,我们在 retn 0x14 处下 F2 断点. F9运行.

我们能看到user32.dll 已经读取出来了.

 

断下回显:

 

 1 013C0020  4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00  MZ?........
 2 013C0030  B8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00  ?......@.......
 3 013C0040  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
 4 013C0050  00 00 00 00 00 00 00 00 00 00 00 00 F0 00 00 00  ............?..
 5 013C0060  0E 1F BA 0E 00 B4 09 CD 21 B8 01 4C CD 21 54 68  
 6 013C0070  69 73 20 70 72 6F 67 72 61 6D 20 63 61 6E 6E 6F  is program canno
 7 013C0080  74 20 62 65 20 72 75 6E 20 69 6E 20 44 4F 53 20  t be run in DOS
 8 013C0090  6D 6F 64 65 2E 0D 0D 0A 24 00 00 00 00 00 00 00  mode....$.......
 9 013C00A0  2E 8D 3F 12 6A EC 51 41 6A EC 51 41 6A EC 51 41  .?j霶Aj霶Aj霶A
10 013C00B0  63 94 D5 41 6B EC 51 41 6A EC 50 41 35 ED 51 41  c斦Ak霶Aj霵A5鞶A
11 013C00C0  63 94 C2 41 6D EC 51 41 63 94 C3 41 6B EC 51 41  c斅Am霶Ac斆Ak霶A
12 013C00D0  63 94 C4 41 6D EC 51 41 63 94 D2 41 17 EC 51 41  c斈Am霶Ac斠A霶A
13 013C00E0  63 94 C5 41 6B EC 51 41 63 94 C0 41 6B EC 51 41  c斉Ak霶Ac斃Ak霶A
14 013C00F0  52 69 63 68 6A EC 51 41 00 00 00 00 00 00 00 00  Richj霶A........
15 013C0100  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
16 013C0110  50 45 00 00 4C 01 04 00 2F DB 5B 4A 00 00 00 00  PE..L./踇J....
17 013C0120  00 00 00 00 E0 00 02 21 0B 01 09 00 00 78 06 00  ....?!
18 013C0130  00 E6 05 00 00 00 00 00 C9 F7 01 00 00 10 00 00  .?.....慎....

 

 

 

 

我们还用0x1 的方法,现在来定位mesageboxa 的地方定位到后,

我们在命令窗口处输入da  回车. (汇编格式显示数据再下个F2断点.然后F9跑起来.

我们点demo上的 messagebox 按钮 .

 

特征码:

1 user32.MessageBoxA:
2 8BFF558BEC??????????????742464A1180000006A00FF7024??????????????????????85C0750A????????????????????6A00FF7514FF7510FF750CFF7508??????????5DC21000

 

 

 

刚按F9运行,OD就弹了一个类似如下的提示:

Unable to read memory of debugged process (0141DE94..0141DE97).

 

这是因为我们刚刚下的断点,已经不见了.为何不见了?

这不是SE的反调试,也不是OD出问题了.而是我们刚刚下断点的那块内存已经free掉了.

 

所以,这证实了,这一次读取的内存,还只是一个 shadow. 那么真正的实现函数在哪里?

还有,现在读取出来的已经是shadow 的函数了.他为何又要free ?

 

 

0x3. 分析为何要alloc memory 2次, 多此一举?

  分析几次,我们可以发现一个规律.第一次readfile 的数据.imagebase是固定不变的

但是rva 始终固定不变,而且同user32.dll 的导出函数的 rva 保持一致.

但是程序真正跑起来后的数据的 imagebase 和  rva 都是变化的 动态的

 

我个人理解的是作者这样做,就是为了让imagebase and rva 动态让用户更难下断.

 

知道了这些,那么我们只人对第一次readfile 的数据做处理至于第二次,他并没有readfile. 而是 new 了一内存,把第一次readfile 的数据拷贝进去但是这些我们都不用管它是怎么处理的呢.

因为我们只要处理他第一次shadow 数据,即可因为第一次的数据虽然会free.但是他后面真正跑起来的shadow 是完全原封不动的拷贝第一次的shadow 数据.所以...你懂的...

 

0x4. 分析用哪种方法处理shadow最好?

  信大家都知道 jmp xxx 的处理方法.我们只要在每个函数首部写上 jmp xxxx 这样即可.

但是这样就会有一个问题了.什么问题?

因为我们分析知道 rva 是固定的,但是imagebase 是动态的我们如何 jmp xxx?

jmp xxx 的算法是 target- current- 5 ,但是我们当前的 imagebase 是动态的

所以 jmp xxx 想法就泡汤了.

 

X86 除了jcc这类直接式的转移指令,还有许多其他有意思的”间接”转移指令.

如 push xxx /retn . 我们用这条指令,就可以解决 动态 imagebase 的问题因为 push xxxx 不用考虑重定位.所以 我们只要打开每个函数的入口,都写上 push xxxx / retn 就可恢复 se  的 shadow了 :)

 

最后来个处女之作--OD插件图 -_-~

 

  具体的实现细节,我在文章中就不说了,大家看码吧~

 

此插件是本人的第一个处女作.之前没有写过OD插件写了之后才发现OD的插件接口真是非常丰富.写起来毫无压力.但是在处理combobox 消息时,花了80%的时间 太久没有玩SDK 都不会写了 :(

 

本插件仅支持win7. Xp 上有些不同,此版本插件没有处理.

另外听朋友说有的OD使用此插件无效,但是朋友说换了个OD就能用了.具体原因我还没有时间看.~

 

源码 插件 文档 下载地址:

http://bbs.pediy.com/showthread.php?t=174005

转载于:https://www.cnblogs.com/BjblCracked/p/3148488.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
 Safengine的代码分析引擎将在保护应用程序时提供完整的分析,从而对应用程序进行系统化的保护,将您的原始代码移动和变形,并且加入无数垃圾代码和反调试、跟踪代码。   Safengine处理的范围是整个程序,而不是程序里的某一个过程。所以,即使您的关键代码在保护后未经变形,也需要耗费破解者很长的时间才能找到,而往往只是一行两行代码,穿插在数以万计的垃圾代码中,是极其隐蔽和猥琐的。   Safengine的代码虚拟机在同类产品中最稳定、最完善,整体运行架构线程安全,不会改变系统对受保护代码的线程的调度。虚拟处理器采用了逻辑门级的指令拆分,使用与非和加法两个基础运算指令实现了大部分复杂的x86指令,并且使用了随机的虚拟寄存器参与运算,极大程度提高了代码保护的安全性。   在同类的软件保护壳中,Safengine提供了最完整的解决方案,集代码加密、虚拟化、授权于一体,并且每一项功能都可圈可点。   Safengine支持多种类型的文件格式:   所有32位PE文件,包括:   ● Win32 可执行文件 (*.exe);   ● Windows 屏幕保护程序 (*.scr);   ● 动态链接库 (*.dll);   ● 32位 ActiveX 控件 (*.ocx);   ● 32位驱动程序 (*.sys); 编辑本段代码虚拟化   Safengine提供强大的代码虚拟机保护您的程序免受逆向工程和非法修改。将您的关键代码(x86汇编形式)转换成一个新的随机指令集,只有在嵌入您程序中的虚拟机解释器才能运行。这些虚拟机代码是随机生成的,并且经过高度混淆,确保唯一性。   在虚拟化过程中,您原始代码的执行流程将被重定向,并加入逻辑混淆。虚拟后的代码将用与非(NAND)实现所有的逻辑操作,大部分数学运算也将用加法实现,使得逆向者很难分辨原始指令的功能。此外,最容易被修改并绕过的条件跳转也将被转换成虚拟机的运算代码,从而使破解者无法改变程序走向。   代码虚拟化分三步:   首先,您的代码将被完整分析,以处理器执行的方式分析分支、外部数据参考、空余寄存器、栈桢以及对EFLAGS寄存器的修改。   然后,根据分析的结果,生成一个只包含必要指令的随机指令集表,通过多态代码生成引擎生成与之对应的x86实现代码。   最后,将根据随机指令集表,结合虚拟机内部混淆、常数加密、自效验等功能,生成最终的虚拟机字节码,模拟原始代码的功能。   Safengine的虚拟机的体积可控,兼容各种运行环境,支持保护包括内核驱动在内的任意32位PE文件。 编辑本段运行时保护   传统的软件保护工具将应用程序加密存放并在执行时解密,但在原程序解密后,保护代码与程序没有关联。这类保护可以通过抓取解密后的程序内存轻松的绕过。   Safengine提供了运行时保护,并与您的程序链接在一起,使得您的程序无法离开保护代码正常运行。保护代码将动态检查您的程序内存是否被修改,如果发现修改将立即中止程序运行。同时还会实时监视系统环境,及时检测调试破解工具。 编辑本段软件授权   Safengine提供内置的授权系统,您无需修改任何代码,即可通过它控制您的软件授权。您可以通过限制运行时间、使用次数、过期日期、机器码绑定等等授权限制来控制软件试用。 Safengine使用强加密算法保证授权模块的安全,如果没有您提供的合法授权,破解这需要数年时间穷举您的软件的解密密钥。 编辑本段网络授权   在Safengine Licensor的基础上,我们推出了基于网络的授权验证平台:   Safengine NetLicensor   它由三部分组成:   ● Safengine Code Protection 软件代码保护(代码变形、虚拟化)   ● Safengine Licensor本地授权认证系统   ● Safengine NetLicensor网络授权验证   受Safengine NetLicensor保护的应用程序,在启动时会连接NetLicensor服务器,验证授权的有效性,授权限制将以服务器时间为准,确保软件试用时间的准确可控。   Safengine NetLicensor解决了几个软件授权中的难题:   1.合法授权被恶意泄露   2.客户刻意修改系统时间   3.多人共享同一个授权   4.需要即时即刻吊销授权   Safengine NetLicensor采用了广泛使用的MySQL作为数据库后台,可以轻松整合到现有的服务器系统中,NetLicensor服务端采用了高效稳定的IOCP网络层架构,并在Safengine系列产品的网络验证系统中得到了充分的测试。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值