xiaohang99 发表于 2017-7-19 09:03

Safengine Shielden 2.3.8.0 脱壳 ∷之∷ 修复IAT

本帖最后由 xiaohang99 于 2017-7-26 11:42 编辑

Safengine Shielden 2.3.8.0(以下称SE)对IAT的破坏还算彻底,虽然对原程序的IAT做了完整的保存,但是保护后的程序是不会调用那里的API地址的,所以原IAT其实是废掉的。

   


         所以在尝试修复SE的IAT时,直接在IAT下断点并没有任何作用。
依据我的研究,SE对API的调用机制是:先映射几个常用的系统DLL到自己分配的内存区域,然后逐个搜索查询需要的shadow API,获取他们的地址。
保存shadow API或者真实 API 的地址到壳段已经被设定好的调用位置,壳程序会通过预先构造好的代码对其进行调用,这种构造好的代码我称之为Fack_API_Entry。
处理所有原程序中对API的调用,使其以E8 call 的方式,通过调用构造好的Fack_API_Entry来实现调用API。

(注:1、这里的 API 地址 和 Fack_API_Entry 是一一对应的,有多少API 地址 就有多少Fack_API_Entry。         2、API 地址是被离散的存储在壳段中的。)

我的思路
         通过阅读L4Nce对于修复SE 2.2.6.0IAT的脚本,我觉得部分内容依然适用于新版面的SE。就是执行到OEP,CODE段被完全解压后,通过搜索call se_data代码,找到可能的API调用位置,将EIP改到call的位置,然后执行call的代码,定位所要找的API。
         但在旧版本中,读取API地址的代码段是唯一的,所以可以通过逆向分析找到关键位置,并下断点,通过脚本对断点拦截处edi的值的读取来获得API地址。而在新版本中,读取API地址的代码不是唯一的,可以说有多少API就有多少段代码,使得L4Nce的脚本在新版本中已经完全不可行。
         我的思路是用类似于找OEP的方式,通过堆栈平衡的方法找到接近Fack_API_Entry出口的位置,然后通过脚本控制单步执行寻找真实被调用的API。
         这种方法最大的缺陷是没有办法处理很大量的VM或者混淆代码。万幸的是,SE中的Fack_API_Entry出口处并不存在大量的VM或者混淆。至于原因,SE作者nooby大神是这么解释的:


So what we need to do is:1. Dump the unpacked target2. Fix its import function calls / rebuild IATIn most cases the target will not contain any shell SDK calls or have many VMed code which do require a running shell, so that's all it takes to unpack the target.Talking about import protections, if you find it difficult to understand, I suggest that you pick ONE specific program like calc.exe or notepad.exe and try to protect it.Soon you will figure out that there is not many ways to do that, you can:1. Use random locations for each function address2. Replace call instructions and retrieve API during runtimeAnd that pretty much covers every different methods you can see in many protectors.For #1, if you found it hard or inefficient to scan entire code section and locate all those locations, you should analyze the shell code and find the part that retrieves & fills API addresses. Make a log or something like what I did in my previous IAT fix scripts.For #2, you will need to scan the code section and identify these calls, then make a run trace to each of them, discover their corresponding API addresses. This is most likely what you will see in SE scripts.You may ask, is it really that simple like ... Yes! Keep in mind that any additional code adding to a simple call will have significant performance impact on the program, so there cannot be many tricks, even the code must be simple. For case #1, the address filling process can loop many thousand times, for case #2, think of a typical message loop. So you won't see any heavy VM there, have a cup of tea and find proper ways to handle them.Why is unpacking all about IAT fixing? Because IAT is the only thing a protector can do with "blind" targets. Unless you are dealing with a protector designed for the sole purpose of protecting that one single program, or it can't just randomly pick some places and insert extra code there. Some protectors feature resource anti dump and stuff, but that either depends on API hooking or resource tree manipulation. Considering there is usually not many resources in UnpackMEs, you can always find & dump them manually.
基本的意思就是,由于API调用,特别是某些常用API的调用每分钟能被调用成千上万次,如果增加太多垃圾代码,会非常影响速度。实现过程   通过ESP定律找到程序的OEP      首先用OD加载程序,停在壳的OEP上,记录ESP的值,这里为0012FFC4         
         之后,重新载入程序,停在系统入口, 修复anti断点后,在的堆栈位置下硬件写入断点,然后F9运行,观察断下来后中的值,断下来三次之后,的值显示为00ADCD41,这里就是程序的OEP了,至于为什么认为这里是OEP,因为被写入的值总共4个,只有这个位置的代码是可执行的。
      

写脚本来执行CODE段中调用API位置的搜索
         在我们找到的OEP位置上下断点,直接运行过去,如果在虚拟机环境下调试,最好在这里保存个快照,因为后面写脚本调试脚本的时候,肯定要来回尝试N次,每次都要把前面的过anti都做一遍,既麻烦又浪费时间。      
在脚本中设定se_data壳段的开始和大小,直接用暴力搜索法搜索所有的call代码。
         当然,最好还是要生成一个ingore 表,搜索的过程中可能会遇到处理不了的API或者并不是call的代码,需要手动修复或者跳过的。



再通过ESP定律寻找真实被调用的API
       获得API在IAT中的位置       获得API的入口地址并用其和IAT中的值匹配
      修复CODE段代码
         CODE段的API调用主要有三种情况:                                             call reg                                             call ds:                                             jmp ds:

题外话:似乎Nooby大神现在把精力转到移动端的加密保护上了,PC端的壳到现在才更新到2.3.9.0,难道PC端的加密真的要没落了?

上传脚本,大家可以试一下

xiaohang99 发表于 2017-7-19 16:47

L4Nce 发表于 2017-7-19 16:25
向你们这些还在坚持研究PE壳的人致敬

L4Nce现在在研究什么啊???我已经开始转mach-o了,这个是一年前的工作笔记了{:1_918:}

xiaohang99 发表于 2017-7-19 10:18

mdzz007 发表于 2017-7-19 09:18
大哥,你搬过来也得看看图是不是挂了,防盗链啦,排版还这个样子

上传原图了,能看见吗?

ugvnui 发表于 2017-7-19 09:17

这图!这排版!~也是没谁了。。。抓紧解决防盗链图片吧。。。。。啥也看不到啊

lukemin 发表于 2017-7-19 09:18

图挂了,看不到!!

mdzz007 发表于 2017-7-19 09:18

大哥,你搬过来也得看看图是不是挂了,防盗链啦,排版还这个样子

索马里的海贼 发表于 2017-7-19 10:32

是自己分析的就厉害了,是转载的注明出处吧。

xiaohang99 发表于 2017-7-19 10:50

索马里的海贼 发表于 2017-7-19 10:32
是自己分析的就厉害了,是转载的注明出处吧。

破文首发在pediy的,都是我发的

胖子哦 发表于 2017-7-19 11:32

学习学习

520wangshun 发表于 2017-7-19 11:39

说看不到图片的人挺多   不过我看得到

gunxsword 发表于 2017-7-19 13:47

历害了,看来SE,以后也没法好好保护程序了!
页: [1] 2 3 4 5 6 7
查看完整版本: Safengine Shielden 2.3.8.0 脱壳 ∷之∷ 修复IAT