吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4402|回复: 8
收起左侧

[原创] IAT劫持在加壳中的运用

[复制链接]
charryyu_ych 发表于 2017-12-25 16:11
本帖最后由 charryyu_ych 于 2017-12-25 16:21 编辑

    来吾爱有一段时间了,看过一些前辈们的文章,受益良多。今天也准备分享一点干货,以示回馈。
    关于加脱壳、PE、IAT的基本概念这里就不重复了,有需要的可以看看其他高手分析的文章。

    程序的一大特点就是具有确定性。只要两套程序在某个时间点具有相同状态,在同样的外部输入下,它们将会得到同样的运行结果。而这就是加壳脱壳的基本前提。我们知道,脱壳的基本流程是:dump、寻找oep、修复IAT(严格来说是IT)。理论上讲,在oep处脱壳后修复了IT的程序,与带壳达到oep的程序基本具有相同的状态,因而能够向后正常运行。但注意是基本相同,也就是说一旦存在一点不同,脱壳就是不彻底的,还需要做额外的修补。

    我们来仔细回顾一下脱壳的过程。假定在第n次运行带壳程序到oep时脱壳,我们将此时的程序状态命名为State[n]。以后第m次启动脱壳后的程序到达oep的状态命名为State[m]。思考:State[n]与State[m]是否都能正常运行?它们有什么区别?
        State[n]:第n次运行原始程序时在oep的程序状态,壳程序参与了初始化,一定能正常运行。
        State[m]:第n次dump的静态程序状态+第m次动态加载到达oep之后的状态,壳程序未参与初始化,可能无法正常运行。
        区别1:壳程序是否参与了oep之前的初始化。
        区别2:不同次启动时的各个dll的基地址不同。
    为什么说State[m]可能无法正常运行呢?假定其中包含的State[n]的部分静态信息是需要被动态修复的,那么它就无法运行。而这个就可以被某些高级加壳程序所利用。举个例子:
    壳程序在到达oep之前,劫持对IAT中某dll API函数dllX!API_X的jmp [RVA_IAT_DLLX_APIX]到壳程序段的私有程序funcKe。但是在funcKe中重新生成要jmp的目标地址ptrTarget。此时ptrTarget1= [RVA_IAT_DLLX_APIX] 。在此时简单脱壳的话, jmp [RVA_IAT_DLLX_APIX] 将永远被保持为被劫持状态,并且指向固定的虚拟地址ptrTarget1。脱壳之后,当重新运行时,dllX的基地址发生了变化,由于壳程序不再参与初始化,原来的ptrTarget1不再有效了。当程序调用 dllX!API_X时,就会进入funcKe,然后使用未修复的ptrTarget1,程序崩溃......


    我第一次遇到这个case是在手动为某流行游戏脱壳的时候发现的。出于商业忌讳,名字我就不说了,但是我相信懂的人有共鸣。当我脱壳后运行游戏时直接crash,起初还怀疑是否脱壳的过程操作不当。后来调试一下脱壳后的程序,发现部分jmp [RVA_IAT]被劫持到了壳程序段才恍然大悟。那段壳程序由几百行混淆汇编代码构成,当时为了确定问题,不得不从最后一行反向阅读汇编代码,分析栈数据的来源。壳程序的一种典型做法是:
        原始IAT中转 jmp [RVA_IAT]----->call funcKe
        funcKe:
        address           call address+1
        address+1       pop eax           //利用栈上的ret拿到了call eip+1这句代码所处的虚拟地址address
         .........
        address+x       sub eax,n        //经过中间运算得到API地址
                               push eax         //将API地址放到栈顶
                               ret                   //利用ret指令实现对API的调用。
     

    领会了这个要领之后,对抗思路也就很清晰了。先按照常规流程进行脱壳,脱壳之后再进行相应处理。
        处理方式1:恢复被劫持代码。将中转jmp的call funcKe恢复为jmp [RVA_IAT]或者在funcKe的首地址处理也可以。
        处理方式2:dll固定基地址技术。记住脱壳时的每个exe、dll的基地址,只要保证每次程序启动时仍然使用相同的基地址即可。本文只是讲壳相关的,该技术不在此论述。

    很高兴能与大家一起学习交流,写得不好的地方还望大家见谅,欢迎批评指正。

免费评分

参与人数 2吾爱币 +8 热心值 +2 收起 理由
Sound + 7 + 1 已答复!
朱朱你堕落了 + 1 + 1 来点实例说明更好。

查看全部评分

本帖被以下淘专辑推荐:

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

Poner 发表于 2017-12-25 16:53
转载的嘛?貌似看过有一模一样的
 楼主| charryyu_ych 发表于 2017-12-25 18:41
Poner 发表于 2017-12-25 16:53
转载的嘛?貌似看过有一模一样的

在看雪上发过,自己亲手写的。
newchange452pj 发表于 2017-12-25 23:15
whatdos 发表于 2017-12-26 11:03
谢谢分享
Sound 发表于 2017-12-26 14:14
不错 通俗易懂
 楼主| charryyu_ych 发表于 2017-12-26 17:51
谢谢大家的支持。
补充一下,大多数情况下脱壳后就可以进行静态分析,但仍需要动态调试的配合,因此需要让它能正常运行。如果为了方便,修复少数几个IAT劫持就可以让程序跑起来了。这是因为一般而言,部分主要的dll加载地址基本都是在固定位置的。但是要注意一点:kernel32.dll、user32.dll、gdi32.dll等主要的dll跟系统的启动有关。因此如果要偷懒,就尽量完成分析之后再重启电脑。否则你会发现有一大堆的kernel32 API需要修复,到那时比起修复的工作量,还不如重新脱壳。
xiaohong 发表于 2018-1-20 08:28
谢谢分享
欧琪茵 发表于 2018-2-7 13:16
谢谢分享!
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

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

GMT+8, 2024-4-28 10:36

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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