VMProtect原理与还原(1)

  1. 什么是VMProtect?
    1. 还原效果:
  2. 预备知识
    1. dll的主要功能
    2. kernel32.dll
      1. user32.dll
      2. gdi32.dll
      3. comdlg32.dll
      4. advapi32.dll
      5. shell32.dll
      6. ole32.dll
      7. odbc32.dll
      8. PE文件格式

​ 工具、脱壳

什么是VMProtect?

​ Virtual Machine Protect. 虚拟机保护

​ VMProtect的基本原则是通过使应用程序代码和逻辑变得非常复杂,执行虚拟化代码片段的虚拟机是嵌入到受保护应用程序的结果代码中的

​ 虚拟化代码,无需解码,不同于对代码进行加密/解密,VMProtect让其在虚拟CPU上运行。而这个异于常规X36/X64CPU的虚拟CPU,会对每个受保护的文件发出不同的指令集。

​ VMP有自己的虚拟CPU和虚拟指令集,那么对原生指令进行保护时,将原生指令转换为虚拟指令。

还原效果:

原汇编代码:

lea eax,dword ptr ds:[edx+0x6]
add eax,ecx
retn

还原后代码:

lea dreg[3c], [ dreg[14] + 00000006 ]
lea dreg[00], [ dreg[08] + dreg[3c] ]  
retn

我们看到寄存器还是虚拟寄存器,最后需要我们进行寄存器的转换分析,转换为真实寄存器,第二条lea指令经过寄存器变换,也将还原成add指令


预备知识

dll的主要功能

kernel32.dll

kernel32.dll是Windows 9x/Me中非常重要的32位动态链接库文件,属于内核级文件。它控制着系统的内存管理、数据的输入输出操作和中断处理,当Windows启动时,kernel32.dll就驻留在内存中特定的写保护区域,使别的程序无法占用这个内存区域。

user32.dll

user32.dll是Windows用户界面相关应用程序接口,用于包括Windows处理,基本用户界面等特性,如创建窗口和发送消息

在早期32-bit 版本的Windows中,用户控件是在ComCtl32中实现的,但是一些控件的显示功能是在User32.dll中实现的。例如在一个窗口中非客户区域(边框和菜单)的绘制就是由User32.dll来完成的。User32.dll 是操作系统的一个核心控件,它和操作系统是紧密联系在一起的。也就是说,不同版本的Windows中User32.dll 是不同。因此,应用程序在不同版本的Windows中运行的时候,由于User32.dll的不同,会导致应用程序的界面通常会有微小的不同。

gdi32.dll

gdi32.dll是Windows GDI图形用户界面相关程序,包含的函数用来绘制图像和显示文字

comdlg32.dll

comdlg32.dll是Windows应用程序公用对话框模块,用于例如打开文件对话框。

advapi32.dll

advapi32.dll是一个高级API应用程序接口服务库的一部分,包含的函数与对象的安全性,注册表的操控以及事件日志有关。

shell32.dll

shell32.dll是Windows的32位外壳动态链接库文件,用于打开网页和文件,建立文件时的默认文件名的设置等大量功能。

严格来讲,它只是代码的合集,真正执行这些功能的是操作系统的相关程序,dll文件只是根据设置调用这些程序的相关功能罢了。

ole32.dll

ole32.dll是对象链接和嵌入相关模块。

odbc32.dll

odbc32.dll是ODBC数据库查询相关文件。

PE文件格式

PE结构可以大致分为:

  • DOS部分 u_IMAGE_DOS_HEADER

    typedef struct _IMAGE_DOS_HEADER 
    {      
        WORD   e_magic;                      
        WORD   e_cblp;                         
        WORD   e_cp;                            
        WORD   e_crlc;                          
        WORD   e_cparhdr;                   
        WORD   e_minalloc;                  
        WORD   e_maxalloc;                 
        WORD   e_ss;                            
        WORD   e_sp;                            
        WORD   e_csum;                       
        WORD   e_ip;                            
        WORD   e_cs;        
            WORD   e_lfarlc;                        
        WORD   e_ovno;                       
        WORD   e_res[4];                      
        WORD   e_oemid;                     
        WORD   e_oeminfo;                  
        WORD   e_res2[10];                  
        LONG    e_lfanew;                      
    } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
    

    该结构体中需要掌握的字段只有 2 个,分别是第一个字段 e_magic 和最后一个字段 e_lfanew 字段

    e_magic字段:
    DOS 可执行文件的标识符,占用 2 字节。该位置保存着的字符是“MZ”

    e_lfanew字段:
    保存着PE头的起始位置。

    作用:

    • 定位PE文件头开始位置,也可用于PE文件合法性检测

​ u_IMAGE_NT_HEADERS NT头(PE头)

DOS头偏移多少是PE头位置

typedef struct _IMAGE_NT_HEADERS 
{  
    DWORD Signature;  //PE标识
    IMAGE_FILE_HEADER FileHeader;  	
    IMAGE_OPTIONAL_HEADER OptionalHeader;

} IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS;
  • PE文件头 u_IMAGE_FILE_HEADER
typedef struct _IMAGE_FILE_HEADER 
{  
    WORD Machine;  
    WORD NumberOfSections;  //主要关心区段数目
    DWORD TimeDateStamp;  
    DWORD PointerToSymbolTable;  
    DWORD NumberOfSymbols;  
    WORD SizeOfOptionalHeader;  
    WORD Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

_IMAGE_OPTIONAL_HEADER

typedef struct _IMAGE_OPTIONAL_HEADER 
{  
    WORD Magic;  
    BYTE MajorLinkerVersion;  
    BYTE MinorLinkerVersion;  
    DWORD SizeOfCode;  
    DWORD SizeOfInitializedData;  
    DWORD SizeOfUninitializedData;  
    DWORD AddressOfEntryPoint;  //入口点
    DWORD BaseOfCode;  
    DWORD BaseOfData;  
    DWORD ImageBase;  //映像基地址/模块地址
    DWORD SectionAlignment;  //区段对齐
    DWORD FileAlignment;  	//文件对齐
    WORD  MajorOperatingSystemVersion;  
    WORD  MinorOperatingSystemVersion;  
    WORD  MajorImageVersion;  
    WORD  MinorImageVersion;  
    WORD  MajorSubsystemVersion;  
    WORD  MinorSubsystemVersion;  
    DWORD    Win32VersionValue;  
    DWORD    SizeOfImage;  //映像大小
    DWORD    SizeOfHeaders;  
    DWORD    CheckSum;  
    WORD     Subsystem;  
    WORD     DllCharacteristics;  //dll属性
    DWORD    SizeOfStackReserve;  
    DWORD    SizeOfStackCommit;  
    DWORD SizeOfHeapReserve;  
    DWORD SizeOfHeapCommit;  
    DWORD LoaderFlags;  
    DWORD NumberOfRvaAndSizes;
    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];//数据目录包含在选项头里
} IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER;
  • 节数据(块数据) u_IMAGE_DATA_DIRECTORY
typedef struct _IMAGE_DATA_DIRECTORY 
{
    DWORD   VirtualAddress;
    DWORD   Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES    16	//16个数据目录
  • 区域段结构 u_IMAGE_SECTION_HEADER
typedef struct _IMAGE_SECTION_HEADER 
{
    BYTE    Name[IMAGE_SIZEOF_SHORT_NAME];//区段名称
    union {
            DWORD   PhysicalAddress;
            DWORD   VirtualSize;//程序加载后区段大小
    } Misc;
    DWORD   VirtualAddress;//程序加载后区段地址
    DWORD   SizeOfRawData;//文件中数据大小
    DWORD   PointerToRawData;//文件中数据偏移
    DWORD   PointerToRelocations;
    DWORD   PointerToLinenumbers;
    WORD    NumberOfRelocations;
    WORD    NumberOfLinenumbers;
    DWORD   Characteristics;//区段属性
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

#define IMAGE_SIZEOF_SECTION_HEADER          40
  • 调试信息

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 jaytp@qq.com

×

喜欢就点赞,疼爱就打赏