移动导出表,移动重定位表【滴水逆向三期51笔记+作业源码】(上)

简介: 移动导出表,移动重定位表【滴水逆向三期51笔记+作业源码】

前面章节我们了解了PE文件中的导出表和重定位表,今天我们来学习如何来移动导出表和重定位表。

一.为什么要移动各种表?

首先,这些表都是由编译器生成的,里面存储了非常重要的信息,在程序启动的时候,系统会根据这些表的内容来做一些初始化的工作,比如将用到的dll中的函数地址存储到IAT表(后续我们将会学习)中,为了保护程序,我们可以对exe二进制进行加密操作,但是问题是:各种表的信息,与代码和数据混在一起(存在于各个节中)如果进行加密的话,系统在初始化的时候就会出问题。

学会移动各种表,是对程序加密解密的基础

二.移动导出表

这里给出移动导出表的基本思路,在文章后面会贴出源码

1.首先,我们在文件中新增一个节,我们可以将导出表等信息移动到导出表中

2.将函数地址表移动到新节(也就是AddressOfFunctions所指向的内容)长度:NumberOfFunctions*4注意函数地址表中存储的是函数地址,因为我们没有移动函数,所以我们在移动导出表后无需修正

3.复制函数导出序号表到新节(也就是AddressOfNameOrdinals所指向的内容)长度:NumberOfNames*2注意导出序号表中存储的就是导出序号,移动导出表后无需修正

4.复制函数名称表移动到新节(也就是AddressOfNames所指向的内容)长度:NumberOfNames*4注意函数名称表中存储的是地址,指向函数名称字符串,这里在复制函数名字符串后立即修正函数名称表

5.复制所有函数名字符串长度=字符串长度

6.复杂IMAGE_EXPORT_DIRECTORY结构

7.修复IMAGE_EXPORT_DIRECTORY结构中的AddressOfFunctions,AddressOfOrdinals,AddressOfNames字段

8.修复数据目录表IMAGE_DATA_DIRECTORY[IMAGE_DIRECTORY_ENTRY_EXPORT]中的VirsualAddress字段,使其指向我们移动后的导出表

三.移动导出表源码

PEFunction.h:
#include <stdio.h>
#include <windows.h>
#include <string.h>
//*************打开文件函数(将文件二进制读取到FileBuffer) ******************
//该函数需要一个char类型的指针,指向想要打开的文件路径
//该函数返回一个char类型的指针,指向FileBuffer
//该函数完成文件的打开,并且将文件的二进制读取到FIleBuffer
//该函数读取完成后会将文件关闭,避免出现误操作
//该函数会通过移动文件指针获取文件大小
//获取的文件大小用于动态申请内存 
//该函数会动态申请内存,用于存放FileBuffer
//***************************************************************************
char* ReadToFileBuffer(char* filename);
//***************************************获取文件大小函数*********************************
//该函数返回文件大小 
//****************************************************************************************
int SizeOfFile(char* filename);
//*****************************获取PE导出表数据函数**************************
//该函数需要一个指针,指向FileBuffer
//该函数在找到导出表之前,需要定义DOS结构指针,标准PE头结构指针和可选PE头指针,以方便找到导出表
//该函数会在控制台输出函数地址表,函数名称表和函数导出序号表 
//***************************************************************************
void ShowExportDirectory(char* FileBuffer);
//*****************************RVA转换为FOA函数******************************
//该函数需要一个指针,指向FileBuffer
//该函数需要一个整数,为要转换的RVA
//该函数返回一个整数,为转换后的FOA地址
//***************************************************************************
int RVAToFOA(IN LPVOID pFileBuffer, IN DWORD dwRva);
//*************************根据函数名称查找函数地址函数**********************
//该函数需要一个指针,指向要打开的文件路径 
//该函数返回一个整数,指向得到的函数地址
//***************************************************************************
void GetAddressOfFunctionByName(char* filename);
//*************************根据函数序号查找函数地址函数**********************
//该函数需要一个指针,指向要打开的文件路径 
//该函数返回一个整数,指向得到的函数地址
//***************************************************************************
void GetAddressOfFunctionByOrdinal(char* filename);
//******************************打印PE重定位表函数***************************
//该函数需要一个指针,指向FIleBuffer
//该函数会在控制台打印出重定位表信息(重定位表偏移,重定位表大小,但不打印重定位表具体项
//***************************************************************************
void ShowBaseRelocation(char* FileBuffer);
//**************************************新增节函数***************************************
//该函数需要一个指针,指向FileBuffer
//该函数需要一个指针,表示FileBuffer大小 
//该函数需要一个字符串,为原文件文件名 
//该函数完成在PE文件中新增一个节
//该函数在新增节之前,PE头部是否足够新增一个节表
//若PE文件头部内存不够新增一个节表,该函数将会提升所有头部,将DOSstob覆盖掉,并且让e_lfanew指向下一个字节 
//该函数会生成一个exe文件,存放于调用该函数的程序源目录下  
//该函数返回一个指针,指向新增节后的FileBuffer 
//****************************************************************************************
char* AddNewSection(char* FileBuffer,int SizeOfFileBuffer);
//*****************************覆盖DOSstob,抬升NT头和原有节表****************************
//该函数需要一个指针,指向需要改动的FileBuffer
//该函数将FileBuffer中的DOSstob覆盖
//该函数将PE头部中,DOS头以后的内容提升到DOSstob的位置 
//抬升成功后会将最后两个节表的数据全初始化为0 
//若头部抬升失败,则返回0 
//若抬升成功,则返回1 
//****************************************************************************************
int UpFile(char* FileBuffer);
//******************************计算文件对齐后的值函数************************************           
//Align:计算对齐后的值         
//参数说明:               
//x  需要进行对齐的值               
//Alignment 对齐大小            
//返回值说明:              
//返回x进行Alignment值对齐后的值                
//****************************************************************************************  
int Align(int x, int Alignment);
//**************************************移动导出表****************************************
//该函数需要一个指针,指向FileBuffer
//该函数需要一个整形参数,表示FileBuffer大小 
//该函数将移动导出表到新节,节名称:.NewSec 
//该函数返回一个指针,指向NewFileBuffer
//****************************************************************************************
char* RemoveExportDirectory(char* FileBuffer,int SizeOfFileBuffer);
main.c:
#include <stdio.h>
int main(int argc, char** argv) {
  char filename1[50];
  char filename2[50];
  printf("******               欢迎使用移动导出表程序               ******\n");
  printf("请输入想要操作的文件路径:");
  scanf("%s",filename1);
  char* FileBuffer=NULL;
  char* NewFileBuffer=NULL;
  int length;
  int* plength=&length; 
  FileBuffer=ReadToFileBuffer(filename1);
  length=SizeOfFile(filename1);
  NewFileBuffer=RemoveExportDirectory(FileBuffer,length);
  printf("请输入您想要保存的文件名称:");
  scanf("%d",filename2);
  FILE* fp;
  if((fp=fopen(filename2,"wb"))==NULL){
    printf("文件新建失败!\n");
    exit(0);
  }else{
    printf("文件新建成功,正在写入数据...\n");
  }
  if(fwrite(NewFileBuffer,length+1000,1,fp)){
    printf("数据写入成功。\n");
  }else{
    printf("数据写入失败!\n");
    exit(0);
  }
  free(FileBuffer);
  free(NewFileBuffer);
  return 0;
}

相关文章
|
6月前
|
分布式计算 Java 测试技术
肝Spark源码的若干骚操作
肝Spark源码的若干骚操作
49 0
|
存储 索引
导入表解析,IAT表解析【滴水逆向三期53笔记】
导入表解析,IAT表解析【滴水逆向三期53笔记】
|
6月前
|
存储 缓存 C++
C++链表常用的函数编写(增查删改)内附完整程序
C++链表常用的函数编写(增查删改)内附完整程序
112 0
|
Linux Python
彩蛋丨利用R语言脚本实现批量合并Excel表格,再也不用手动点来点去了!
彩蛋丨利用R语言脚本实现批量合并Excel表格,再也不用手动点来点去了!
新增节添加ShellCode【滴水逆向三期46作业源码】
新增节添加ShellCode【滴水逆向三期46作业源码】
【滴水逆向三期41作业】C语言提取文件PE头部信息
【滴水逆向三期41作业】C语言提取文件PE头部信息
移动导出表,移动重定位表【滴水逆向三期51笔记+作业源码】(下)
移动导出表,移动重定位表【滴水逆向三期51笔记+作业源码】
|
存储 C语言
PE导出表,C语言打印导出表信息【滴水逆向三期49笔记+作业】(下)
PE导出表,C语言打印导出表信息【滴水逆向三期49笔记+作业】
|
存储 C语言
PE导出表,C语言打印导出表信息【滴水逆向三期49笔记+作业】(上)
PE导出表,C语言打印导出表信息【滴水逆向三期49笔记+作业】
|
编译器
进程4GB空间简析,PE重定位表【滴水逆向三期50笔记+作业】
进程4GB空间简析,PE重定位表【滴水逆向三期50笔记+作业】