zoukankan      html  css  js  c++  java
  • 一款自制壳的脱壳

    1.进行查壳操作

    因其是自制的壳,所以用工具是查不到壳的特征码,也就查不出壳;

    2.确定重定位已分离

    如果不进行重定位分离的话,会产生随机基址,从而导致脱壳失败

    3.查找OEP

    ①使用ESP定理
    ②寻找OEP位置(OEP:47148B
    记得“右键”点击“分析”选择“删除分析”

    4.查看导入地址表IAT

    由于已经找到了OEP,而导入地址表IAT的加载在OEP后的不远处,通过单步步过,可以发现004714B1 FF15 80504700 call dword ptr ds:[0x475080]是导入地址表IAT的加载,在此处右键单击“数据窗口中跟随”选择“内存地址”
    我们可以看到其地址所存的内存地址数值在0027XXXX的位置,是一块堆空间,而正常的IAT的地址应当在7XXXXXXXX的地方,所以,判定IAT被加密。

    5.进入IAT被加密位置

    ①在IAT修改处下硬件断点
    在图中的00275039的位置下硬件写入断点,就能跳转到IAT被加密的位置
    ②重新开始,运行找修改处
    第一次运行,命中的是ntdll模块
    再继续运行,找到001E0895,此处就是在填充IAT
    此处的地址为001E0897,这是一个VA地址,是申请在堆内存中的一个地址,所以我们只需要记录其的RVA地址0897,而01E0000就是程序动态申请的地址,在写脚本的时候需要动态获取这个地址。
    001E0895 8902 mov dword ptr ds:[edx],eax
    001E0897 E8 39000000 call 001E08D5
    ③如何确定其申请的动态基址
    从新加载程序,进行单步步入跟踪,我们知道,程序比如会先加载壳代码,也就必然会开辟堆空间,,而开辟堆空间会用到VirtualAlloc,这样我们可以通过函数名快速的找到申请堆空间位置。
    由图可以看到,在0047A37D处会显示字符串“VirtualAlloc”,由此,我们确定申请的堆空间地址会直接存入eax中,再单步一下,就能看到eax寄存器中出现堆空间地址001E0000

    6.脱壳思路

    此壳的加密行为为,申请一块堆空间,将原本的IAT数据写人到堆空间中,再用堆空间内存地址覆盖IAT,相当于做了一次中间转换,如果能其加密结束处将正确的IAT原始数据重新写入IAT中进行覆盖操作,就能顶掉壳的中间跳转操作,达到脱壳效果。

    7.找到关键地址

    ①找回原始函数地址思路
    我们知道了填充加密IAT的代码位置,就能找到存放原始函数API地址的堆空间,就能找回原始函数,就在执行用堆空间地址覆盖IAT代码的前不远处。
    ②Run追踪
    我们需要使用Run跟踪来帮助我们快速找到,获得存放原始函数地址的位置。首先在填充IAT的位置,删除之前的硬件断点,再在这个位置下软件断点,点击导航栏的调试,单击“打开RUN追踪”,再选择跟踪步入
    打开RUN追踪窗口,在导航栏点击“查看“,再点击“RUN追踪”即可
    等待片刻
    ③找到关键位置
    查看RUN跟踪记录的指令信息,重点关注这次循环过程中,寄存器发生的变化,从最后一条记录向前找,找寄存器中的值像真实函数地址的指令
    为了确认,双击此条信息,反汇编窗口跟随,设置软件短句,运行到此处,右键单击,数据窗口跟随,点击“隐含堆栈地址”,再在数值处,右键选择“反汇编窗口中跟随”
    ④确认关键点
    我们需要在获取函数地址指令的下一行,获取EXD的值,用来引向正确的IAT,记录其偏移10F7
    001710F6 5A pop edx ; kernel32.HeapFree
    001710F7 E8 02F4FFFF call 001704FE

    8.编写OD脚本恢复IAT

    ①准备阶段
    0047148B  ==  OEP
    0047A37F  ==  申请的堆空间,里面有壳代码,返回值EAX
    0x0897      ==  填充IAT的下一行指令位置,我们需要用真实地址覆盖填充过的加密IAT
    0x10F7      ==  获取真实函数地址的下一行,真实地址保存在EDX中

    MOV ddEDX,0
    MOV dwAddress,0
    MOV ddGetVirtualAlloc,0047A37F
    MOV dwGetFunctionRVA,10F7
    MOV dwWriteIATRVA,0897
    MOV ddOEPAddr,0047148B
    BC
    BPHWCALL
    BPHWS ddGetVirtualAlloc,"x"
    BPHWS ddOEPAddr,"x"
    LOOP1:
    RUN
    GetVir:
    CMP eip,ddGetVirtualAlloc
    JNE CASE1
    MOV dwAddress,eax
    ADD dwGetFunctionRVA,dwAddress
    MSG dwGetFunctionRVA
    ADD dwWriteIATRVA,dwAddress
    MSG dwWriteIATRVA
    BPHWS dwGetFunctionRVA,"x"
    BPHWS dwWriteIATRVA,"x"
    JMP LOOP1
    CASE1:
    CMP eip,dwGetFunctionRVA
    JNE CASE2
    MOV ddEDX,edx
    JMP LOOP1
    CASE2:
    CMP eip,dwWriteIATRVA
    JNE CASE3
    MOV [edx],ddEDX
    JMP LOOP1
    CASE3:
    CMP eip,ddOEPAddr
    JNE LOOP1
    MSG "到达OEP,可以dump了!!!"
    x
     
    1
    MOV ddEDX,0
    2
    MOV dwAddress,0
    3
    MOV ddGetVirtualAlloc,0047A37F
    4
    MOV dwGetFunctionRVA,10F7
    5
    MOV dwWriteIATRVA,0897
    6
    MOV ddOEPAddr,0047148B
    7
    BC
    8
    BPHWCALL
    9
    BPHWS ddGetVirtualAlloc,"x"
    10
    BPHWS ddOEPAddr,"x"
    11
    LOOP1:
    12
    RUN
    13
    GetVir:
    14
    CMP eip,ddGetVirtualAlloc
    15
    JNE CASE1
    16
    MOV dwAddress,eax
    17
    ADD dwGetFunctionRVA,dwAddress
    18
    MSG dwGetFunctionRVA
    19
    ADD dwWriteIATRVA,dwAddress
    20
    MSG dwWriteIATRVA
    21
    BPHWS dwGetFunctionRVA,"x"
    22
    BPHWS dwWriteIATRVA,"x"
    23
    JMP LOOP1
    24
    CASE1:
    25
    CMP eip,dwGetFunctionRVA
    26
    JNE CASE2
    27
    MOV ddEDX,edx
    28
    JMP LOOP1
    29
    CASE2:
    30
    CMP eip,dwWriteIATRVA
    31
    JNE CASE3
    32
    MOV [edx],ddEDX
    33
    JMP LOOP1
    34
    CASE3:
    35
    CMP eip,ddOEPAddr
    36
    JNE LOOP1
    37
    MSG "到达OEP,可以dump了!!!"















  • 相关阅读:
    怎么看待MYSQL的性能
    java dom4j 读写XML
    cas4.2的安装
    java websocket
    解决openresty http客户端不支持https的问题
    开源许可证GPL、BSD、MIT、Mozilla、Apache和LGPL的区别
    SpringMVC框架的学习(一):初步认识
    Spring框架: 理解为它是一个管理对象的创建,依赖,销毁的容器。
    Springmvc如何进行异常处理
    Springmvc:注解有哪些。
  • 原文地址:https://www.cnblogs.com/HOPEAMOR/p/12017292.html
Copyright © 2011-2022 走看看