【逆向】导入表注入

news2024/9/29 19:21:07
练手的exe链接

链接:https://pan.baidu.com/s/1_87QNHaZYlfY_5uwIRePUQ?pwd=6gds 
提取码:6gds

原理:

在动态链接库一章提到DllMain,这里再回顾一次

当dll被加载进4GB空间时,会调用一次DllMain(入口方法)

当程序执行完了要把dll从4GB空间被卸载,也会调用一次DllMain

很淦,各种问题频出,这回做了整整六个小时,六个小时啊有木有,总结就是,太自大了,没认真听课,直接上手,吃瘪了。

首先说说创建dll文件吧,我选择的是用.def导出,这样我就可以用Depend查看里边的具体函数名和导出序号。很淦的是,当学到动态链接库的时候尝试过自己用def导出dll文件,当时啥问题都没有,一路畅通,但是很淦的是,昨天却死活导不出,只有dll没有lib文件,导致把dll放到Depend什么东东都没看见。各大资料,博客哥们都要翻烂了,还是没能解决,最后.......家人们,好无语啊,原来我添加def的时候是通过手动改后缀为.def,然后死活不行,机缘巧合,我删了原来的def,采用下图这样添加.def文件,然后导出,涅马,成功导出dll和lib了。(耗费一小时)

 以下是dll具体实现
 


#include "pch.h"
#include "Dll2.h"
#include "framework.h"


void Init()
{
    MessageBox(0, L"INIT", L"INIT", MB_OK);
}

void Destroy()
{
    MessageBox(0, L"Destroy", L"Destroy", MB_OK);
}

void ExportFunction()
{
    MessageBox(0, L"ExportFunction", L"ExportFunction", MB_OK);

}


BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        Init();
        break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        Destroy();
        break;
    }
    return TRUE;
}

def文件

LIBRARY "dllmain"

 
EXPORTS
 
Init @14
ExportFunction @15
Destroy @16
导入表和导出表的关系

谈谈我的理解,当exe想要调用dll里的函数的时候,首先去导入表找对应的函数名或者导出序号,如果IAT有现成的已经绑定好的地址,那么就直接调用,如果没有,则需要通过INT IAT表存着的函数名或者导出序号,然后调用GetProcAddress() 函数去导出表找对应的函数真实地址,填在IAT,然后调用函数。(精简的回答)

导入表注入的步骤:

第一步,移动导入表:
首先我们要明白为什么要移动导入表,为什么不能在EXE程序最后一个导入表后面追加一个导入表呢?

就拿我这个程序来说,黑色部分就是导入表了,可以看到,导入表的后门就是一大堆我也不知道啥数据,但是肯定动了就寄了,因此根本没空间让我们新添加东西,所以我们只能扩大节或者新增节,去挪动我们的导入表,这里我选择的是新增节

第二步:修改exe的信息:
改PE头关于节的属性,改exe程序的大小,记住新增节的属性是0XC0000060(反正权限都给就对了),然后讲节表里的导入表的偏移地址修改成挪动后的地址

第三步,新增导入表:
按照这个结构来,注意注意,我在这踩坑了,哎。
就是构造IAT,INT的时候要注意结束符!!要留够一个DWORD大小的0,不然在PEtool甚至不能分析新增dll的,和里面的函数。淦,太淦了,还有导入表的OriginalFirstThunk和FirstThunk要先指向一个IMAGE_THUNK_DATA的结构,这个结构是一个联合体

typedef struct _IMAGE_THUNK_DATA32 {						
    union {						
        PBYTE  ForwarderString;						
        PDWORD Function;						
        DWORD Ordinal;						 //序号
        PIMAGE_IMPORT_BY_NAME  AddressOfData;//指向IMAGE_IMPORT_BY_NAME
    } u1;						
} IMAGE_THUNK_DATA32;						
typedef IMAGE_THUNK_DATA32 * PIMAGE_THUNK_DATA32;	

其他三个没有用,只用到
PIMAGE_IMPORT_BY_NAME  AddressOfData;
指向一个IMAGE_IMPORT_BY_NAME结构

而不是让导入表的OriginalFirstThunk和FirstThunk直接指向IMAGE_IMPORT_BY_NAME结构。

以下是代码:

VOID PE::Import_Table_Injection(Data& my_data)
{
	//首先先要挪动导出表
	//获得dll的大小
	DWORD real_dll_size = my_data.Import_Directory_num * sizeof(IMAGE_IMPORT_DESCRIPTOR);
	
	DWORD dll_size = Section_Align(real_dll_size, my_data);
	DWORD size_of_rawdata = File_Align(real_dll_size, my_data);

	//申请一个新的空间
	DWORD new_data_size = my_data.my_optional->SizeOfImage+dll_size;
	Data new_data;
	new_data.Stretch_Data = new char[new_data_size];
	memset(new_data.Stretch_Data, 0, new_data_size);
	DWORD SIZE = _msize(new_data.Stretch_Data);
	memcpy_s(new_data.Stretch_Data, new_data_size, my_data.Stretch_Data, my_data.my_optional->SizeOfImage);
	
	//修改节的属性
	Analyze_PE(new_data, 2);
	new_data.my_file->NumberOfSections += 1;
	Analyze_PE(new_data, 2);//必须再分析一次,否则Remove_Relocation_Data.my_section[Remove_Relocation_Data.my_file->NumberOfSections - 1]会报错
	new_data.my_optional->SizeOfImage = new_data_size;
	new_data.my_section[new_data.my_file->NumberOfSections - 1]->Characteristics = my_data.my_section[0]->Characteristics;
	new_data.my_section[new_data.my_file->NumberOfSections - 1]->Misc.VirtualSize = real_dll_size;
	memcpy_s(new_data.my_section[new_data.my_file->NumberOfSections - 1]->Name, 7, "inject", 7);
	new_data.my_section[new_data.my_file->NumberOfSections - 1]->NumberOfLinenumbers = my_data.my_section[0]->NumberOfLinenumbers;
	new_data.my_section[new_data.my_file->NumberOfSections - 1]->NumberOfRelocations = my_data.my_section[0]->NumberOfRelocations;
	new_data.my_section[new_data.my_file->NumberOfSections - 1]->PointerToLinenumbers = my_data.my_section[0]->PointerToLinenumbers;
	new_data.my_section[new_data.my_file->NumberOfSections - 1]->PointerToRawData = my_data.my_section[my_data.my_file->NumberOfSections - 1]->PointerToRawData + my_data.my_section[my_data.my_file->NumberOfSections - 1]->SizeOfRawData;
	new_data.my_section[new_data.my_file->NumberOfSections - 1]->PointerToRelocations = my_data.my_section[0]->PointerToRelocations;
	new_data.my_section[new_data.my_file->NumberOfSections - 1]->SizeOfRawData = size_of_rawdata;
	new_data.my_section[new_data.my_file->NumberOfSections - 1]->VirtualAddress = my_data.my_section[my_data.my_file->NumberOfSections - 1]->VirtualAddress + Section_Align(my_data.my_section[my_data.my_file->NumberOfSections - 1]->Misc.VirtualSize, my_data);
	cout<<hex<<Rva_To_Foa(0x10eac, new_data)<<endl;
	cout << hex << Rva_To_Foa(0x10ea4, new_data) << endl;
	//挪动导入表
	DWORD import_table_size = my_data.Import_Directory_num * sizeof(IMAGE_IMPORT_DESCRIPTOR);
	DWORD* import_table_ptr = (DWORD*)my_data.my_Import_Directory[0];
	DWORD* new_data_ptr = (DWORD*)((DWORD)new_data.Stretch_Data + (DWORD)new_data.my_section[new_data.my_file->NumberOfSections - 1]->VirtualAddress);
	DWORD GAP = (DWORD)new_data_ptr - (DWORD)new_data.Stretch_Data;
	memcpy_s(new_data_ptr, import_table_size, import_table_ptr, import_table_size);

	//修改导入表的入口地址和大小
	new_data.my_Data_Directory[1]->VirtualAddress = (DWORD)new_data_ptr-(DWORD)new_data.Stretch_Data;
	new_data.my_Data_Directory[1]->Size=0x3c;

	//新增导入表
	PIMAGE_IMPORT_DESCRIPTOR new_import_ptr2=(PIMAGE_IMPORT_DESCRIPTOR)((DWORD)new_data_ptr+ import_table_size);
	new_import_ptr2->FirstThunk = (DWORD)nullptr;
	
	new_import_ptr2->TimeDateStamp = 0;
	new_import_ptr2->OriginalFirstThunk = (DWORD)nullptr;
	new_import_ptr2->ForwarderChain = 0;

	//让FirstThunk指向自己伪造的IAT表,让OriginalFirstThunk指向伪造的INT表
	PIMAGE_IMPORT_BY_NAME new_data_import_by_name = (PIMAGE_IMPORT_BY_NAME)((DWORD)new_data_ptr+3*0X14+0X10 );//指向新的空间
	PIMAGE_IMPORT_BY_NAME temp_by_name_ptr = new_data_import_by_name;
	new_data_import_by_name->Hint = 0;
	strcpy_s(new_data_import_by_name->Name, 0x5, "Init");
	new_data_import_by_name = (PIMAGE_IMPORT_BY_NAME)((DWORD)new_data_import_by_name + 0x7);

	strcpy_s((PCHAR)((DWORD)new_data_import_by_name), 0x9, "Dll2.dll");
	new_import_ptr2->Name = (DWORD)new_data_import_by_name-(DWORD)new_data.Stretch_Data;
	new_data_import_by_name = (PIMAGE_IMPORT_BY_NAME)((DWORD)new_data_import_by_name - 0x7);
	IMAGE_THUNK_DATA32* thunk_ptr = (IMAGE_THUNK_DATA32*)((DWORD)new_data_ptr + 3 * 0x14);
	thunk_ptr->u1.AddressOfData = (DWORD)new_data_import_by_name - (DWORD)new_data.Stretch_Data;
	new_import_ptr2->FirstThunk = (DWORD)thunk_ptr - (DWORD)new_data.Stretch_Data;

	thunk_ptr = (IMAGE_THUNK_DATA32*)((DWORD)thunk_ptr + 0X8);
	thunk_ptr->u1.AddressOfData = (DWORD)new_data_import_by_name - (DWORD)new_data.Stretch_Data;
	new_import_ptr2->OriginalFirstThunk = (DWORD)thunk_ptr - (DWORD)new_data.Stretch_Data;


	//缩小保存
	FILE* my_dll;
	Shrink_PE(new_data);
	Analyze_PE(new_data, 3);
	DWORD Size = _msize(new_data.Shrink_Data);
	if (fopen_s(&my_dll, "inject", "wb") == 0)
	{
		fwrite(new_data.Shrink_Data, 1, Size, my_dll);
		cout << "写入成功!" << endl;
		return;
	}
	else
	{
		cout << "写入失败!" << endl;
	}
}

完整的代码,可直接运行:
 

#include <windows.h>
#include <iostream>
#include <string>
#include <cstring>
#include <malloc.h>
using namespace std;

int MAX(int a, int b)
{
	return a >= b ? a : b;
}

class Data
{
public:
	PIMAGE_DOS_HEADER my_dos;//dos头结构
	PIMAGE_FILE_HEADER my_file;//file结构
	PIMAGE_OPTIONAL_HEADER32 my_optional;//可选PE头结构
	PIMAGE_SECTION_HEADER* my_section;//节表结构
	PIMAGE_DATA_DIRECTORY* my_Data_Directory;//数据目录结构
	//0.导出表	1.导入表	2.资源表	3.异常信息表	4.安全证书表	5.重定位表	6.调试信息表	7.版权所以表	
	//8.全局指针表	9.TLS表	10.加载配置表	11.绑定导入表	12.IAT表	13.延迟绑定表	14.COM信息表	15.未使用
	CHAR my_Export_Name[50][30];//导出表的名字
	PIMAGE_EXPORT_DIRECTORY my_Export_Directory; //指向导出表结构的指针
	DWORD	Export_AddressOfFunction[50];  //指向导出表中函数的地址
	PIMAGE_BASE_RELOCATION Relocation_Table[500]; //指向重定位表的数组
	PIMAGE_IMPORT_DESCRIPTOR* my_Import_Directory; //指向导入表
	DWORD Import_Directory_num; //导入表的数量



	void* Before_Stretch_Data; //指向拉伸前的内容
	void* Stretch_Data; //指向拉伸后的内容
	void* Shrink_Data; //指向缩小PE结构的内容


	Data()
	{
		my_dos = nullptr;//dos头结构
		my_file = nullptr;//file结构
		my_optional = nullptr;//可选PE头结构
		my_section = nullptr;//节表结构
		my_Data_Directory = nullptr;
		my_Import_Directory = nullptr;

		Before_Stretch_Data = nullptr; //指向拉伸前的内容
		Stretch_Data = nullptr; //指向拉伸后的内容
		Shrink_Data = nullptr; //指向缩小PE结构的内容

		Import_Directory_num = 0;
	}

	~Data()
	{
		if (Before_Stretch_Data != nullptr)
		{
			free(Before_Stretch_Data);
			Before_Stretch_Data = nullptr;
		}

		if (Stretch_Data != nullptr)
		{
			free(Stretch_Data);
			Stretch_Data = nullptr;
		}

		if (Shrink_Data != nullptr)
		{
			free(Shrink_Data);
			Shrink_Data = nullptr;
		}
	}


	VOID Copy_Before_Strectch_Data(Data my_data); //只深拷贝Before_Strectch_Data
};

VOID Data::Copy_Before_Strectch_Data(Data my_data)
{
	int size = _msize(my_data.Before_Stretch_Data);
	memcpy_s(this->Before_Stretch_Data, size, my_data.Before_Stretch_Data, size);
}



class PE
{
public:
	VOID Readfile(char* filename, Data& my_data);  //读取pe文件

	VOID Analyze_PE(Data& my_data, int num);  //分析pe结构

	VOID Stretch_PE(Data& my_data);  //拉伸pe结构

	VOID Shrink_PE(Data& my_data); //缩小pe结构

	VOID New_Section(char* filename, Data& my_data);//新增节,非扩大节,并写入新的exe文件中

	VOID Expand_Section(Data& my_data, char* filename);  //扩大节

	DWORD Section_Align(DWORD temp, Data& my_data); //返回内存对齐后的大小

	DWORD File_Align(DWORD temp, Data& my_data); //返回文件对齐后的大小

	VOID Combine_Section(char* filename, Data& my_data); //合并节

	VOID Copy_Data(Data& my_data);

	VOID Print_IMAGE_DATA_DIRECTORY(Data& my_data);  //打印目录结构

	VOID Analyze_Data_Directory(Data& my_data); //分析目录结构 //先分析才能打印

	DWORD  Rva_To_Foa(DWORD Rva_Offset, Data& my_data); //Rva转Foa

	VOID Print_ExportTable(Data& my_data);  //打印导出表

	VOID GetFunctionAddrByName(Data& my_data, char* name);  //通过函数名字输出DLL里函数的偏移

	VOID GetFunctionAddrByOrdinal(Data& my_data, int ordinal);  //通过序号输出DLL里函数的偏移

	VOID Print_Relocation(Data& mydata);  //打印重定位表

	VOID Remove_Export_Table(Data& my_data);  //移动导出表

	VOID Remove_Relocation(Data& my_data);  //移动重定位表

	VOID Analyze_Import_Table(Data& my_data);  //分析导入表

	VOID Print_Import_Table(Data& my_data); //打印导入表

	VOID Print_IAT(Data& my_data); //打印IAT表

	VOID Print_INT(Data& my_data);//打印INT表

	VOID Print_BOUND_IMPORT(Data& my_data);//打印绑定导出表的内容

	VOID Import_Table_Injection(Data& my_data); //导入表注入
};

VOID PE::Import_Table_Injection(Data& my_data)
{
	//首先先要挪动导出表
	
	//获得dll的大小
	
	

	DWORD real_dll_size = my_data.Import_Directory_num * sizeof(IMAGE_IMPORT_DESCRIPTOR);
	
	DWORD dll_size = Section_Align(real_dll_size, my_data);
	DWORD size_of_rawdata = File_Align(real_dll_size, my_data);

	//申请一个新的空间
	DWORD new_data_size = my_data.my_optional->SizeOfImage+dll_size;
	Data new_data;
	new_data.Stretch_Data = new char[new_data_size];
	memset(new_data.Stretch_Data, 0, new_data_size);
	DWORD SIZE = _msize(new_data.Stretch_Data);
	memcpy_s(new_data.Stretch_Data, new_data_size, my_data.Stretch_Data, my_data.my_optional->SizeOfImage);
	
	//修改节的属性
	Analyze_PE(new_data, 2);
	new_data.my_file->NumberOfSections += 1;
	Analyze_PE(new_data, 2);//必须再分析一次,否则Remove_Relocation_Data.my_section[Remove_Relocation_Data.my_file->NumberOfSections - 1]会报错
	new_data.my_optional->SizeOfImage = new_data_size;
	new_data.my_section[new_data.my_file->NumberOfSections - 1]->Characteristics = my_data.my_section[0]->Characteristics;
	new_data.my_section[new_data.my_file->NumberOfSections - 1]->Misc.VirtualSize = real_dll_size;
	memcpy_s(new_data.my_section[new_data.my_file->NumberOfSections - 1]->Name, 7, "inject", 7);
	new_data.my_section[new_data.my_file->NumberOfSections - 1]->NumberOfLinenumbers = my_data.my_section[0]->NumberOfLinenumbers;
	new_data.my_section[new_data.my_file->NumberOfSections - 1]->NumberOfRelocations = my_data.my_section[0]->NumberOfRelocations;
	new_data.my_section[new_data.my_file->NumberOfSections - 1]->PointerToLinenumbers = my_data.my_section[0]->PointerToLinenumbers;
	new_data.my_section[new_data.my_file->NumberOfSections - 1]->PointerToRawData = my_data.my_section[my_data.my_file->NumberOfSections - 1]->PointerToRawData + my_data.my_section[my_data.my_file->NumberOfSections - 1]->SizeOfRawData;
	new_data.my_section[new_data.my_file->NumberOfSections - 1]->PointerToRelocations = my_data.my_section[0]->PointerToRelocations;
	new_data.my_section[new_data.my_file->NumberOfSections - 1]->SizeOfRawData = size_of_rawdata;
	new_data.my_section[new_data.my_file->NumberOfSections - 1]->VirtualAddress = my_data.my_section[my_data.my_file->NumberOfSections - 1]->VirtualAddress + Section_Align(my_data.my_section[my_data.my_file->NumberOfSections - 1]->Misc.VirtualSize, my_data);
	cout<<hex<<Rva_To_Foa(0x10eac, new_data)<<endl;
	cout << hex << Rva_To_Foa(0x10ea4, new_data) << endl;
	//挪动导入表
	DWORD import_table_size = my_data.Import_Directory_num * sizeof(IMAGE_IMPORT_DESCRIPTOR);
	DWORD* import_table_ptr = (DWORD*)my_data.my_Import_Directory[0];
	DWORD* new_data_ptr = (DWORD*)((DWORD)new_data.Stretch_Data + (DWORD)new_data.my_section[new_data.my_file->NumberOfSections - 1]->VirtualAddress);
	DWORD GAP = (DWORD)new_data_ptr - (DWORD)new_data.Stretch_Data;
	memcpy_s(new_data_ptr, import_table_size, import_table_ptr, import_table_size);

	//修改导入表的入口地址和大小
	new_data.my_Data_Directory[1]->VirtualAddress = (DWORD)new_data_ptr-(DWORD)new_data.Stretch_Data;
	new_data.my_Data_Directory[1]->Size=0x3c;

	//新增导入表
	PIMAGE_IMPORT_DESCRIPTOR new_import_ptr2=(PIMAGE_IMPORT_DESCRIPTOR)((DWORD)new_data_ptr+ import_table_size);
	new_import_ptr2->FirstThunk = (DWORD)nullptr;
	
	new_import_ptr2->TimeDateStamp = 0;
	new_import_ptr2->OriginalFirstThunk = (DWORD)nullptr;
	new_import_ptr2->ForwarderChain = 0;

	//让FirstThunk指向自己伪造的IAT表,让OriginalFirstThunk指向伪造的INT表
	PIMAGE_IMPORT_BY_NAME new_data_import_by_name = (PIMAGE_IMPORT_BY_NAME)((DWORD)new_data_ptr+3*0X14+0X10 );//指向新的空间
	PIMAGE_IMPORT_BY_NAME temp_by_name_ptr = new_data_import_by_name;
	new_data_import_by_name->Hint = 0;
	strcpy_s(new_data_import_by_name->Name, 0x5, "Init");
	new_data_import_by_name = (PIMAGE_IMPORT_BY_NAME)((DWORD)new_data_import_by_name + 0x7);

	strcpy_s((PCHAR)((DWORD)new_data_import_by_name), 0x9, "Dll2.dll");
	new_import_ptr2->Name = (DWORD)new_data_import_by_name-(DWORD)new_data.Stretch_Data;
	new_data_import_by_name = (PIMAGE_IMPORT_BY_NAME)((DWORD)new_data_import_by_name - 0x7);
	IMAGE_THUNK_DATA32* thunk_ptr = (IMAGE_THUNK_DATA32*)((DWORD)new_data_ptr + 3 * 0x14);
	thunk_ptr->u1.AddressOfData = (DWORD)new_data_import_by_name - (DWORD)new_data.Stretch_Data;
	new_import_ptr2->FirstThunk = (DWORD)thunk_ptr - (DWORD)new_data.Stretch_Data;

	thunk_ptr = (IMAGE_THUNK_DATA32*)((DWORD)thunk_ptr + 0X8);
	thunk_ptr->u1.AddressOfData = (DWORD)new_data_import_by_name - (DWORD)new_data.Stretch_Data;
	new_import_ptr2->OriginalFirstThunk = (DWORD)thunk_ptr - (DWORD)new_data.Stretch_Data;


	//缩小保存
	FILE* my_dll;
	Shrink_PE(new_data);
	Analyze_PE(new_data, 3);
	DWORD Size = _msize(new_data.Shrink_Data);
	if (fopen_s(&my_dll, "inject", "wb") == 0)
	{
		fwrite(new_data.Shrink_Data, 1, Size, my_dll);
		cout << "写入成功!" << endl;
		return;
	}
	else
	{
		cout << "写入失败!" << endl;
	}
}

VOID PE::Print_BOUND_IMPORT(Data& my_data)
{
	for (int i = 0; i < my_data.Import_Directory_num; i++)
	{
		PIMAGE_IMPORT_DESCRIPTOR temp_import_ptr = my_data.my_Import_Directory[i];
		if (temp_import_ptr->TimeDateStamp == 0)
		{
			cout << "导入表:" << (PCHAR)(temp_import_ptr->Name + (DWORD)my_data.Stretch_Data) << "未进行绑定,需要进行由编译器修复IAT" << endl;
			cout << "-----------------------------------------------------------------------------" << endl;
		}
		else
		{
			cout << "导入表:" << (PCHAR)(temp_import_ptr->Name+(DWORD)my_data.Stretch_Data) << "已经绑定,不需要由编译器修复IAT" << endl;
			cout << "-----------------------------------------------------------------------------" << endl;
		}
	}
	PIMAGE_BOUND_IMPORT_DESCRIPTOR temp_bound_import_ptr = nullptr;
	if (my_data.my_Data_Directory[11]->VirtualAddress != 0)
	{
		temp_bound_import_ptr = (PIMAGE_BOUND_IMPORT_DESCRIPTOR)((DWORD)my_data.my_Data_Directory[11]->VirtualAddress + (DWORD)my_data.Stretch_Data);
	}
	else
	{
		cout << "该应用程序没有绑定导入表!" << endl;
		return;
	}
	while (*(DWORD*)temp_bound_import_ptr != 0)
	{
		if (temp_bound_import_ptr->TimeDateStamp != my_data.my_file->TimeDateStamp)
		{
			cout << "DLL:"<<(PCHAR)(temp_bound_import_ptr->OffsetModuleName+temp_bound_import_ptr)<<"PE头的时间戳和绑定导出表的时间戳不一致!需要进行IAT重定位" << endl;
		}
		else
		{
			DWORD* temp_name_ptr = (DWORD*)((DWORD)my_data.Stretch_Data + (DWORD)temp_bound_import_ptr + (DWORD)temp_bound_import_ptr->OffsetModuleName);
			cout << "从该绑定导出表可知,该dll的名字为:" << (PCHAR)temp_name_ptr << ",它依赖的其他dll的个数为" << temp_bound_import_ptr->NumberOfModuleForwarderRefs << endl << "这些dll的名字是" << endl;
			for (int i = 0; i < temp_bound_import_ptr->NumberOfModuleForwarderRefs; i++)
			{
				PIMAGE_BOUND_FORWARDER_REF temp_ref_ptr = (PIMAGE_BOUND_FORWARDER_REF)((DWORD)temp_bound_import_ptr + 0x8) + i * 0x8;
				cout << (PCHAR)((DWORD)my_data.Stretch_Data + (DWORD)temp_bound_import_ptr + (DWORD)temp_ref_ptr->OffsetModuleName) << endl;
			}
			cout << endl;
		}
		temp_bound_import_ptr = (PIMAGE_BOUND_IMPORT_DESCRIPTOR)((DWORD)temp_bound_import_ptr + 0x8+(DWORD)temp_bound_import_ptr->NumberOfModuleForwarderRefs * 0x8);
	}
}

VOID PE::Print_INT(Data& my_data)
{
	for (int i = 0; i < my_data.Import_Directory_num; i++)
	{
		cout << "这是第" << i << "个导入表" << endl;
		cout << "此时dll的名字是" << (PCHAR)((DWORD)my_data.my_Import_Directory[i]->Name + (DWORD)my_data.Stretch_Data) << endl;
		DWORD* Temp_ptr = (DWORD*)((DWORD)my_data.my_Import_Directory[i]->OriginalFirstThunk + (DWORD)my_data.Stretch_Data);
		int count = 0;
		while (*Temp_ptr != 0)
		{
			cout << "第" << ++count << "个INT表的偏移是0x" <<hex<< *Temp_ptr << endl;
			Temp_ptr++;
		}
	}
}

VOID PE::Print_IAT(Data& my_data)
{
	
	for (int i = 0; i < my_data.Import_Directory_num; i++)
	{
		cout << "这是第" << i << "个导入表" << endl;
		cout << "此时dll的名字是" << (PCHAR)((DWORD)my_data.my_Import_Directory[i]->Name + (DWORD)my_data.Stretch_Data) << endl;
		DWORD* Temp_ptr = (DWORD*)((DWORD)my_data.my_Import_Directory[i]->FirstThunk + (DWORD)my_data.Stretch_Data);
		int count = 0;
		while (*Temp_ptr != 0)
		{
			cout << "第" << ++count << "个IAT表的偏移是0x" <<hex<< *Temp_ptr << endl;
			Temp_ptr++;
		}
	}


}


VOID PE::Print_Import_Table(Data& my_data)
{
	
	for (int i = 0; i < my_data.Import_Directory_num; i++)
	{
		cout << "第" << i << "个导入表的名字——" << endl<< (PCHAR)(my_data.my_Import_Directory[i]->Name+(DWORD)my_data.Stretch_Data) << endl;
		PIMAGE_THUNK_DATA32 pimage_thunk_data32 = (PIMAGE_THUNK_DATA32)((my_data.my_Import_Directory[0]->OriginalFirstThunk+ (DWORD)my_data.Stretch_Data));
		for (int j = 0; j < 100; j++)
		{
			if ((DWORD)pimage_thunk_data32->u1.AddressOfData >> 31 == 1)
			{
				cout << "函数对应的序号是" << (pimage_thunk_data32->u1.AddressOfData & 0x7FFF) << endl;
			}
			else if ((DWORD)pimage_thunk_data32->u1.AddressOfData != 0)
			{
				cout << "对应的函数名是: " << (PCHAR)(pimage_thunk_data32->u1.AddressOfData+ (DWORD)my_data.Stretch_Data) << endl;
			}
			else if ((DWORD)pimage_thunk_data32->u1.AddressOfData == 0)
			{
				break;
			}
			pimage_thunk_data32++;
		}
		
	}
}

VOID PE::Analyze_Import_Table(Data& my_data)
{
	PIMAGE_IMPORT_DESCRIPTOR Temp_Ptr = (PIMAGE_IMPORT_DESCRIPTOR)my_data.my_Data_Directory[1];
	my_data.my_Import_Directory = new PIMAGE_IMPORT_DESCRIPTOR[100];
	Temp_Ptr = (PIMAGE_IMPORT_DESCRIPTOR)(*(DWORD*)Temp_Ptr + (DWORD)my_data.Stretch_Data);
	int i = 0;
	for ( i = 0; i < 100; i++)
	{
		if (Temp_Ptr->Characteristics == 0 && Temp_Ptr->Name == 0 && Temp_Ptr->TimeDateStamp == 0)
		{
			break;
		}
		my_data.my_Import_Directory[i] = Temp_Ptr;
		Temp_Ptr = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)Temp_Ptr + 5 * sizeof(DWORD));
	}
	my_data.Import_Directory_num = i;
	
	return;
}

VOID PE::Remove_Relocation(Data& my_data)
{
	Data Remove_Relocation_Data;
	DWORD Relocation_Data_Size = 0;//重定位表的大小
	LPVOID Temp_Ptr = (LPVOID)((DWORD)my_data.my_Data_Directory[5]->VirtualAddress + (DWORD)my_data.Stretch_Data);
	PIMAGE_BASE_RELOCATION relocation_ptr = (PIMAGE_BASE_RELOCATION)Temp_Ptr;
	while (TRUE)
	{
		if (relocation_ptr->SizeOfBlock == 0)
		{
			break;
		}
		Relocation_Data_Size += relocation_ptr->SizeOfBlock;
		relocation_ptr = (PIMAGE_BASE_RELOCATION)((DWORD)relocation_ptr+(DWORD)relocation_ptr->SizeOfBlock);
	}
	DWORD Real_Size = Relocation_Data_Size;
	DWORD SizeOfRawData = File_Align(Relocation_Data_Size, my_data);
	Relocation_Data_Size = Section_Align(Relocation_Data_Size, my_data);

	Remove_Relocation_Data.Stretch_Data = new char[Relocation_Data_Size+ my_data.my_optional->SizeOfImage];
	if (Remove_Relocation_Data.Stretch_Data == nullptr)
	{
		cout << "Remove_Relocation_Data.Stretch_Data分配空间失败!" << endl;
		return;
	}
	memcpy_s(Remove_Relocation_Data.Stretch_Data, Relocation_Data_Size + my_data.my_optional->SizeOfImage, my_data.Stretch_Data, my_data.my_optional->SizeOfImage);
	//现在要将新的节设置好
	//	1. 添加一个新的节
	//	2. 在新增节后面,填充一个节大小的000
	//	3. 修改PE头节的数量
	//	4. 修改sizeOfImage的大小
	//	5. 再原有的数据的最后,新增一个节的数据(内存对齐的整数倍)
	//	6. 修正新增节的属性
	//	7. (被坑了好久)记得在对应节填上数据!!!否则会因为数据为空而不能运行
	Temp_Ptr = (LPVOID)((DWORD)Remove_Relocation_Data.Stretch_Data + (DWORD)my_data.my_optional->SizeOfImage);
	memset(Temp_Ptr, 0, Relocation_Data_Size);
	Analyze_PE(Remove_Relocation_Data, 2);
	Remove_Relocation_Data.my_file->NumberOfSections += 1;
	Analyze_PE(Remove_Relocation_Data, 2);//必须再分析一次,否则Remove_Relocation_Data.my_section[Remove_Relocation_Data.my_file->NumberOfSections - 1]会报错
	Remove_Relocation_Data.my_optional->SizeOfImage += Relocation_Data_Size;
	Remove_Relocation_Data.my_section[Remove_Relocation_Data.my_file->NumberOfSections - 1]->Characteristics = my_data.my_section[0]->Characteristics;
	Remove_Relocation_Data.my_section[Remove_Relocation_Data.my_file->NumberOfSections - 1]->Misc.VirtualSize =Relocation_Data_Size;
	memcpy_s(Remove_Relocation_Data.my_section[Remove_Relocation_Data.my_file->NumberOfSections - 1]->Name, 7, "reloca", 7);
	Remove_Relocation_Data.my_section[Remove_Relocation_Data.my_file->NumberOfSections - 1]->NumberOfLinenumbers = my_data.my_section[0]->NumberOfLinenumbers;
	Remove_Relocation_Data.my_section[Remove_Relocation_Data.my_file->NumberOfSections - 1]->NumberOfRelocations = my_data.my_section[0]->NumberOfRelocations;
	Remove_Relocation_Data.my_section[Remove_Relocation_Data.my_file->NumberOfSections - 1]->PointerToLinenumbers = my_data.my_section[0]->PointerToLinenumbers;
	Remove_Relocation_Data.my_section[Remove_Relocation_Data.my_file->NumberOfSections - 1]->PointerToRawData = my_data.my_section[my_data.my_file->NumberOfSections - 1]->PointerToRawData + my_data.my_section[my_data.my_file->NumberOfSections - 1]->SizeOfRawData;
	Remove_Relocation_Data.my_section[Remove_Relocation_Data.my_file->NumberOfSections - 1]->PointerToRelocations = my_data.my_section[0]->PointerToRelocations;
	Remove_Relocation_Data.my_section[Remove_Relocation_Data.my_file->NumberOfSections - 1]->SizeOfRawData = SizeOfRawData;
	Remove_Relocation_Data.my_section[Remove_Relocation_Data.my_file->NumberOfSections - 1]->VirtualAddress = my_data.my_section[my_data.my_file->NumberOfSections - 1]->VirtualAddress + Section_Align(my_data.my_section[my_data.my_file->NumberOfSections - 1]->Misc.VirtualSize, my_data);

	memcpy_s(Temp_Ptr, Real_Size, (LPVOID)((DWORD)my_data.my_Data_Directory[5]->VirtualAddress+ (DWORD)my_data.Stretch_Data), Real_Size);
	Remove_Relocation_Data.my_Data_Directory[5]->VirtualAddress = (DWORD)my_data.my_optional->SizeOfImage;
	FILE* my_file;
	Shrink_PE(Remove_Relocation_Data);
	Analyze_PE(Remove_Relocation_Data, 1);
	DWORD Size = _msize(Remove_Relocation_Data.Shrink_Data);
	if (fopen_s(&my_file, "reloca", "wb") == 0)
	{
		fwrite(Remove_Relocation_Data.Shrink_Data, 1, Size, my_file);
		cout << "写入成功!" << endl;
		return;
	}
	else
	{
		cout << "写入失败!" << endl;
	}
	

}

VOID PE::Remove_Export_Table(Data& my_data)
{
	DWORD Export_Size = my_data.my_Export_Directory->NumberOfFunctions * sizeof(DWORD) + my_data.my_Export_Directory->NumberOfNames * sizeof(WORD) + my_data.my_Export_Directory->NumberOfNames * sizeof(DWORD);
	for (int i = 0; i < my_data.my_Export_Directory->NumberOfNames; i++)
	{
		Export_Size += strlen(my_data.my_Export_Name[i]);
	}
	Export_Size = Section_Align(Export_Size, my_data);
	DWORD Total_Size =Export_Size+ my_data.my_optional->SizeOfImage;
	Data Remove_Export_Data;
	Remove_Export_Data.Stretch_Data = new char[Total_Size];
	if (Remove_Export_Data.Stretch_Data == nullptr)
	{
		cout << "Remove_Export_Data分配空间失败!!" << endl;
	}
	memcpy_s(Remove_Export_Data.Stretch_Data, Total_Size, my_data.Stretch_Data, my_data.my_optional->SizeOfImage);

	LPVOID Temp_Ptr= (LPVOID)((DWORD)Remove_Export_Data.Stretch_Data + my_data.my_optional->SizeOfImage);//这里是指向新的节
	//现在要将新的节设置好
	//	1. 添加一个新的节
	//	2. 在新增节后面,填充一个节大小的000
	//	3. 修改PE头节的数量
	//	4. 修改sizeOfImage的大小
	//	5. 再原有的数据的最后,新增一个节的数据(内存对齐的整数倍)
	//	6. 修正新增节的属性
	//	7. (被坑了好久)记得在对应节填上数据!!!否则会因为数据为空而不能运行
	memset(Temp_Ptr, 0, Export_Size);
	Analyze_PE(Remove_Export_Data, 2);
	Remove_Export_Data.my_file->NumberOfSections++;
	Remove_Export_Data.my_optional->SizeOfImage += Export_Size;
	Analyze_PE(Remove_Export_Data, 2); //可以分析到新的节表
	//开始修改节的属性
	Remove_Export_Data.my_section[Remove_Export_Data.my_file->NumberOfSections - 1]->Characteristics = my_data.my_section[0]->Characteristics;
	Remove_Export_Data.my_section[Remove_Export_Data.my_file->NumberOfSections - 1]->Misc.VirtualSize = Export_Size;
	memcpy_s(Remove_Export_Data.my_section[Remove_Export_Data.my_file->NumberOfSections - 1]->Name, 7, "remove",7);
	Remove_Export_Data.my_section[Remove_Export_Data.my_file->NumberOfSections - 1]->NumberOfLinenumbers = my_data.my_section[0]->NumberOfLinenumbers;
	Remove_Export_Data.my_section[Remove_Export_Data.my_file->NumberOfSections - 1]->NumberOfRelocations = my_data.my_section[0]->NumberOfRelocations;
	Remove_Export_Data.my_section[Remove_Export_Data.my_file->NumberOfSections - 1]->PointerToLinenumbers = my_data.my_section[0]->PointerToLinenumbers;
	Remove_Export_Data.my_section[Remove_Export_Data.my_file->NumberOfSections - 1]->PointerToRawData = my_data.my_section[my_data.my_file->NumberOfSections-1]->PointerToRawData+ my_data.my_section[my_data.my_file->NumberOfSections - 1]->SizeOfRawData;
	Remove_Export_Data.my_section[Remove_Export_Data.my_file->NumberOfSections - 1]->PointerToRelocations = my_data.my_section[0]->PointerToRelocations;
	Remove_Export_Data.my_section[Remove_Export_Data.my_file->NumberOfSections - 1]->SizeOfRawData = Export_Size;
	Remove_Export_Data.my_section[Remove_Export_Data.my_file->NumberOfSections - 1]->VirtualAddress = my_data.my_section[my_data.my_file->NumberOfSections - 1]->VirtualAddress + Section_Align(my_data.my_section[my_data.my_file->NumberOfSections - 1]->SizeOfRawData,my_data);
	
	Print_ExportTable(Remove_Export_Data);
	//开始移动导出表的信息!
	memcpy_s(Temp_Ptr, sizeof(DWORD) * my_data.my_Export_Directory->NumberOfFunctions, (LPVOID)(my_data.my_Export_Directory->AddressOfFunctions+(DWORD)my_data.Stretch_Data), sizeof(DWORD) * my_data.my_Export_Directory->NumberOfFunctions);
	Remove_Export_Data.my_Export_Directory->AddressOfFunctions = (DWORD)Temp_Ptr-(DWORD)Remove_Export_Data.Stretch_Data;
	Temp_Ptr = (LPVOID)((DWORD)Temp_Ptr + sizeof(DWORD) * my_data.my_Export_Directory->NumberOfFunctions);

	memcpy_s(Temp_Ptr, sizeof(WORD) * my_data.my_Export_Directory->NumberOfNames, (LPVOID)(my_data.my_Export_Directory->AddressOfNameOrdinals + (DWORD)my_data.Stretch_Data), sizeof(WORD) * my_data.my_Export_Directory->NumberOfNames);
	Remove_Export_Data.my_Export_Directory->AddressOfNameOrdinals = (DWORD)Temp_Ptr - (DWORD)Remove_Export_Data.Stretch_Data;
	Temp_Ptr = (LPVOID)((DWORD)Temp_Ptr + sizeof(WORD) * my_data.my_Export_Directory->NumberOfNames);

	memcpy_s(Temp_Ptr, sizeof(DWORD) * my_data.my_Export_Directory->AddressOfNames, (LPVOID)(my_data.my_Export_Directory->AddressOfNames + (DWORD)my_data.Stretch_Data), sizeof(DWORD) * my_data.my_Export_Directory->NumberOfNames);
	Remove_Export_Data.my_Export_Directory->AddressOfNames = (DWORD)Temp_Ptr - (DWORD)Remove_Export_Data.Stretch_Data;
	Temp_Ptr = (LPVOID)((DWORD)Temp_Ptr + sizeof(DWORD) * my_data.my_Export_Directory->AddressOfNames);

	FILE* my_file;
	Shrink_PE(Remove_Export_Data);
	DWORD Size = _msize(Remove_Export_Data.Shrink_Data);
	if (fopen_s(&my_file, "remove", "wb") == 0)
	{
		fwrite(Remove_Export_Data.Shrink_Data, 1, Size, my_file);
		cout << "写入成功!" << endl;
		return;
	}
	else
	{
		cout << "写入失败!" << endl;
	}

}

VOID PE::Print_Relocation(Data& my_data)
{
	DWORD Temp_ptr = (DWORD)my_data.my_Data_Directory[5]->VirtualAddress+(DWORD)my_data.Stretch_Data;
	int count = 1;//这是需要重定位函数的个数
	cout << endl << endl;
	for (int i = 0; i < 500; i++)
	{
		cout << endl;
		cout << "第" << i+1 << "个块" << endl;
		cout << "-----------------------------------------------------" << endl;
		my_data.Relocation_Table[i] = (PIMAGE_BASE_RELOCATION)Temp_ptr;
		my_data.Relocation_Table[i]->VirtualAddress = *(DWORD*)Temp_ptr;
		my_data.Relocation_Table[i]->SizeOfBlock = *(DWORD*)(Temp_ptr + 0x4);
		Temp_ptr += 0x8;


		for (int index = 0; index < (my_data.Relocation_Table[i]->SizeOfBlock - 0x8) / 2; index++)
		{
			PWORD Temp_ptr2 = (PWORD)(Temp_ptr +  2*index);
			int num = (*Temp_ptr2 >> 12);
			if (num == 3)
			{
				cout << count++ << ": 0x" << hex << my_data.Relocation_Table[i]->VirtualAddress + (*(Temp_ptr2) & 0XFFF)<<"  ";
			}
		}
		cout << endl;
		count = 1;
		Temp_ptr += my_data.Relocation_Table[i]->SizeOfBlock-0x8;
		if (*(DWORD*)Temp_ptr == 0&& *(DWORD*)(Temp_ptr+1)==0)
		{
			break;
		}

	}

}

VOID PE::GetFunctionAddrByOrdinal(Data& my_data, int ordinal)
{
	DWORD AddressOfNames_ptr = (DWORD)((DWORD)my_data.my_Export_Directory->AddressOfNameOrdinals + (DWORD)my_data.Stretch_Data);
	for (int i = 0; i < my_data.my_Export_Directory->NumberOfNames; i++)
	{
		if (*(WORD*)AddressOfNames_ptr + my_data.my_Export_Directory->Base == ordinal)
		{
			cout << "成功通过函数的序号找到函数地址!" << endl;
			cout << "0x" << hex << my_data.Export_AddressOfFunction[i] << endl;
			return;
		}
		AddressOfNames_ptr = (DWORD)((char*)AddressOfNames_ptr + 2);
	}
	cout << "没有匹配上!" << endl;
}


VOID PE::GetFunctionAddrByName(Data& my_data, char* name)
{
	int i = 0;
	for (i = 0; i < my_data.my_Export_Directory->NumberOfNames; i++)
	{
		if (!strcmp(name, my_data.my_Export_Name[i]))
		{
			cout << "成功通过函数名匹配到函数!" << endl;
			break;
		}
		if (i == my_data.my_Export_Directory->NumberOfNames - 1)
		{
			cout << "没有匹配到函数名!" << endl;
			return ;
		}
	}
	cout << "0x" << hex << my_data.Export_AddressOfFunction[i] << endl;
	
}


void PE::Print_ExportTable(Data& my_data)
{
	PIMAGE_EXPORT_DIRECTORY my_export_directory_ptr = (PIMAGE_EXPORT_DIRECTORY)((DWORD)my_data.my_Data_Directory[0]->VirtualAddress + (DWORD)my_data.Stretch_Data);
	my_data.my_Export_Directory = my_export_directory_ptr;
	DWORD AddressOfFunctions_ptr = (DWORD)((DWORD)my_export_directory_ptr->AddressOfFunctions + (DWORD)my_data.Stretch_Data);
	DWORD AddressOfNames_ptr = (DWORD)((DWORD)my_export_directory_ptr->AddressOfNames + (DWORD)my_data.Stretch_Data);
	DWORD AddressOfNameOrdinals_ptr = (DWORD)((DWORD)my_export_directory_ptr->AddressOfNameOrdinals + (DWORD)my_data.Stretch_Data);

	cout << "---------------AddressOfFunctions------------------" << endl;
	int number = my_export_directory_ptr->NumberOfFunctions;
	for (int i = 0; i < number; i++)
	{
		cout << i << ": " << "0x" << hex << *((DWORD*)AddressOfFunctions_ptr) << endl;
		my_data.Export_AddressOfFunction[i] = *((DWORD*)AddressOfFunctions_ptr);
		AddressOfFunctions_ptr += 0x4;
		while (*((DWORD*)AddressOfFunctions_ptr) == 0)
		{
			AddressOfFunctions_ptr += 0x4;
		}
	}

	cout << "---------------------Names------------------" << endl;
	number = my_export_directory_ptr->NumberOfNames;
	for (int i = 0; i < number; i++)
	{
		strcpy_s(my_data.my_Export_Name[i], (PCHAR)(*(DWORD*)AddressOfNames_ptr + (DWORD)my_data.Stretch_Data));
		cout << i << ": " << (PCHAR)(*(DWORD*)AddressOfNames_ptr + (DWORD)my_data.Stretch_Data) << endl;
		AddressOfNames_ptr += 0x4;
	}

	cout << "----------------------NameOrdinals---------------" << endl;
	cout << "base: " << my_export_directory_ptr->Base << endl;
	for (int i = 0; i < number; i++)
	{
		cout << i << ": " << *(WORD*)AddressOfNames_ptr << endl;
		AddressOfNames_ptr += 0x2;
	}
}





DWORD PE::Rva_To_Foa(DWORD Rva_Offset, Data& my_data)
{
	int index = 0;
	if (Rva_Offset <= my_data.my_optional->SizeOfHeaders)
	{
		return Rva_Offset;
	}
	else
	{

		while (Rva_Offset > my_data.my_section[index]->VirtualAddress)
		{
			if (index == my_data.my_file->NumberOfSections - 1)
				break;
			index++;
		}
		
		//计算在节的偏移
		DWORD Section_Offset = Rva_Offset - my_data.my_section[index]->VirtualAddress;
		return my_data.my_section[index]->PointerToRawData + Section_Offset;
	}
}

void PE::Analyze_Data_Directory(Data& my_data)
{
	my_data.my_Data_Directory = nullptr;
	my_data.my_Data_Directory = (PIMAGE_DATA_DIRECTORY*)malloc(16 * sizeof(PIMAGE_DATA_DIRECTORY));
	void* Temp_ptr = my_data.my_optional->DataDirectory;
	for (int i = 0; i < 16; i++)
	{
		my_data.my_Data_Directory[i] = (PIMAGE_DATA_DIRECTORY)Temp_ptr;
		Temp_ptr = (char*)Temp_ptr + 0x8;
	}
}

void PE::Print_IMAGE_DATA_DIRECTORY(Data& my_data)
{
	char arr[16][40] = {
	"IMAGE_DIRECTORY_ENTRY_EXPORT",
	"IMAGE_DIRECTORY_ENTRY_IMPORT",
	"IMAGE_DIRECTORY_ENTRY_RESOURCE",
	"IMAGE_DIRECTORY_ENTRY_EXCEPTION",
	"IMAGE_DIRECTORY_ENTRY_SECURITY",
	"IMAGE_DIRECTORY_ENTRY_BASERELOC",
	"IMAGE_DIRECTORY_ENTRY_DEBUG",
	"IMAGE_DIRECTORY_ENTRY_COPYRIGHT",
	"IMAGE_DIRECTORY_ENTRY_GLOBALPTR",
	"IMAGE_DIRECTORY_ENTRY_TLS",
	"IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG",
	"IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT",
	"IMAGE_DIRECTORY_ENTRY_IAT",
	"IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT",
	"IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR",
	"RESERVED"
	};

	for (int i = 0; i < 16; i++)
	{
		cout << arr[i] << " :" << endl;
		cout << "Size: " << hex << my_data.my_Data_Directory[i]->Size << endl;
		cout << "Virtual_Address: " << my_data.my_Data_Directory[i]->VirtualAddress << endl;
		cout << "------------------------------------------------------------------------" << endl;
	}
	return;
}


void PE::Combine_Section(char* filename, Data& my_data)
{

	int Max = MAX(my_data.my_section[my_data.my_file->NumberOfSections - 1]->SizeOfRawData, my_data.my_section[my_data.my_file->NumberOfSections - 1]->Misc.VirtualSize);
	int Size = my_data.my_section[my_data.my_file->NumberOfSections - 1]->VirtualAddress + Section_Align(Max, my_data) - Section_Align(my_data.my_optional->SizeOfHeaders, my_data) + MAX(my_data.my_section[0]->SizeOfRawData, my_data.my_section[0]->Misc.VirtualSize);
	Data Comebine_Data;
	int temp_size = _msize(my_data.Stretch_Data) + Max;
	Comebine_Data.Stretch_Data = (void*)malloc(temp_size);
	memset(Comebine_Data.Stretch_Data, 0, Size);

	temp_size = _msize(my_data.Stretch_Data);
	memcpy_s(Comebine_Data.Stretch_Data, temp_size, my_data.Stretch_Data, temp_size);
	Analyze_PE(Comebine_Data, 2);

	void* temp_ptr = (char*)Comebine_Data.Stretch_Data + Max + my_data.my_section[my_data.my_file->NumberOfSections - 1]->VirtualAddress;
	memcpy_s(temp_ptr, MAX(my_data.my_section[0]->SizeOfRawData, my_data.my_section[0]->Misc.VirtualSize), my_data.my_section[0]->VirtualAddress + (char*)my_data.Stretch_Data, MAX(my_data.my_section[0]->SizeOfRawData, my_data.my_section[0]->Misc.VirtualSize));

	Comebine_Data.my_optional->SizeOfImage += Section_Align(MAX(my_data.my_section[0]->SizeOfRawData, my_data.my_section[0]->Misc.VirtualSize), my_data);

	Comebine_Data.my_section[my_data.my_file->NumberOfSections - 1]->SizeOfRawData += File_Align(MAX(my_data.my_section[0]->SizeOfRawData, my_data.my_section[0]->Misc.VirtualSize), my_data);
	Comebine_Data.my_section[my_data.my_file->NumberOfSections - 1]->Misc.VirtualSize = Section_Align(Comebine_Data.my_section[my_data.my_file->NumberOfSections - 1]->Misc.VirtualSize, my_data) + Section_Align(MAX(my_data.my_section[0]->SizeOfRawData, my_data.my_section[0]->Misc.VirtualSize), my_data);

	FILE* my_file;
	if (fopen_s(&my_file, filename, "wb") != 0)
	{
		cout << "打开文件失败" << endl;
		return;
	}

	Shrink_PE(Comebine_Data);
	Analyze_PE(Comebine_Data, 3);

	fwrite(Comebine_Data.Shrink_Data, 1, _msize(Comebine_Data.Shrink_Data), my_file);
	cout << "写入成功!" << endl;

	fclose(my_file);
}


void PE::Expand_Section(Data& my_data, char* filename)
{
	this->Stretch_PE(my_data);
	unsigned Size = 0;//扩大节后新的文件大小
	Size = my_data.my_optional->ImageBase + Section_Align(MAX(my_data.my_section[0]->SizeOfRawData, my_data.my_section[0]->Misc.VirtualSize), my_data);

	Data Expand_Data;
	Expand_Data.Stretch_Data = (void*)malloc(Size);
	memset(Expand_Data.Stretch_Data, 0, Size);
	memcpy_s(Expand_Data.Stretch_Data, _msize(my_data.Stretch_Data), my_data.Stretch_Data, _msize(my_data.Stretch_Data));

	Analyze_PE(Expand_Data, 2);

	Expand_Data.my_section[my_data.my_file->NumberOfSections - 1]->SizeOfRawData = Section_Align(MAX(my_data.my_section[0]->SizeOfRawData, my_data.my_section[0]->Misc.VirtualSize), my_data) + Section_Align(MAX(my_data.my_section[my_data.my_file->NumberOfSections - 1]->SizeOfRawData, my_data.my_section[my_data.my_file->NumberOfSections - 1]->Misc.VirtualSize), my_data);
	Expand_Data.my_section[my_data.my_file->NumberOfSections - 1]->Misc.VirtualSize = Expand_Data.my_section[my_data.my_file->NumberOfSections - 1]->SizeOfRawData;

	Expand_Data.my_optional->SizeOfImage += Section_Align(MAX(my_data.my_section[0]->SizeOfRawData, my_data.my_section[0]->Misc.VirtualSize), my_data);

	void* Temp_Ptr = (char*)Expand_Data.Stretch_Data + Expand_Data.my_section[Expand_Data.my_file->NumberOfSections - 1]->VirtualAddress + Section_Align(MAX(my_data.my_section[Expand_Data.my_file->NumberOfSections - 1]->SizeOfRawData, my_data.my_section[Expand_Data.my_file->NumberOfSections - 1]->Misc.VirtualSize), my_data);
	int temp_size = Section_Align(MAX(my_data.my_section[0]->SizeOfRawData, my_data.my_section[0]->Misc.VirtualSize), my_data);
	void* Temp_Ptr2 = (char*)my_data.Stretch_Data + my_data.my_section[0]->VirtualAddress;

	memcpy_s(Temp_Ptr, temp_size, Temp_Ptr2, temp_size);


	Shrink_PE(Expand_Data);

	FILE* my_file;
	if (fopen_s(&my_file, filename, "wb") != 0)
	{
		cout << "打开文件失败!" << endl;

	}
	else
	{
		Size = _msize(Expand_Data.Shrink_Data);
		fwrite(Expand_Data.Shrink_Data, 1, Size, my_file);
		cout << "写入成功!" << endl;
	}
	fclose(my_file);
}


DWORD PE::Section_Align(DWORD temp, Data& my_data)
{
	int i = 0;
	while (temp > i * my_data.my_optional->SectionAlignment)
	{
		i++;
	}
	return i * my_data.my_optional->SectionAlignment;

}

DWORD PE::File_Align(DWORD temp, Data& my_data)
{
	int i = 0;
	while (temp > i * my_data.my_optional->FileAlignment)
	{
		i++;
	}
	return i * my_data.my_optional->FileAlignment;
}

void PE::New_Section(char* filename, Data& my_data)
{
	unsigned int Size; //Size是新文件的大小,是原来的文件大小加上.VirtualSize和SizeOfRawData较大的那个
	Size = my_data.my_optional->SizeOfHeaders;
	for (int i = 0; i < my_data.my_file->NumberOfSections; i++)
	{
		Size += my_data.my_section[i]->SizeOfRawData;
	}
	Size += my_data.my_section[0]->SizeOfRawData;//这是最终新的文件的大小

	Data New_Data;
	New_Data.Before_Stretch_Data = (void*)malloc(Size * 1);
	memset(New_Data.Before_Stretch_Data, 0, Size);
	memcpy_s(New_Data.Before_Stretch_Data, Size, my_data.Before_Stretch_Data, Size - my_data.my_section[0]->SizeOfRawData);//将原来的文件复制过来

	Analyze_PE(New_Data, 1);//让New_Data的dos,file,optional,section有数据

	//复制新的节表
	void* Temp_ptr1 = (char*)my_data.Before_Stretch_Data + 0x98 + my_data.my_file->SizeOfOptionalHeader;
	void* Temp_ptr2 = (char*)New_Data.Before_Stretch_Data + 0x98 + my_data.my_file->SizeOfOptionalHeader + my_data.my_file->NumberOfSections * 0x28;
	memcpy_s(Temp_ptr2, 0x28, Temp_ptr1, 0x28);
	//复制新的节
	Temp_ptr1 = (char*)my_data.Before_Stretch_Data + my_data.my_optional->SizeOfHeaders;//指向.text段
	Temp_ptr2 = (char*)New_Data.Before_Stretch_Data + Size - my_data.my_section[0]->SizeOfRawData;

	memcpy_s(Temp_ptr2, my_data.my_section[0]->SizeOfRawData, Temp_ptr1, my_data.my_section[0]->SizeOfRawData);//复制完.text段作为新增节

	//接下来要改Header的各项数据
	New_Data.my_file->NumberOfSections++;
	New_Data.my_optional->SizeOfImage += my_data.my_section[0]->SizeOfRawData;

	Analyze_PE(New_Data, 1);
	New_Data.my_section[New_Data.my_file->NumberOfSections - 1]->PointerToRawData = New_Data.my_section[New_Data.my_file->NumberOfSections - 2]->PointerToRawData + New_Data.my_section[New_Data.my_file->NumberOfSections - 2]->SizeOfRawData;
	int size;
	if (New_Data.my_section[New_Data.my_file->NumberOfSections - 2]->Misc.VirtualSize >= New_Data.my_section[New_Data.my_file->NumberOfSections - 2]->SizeOfRawData)
	{
		size = New_Data.my_section[New_Data.my_file->NumberOfSections - 2]->Misc.VirtualSize;
	}
	else
	{
		size = New_Data.my_section[New_Data.my_file->NumberOfSections - 2]->SizeOfRawData;
	}
	size = size / my_data.my_optional->SectionAlignment + my_data.my_optional->SectionAlignment;
	New_Data.my_section[New_Data.my_file->NumberOfSections - 1]->VirtualAddress = New_Data.my_section[New_Data.my_file->NumberOfSections - 2]->VirtualAddress + size;

	FILE* my_file;
	if (fopen_s(&my_file, filename, "wb") == 0)
	{
		fwrite(New_Data.Before_Stretch_Data, 1, Size, my_file);
		cout << "写入成功!" << endl;
		return;
	}
	else
	{
		cout << "打开文件失败" << endl;
		return;
	}
	fclose(my_file);
}


void PE::Readfile(char* filename, Data& my_data)
{
	unsigned int size;
	FILE* datafile;
	void* data;
	//打开文件
	if (fopen_s(&datafile, filename, "rb") != 0)
	{
		cout << "打开文件失败" << endl;
		return;
	}


	else
	{
		//获取文件的大小
		cout << "打开文件成功!" << endl;
		fseek(datafile, 0, SEEK_END);
		size = ftell(datafile);
		fseek(datafile, 0, SEEK_SET);
		if (size == -1L)
		{
			cout << "文件大小判断失败!" << endl;
			return;
		}

		//申请内存空间把文件内容保存下来
		my_data.Before_Stretch_Data = (void*)malloc(size * sizeof(char));

		if (fread_s(my_data.Before_Stretch_Data, size, sizeof(char), size, datafile) == 0)
		{
			cout << "写入数据失败!" << endl;
			return;
		}
		cout << "写入数据成功,成功获取Data!" << endl;
		return;
	}

}

//分析PE结构
void PE::Analyze_PE(Data& data, int num)
{
	if (num == 1)
	{
		if (data.Before_Stretch_Data != nullptr)
		{
			DWORD* Temp_ptr = (DWORD*)data.Before_Stretch_Data;
			data.my_dos = (PIMAGE_DOS_HEADER)Temp_ptr;

			Temp_ptr = (DWORD*)((char*)data.Before_Stretch_Data + data.my_dos->e_lfanew);
			Temp_ptr++;
			data.my_file = (PIMAGE_FILE_HEADER)Temp_ptr;

			Temp_ptr = (DWORD*)((char*)Temp_ptr + 0x14);
			data.my_optional = (PIMAGE_OPTIONAL_HEADER)Temp_ptr;


			Temp_ptr = (DWORD*)((char*)data.my_optional + data.my_file->SizeOfOptionalHeader);
			data.my_section = (PIMAGE_SECTION_HEADER*)malloc(sizeof(PIMAGE_SECTION_HEADER) * data.my_file->NumberOfSections);
			memset(data.my_section, 0, sizeof(PIMAGE_SECTION_HEADER) * data.my_file->NumberOfSections);
			for (int i = 0; i < data.my_file->NumberOfSections; i++)
			{
				data.my_section[i] = (PIMAGE_SECTION_HEADER)Temp_ptr;
				Temp_ptr = (DWORD*)((char*)Temp_ptr + 0x28);
			}
			Analyze_Data_Directory(data);
			
			return;
		}
		cout << "分析PE结构失败!" << endl;
	}

	if (num == 2)
	{
		if (data.Stretch_Data != nullptr)
		{
			DWORD* Temp_ptr = (DWORD*)data.Stretch_Data;
			data.my_dos = (PIMAGE_DOS_HEADER)Temp_ptr;

			Temp_ptr = (DWORD*)((char*)data.Stretch_Data + data.my_dos->e_lfanew);
			Temp_ptr++;
			data.my_file = (PIMAGE_FILE_HEADER)Temp_ptr;

			Temp_ptr = (DWORD*)((char*)Temp_ptr + 0x14);
			data.my_optional = (PIMAGE_OPTIONAL_HEADER)Temp_ptr;

			Temp_ptr = (DWORD*)((char*)data.my_optional + data.my_file->SizeOfOptionalHeader);
			data.my_section = nullptr;
			data.my_section = (PIMAGE_SECTION_HEADER*)malloc(sizeof(PIMAGE_SECTION_HEADER) * data.my_file->NumberOfSections);
			for (int i = 0; i < data.my_file->NumberOfSections; i++)
			{
				data.my_section[i] = (PIMAGE_SECTION_HEADER)Temp_ptr;
				Temp_ptr = (DWORD*)((char*)Temp_ptr + 0x28);
			}
			Analyze_Data_Directory(data);
			PIMAGE_EXPORT_DIRECTORY my_export_directory_ptr = (PIMAGE_EXPORT_DIRECTORY)((DWORD)data.my_Data_Directory[0]->VirtualAddress + (DWORD)data.Stretch_Data);
			data.my_Export_Directory = my_export_directory_ptr;
			DWORD AddressOfFunctions_ptr = (DWORD)((DWORD)my_export_directory_ptr->AddressOfFunctions + (DWORD)data.Stretch_Data);
			DWORD AddressOfNames_ptr = (DWORD)((DWORD)my_export_directory_ptr->AddressOfNames + (DWORD)data.Stretch_Data);
			DWORD AddressOfNameOrdinals_ptr = (DWORD)((DWORD)my_export_directory_ptr->AddressOfNameOrdinals + (DWORD)data.Stretch_Data);
			Analyze_Import_Table(data);
			return;
		}
		cout << "分析PE结构失败!" << endl;
	}

	if (num == 3)
	{
		if (data.Shrink_Data != nullptr)
		{
			DWORD* Temp_ptr = (DWORD*)data.Shrink_Data;
			data.my_dos = (PIMAGE_DOS_HEADER)Temp_ptr;

			Temp_ptr = (DWORD*)((char*)data.Shrink_Data + data.my_dos->e_lfanew);
			Temp_ptr++;
			data.my_file = (PIMAGE_FILE_HEADER)Temp_ptr;

			Temp_ptr = (DWORD*)((char*)Temp_ptr + 0x14);
			data.my_optional = (PIMAGE_OPTIONAL_HEADER)Temp_ptr;

			Temp_ptr = (DWORD*)((char*)data.my_optional + data.my_file->SizeOfOptionalHeader);
			data.my_section = (PIMAGE_SECTION_HEADER*)malloc(sizeof(PIMAGE_SECTION_HEADER) * data.my_file->NumberOfSections);
			for (int i = 0; i < data.my_file->NumberOfSections; i++)
			{
				data.my_section[i] = (PIMAGE_SECTION_HEADER)Temp_ptr;
				Temp_ptr = (DWORD*)((char*)Temp_ptr + 0x28);
			}
			Analyze_Data_Directory(data);
			return;
		}
		cout << "分析pe结构失败!" << endl;
	}

}

//拉伸PE结构   注意看PIMAGE_XXX_HEADER的定义,它们本就是指向结构体的指针
void PE::Stretch_PE(Data& my_data)
{
	unsigned Memory_Size = 0;
	Memory_Size = my_data.my_optional->SizeOfImage;
	my_data.Stretch_Data = (void*)malloc(sizeof(char) * Memory_Size);
	memset(my_data.Stretch_Data, 0, Memory_Size);
	void* temp_before_stretch_data_ptr = my_data.Before_Stretch_Data;
	int size_of_dos = 0x40;
	int size_of_junk = 0x40;
	int size_of_file = 0x18;
	unsigned Size_Of_Optional = my_data.my_file->SizeOfOptionalHeader;
	unsigned Size_Of_Section = 0x28;
	unsigned Size_Of_Header = my_data.my_optional->SizeOfHeaders;//还未对齐
	memcpy_s(my_data.Stretch_Data, Memory_Size, my_data.Before_Stretch_Data, Size_Of_Header);
	void* temp_stretch_data = my_data.Stretch_Data;
	//现在计算head头对齐后的大小
	int Size = Size_Of_Header % my_data.my_optional->SectionAlignment;
	Size_Of_Header = my_data.my_optional->SectionAlignment * Size;


	for (int i = 0; i < my_data.my_file->NumberOfSections; i++)
	{
		temp_stretch_data = (void*)((char*)my_data.Stretch_Data + my_data.my_section[i]->VirtualAddress);
		temp_before_stretch_data_ptr = (void*)((char*)my_data.Before_Stretch_Data + my_data.my_section[i]->PointerToRawData);
		memcpy_s(temp_stretch_data, my_data.my_section[i]->SizeOfRawData, temp_before_stretch_data_ptr, my_data.my_section[i]->SizeOfRawData);
	}
	cout << "拉伸成功" << endl;
}



void PE::Shrink_PE(Data& my_data)
{
	unsigned int Size = 0;
	Size = my_data.my_section[my_data.my_file->NumberOfSections - 1]->PointerToRawData + my_data.my_section[my_data.my_file->NumberOfSections - 1]->SizeOfRawData;
	my_data.Shrink_Data = (void*)malloc(Size);
	memset(my_data.Shrink_Data, 0, Size);
	//从Stretch_Data缩小

	//复制Heads
	memcpy_s(my_data.Shrink_Data, my_data.my_optional->SizeOfHeaders, my_data.Stretch_Data, my_data.my_optional->SizeOfHeaders);

	//复制节
	void* temp_shrink_data_ptr = my_data.Shrink_Data;
	void* temp_stretch_data_ptr = my_data.Stretch_Data;
	for (int i = 0; i < my_data.my_file->NumberOfSections; i++)
	{
		temp_shrink_data_ptr = (void*)((char*)my_data.Shrink_Data + my_data.my_section[i]->PointerToRawData);
		temp_stretch_data_ptr = (void*)((char*)my_data.Stretch_Data + my_data.my_section[i]->VirtualAddress);
		memcpy_s(temp_shrink_data_ptr, my_data.my_section[i]->SizeOfRawData, temp_stretch_data_ptr, my_data.my_section[i]->SizeOfRawData);
	}
	cout << "缩小成功" << endl;
	return;

}


int main()
{
	char filename[100] = "Afkayas.1.Exe";
	PE my_pe;
	Data my_data;
	my_pe.Readfile(filename, my_data);
	my_pe.Analyze_PE(my_data, 1);   //char*& Data, PIMAGE_DOS_HEADER& dos, PIMAGE_FILE_HEADER& file, PIMAGE_OPTIONAL_HEADER32& optional, PIMAGE_SECTION_HEADER*& section
	my_pe.Stretch_PE(my_data);
	my_pe.Analyze_PE(my_data, 2);
	my_pe.Shrink_PE(my_data);
	my_pe.Analyze_Data_Directory(my_data);
	//my_pe.Print_IMAGE_DATA_DIRECTORY(my_data);
	//my_pe.Print_ExportTable(my_data);
	//cout << "转化的文件偏移是" << hex << my_pe.Rva_To_Foa(0x3100, my_data) << endl;
	((void(*)())addr)();//调用
	//HMODULE hDll = GetModuleHandleA("Dll1.dll");
	//my_pe.GetFunctionAddrByName(my_data, (char*)"Print");
	//my_pe.GetFunctionAddrByOrdinal(my_data, 14);
	//my_pe.Print_ExportTable(my_data);
	//cout << hex << "0x" << my_pe.Rva_To_Foa(0x6000, my_data) << endl;
	//my_pe.Print_Relocation(my_data);
	//cout << hex << my_pe.Rva_To_Foa(0x1b0e0, my_data) << endl;
	my_pe.Remove_Export_Table(my_data);
	//my_pe.Remove_Relocation(my_data);
	//my_pe.Analyze_Import_Table(my_data);
	//my_pe.Print_Import_Table(my_data);
	my_pe.Print_INT(my_data);
	my_pe.Print_IAT(my_data);
	my_pe.Print_BOUND_IMPORT(my_data);
	my_pe.Import_Table_Injection(my_data);
	
	return 0;
}

有错请师父不吝指出,万分感谢

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1129813.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在家制作电子相册一定需要的一款工具

​随着科技的发展&#xff0c;越来越多的人开始喜欢在家制作电子相册&#xff0c;记录自己的生活点滴。那么&#xff0c;如何在家制作电子相册呢&#xff1f; 一款好的工具是必不可少的。可以使用这款工具&#xff0c;轻松上手----FLBOOK在线制作电子杂志平台 1.打开FLBOOK在线…

手撕Vue-实现事件相关指令

经过上一篇文章的学习&#xff0c;实现了界面驱动数据更新&#xff0c;接下来实现一下其它相关的指令&#xff0c;比如事件相关的指令&#xff0c;v-on 这个指令的使用频率还是很高的&#xff0c;所以我们先来实现这个指令。 v-on 的作用是什么&#xff0c;是不是可以给某一个元…

SpringCloud复习:(3)LoadBalancerInterceptor

使用Ribbon时&#xff0c;execute方法会由RibbonLoadBalancerClient类来实现 它会调用重载的execute方法 getLoadBalancer默认会返回ZoneAwareLoadBalancer&#xff08;基类是BaseLoadBalancer).此处调用的getServer方法就会根据负载均衡策略选择适当的服务器来为下一步的htt…

电脑缺失duilib.dll是什么情况,有什么办法可以解决duilib.dll缺失

在使用电脑时突然提示duilib.dll丢失&#xff0c;这是什么情况&#xff1f;有什么办法可以解决这个问题呢&#xff1f;今天就给大家分享几种解决duilib.dll丢失的办法&#xff0c;解决duilib.dll丢失的办法其实还是非常的简单的&#xff0c;来看看有什么办法可以解决duilib.dll…

使用Spring Boot限制在一分钟内某个IP只能访问10次

有些时候&#xff0c;为了防止我们上线的网站被攻击&#xff0c;或者被刷取流量&#xff0c;我们会对某一个ip进行限制处理&#xff0c;这篇文章&#xff0c;我们将通过Spring Boot编写一个小案例&#xff0c;来实现在一分钟内同一个IP只能访问10次&#xff0c;当然具体数值&am…

【Happy!1024】C++智能指针

&#x1f34e; 博客主页&#xff1a;&#x1f319;披星戴月的贾维斯 &#x1f34e; 欢迎关注&#xff1a;&#x1f44d;点赞&#x1f343;收藏&#x1f525;留言 &#x1f347;系列专栏&#xff1a;&#x1f319; C/C专栏 &#x1f319;请不要相信胜利就像山坡上的蒲公英一样唾…

【计算摄像学】博资考

TOC 本博客将覆盖的内容&#xff1a; 数字相机&#xff08;Digital Camera&#xff09; 小孔成像模型&#xff08;pinhole imaging model&#xff09; 如下图所示&#xff0c;物体反射的光线射向四面八方&#xff0c;直接使用传感器无法直接得到物体形貌。 小孔成像模型在传…

Spring中AOP详解

目录 一、AOP的概念 二、AOP的底层实现原理 2.1 JDK的动态代理 2.1.1 invocationhandler接口 2.1.2 代理对象和原始类实现相同的接口 interfaces 2.1.3 类加载器ClassLoador 2.1.4 编码实现 2.2 Cglib动态代理 2.2.1 Cglib动态代理编码实现 三、AOP如何通过原始对象的id获取到代…

PCL入门1之点云读取及可视化

0 引言 本文主要记录在Ubuntu系统的PCL点云库安装过程&#xff0c;以及PCL点云读取和可视化的c代码示例。 1 PCL安装 本文是安装了pcl1.8大版本&#xff0c;可先下载 下载pcl 1.8.1 版本&#xff08;点击Source code(zip&#xff09; 先安装pcl1.8.1所需的依赖库&#xff1…

【在英伟达nvidia的jetson-orin-nx和PC电脑ubuntu20.04上-装配ESP32开发调试环境-基础测试】

【在英伟达nvidia的jetson-orin-nx和PC电脑ubuntu20.04上-装配ESP32开发调试环境-基础测试】 1、概述2、实验环境3、 物品说明4、参考资料与自我总结5、实验过程1、创建目录2、克隆下载文件3、 拉取子目录安装和交叉编译工具链等其他工具4、添加环境变量6、将样例文件拷贝到桌面…

使用el-tree问题之清空勾数据不生效

一、问题场景描述 在做角色菜单按钮权限时&#xff0c;多数采用树结构勾选数据&#xff0c;这里使用了element中的el-tree。如下图&#xff1a; 1、我给角色1勾选了权限列表数据的前三行&#xff0c; 点击弹框的确定 2、紧接着点击角色2的权限按钮&#xff0c;给角色2分配修…

Lvs +keepalivede : 高可用集群

keepalived为Ivs应运而生的高可用服务。Ivs的调度器无法做高可用&#xff0c;于是keepalived这个软件。 实现的是调度器的高可用。 但是: keepalived不是专为Ivs集群服务的&#xff0c;也可以做其他代理服务器的高可用。 lvs的高可用集群&#xff1a;主调度器和备调度器&#…

[springboot源码分析]-Conditional

https://www.baeldung.com/spring-conditional-annotations Condition元数据 1 org.springframework.context.annotation.Conditional 1.1Conditional定义 Target({ElementType.TYPE, ElementType.METHOD}) Retention(RetentionPolicy.RUNTIME) Documented public interface…

区块链技术在现代商业中的应用:打造透明与信任的新经济体系

区块链技术以其独特的不可篡改和去中心化特点&#xff0c;在全球范围内受到了广泛的关注和讨论。从金融、供应链管理到版权保护和身份验证&#xff0c;区块链技术正在逐步改变着传统商业运营模式&#xff0c;为企业和消费者带来更加透明、安全和高效的商业环境。本文将深入探讨…

计算机网络第一章笔记

b站深入浅出计算机网络 微课视频 第一章 概述 因特网概述 区别&#xff1a; 若干节点和链路互连形成网络若干网络通过路由器互连形成互连网&#xff08;互联网&#xff09;因特网是当今世界上最大的互联网 发展的三个阶段&#xff1a; 1969年&#xff0c;第一个分组交换网…

MQTT协议和边缘计算

1.基本概念 MQTT是基于TCP/IP协议栈构建的异步通信消息协议&#xff0c;是一种轻量级的发布、订阅信息传输协议。可以在不可靠的网络环境中进行扩展&#xff0c;适用于设备硬件存储空间或网络带宽有限的场景。使用MQTT协议&#xff0c;消息发送者与接收者不受时间和空间的限制…

【AI视野·今日CV 计算机视觉论文速览 第273期】Mon, 23 Oct 2023

AI视野今日CS.CV 计算机视觉论文速览 Mon, 23 Oct 2023 Totally 73 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computer Vision Papers Using Human-like Mechanism to Weaken Effect of Pre-training Weight Bias in Face-Recognition Convolutional Neural N…

力扣每日一题62:不同路径

题目描述&#xff1a; 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。 问总共有多少条不同的路径&#xff1f; 示例 1&#xff1a; 输入&#xff1a;m 3, n 7 输出&#xff1a;28 示例 2&#xff…

《红蓝攻防对抗实战》八.利用OpenSSL对反弹shell流量进行加密

前文推荐&#xff1a; 《红蓝攻防对抗实战》一. 隧道穿透技术详解《红蓝攻防对抗实战》二.内网探测协议出网之TCP/UDP协议探测出网《红蓝攻防对抗实战》三.内网探测协议出网之HTTP/HTTPS协议探测出网《红蓝攻防对抗实战》四.内网探测协议出网之ICMP协议探测出网《红蓝攻防对抗…

cmp云管平台专业厂商哪家好?有什么优势?

企业上云后&#xff0c;使用CMP云管平台就至关重要了&#xff0c;不仅方便云管理&#xff0c;还能节约云成本&#xff0c;还能保障云资源安全。但很多小伙伴不知道cmp云管平台专业厂商哪家好&#xff1f;有什么优势&#xff1f;这里就简单回答一下。 cmp云管平台专业厂商哪家好…