首页 > 其他分享 >导入表注入初步介绍

导入表注入初步介绍

时间:2023-06-22 19:57:29浏览次数:49  
标签:WORD IMAGE 初步 导入 IAT IMPORT DWORD 注入

目录

初识PE文件格式

img

DOS

img

Dos header

比较重要的有e_magic和e_lfanew两个属性。

其中e_magic属性用来判断这个文件是否为PE文件

e_lfnaw属性用来确定NT header相对于整个文件头的偏移量

typedef struct _IMAGE_DOS_HEADER {      // DOS .EXE header
    WORD   e_magic;                     // Magic number
    WORD   e_cblp;                      // Bytes on last page of file
    WORD   e_cp;                        // Pages in file
    WORD   e_crlc;                      // Relocations
    WORD   e_cparhdr;                   // Size of header in paragraphs
    WORD   e_minalloc;                  // Minimum extra paragraphs needed
    WORD   e_maxalloc;                  // Maximum extra paragraphs needed
    WORD   e_ss;                        // Initial (relative) SS value
    WORD   e_sp;                        // Initial SP value
    WORD   e_csum;                      // Checksum
    WORD   e_ip;                        // Initial IP value
    WORD   e_cs;                        // Initial (relative) CS value
    WORD   e_lfarlc;                    // File address of relocation table
    WORD   e_ovno;                      // Overlay number
    WORD   e_res[4];                    // Reserved words
    WORD   e_oemid;                     // OEM identifier (for e_oeminfo)
    WORD   e_oeminfo;                   // OEM information; e_oemid specific
    WORD   e_res2[10];                  // Reserved words
    LONG   e_lfanew;                    // File address of new exe header
  } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

Dos Stub(存根)

如果在 MS-DOS 中执行文件,则会调用存根程序。它通常显示合适的消息;但是,任何有效的 MS-DOS 应用程序都可以是存根程序。

NT Header

img
整个NT文件头由三个部分组成

typedef struct _IMAGE_NT_HEADERS64 {
    DWORD Signature;
    IMAGE_FILE_HEADER FileHeader;
    IMAGE_OPTIONAL_HEADER64 OptionalHeader;
} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64;

Signature

这个参数是一个标志。在一个有效的PE文件里, Signature字段被设置为 00004550h。

FileHeader

typedef struct _IMAGE_FILE_HEADER {
    WORD    Machine;			//标志着运行平台
    WORD    NumberOfSections;	//节的数量
    DWORD   TimeDateStamp;		//This represents the date and time the image was created by the linker.
    DWORD   PointerToSymbolTable;
    DWORD   NumberOfSymbols;
    WORD    SizeOfOptionalHeader;//可选头的大小
    WORD    Characteristics;	//说明了文件的可写、可读属性
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

OptionalHeader

下面列出了其中几个比较重要的属性

typedef struct _IMAGE_OPTIONAL_HEADER64 {
    DWORD       AddressOfEntryPoint;//指出文件被执行时的入口地址,注意这里是一个RVA地址
    ULONGLONG   ImageBase;			//程序的首选装载地址
    DWORD       SectionAlignment;	//内存中的区块的对齐大小
    DWORD       FileAlignment;		//文件中的区块的对齐大小
    DWORD       SizeOfImage;		//映像装入内存后的总尺寸
    WORD        DllCharacteristics; // DllMain()函数何时被调用
    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
    //数据目录表。这个字段是一个指针,它由16个相同的 IMAGE_DATA_DIRECTORY结构组成。
} IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64;

IMAGE_DATA_DIRECTORY

typedef struct _IMAGE_DATA_DIRECTORY {
    DWORD   VirtualAddress;	//虚拟地址(RVA)
    DWORD   Size;			//目录大小
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

其中每个目录有特殊的含义,比较重要的有:

  • 第0个 导出表
  • 第1个 导入表
  • 第5个 基址重定位
  • 第12个 IAT表

Section Table

img

typedef struct _IMAGE_SECTION_HEADER {
    BYTE    Name[IMAGE_SIZEOF_SHORT_NAME]; //名字填充
    union {
            DWORD   PhysicalAddress;	   //文件地址
            DWORD   VirtualSize;		   //加载到内存中的节的总大小
    } Misc;
    DWORD   VirtualAddress;					
    //加载到内存中的部分的第一个字节的地址,相对于映像基。对于对象文件,这是在应用重定位之前的第一个字节的地址。
    DWORD   SizeOfRawData;					//在磁盘上的初始化的数据大小
    DWORD   PointerToRawData;				//COFF 文件中第一页的文件指针。
    DWORD   Characteristics;				//说明了节区的属性
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

Import Table

img

想要找到导入表,我们首先找到Optional Header中的DataDirectory。

其次找到对应目录中的VirtualAddress。

typedef struct _IMAGE_IMPORT_DESCRIPTOR {
    union {
        DWORD   Characteristics;           
        DWORD   OriginalFirstThunk;        //指向INT的RVA 
    } DUMMYUNIONNAME;
    DWORD   Name;						  	//指向导入映像文件的名称
    DWORD   FirstThunk;                     // 指向IAT的RVA
} IMAGE_IMPORT_DESCRIPTOR;

img

typedef struct _IMAGE_THUNK_DATA64 {
    union {
        ULONGLONG ForwarderString;  // PBYTE 
        ULONGLONG Function;         // PDWORD
        ULONGLONG Ordinal;
        ULONGLONG AddressOfData;    // PIMAGE_IMPORT_BY_NAME
    } u1;
} IMAGE_THUNK_DATA64;
typedef IMAGE_THUNK_DATA64 * PIMAGE_THUNK_DATA64;

想要找到一个导入函数,我们首先通过OriginalFirstThunk找到我们存放Image_Thunk_Data,随后进一步找到我们需要的导入函数。

INT和IAT之间的区别

注意上图PE文件加载前,IAT表和INT表的完全相同的,所以此时IAT表也可以判断函数导出序号,或指向函数名字结构体。

而在加载后,差别就是IAT表发生变化,系统会先根据结构体变量Name加载对应的dll(拉伸),读取dll的导出表,对应原程序的INT表,匹配dll导出函数的地址,返回其地址,贴在对应的IAT表上,挨个修正地址(也就是GetProcAddress的功能)。

IMAGE_IMPORT_BY_NAME

typedef struct _IMAGE_IMPORT_BY_NAME {
    WORD    Hint;
    CHAR   Name[1];	//function name string
} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;

开始我们注入导入表的旅程吧

首先我们需要明确我们要做什么:

我们要将给定的DLL添加到一个应用程序中,并且当这个应用程序启动时,它会自动感染当前目录下的所有应用程序并将DLL文件分别添加到所有应用程序的导入表中。

根据我们上面提到的基础知识,我们首先需要指导一个导入表加载到IAT中的过程。
img

所以如果我们想要添加dll到导入表内,我们需要修改IAT和INT表、添加一个IMAGE_IMPORT_DESCRIPTOR和IMAGE_IMPORT_BY_NAME。

想要添加东西我们就必须要思考,是在原来的节区中添加还是新添加一个节区来存放我们需要的内容。最终我们选择新加一个节区,这里考虑到原来的节区可能存放的东西比较乱,不如我们新建一个节区比较好。

我们回顾一下我们整个程序需要修改的地方:

  1. 我们新添加一个节区头,肯定要修改NT头中Optional Header中的SizeOfImage

  2. 我们需要在原来的sectionHeader后面添加上我们新的文件头,然后把原来导入表所在的节区的节区头完全拷入到我们新建的节区头中。

  3. 添加新的节区头之后,我们肯定要把指向原来导入表的值修改为指向我们新加节头的地址。这里主要修改可选头中的DataDirectory[1]中的虚拟地址

  4. 修改完节点头之后,我们需要在整个文件后面添加新的节区。

    在这个新的节区中,我们主要添加7个部分:

    1.一个映像导入描述符。需要修改这个描述符的INT和IAT地址。

    2.一个空白的描述符,来说明描述符结束。

    3.一个INT。修改其AddressOfData属性,使其指向新添加得到IMAGE_IMPORT_BY_NAME

    4.一个空白的INT。表明INT结束。

    5.一个IAT,使其指向新添加的IMAGE_IMPORT_BY_NAME。

    6.一个空白的IAT,表明IAT结束。

    7.一个IMAGE_IMPORT_BY_NAME,修改其Name,Hint属性

有几个需要值得注意的地方:

  1. 新添加节的属性一定要包含IMAGE_SCN_MEM_WRITE属性。
  2. 注意区分32位和64位程序。

标签:WORD,IMAGE,初步,导入,IAT,IMPORT,DWORD,注入
From: https://www.cnblogs.com/imomi3/p/17498214.html

相关文章

  • 浅析GeoServer CVE-2023-25157 SQL注入
    简介GeoServer是一个开源的地图服务器,它是遵循OpenGISWeb服务器规范的J2EE实现,通过它可以方便的将地图数据发布为地图服务,实现地理空间数据在用户之间的共享。影响版本geoserver<2.18.72.19.0<=geoserver<2.19.72.20.0<=geoserver<2.20.72.21.0<=geoserver<2.21.42.22.0<=......
  • springboot集成easyexcel实现导入导出
    1、添加依赖<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.0.5</version></dependency>2、controller/***基于Liste......
  • Postgresql 数据库导入导出 物理VS逻辑 集合
    PostgreSQL数据的导入导出本身并没有特别高的技术要求,属于日常操作,但熟悉导入导出以及选择数据导入导出的方式还是有点思考空间的。怎么导出数据的方式更稳妥,更适应业务的需求。下面就先总结数据导入导出中的数据导出的一部分方式和命令的实例,其中一些也是我在总结中发现的,例如COP......
  • 【web开发】PHP命名空间的别名和导入
    前言前面两篇文章我们详细介绍了PHP命名空间的定义和基本使用以及命名空间相关术语解读,对PHP的命名空间的有了更多的了解,本文我们再深入探索PHP命名空间的更多使用技巧。废话不多说,直接上菜。命名空间的别名和导入涉及到命名空间的使用,命名空间中的别名和导入这俩个概念我们是无法......
  • 旋转高频电压注入PMSM无感控制MATLAB仿真模型,Mat
    旋转高频电压注入PMSM无感控制MATLAB仿真模型,MatID:2238606091675051......
  • Pycharm更换pip源与依赖包导入导出
    1Pycharm更换安装源在下载安装好Pycharm后,一个在实际编程开发过程中非常重要的问题是第三方库添加,然而Python默认的源网络速度有点慢,因此,我们常常需要做的是更换Pycharm的安装源。首先在项目开始出,点击下面的PythonPackages,然后点击左上方的小齿轮(注意不是右上方的小齿轮),过......
  • Spring依赖注入(三) - 注入来源
    Spring依赖注入来源上一章中,我们在第三步的代码分析中可看到,在进行注入的依赖查找的时候,查找来源会从如下几个方式去查找:• 1、先看注入是否是外部化配置,如果是,则注入(@Value的方式)• 2、遍历看注入的对象是否是resolvableDependencies中包含的对象,如果是则返回(非Spring容器管理的......
  • MongoDB批量导入Redis优化迭代笔记
    背景统计最近五天所有content信息的正文字节数(正文字段占用较多),然后根据这个大小,推送存在redis要配置多少的内存。统计方法1.在mongodb中查询db.content_.aggregate([{$match:{updatetime:{$gte:1686134400000,//对应日期"2023-06-07T00:00:00Z"的......
  • excel导入时,对两种版本格式的支持
    InputStreamfis=file.getInputStream();Workbookwookbook=null;Stringfilename=file.getOriginalFilename();filename=filename.trim();filename=filename.substring(0,filename.lastIndexOf("."));......
  • 规则引擎调研及初步使用
    一、产生的背景生产过程中,线上的业务规则内嵌在系统的各处代码中,每次策略的调整都需要更新线上系统,进行从需求->设计->编码->测试->上线这种长周期的流程,满足不了业务规则的快速变化以及低成本的更新试错迭代。因此需要有一种解决方案将商业决策逻辑和应用开发者的技术决策分离......