壳版本:VMProtect.Ultimate.2.12.3

样本:notepad.exe

目的:IAT修复

作者:MrWrong

标题:探讨VMP 2.12.3 导入表修复

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

由于仅是对VMP壳的导入表加密进行较为肤浅地探讨,所以对样本notepad的加VMP壳时,资源保护并未选择,也并未对OEP进行偷取或对其VM(虚拟化)。

一般加密壳都是将对调用导入表中系统函数的FF25型、FF15型、MOV reg, [iat_addr]型指令转换成call addr_in_shell_section(目标地址在壳区段的call)。这些call所做的工作是通过加壳时保存的数据信息,“绕着弯儿”执行原指令。VMP也不例外,只是它不拘一格,形式多变,难以修复。

修复导入表是实现脱壳文件可跨平台运行的关键,大致过程如下:

1、OD加载并执行到OEP后,保存环境。

2、在代码段搜索call addr_in_vmp_section,直到搜索完整个待修复区域,跳到4。

3、修复找到的位置,回到1。

4、上UIF。

5、上ImportREC。

6、上LoadPE删除VMP0和VMP1两个区段,并重建PE。

过程3是关键:

在找到的位置新建eip并记录此地址为S,F7(步入)跟踪执行直到如下指令对出现:

push dword ptr[esp+param1]

retn param2

在"retn param2"处停下,并记录:

A=[esp];

B=[esp+param1+8];

C=[esp+4];

D=param2-param1;

此后分几种情况分析:

第一种情况: FF25(call dword ptr[iataddr])的变形

如果A是一个系统函数地址,并有(D==4)&&(B==(S+6)||B==(S+5))为真

则此E8的call是变形自FF25形式的call。

此时修复为:

*(byte*)(B-6)=0x90;

*(byte*)(B-5)=0xE8;

*(dword*)(B-4)=A-B;

第二种情况 FF15(jmp dword ptr[iataddr])的变形

如果A是一个系统函数地址,并有(D==8)&&(B==(S+6)||B==(S+5))为真

则此E8的call是变形自FF15形式的jmp dword prt[iataddr]。

此时修复为:

*(byte*)(B-6)=0x90;

*(byte*)(B-5)=0xE9;

*(dword*)(B-4)=A-B;

第三种情况 mov e??, dword ptr[iataddr]的变形

A不是一个系统函数地址,并有(D==4)&&(A==(S+6)||A==(S+5))为真

则此时有一下几种情况需要判断,这是由于被变形前字节数的原因。

因为 "mov eax, dword ptr[iataddr]"是5个字节(A1+iataddress)

而其他的都是六字节,如:

mov ebx, dword ptr[iataddr] (8B1D+iataddress)

mov ecx, dword ptr[iataddr] (8B0D+iataddress)

mov edx, dword ptr[iataddr] (8B15+iataddress)

mov esi, dword ptr[iataddr] (8B35+iataddress)

mov edi, dword ptr[iataddr] (8B3D+iataddress)

确定为第三种情况后,则先记录下"call addr_in_shell_section"处的寄存器环境,

在"retn param2"处对各个寄存器进行对比,哪个更改了,要修复的目标函数地址就在哪个寄存器里。

5字节的情况直接修复成:mov eax, iataddress

6字节的情况修复成: mov e??, iataddress + (nop)

目前由于本实例只看到6字节的情况,所以本条规则还不完全,暂定于此。

另外一个值得重视的情形是:

mov ebx, dword ptr[iataddr] (8B1D+iataddress)

mov ecx, dword ptr[iataddr] (8B0D+iataddress)

mov edx, dword ptr[iataddr] (8B15+iataddress)

mov esi, dword ptr[iataddr] (8B35+iataddress)

mov edi, dword ptr[iataddr] (8B3D+iataddress)

这5种6字节情况都有可能被修改成

push e??

call addr_in_shell_section

指令对的形式。

这中情况下,对比寄存器是否改变的方式就会有不足之处:因为call  addr_in_shell_section里面的代码会在"retn param2"之前已经将push e??的值从堆栈中取出并赋给了e??,而之前保存的寄存器环境是在call addr_in_shell_section指令处。这会导致对比e??的环境也发生了改变,而e??并不是我们所要寻找的目标。

这种情况可以在对比寄存器的时候,若发现有两个寄存器值不相同,则去取push e??这条指令,把e??排除。

我相信这些壳方面的技术早早地已经掌握在大牛们的手里了,只是最近壳的人气日衰,很少有人发表相关技术。可能还有诸多情况,鄙人水平有限,错误在所难免,修复的脚本在别的系统跑起来好像会存在一点点问题,好在自己的win7 64位系统是跑过了。仅是抛个砖,不足之处还请诸位大侠赐教。

最后特别感谢好朋友KeyKernel的帮助。独学而无友,则孤陋而寡闻。

怎么上传附件啊我擦

http://files.cnblogs.com/MrWrong/vmp2.12.3_iat_fix.zip

探讨VMP 2.12.3 导入表修复的更多相关文章

  1. VMProtect修复导入表的插件

    壳版本:VMProtect.Ultimate.2.12.3 样本:TKLobby.exe 目的:IAT修复 作者:MrWrong 标题:VMProtect修复导入表的插件 只是感兴趣,没有其他目的.失 ...

  2. C/C++ 手工实现IAT导入表注入劫持

    DLL注入有多种方式,今天介绍的这一种注入方式是通过修改导入表,增加一项导入DLL以及导入函数,我们知道当程序在被运行起来之前,其导入表中的导入DLL与导入函数会被递归读取加载到目标空间中,我们向导入 ...

  3. 利用PE数据目录的导入表获取函数名及其地址

    PE文件是以64字节的DOS文件头开始的(IMAGE_DOS_HEADER),接着是一段小DOS程序,然后是248字节的 NT文件头(IMAGE_NT_HEADERS),NT的文件头位置由IMAGE_ ...

  4. IDA分析脱壳后丢失导入表的PE

    1. 问题 一些程序经过脱壳后(如用OD的dump插件),一些导入表信息丢失了,导致拖入IDA后看不到API的信息(如右图所示,第一个红圈处实际是GetCurrentProcessId),给分析造成极 ...

  5. PE知识复习之PE的绑定导入表

    PE知识复习之PE的绑定导入表 一丶简介 根据前几讲,我们已经熟悉了导入表结构.但是如果大家尝试过打印导入表的结构. INT IAT的时候. 会出现问题. PE在加载前 INT IAT表都指向一个名称 ...

  6. Oracle导出表数据与导入表数据dmp,以及导入导出时候常见错误

    使用DOS 操作界面导出表数据,导入表数据(需要在数据库所在的服务器上边执行) exp UserName/Password@192.168.0.141/orcl   file=d:\xtables.d ...

  7. impdp导入表不创建segments

    一.文档说明 1.0 需求:需要将生产环境PICC用户导出,在测试环境中docker 测试数据库导入,只需要表结构: 2.0 思路:根据开发人员提供的需求,数据库源端aix 11.2.0.4, 目标端 ...

  8. C/C++ 导入表与IAT内存修正

    本章教程中,使用的工具是上次制作的PE结构解析器,如果还不会使用请先看前一篇文章中对该工具的介绍,本章节内容主要复习导入表结构的基础知识点,并通过前面编写的一些小案例,实现对内存的转储与导入表的脱壳修 ...

  9. 手动添加导入表修改EXE功能

    目标: 改动PE导入表,手工给HelloWorld增加一个功能,就是启动的时候写入一条开机启动项,C:\cmd0000000000000000000000000000.exe 实现方法: 直接在注册相 ...

随机推荐

  1. 关于oledb对Excel的读取

    这两天项目需求要检索excel的内容,于是就研究了一下,话不多说,我就直接贴代码1.首先是连接excel. public DataTable SearchSheetToDT(string strSea ...

  2. 建议别买三星Gear:半电脑产品 设计糟糕

    不久之前,三星刚刚发布了智能腕表Galaxy Gear,据<纽约时报>周三报道,尽管三星电子的智能手表Galax Gear集各种酷炫新功能于一身,但对消费者来说,却是个差劲的选择. < ...

  3. Unity3D基础学习 NGUI Example 7-Scroll View(Panel)制作固定包裹栏,点击传递参数显示物体

    最终效果如下: 实现ScrollView主要是NGUI的三个脚本"UIDraggable Panel","UIGrid","UIDrag Panel ...

  4. 【转】Android onTouch()和onTouchEvent()区别

    1.onTouch()方法: onTouch方式是View的OnTouchListener接口中定义的方法. 当一个View绑定了OnTouchListener后,当有Touch事件触发时,就会调用o ...

  5. 通过源码安装最新版Git

    下载源码 到Git的Github主页上下载最新的源码到本地,解压并进入目录. 编译安装 cd 你的git源码目录 autoconf ./configure make 第一个报错 报错内容: usr/b ...

  6. MM32 RTC学习(兼容STM32)

    RTC学习 RTC简述 实时时钟是一个独立的定时器. RTC模块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟日历的功能. 修改计数器的值可以重新设置系统当前的时间和日期. RTC模块和时钟配 ...

  7. 类名.this与类名.class

    1..当在内部类中使用this指的就是内部类的对象, 为了访问外层类对象,就可以使用外层类名.this来访问. 2.在java中,每个class都有一个相应的Class对象,当编写好一个类,编译完成后 ...

  8. Asp.Net WebApi 启用CORS跨域访问指定多个域名

    1.后台action指定 EnableCors指定可访问的域名多个,使用逗号隔开 //支持客户端凭据提交,指定多个域名,使用逗号隔开 [EnableCors("http://localhos ...

  9. Android Translate 动画跳跃和缓慢移动

    1.动画跳跃:在动画结束的时候设置位置 Animation.AnimationListener listener = new Animation.AnimationListener() { @Over ...

  10. mySQL优化 my.ini 配置说明

    [mysqld] port = 3306 serverid = 1 socket = /tmp/mysql.sock skip-name-resolve #禁止MySQL对外部连接进行DNS解析,使用 ...