zoukankan      html  css  js  c++  java
  • 脱壳1

    概述

    脱壳是一项综合技术,结合PE文件格式、汇编指令的分析,调试加密的程序并将其还 原的一个过程。

    壳一般分为两种,加密壳和压缩壳,里面所使用的技术有,压缩算法、对代码加密、 对IAT加密、对资源加密。

    我们从简单入手­压缩壳

    关于压缩算法

    1. 有损压缩 一个像素点:RGB 红绿蓝 一个图片:(3,4,5),(4,5,3),(5,4,3) 压缩后:(4,4,4),3

    2. 无损压缩 一个文件:0,0,0,0,0,0,0 压缩后:0,7

    脱壳三步法

    1. 寻找原始OE

    2. dump内存到文件

    3. 修复文件

    脱壳三步法­寻址OEP技巧

    1. 堆栈平衡法(ESP定律) 壳代码就像一个函数,进入时会开辟堆栈、保存寄存器环境,退出时会恢复堆 栈、恢复寄存器。所以应该是堆栈平衡的,那我们可以在壳代码操作了堆栈后对 堆栈设置访问或写入断点,然后运行程序,当断点命中的时候,应该就是退出壳 代码的时候。在其附近单步几次,应该就能到达程序的原始OEP。

    2. 特征定位法 在我们熟悉的程序中,我们可以使用特征来定位程序原始OEP。特征有几种: ① 二进制特征 比如release版的VS2013是: E8????????E9 ② API特征 比如release版的VS2013的第一个API调用是: GetSystemTimeAsFileTime 比如vc6.0的第一个API调用是: GetVersion 比如Delphi程序第一个API调用是: GetModuleHandleA

    3. 单步跟踪法 这种方法一般使用在分析自己加壳的程序或者是练习分析壳时。

    脱壳­0.aspack.exe

    1. 用010Editor把重定位关闭

    2. 寻址OEP ESP定律

    3. 跑到入口点的位置再dump

    4. dump内存

       

    1. 修复文件

     

    RVA这个测试程序用的是0.

    注意:如果程序有随机基址,脱壳后需要把随机基址标志位置0.

    壳代码的基本流程

    ① 保存寄存器环境

    ② 加载一些必要的API

    ③ 解密代码和数据

    ④ 修复重定位

    ⑤ 填充IAT

    ⑥ 恢复寄存器环境

    分析壳代码­0.aspack.exe

    ① 壳OEP

     

    ② 加载必要API

     

    ③ 解密解压缩代码

     

    ④ 修复重定位

     

    修复重定位的公式:

    重定位表中存储两个有用字段:

    1. 需要重定位的分页地址

    2. 需要重定位的分页偏移

      重定位分为两步:

    3. 计算出 重定位地址,要重定位的地址=模块基地址+分页地址+分页偏移

    4. 修复要重定位的地址中数据,[要重定位的地址] ­ 默认模块基地址 + 当前模块基 地址

    5. 填充IAT

      原理:

      ① 从导入表中获取dll名称

      ② 从导入表中的INT,获取函数名称或者序号 ③ 通过GetModuleHandleA或者LoadLibraryA获取模块基地址 通过GetProcAddress获取函数地址

      ④ 将函数地址填充到对应IAT数组中

    001D726F    03F2          ADD ESI,EDX                        ; esi=导 入表结构 
    001D7271 8B46 0C MOV EAX,DWORD PTR DS:[ESI+0xC] ; 获取模 块DLL名称RVA
    001D7274 85C0 TEST EAX,EAX 001D7276 0F84 0D010000 JE 00_aspac.001D7389
    001D727C 03C2 ADD EAX,EDX ; 加上基 地址,字符串VA
    001D727E 8BD8 MOV EBX,EAX
    001D7280
    50 PUSH EAX
    001D7281 FF95 A90F0000 CALL DWORD PTR SS:[EBP+0xFA9] ; 获取模 块基地址
    001D7287 85C0 TEST EAX,EAX
    001D7289 75 07 JNZ SHORT 00_aspac.001D7292 001D728B 53 PUSH EBX 001D728C FF95 AD0F0000 CALL DWORD PTR SS:[EBP+0xFAD]
    001D7292 8985 A9050000 MOV DWORD PTR SS:[EBP+0x5A9],EAX ; 保存模 块基地址
    001D7298 C785 AD050000>MOV DWORD PTR SS:[EBP+0x5AD],0x0
    001D72A2 8B95 88040000 MOV EDX,DWORD PTR SS:[EBP+0x488] ; 获取基 地址
    001D72A8 8B06 MOV EAX,DWORD PTR DS:[ESI] ; 获取指 向OrignalFirstThunk RVA 001D72AA 85C0 TEST EAX,EAX
    001D72AC
    75 03 JNZ SHORT 00_aspac.001D72B1
    001D72AE 8B46 10 MOV EAX,DWORD PTR DS:[ESI+0x10]
    001D72B1 03C2 ADD EAX,EDX ; 计算出 OrignalFirstThunk VA 001D72B3
    0385 AD050000 ADD EAX,DWORD PTR SS:[EBP+0x5AD] ; 0
    001D72B9 8B18 MOV EBX,DWORD PTR DS:[EAX] ; 获取 INT中的数据,即指向函数名称的 RVA 001D72BB 8B7E
    10 MOV EDI,DWORD PTR DS:[ESI+0x10] ; 获取 FirstThunk
    001D72BE 03FA ADD EDI,EDX ; 计算得 出 IAT 地址
    001D72C0 03BD AD050000 ADD EDI,DWORD PTR SS:[EBP+0x5AD] ; 0 001D72C6 85DB TEST EBX,EBX ; 判断结 束
    001D72C8 0F84 A5000000 JE 00_aspac.001D7373
    001D72CE F7C3
    00000080 TEST EBX,0x80000000 ; 判断是 否是序号
    001D72D4 75 04 JNZ SHORT 00_aspac.001D72DA
    001D72D6 03DA ADD EBX,EDX ; 指向函 数字符串结构=INT[i]+模块基地址 001D72D8 43 INC EBX ; 减去 2,跳过字符串结构的序号
    001D72D9 43 INC EBX
    001D72DA 53 PUSH EBX ; 保存寄 存器环境
    001D72DB 81E3 FFFFFF7F AND EBX,0x7FFFFFFF
    001D72E1 53 PUSH EBX ; 压入字 符串或是序号
    001D72E2 FFB5 A9050000 PUSH DWORD PTR SS:[EBP+0x5A9]
    001D72E8 FF95 A50F0000 CALL DWORD PTR SS:[EBP+0xFA5] ; 获取函 数地址
    001D72EE 85C0 TEST EAX,EAX
    001D72F0 5B POP EBX ; 恢复寄 存器环境 ​

    ⑤ 修改属性,跳转原始OEP

     

  • 相关阅读:
    链表--判断一个链表是否为回文结构
    矩阵--“之”字形打印矩阵
    二叉树——平衡二叉树,二叉搜索树,完全二叉树
    链表--反转单向和双向链表
    codeforces 490C. Hacking Cypher 解题报告
    codeforces 490B.Queue 解题报告
    BestCoder19 1001.Alexandra and Prime Numbers(hdu 5108) 解题报告
    codeforces 488A. Giga Tower 解题报告
    codeforces 489C.Given Length and Sum of Digits... 解题报告
    codeforces 489B. BerSU Ball 解题报告
  • 原文地址:https://www.cnblogs.com/ltyandy/p/11269928.html
Copyright © 2011-2022 走看看