滴水三期(PE源码)File->FileBuffer->ImageBuffer->存盘

目录

//将文件读入FileBuffer函数    To_FileBuffer

//打印各种头    PE_header_print

//目录项打印    data_dictory_print

//RVA_to_FOA

//FOA_to_RVA

//导出表打印    ExportTable_print

//重定位表打印  Relocation_print

//导入表打印  Import_table_print

//函数名查找函数    GetFunctionAddrByName

//函数序号查找函数    GetFunctionAddrByOrdinals

//FileBuffer_TO_Imagebuffer

//计算文件在硬盘上的大小  computer_buffersize

//Imagebuffer_TO_Newbuffer

//imagebuffer存盘到电脑硬盘上   Save_to_disk  

//向第一个节注入代码  add_shellcode_to_first_section

//向任意节注入代码  add_shellcode_to_specific_section

//求最小公倍数least_common_multiple

//在imagebuffer中新增一个节add_a_section_in_imagebuffer

//在filebuffer中新增一个节add_a_section_in_filebuffer

//扩大最后一个节expand_last_section

//添加shellcode到新增的地方 add_shellcode_to_expanded_section

//合并节 merge_section

//定义函数,能够返回对齐后的大小 aligement_size

//移动导出表move_export_table

//移动重定位表move_relocation_table

//修复重定位表repair_relocation


#define _CRT_SECURE_NO_DEPRECATE 1

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef unsigned short WORD;
typedef unsigned int DWORD;
typedef unsigned char BYTE;
#define IMAGE_SIZEOF_SHORT_NAME 8
#define MessageBox 0x76250D80
BYTE shellcode[] = { 0x6A,02,0x6A,00, 0x6A,00, 0x6A,00,
					0xE8,00,00,00,00,
					0xE9,00,00,00,00 };

//DOS头
struct _IMAGE_DOS_HEADER {
	WORD e_magic;  //MZ标记
	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];
	DWORD e_lfanew;  //PE文件真正开始的偏移地址
};
//标准PE头
struct _IMAGE_FILE_HEADER {
	WORD Machine;  //文件运行平台
	WORD NumberOfSections;  //节数量
	DWORD TimeDateStamp;  //时间戳
	DWORD PointerToSymbolTable;
	DWORD NumberOfSymbols;
	WORD SizeOfOptionalHeader;  //可选PE头大小
	WORD Characteristics;  //特征值
};
//数据目录
struct _IMAGE_DATA_DIRECTORY {
	DWORD VirtualAddress;  //内存偏移,必须有
	DWORD Size;  //大小,破坏了也不会影响程序运行
};
//可选PE头
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;  //DOS、NT头和节表大小
	DWORD CheckSum;  //校验和
	WORD Subsystem;
	WORD DllCharacteristics;
	DWORD SizeOfStackReserve;  //预留堆栈大小
	DWORD SizeOfStackCommit;  //实际分配堆栈大小
	DWORD SizeOfHeapReserve;  //预留堆大小
	DWORD SizeOfHeapCommit;  //实际分配堆大小
	DWORD LoaderFlags;
	DWORD NumberOfRvaAndSizes;  //目录项数目
	_IMAGE_DATA_DIRECTORY DataDirectory[16];  //这个先不管
};
//NT头
struct _IMAGE_NT_HEADERS {
	DWORD Signature;  //PE签名
	_IMAGE_FILE_HEADER FileHeader;
	_IMAGE_OPTIONAL_HEADER OptionalHeader;
};
//节表
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;  //该节特征属性
};
//导出表
struct _IMAGE_EXPORT_DIRECTORY {
	DWORD Characteristics;  //未使用		
	DWORD TimeDateStamp;  //时间戳		
	WORD MajorVersion;  //未使用		
	WORD MinorVersion;	//未使用		
	DWORD Name;  //指向该导出表文件名字符串  *
	DWORD Base;  //导出函数起始序号  *
	DWORD NumberOfFunctions;  //所有导出函数的个数  *		
	DWORD NumberOfNames;  //以函数名字导出的函数个数  *
	DWORD AddressOfFunctions;  //导出函数地址表RVA  *					
	DWORD AddressOfNames;  //导出函数名称表RVA  *						
	DWORD AddressOfNameOrdinals;  //导出函数序号表RVA  *
};
//重定位表
struct _IMAGE_BASE_RELOCATION {
	DWORD VirtualAddress;
	DWORD SizeOfBlock;
	//具体项
};
//导入表
struct _IMAGE_IMPORT_DESCRIPTOR {
	union {
		DWORD Characteristics;
		DWORD OriginalFirstThunk;  //RVA,指向IMAGE_THUNK_DATA结构数组(INT表)
	};
	DWORD TimeDateStamp;  //时间戳	(用于判断是否有绑定导入表/IAT表中是否已经绑定绝对地址)
	DWORD ForwarderChain;
	DWORD Name;  //RVA,指向dll名字字符串存储地址
	DWORD FirstThunk;  //RVA,指向IMAGE_THUNK_DATA结构数组(IAT表)
};


struct _IMAGE_IMPORT_BY_NAME {
	WORD Hint;  //可能为空(编译器决定);如果不为空,表示函数在导出表中的索引	
	BYTE Name[1];  //函数名称,以0结尾	
};

struct _IMAGE_THUNK_DATA32
{								
	union 
	{
		BYTE ForwarderString;
		DWORD Function;
		DWORD Ordinal;  //序号。最高位为1,代表以序号导出,为0则以名称导出		
		_IMAGE_IMPORT_BY_NAME* AddressOfData;  //RVA,指向IMAGE_IMPORT_BY_NAME
	};
};

//将文件读入FileBuffer函数
char* To_FileBuffer(char* FilePath)
{
	FILE* fp = fopen(FilePath, "rb");
	//printf("fp %p",fp);
	if (fp == NULL)
	{
		printf("open the file error");
		exit(0);
	}
	fseek(fp, 0, 2);
	DWORD size = ftell(fp);
	fseek(fp, 0, 0);

	char* mp = (char*)malloc(sizeof(char) * size);
	if (mp == NULL)
	{
		printf("malloc error");
		fclose(fp);//失败了就关闭打开的文件
		exit(0);
	}

	int  succeed = fread(mp, size, 1, fp);//fread的返回值是读取成功的数字。
	if (succeed == 0)
	{
		printf("file read to filebuffer error");
		fclose(fp);
		free(mp);
		exit(0);
	}
	fclose(fp);
	return mp;

}
//打印各种头
void PE_header_print(char* FilePath)
{
	char* filebuffer = To_FileBuffer(FilePath);
	_IMAGE_DOS_HEADER* dos_header = NULL;
	_IMAGE_FILE_HEADER* file_header = NULL;
	_IMAGE_OPTIONAL_HEADER* optional_header = NULL;
	_IMAGE_NT_HEADERS* nt_header = NULL;
	dos_header = (_IMAGE_DOS_HEADER*)filebuffer;
	nt_header = (_IMAGE_NT_HEADERS*)((char*)dos_header + dos_header->e_lfanew);
	file_header = (_IMAGE_FILE_HEADER*)((char*)nt_header + 4);
	optional_header = (_IMAGE_OPTIONAL_HEADER*)((char*)file_header + 20);
	printf("-------DOS--头\n");
	printf("e_magic:%X\n", dos_header->e_magic);
	printf("e_lfanew:%X\n", dos_header->e_lfanew);
	printf("-------NT--头\n");
	printf("Signature:%X\n", nt_header->Signature);
	printf("-------file--头\n");
	printf("NumberOfSections:%X\n", file_header->NumberOfSections);
	printf("SizeOfOptionalHeader:%X\n", file_header->SizeOfOptionalHeader);
	printf("-------optional--头\n");
	printf("FileAlignment:%X\n", optional_header->FileAlignment);
	printf("AddressOfEntryPoint:%X\n", optional_header->AddressOfEntryPoint);
	printf("Magic:%X\n", optional_header->Magic);
	printf("ImageBase:%X\n", optional_header->ImageBase);
	printf("SizeOfImage:%X\n", optional_header->SizeOfImage);

	_IMAGE_DATA_DIRECTORY* data_directory = optional_header->DataDirectory;//目录项地址
	printf("data_directory:%p\n", data_directory);
	printf("optional_header->NumberOfRvaAndSizes:%X\n", optional_header->NumberOfRvaAndSizes);
	char* arr[16] = { (char*)"IMAGE_DIRECTORY_ENTRY_EXPORT(导出表)          ",
						(char*)"IMAGE_DIRECTORY_ENTRY_IMPORT(导入表)          ",
						(char*)"IMAGE_DIRECTORY_ENTRY_RESOURCE(资源表)        ",
						(char*)"IMAGE_DIRECTORY_ENTRY_EXCEPTION(异常信息表)   ",
						(char*)"IMAGE_DIRECTORY_ENTRY_SECURITY(安全证书表)    ",
						(char*)"IMAGE_DIRECTORY_ENTRY_BASERELOC(重定位表)     ",
						(char*)"IMAGE_DIRECTORY_ENTRY_DEBUG(调试信息表)       ",
						(char*)"IMAGE_DIRECTORY_ENTRY_COPYRIGHT(版权所有表)   ",
						(char*)"IMAGE_DIRECTORY_ENTRY_GLOBALPTR(全局指针表)   ",
						(char*)"IMAGE_DIRECTORY_ENTRY_TLS(TLS表)              ",
						(char*)"IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG(加载配置表) ",
						(char*)"IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT(绑定导入表)",
						(char*)"IMAGE_DIRECTORY_ENTRY_IAT(IAT表)              ",
						(char*)"IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT(延迟导入表)",
						(char*)"IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR(COM信息表)",
						(char*)"保留                                           "
	};

	for (DWORD i = 0; i < optional_header->NumberOfRvaAndSizes; i++)
	{
		printf("%s VirtualAddress:%08X  Size:%08X\n", arr[i], data_directory->VirtualAddress, data_directory->Size);
		data_directory++;
	}

}
//目录项打印
void data_dictory_print(char* filepath)
{
	char* filebuffer = To_FileBuffer(filepath);
	_IMAGE_DOS_HEADER* dos_header = NULL;
	_IMAGE_FILE_HEADER* file_header = NULL;
	_IMAGE_OPTIONAL_HEADER* optional_header = NULL;
	_IMAGE_NT_HEADERS* nt_header = NULL;
	_IMAGE_DATA_DIRECTORY* data_directory = NULL;
	dos_header = (_IMAGE_DOS_HEADER*)filebuffer;
	nt_header = (_IMAGE_NT_HEADERS*)((char*)dos_header + dos_header->e_lfanew);
	file_header = (_IMAGE_FILE_HEADER*)((char*)nt_header + 4);
	optional_header = (_IMAGE_OPTIONAL_HEADER*)((char*)file_header + 20);
	data_directory = (_IMAGE_DATA_DIRECTORY*)optional_header->DataDirectory;//目录项首地址

	char* arr[16] = { (char*)"IMAGE_DIRECTORY_ENTRY_EXPORT(导出表)          ",
						(char*)"IMAGE_DIRECTORY_ENTRY_IMPORT(导入表)          ",
						(char*)"IMAGE_DIRECTORY_ENTRY_RESOURCE(资源表)        ",
						(char*)"IMAGE_DIRECTORY_ENTRY_EXCEPTION(异常信息表)   ",
						(char*)"IMAGE_DIRECTORY_ENTRY_SECURITY(安全证书表)    ",
						(char*)"IMAGE_DIRECTORY_ENTRY_BASERELOC(重定位表)     ",
						(char*)"IMAGE_DIRECTORY_ENTRY_DEBUG(调试信息表)       ",
						(char*)"IMAGE_DIRECTORY_ENTRY_COPYRIGHT(版权所有表)   ",
						(char*)"IMAGE_DIRECTORY_ENTRY_GLOBALPTR(全局指针表)   ",
						(char*)"IMAGE_DIRECTORY_ENTRY_TLS(TLS表)              ",
						(char*)"IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG(加载配置表) ",
						(char*)"IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT(绑定导入表)",
						(char*)"IMAGE_DIRECTORY_ENTRY_IAT(IAT表)              ",
						(char*)"IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT(延迟导入表)",
						(char*)"IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR(COM信息表)",
						(char*)"保留                                           "
	};

	for (DWORD i = 0; i < optional_header->NumberOfRvaAndSizes; i++)
	{
		printf("%s VirtualAddress:%08X  Size:%08X\n", arr[i], data_directory->VirtualAddress, data_directory->Size);
		data_directory++;
	}
}
DWORD RVA_to_FOA(char* filebuffer, DWORD RVA)
{
	_IMAGE_DOS_HEADER* dos_header = NULL;
	_IMAGE_FILE_HEADER* file_header = NULL;
	_IMAGE_OPTIONAL_HEADER* optional_header = NULL;
	_IMAGE_NT_HEADERS* nt_header = NULL;
	_IMAGE_SECTION_HEADER* section_header = NULL;

	dos_header = (_IMAGE_DOS_HEADER*)filebuffer;
	nt_header = (_IMAGE_NT_HEADERS*)((char*)dos_header + dos_header->e_lfanew);
	file_header = (_IMAGE_FILE_HEADER*)((char*)nt_header + 4);
	optional_header = (_IMAGE_OPTIONAL_HEADER*)((char*)file_header + 20);
	section_header = (_IMAGE_SECTION_HEADER*)((char*)optional_header + file_header->SizeOfOptionalHeader);

	//先判断address这个地址在那个节中。
	bool flag = 0;
	if (section_header->VirtualAddress > RVA)//说明addres在头里面;
		return RVA;

	for (int i = 0; i < file_header->NumberOfSections; i++)//判断address是否在空白区,如果是空白区,那么filebuffer里面就不会保存,就不存在转FOA了。
	{
		if (RVA >= section_header->VirtualAddress && RVA < section_header->VirtualAddress + section_header->Misc.VirtualSize)
		{
			flag = 1;
			break;
		}
		else
			section_header++;
	}

	if (flag == 0)
	{
		printf("地址不在文件中\n");
		return 0;
	}
	DWORD RVA_offset_to_viturladdress = RVA - section_header->VirtualAddress;//这个vadd距离节起始位置的偏移
	return section_header->PointerToRawData + RVA_offset_to_viturladdress;
}
DWORD FOA_to_RVA(char* filebuffer, DWORD FOA)
{
	_IMAGE_DOS_HEADER* dos_header = NULL;
	_IMAGE_FILE_HEADER* file_header = NULL;
	_IMAGE_OPTIONAL_HEADER* optional_header = NULL;
	_IMAGE_NT_HEADERS* nt_header = NULL;
	_IMAGE_SECTION_HEADER* section_header = NULL;

	dos_header = (_IMAGE_DOS_HEADER*)filebuffer;
	nt_header = (_IMAGE_NT_HEADERS*)((char*)dos_header + dos_header->e_lfanew);
	file_header = (_IMAGE_FILE_HEADER*)((char*)nt_header + 4);
	optional_header = (_IMAGE_OPTIONAL_HEADER*)((char*)file_header + 20);
	section_header = (_IMAGE_SECTION_HEADER*)((char*)optional_header + file_header->SizeOfOptionalHeader);

	//先判断address这个地址在那个节中。
	bool flag = 0;
	if (FOA < section_header->PointerToRawData)//说明addres在头里面;
		return FOA;
	for (int i = 0; i < file_header->NumberOfSections; i++)//判断address是否在节中。在哪一个节中
	{
		DWORD tempSize = section_header->Misc.VirtualSize < section_header->SizeOfRawData ? section_header->Misc.VirtualSize : section_header->SizeOfRawData;//谁小返回谁(例子 a<b?a:b)。 谁大返回谁(a>b?a:b)
		if (FOA >= section_header->PointerToRawData && FOA < section_header->PointerToRawData + tempSize)
		{
			flag = 1;
			break;
		}
		else
			section_header++;
	}
	if (flag == 0)
	{
		printf("FOA地址不在imagebuffer文件中\n");
		return 0;
	}
	DWORD FOA_offset_to_pointrawdata = FOA - section_header->PointerToRawData;//这个FOA距离节起始位置的偏移
	return section_header->VirtualAddress + FOA_offset_to_pointrawdata;
}
//导出表打印
void ExportTable_print(char* filepath)
{
	char* filebuffer = To_FileBuffer(filepath);
	_IMAGE_DOS_HEADER* dos_header = NULL;
	_IMAGE_FILE_HEADER* file_header = NULL;
	_IMAGE_OPTIONAL_HEADER* optional_header = NULL;
	_IMAGE_NT_HEADERS* nt_header = NULL;
	_IMAGE_DATA_DIRECTORY* data_directory = NULL;
	_IMAGE_EXPORT_DIRECTORY* export_directory = NULL;

	dos_header = (_IMAGE_DOS_HEADER*)filebuffer;
	nt_header = (_IMAGE_NT_HEADERS*)((char*)dos_header + dos_header->e_lfanew);
	file_header = (_IMAGE_FILE_HEADER*)((char*)nt_header + 4);
	optional_header = (_IMAGE_OPTIONAL_HEADER*)((char*)file_header + 20);
	data_directory = (_IMAGE_DATA_DIRECTORY*)(optional_header->DataDirectory+0);//指向导出表的目录项地址:导出表为目录项的第0项,目录项指针+0为起始地址;
	if (data_directory->VirtualAddress == 0)
	{
		printf("该PE没有导出表\n");
		exit(0);
	}
	//因为是在filebuffer中,这里全部都是vitaladdress,需要转换为OFA;
	export_directory = (_IMAGE_EXPORT_DIRECTORY*)(RVA_to_FOA(filebuffer, data_directory->VirtualAddress) + (DWORD)filebuffer);
	printf("-----------导出表------------------\n");
	char* name = (char*)(RVA_to_FOA(filebuffer, export_directory->Name) + (DWORD)filebuffer);//export_directory->Name指向的是name的字符串地址,必须要用一个指针接收后打印
	printf("Base:%08X\n", export_directory->Base);
	printf("NumberOfFunctions:%08X\n", export_directory->NumberOfFunctions);
	printf("NumberOfNames:%08X\n", export_directory->NumberOfNames);
	printf("AddressOfFunctions:%08X\n", export_directory->AddressOfFunctions);
	printf("AddressOfNames:%08X\n", export_directory->AddressOfNames);
	printf("AddressOfNameOrdinals:%08X\n", export_directory->AddressOfNameOrdinals);

	printf("-----------函数地址表------------------\n");

	DWORD* functions = (DWORD*)(RVA_to_FOA(filebuffer, export_directory->AddressOfFunctions) + (DWORD)filebuffer);

	for (DWORD i = 0; i < export_directory->NumberOfFunctions; i++)
	{
		printf("函数地址%02d: %08X\n", i + 1, *(functions + i));
	}

	printf("-----------函数名称表------------------\n");
	DWORD* names = (DWORD*)(RVA_to_FOA(filebuffer, export_directory->AddressOfNames) + (DWORD)filebuffer);//先获得导出表名称表的首地址


	for (DWORD i = 0; i < export_directory->NumberOfNames; i++)
	{
		printf("函数名%02d: %08X %s\n", i + 1, *(names + i), (char*)(RVA_to_FOA(filebuffer, *(names + i)) + (DWORD)filebuffer));//将名称表所指向的函数地址转换为FOA地址后 输出。
	}

	printf("-----------函数序号表------------------\n");
	WORD* AddressOfNameOrdinals = (WORD*)(RVA_to_FOA(filebuffer, export_directory->AddressOfNameOrdinals) + (DWORD)filebuffer);

	for (DWORD i = 0; i < export_directory->NumberOfFunctions; i++)
	{
		printf("函数序号%02d: %08X\n", i + 1, *(AddressOfNameOrdinals + i));
	}


}
//重定位表打印
void Relocation_print(char* filepath)
{
	char* filebuffer = To_FileBuffer(filepath);
	_IMAGE_DOS_HEADER* dos_header = NULL;
	_IMAGE_FILE_HEADER* file_header = NULL;
	_IMAGE_OPTIONAL_HEADER* optional_header = NULL;
	_IMAGE_NT_HEADERS* nt_header = NULL;
	_IMAGE_DATA_DIRECTORY* data_directory = NULL;
	_IMAGE_BASE_RELOCATION* relocation_directory = NULL;

	dos_header = (_IMAGE_DOS_HEADER*)filebuffer;
	nt_header = (_IMAGE_NT_HEADERS*)((char*)dos_header + dos_header->e_lfanew);
	file_header = (_IMAGE_FILE_HEADER*)((char*)nt_header + 4);
	optional_header = (_IMAGE_OPTIONAL_HEADER*)((char*)file_header + 20);
	data_directory = (_IMAGE_DATA_DIRECTORY*)(optional_header->DataDirectory + 5);//指向目录项地址,重定位表为目录项的第6项,结构体指针只需要+5;
	if (data_directory->VirtualAddress == 0)
	{
		printf("该PE没有重定位表\n");
		exit(0);
	}
	_IMAGE_BASE_RELOCATION* relocation = (_IMAGE_BASE_RELOCATION*)(RVA_to_FOA(filebuffer, data_directory->VirtualAddress) + (DWORD)filebuffer);//指针指向重定位表
	printf("-----------重定位表--------------\n");
	for (int i = 0; relocation->VirtualAddress != 0; i++)
	{
		printf("第%d块 VirtualAaaress: %08X SizeOfBlock: %08X\n", i + 1, relocation->VirtualAddress, relocation->SizeOfBlock);

		for (DWORD j = 0; j < (relocation->SizeOfBlock - 8) / 2; j++)
		{
			//高四位                                                                           //低12位

			printf("索引:%03d 高4位:%02d  地址:%08X\n", j + 1, *((WORD*)((char*)relocation + 8 + j * 2)) >> 12, relocation->VirtualAddress + (*((WORD*)((char*)relocation + 8 + j * 2)) & 0X0FFF));

		}
		relocation = (_IMAGE_BASE_RELOCATION*)((char*)relocation + relocation->SizeOfBlock);
	}
}
void Import_table_print(char* filebuffer)
{
	_IMAGE_DOS_HEADER* dos_header = NULL;
	_IMAGE_FILE_HEADER* file_header = NULL;
	_IMAGE_OPTIONAL_HEADER* optional_header = NULL;
	_IMAGE_NT_HEADERS* nt_header = NULL;
	_IMAGE_DATA_DIRECTORY* data_directory = NULL;
	_IMAGE_BASE_RELOCATION* relocation_directory = NULL;

	dos_header = (_IMAGE_DOS_HEADER*)filebuffer;
	nt_header = (_IMAGE_NT_HEADERS*)((char*)dos_header + dos_header->e_lfanew);
	file_header = (_IMAGE_FILE_HEADER*)((char*)nt_header + 4);
	optional_header = (_IMAGE_OPTIONAL_HEADER*)((char*)file_header + 20);
	data_directory = (_IMAGE_DATA_DIRECTORY*)(optional_header->DataDirectory + 1);//指向目录项地址,导入表为目录项的第2项,结构体指针只需要+1;

	if (data_directory->VirtualAddress == 0)
	{
		printf("该PE没有导入表\n");
		exit(0);
	}
	_IMAGE_IMPORT_DESCRIPTOR* import_table=(_IMAGE_IMPORT_DESCRIPTOR*)(RVA_to_FOA(filebuffer,data_directory->VirtualAddress)+filebuffer);
	while (1)
	{
		int i = 0;
		for (i = 0; i < sizeof(*import_table); i++)
		{
			if (*((char*)import_table + i) != 0)
			{
				//printf("当前dll导入表结构不全为0\n");
				break;
			}
		}
		if (i == sizeof(*import_table))
		{
			printf("导入表结构内容全部为0,停止打印导入表\n");
			break;
		}
		/*打印导出表*/
		printf("********************导出表***********************\n");
		printf("INT表的RVA:%08X\n", import_table->OriginalFirstThunk);
		printf("IAT表的RVA:%08X\n", import_table->FirstThunk);
		printf("TimeDateStamp:%08X\n", import_table->TimeDateStamp);
		printf("Name的RVA:%08X\n", import_table->Name);
		printf("ForwarderChain:%08X\n", import_table->ForwarderChain);
		
		/*打印INT表*/
		printf("********************INT表***********************\n");
		if (import_table->OriginalFirstThunk != 0)
		{
			_IMAGE_THUNK_DATA32* INT_table = (_IMAGE_THUNK_DATA32*)(RVA_to_FOA(filebuffer, import_table->OriginalFirstThunk) + filebuffer);
			while (INT_table->Ordinal != 0)
			{
				if ((INT_table->Ordinal & 0x80000000) == 0x80000000)//表示这个值最高位为1,以序号导出
				{
					printf("(以序号导出)%d\n", INT_table->Ordinal & 0x7FFFFFFF);
				}
				else
				{
					_IMAGE_IMPORT_BY_NAME* names = (_IMAGE_IMPORT_BY_NAME*)(RVA_to_FOA(filebuffer, INT_table->Ordinal) + filebuffer);
					
					printf("(以名字导出)Hint--> %X %s\n", names->Hint,names->Name);
				}
				INT_table++;
			}
		}
		else
		{
			printf("此dll无INT表\n");
		}
			
		/*打印IAT表*/
		printf("********************IAT表***********************\n");
		_IMAGE_THUNK_DATA32* IAT_table = (_IMAGE_THUNK_DATA32*)(RVA_to_FOA(filebuffer, import_table->FirstThunk) + filebuffer);
		while (IAT_table->Ordinal != 0)
		{
			if ((IAT_table->Ordinal & 0x80000000) == 0x80000000)//表示这个值最高位为1,以序号导出
			{
				printf("(以序号导出)%d\n", IAT_table->Ordinal & 0x7FFFFFFF);
			}
			else
			{
				_IMAGE_IMPORT_BY_NAME* names = (_IMAGE_IMPORT_BY_NAME*)(RVA_to_FOA(filebuffer, IAT_table->Ordinal) + filebuffer);
			

				printf("(以名字导出)Hint--> %X %s\n", names->Hint, names->Name);//错误, 分别是2个字节的。
			}
			IAT_table++;
		}

		import_table++;
	}
}


DWORD GetFunctionAddrByName(char* filebuffer, char* funcName)
{
	_IMAGE_DOS_HEADER* _image_dos_header = NULL;
	_IMAGE_FILE_HEADER* _image_file_header = NULL;
	_IMAGE_OPTIONAL_HEADER* _image_optional_header = NULL;
	_IMAGE_DATA_DIRECTORY* _image_data_directory = NULL;
	_IMAGE_EXPORT_DIRECTORY* _image_export_directory = NULL;
	_image_dos_header = (_IMAGE_DOS_HEADER*)filebuffer;
	_image_file_header = (_IMAGE_FILE_HEADER*)(filebuffer + _image_dos_header->e_lfanew + 4);
	_image_optional_header = (_IMAGE_OPTIONAL_HEADER*)((char*)_image_file_header + 20);
	_image_data_directory = (_IMAGE_DATA_DIRECTORY*)_image_optional_header->DataDirectory;
	if (_image_data_directory->VirtualAddress == 0) {
		printf("此PE文件没有导出表,没有函数导出");
		exit(0);
	}
	//1.先获取导出表指针????????????????????????目录项指向的vitualaddreess   就是导出表指针开始的位置
	_image_export_directory = (_IMAGE_EXPORT_DIRECTORY*)(RVA_to_FOA(filebuffer, _image_data_directory->VirtualAddress) + (DWORD)filebuffer);
	//2.在获取导出表->函数名表   指针
	DWORD* add_of_functionsnames = (DWORD*)(RVA_to_FOA(filebuffer, _image_export_directory->AddressOfNames) + (DWORD)filebuffer);
	DWORD index = 0;
	int flag = 0;
	for (index = 0; index < _image_export_directory->NumberOfNames; index++)
	{
		char* temp = (char*)(RVA_to_FOA(filebuffer, *(add_of_functionsnames)) + (DWORD)filebuffer);
		if (strcmp(temp, funcName) == 0)
		{
			flag = 1;
			break;
		}
		add_of_functionsnames++;
	}
	if (flag == 0)
	{
		printf("没有此导出函数");
		exit(0);
	}
	//3.在获取导出表->函数序号表 指针  ///(序号表是2字节,用word  这里易错!!!!!!!!!!。)
	WORD* add_of_NameOrdinals = (WORD*)(RVA_to_FOA(filebuffer, _image_export_directory->AddressOfNameOrdinals) + (DWORD)filebuffer);
	WORD funindex = *(add_of_NameOrdinals + index);

	//在获取导出表->函数序号表 指针
	DWORD* add_of_Functions = (DWORD*)(RVA_to_FOA(filebuffer, _image_export_directory->AddressOfFunctions) + (DWORD)filebuffer);
	return *(add_of_Functions + funindex);

}
DWORD GetFunctionAddrByOrdinals(char* filebuffer, DWORD ordinal)
{
	_IMAGE_DOS_HEADER* _image_dos_header = NULL;
	_IMAGE_FILE_HEADER* _image_file_header = NULL;
	_IMAGE_OPTIONAL_HEADER* _image_optional_header = NULL;
	_IMAGE_DATA_DIRECTORY* _image_data_directory = NULL;
	_IMAGE_EXPORT_DIRECTORY* _image_export_directory = NULL;
	_image_dos_header = (_IMAGE_DOS_HEADER*)filebuffer;
	_image_file_header = (_IMAGE_FILE_HEADER*)(filebuffer + _image_dos_header->e_lfanew + 4);
	_image_optional_header = (_IMAGE_OPTIONAL_HEADER*)((char*)_image_file_header + 20);
	_image_data_directory = (_IMAGE_DATA_DIRECTORY*)_image_optional_header->DataDirectory;
	if (_image_data_directory->VirtualAddress == 0) {
		printf("此PE文件没有导出表,没有函数导出");
		exit(0);
	}
	//1.先获取导出表指针 目录项指向的vitualaddreess   就是导出表指针开始的位置
	_image_export_directory = (_IMAGE_EXPORT_DIRECTORY*)(RVA_to_FOA(filebuffer, _image_data_directory->VirtualAddress) + (DWORD)filebuffer);
	//判断是否在函数序号表范围内。        函数序号= ordinal-base
	if ((ordinal - _image_export_directory->Base) > _image_export_directory->NumberOfFunctions - 1)
	{
		printf("导出序号有误");
		exit(0);
	}

	DWORD* add_of_functions = (DWORD*)(RVA_to_FOA(filebuffer, _image_export_directory->AddressOfFunctions) + (DWORD)filebuffer);
	//易错。 传入序号还需要减去base
	return *(add_of_functions + (ordinal - _image_export_directory->Base));

}
char* FileBuffer_TO_Imagebuffer(char* filebuffer)
{

	_IMAGE_DOS_HEADER* dos_header = NULL;
	_IMAGE_FILE_HEADER* file_header = NULL;
	_IMAGE_OPTIONAL_HEADER* optional_header = NULL;
	_IMAGE_NT_HEADERS* nt_header = NULL;
	_IMAGE_SECTION_HEADER* section_header = NULL;

	dos_header = (_IMAGE_DOS_HEADER*)filebuffer;
	nt_header = (_IMAGE_NT_HEADERS*)((char*)dos_header + dos_header->e_lfanew);
	file_header = (_IMAGE_FILE_HEADER*)((char*)nt_header + 4);
	optional_header = (_IMAGE_OPTIONAL_HEADER*)((char*)file_header + 20);
	section_header = (_IMAGE_SECTION_HEADER*)((char*)optional_header + file_header->SizeOfOptionalHeader);

	//计算imagebuffer大小。
	DWORD size = optional_header->SizeOfImage;
	char* Imagebuffer = (char*)malloc(sizeof(char) * size);
	if (Imagebuffer == NULL)
	{
		printf("Imagebuffer malloc error");
		exit(0);
	}
	//初始化0 ,Iimagebuffer
	for (DWORD i = 0; i < size; i++)
	{
		*(Imagebuffer + i) = 0x00;
	}
	//拷贝头
	for (DWORD i = 0; i < optional_header->SizeOfHeaders; i++)
	{
		*(Imagebuffer + i) = *((char*)filebuffer + i);

	}
	//拷贝节表
	for (DWORD i = 0; i < file_header->NumberOfSections; i++)
	{
		for (DWORD j = 0; j < section_header->SizeOfRawData; j++)
		{
			*(Imagebuffer + section_header->VirtualAddress + j) = *(filebuffer + section_header->PointerToRawData + j);
		}
		section_header++;
	}
	//printf("Imagebuffer:%X", Imagebuffer);
	return Imagebuffer;
}
int computer_buffersize(char* buffer)
{
	_IMAGE_DOS_HEADER* dos_header = NULL;
	_IMAGE_FILE_HEADER* file_header = NULL;
	_IMAGE_OPTIONAL_HEADER* optional_header = NULL;
	_IMAGE_NT_HEADERS* nt_header = NULL;
	_IMAGE_SECTION_HEADER* section_header = NULL;
	_IMAGE_SECTION_HEADER* last_section_header = NULL;

	dos_header = (_IMAGE_DOS_HEADER*)buffer;
	nt_header = (_IMAGE_NT_HEADERS*)((char*)dos_header + dos_header->e_lfanew);
	file_header = (_IMAGE_FILE_HEADER*)((char*)nt_header + 4);
	optional_header = (_IMAGE_OPTIONAL_HEADER*)((char*)file_header + 20);
	section_header = (_IMAGE_SECTION_HEADER*)((char*)optional_header + file_header->SizeOfOptionalHeader);
	last_section_header = section_header + file_header->NumberOfSections - 1;
	//newbuffer的大小=最后一个节的poiontorawdata+sizeofrawdata
	int newbufferSize = last_section_header->PointerToRawData + last_section_header->SizeOfRawData;
	return newbufferSize;
}
char* Imagebuffer_TO_Newbuffer(char* Imagebuffer)
{
	_IMAGE_DOS_HEADER* dos_header = NULL;
	_IMAGE_FILE_HEADER* file_header = NULL;
	_IMAGE_OPTIONAL_HEADER* optional_header = NULL;
	_IMAGE_NT_HEADERS* nt_header = NULL;
	_IMAGE_SECTION_HEADER* section_header = NULL;
	_IMAGE_SECTION_HEADER* last_section_header = NULL;

	dos_header = (_IMAGE_DOS_HEADER*)Imagebuffer;
	nt_header = (_IMAGE_NT_HEADERS*)((char*)dos_header + dos_header->e_lfanew);
	file_header = (_IMAGE_FILE_HEADER*)((char*)nt_header + 4);
	optional_header = (_IMAGE_OPTIONAL_HEADER*)((char*)file_header + 20);
	section_header = (_IMAGE_SECTION_HEADER*)((char*)optional_header + file_header->SizeOfOptionalHeader);
	last_section_header = section_header + file_header->NumberOfSections - 1;
	//newbuffer的大小=最后一个节的poiontorawdata+sizeofrawdata
	DWORD newbufferSize = computer_buffersize(Imagebuffer);
	char* NewBuffer = (char*)malloc(sizeof(char) * newbufferSize);
	if (NewBuffer == NULL)
	{
		printf("newbuffer malloc error");
		exit(0);
	}

	//初始化0 ,Iimagebuffer
	for (DWORD i = 0; i < newbufferSize; i++)
	{
		*(NewBuffer + i) = 0x00;
	}
	//拷贝头
	for (DWORD i = 0; i < optional_header->SizeOfHeaders; i++)
	{
		*(NewBuffer + i) = *((char*)Imagebuffer + i);

	}
	//拷贝节表
	for (DWORD i = 0; i < file_header->NumberOfSections; i++)
	{
		for (DWORD j = 0; j < section_header->SizeOfRawData; j++)
		{

			*(NewBuffer + section_header->PointerToRawData + j) = *(Imagebuffer + section_header->VirtualAddress + j);
		}
		section_header++;
	}
	return NewBuffer;
}
int  Save_to_disk(char* buffer, char* diskpath, int size)
{
	FILE* fp = fopen(diskpath, "wb");
	if (fp == NULL)
	{
		printf("打开存盘文件失败");
		return 0;
	}
	int succeed = fwrite(buffer, 1, size, fp);
	if (succeed == 0)
	{
		free(buffer);
		fclose(fp);
		return 0;
	}
	fclose(fp);
	return 1;
}
//向第一个节中注入代码。
int add_shellcode_to_first_section(char* Imagebuffer)
{
	_IMAGE_DOS_HEADER* dos_header = NULL;
	_IMAGE_FILE_HEADER* file_header = NULL;
	_IMAGE_OPTIONAL_HEADER* optional_header = NULL;
	_IMAGE_NT_HEADERS* nt_header = NULL;
	_IMAGE_SECTION_HEADER* section_header = NULL;
	_IMAGE_SECTION_HEADER* last_section_header = NULL;

	dos_header = (_IMAGE_DOS_HEADER*)Imagebuffer;
	nt_header = (_IMAGE_NT_HEADERS*)((char*)dos_header + dos_header->e_lfanew);
	file_header = (_IMAGE_FILE_HEADER*)((char*)nt_header + 4);
	optional_header = (_IMAGE_OPTIONAL_HEADER*)((char*)file_header + 20);
	section_header = (_IMAGE_SECTION_HEADER*)((char*)optional_header + file_header->SizeOfOptionalHeader);

	//首先判断节中的空白区是否能放的下shellcoded的代码大小。假定sizeofrawdata>vituralsize
	if (section_header->SizeOfRawData - section_header->Misc.VirtualSize < sizeof(shellcode) / sizeof(shellcode[0]))
	{
		printf("第一个节的空白区不足");
		return 0;
	}
	//空白区足够的话,就拷贝数据过去,拷贝到虚拟地址中去, 从imagebuffer+sec_>vituraladd+vtsize的地方开始,拷贝shellcode个字节。
	char* shellcodeP = Imagebuffer + section_header->VirtualAddress + section_header->Misc.VirtualSize;
	char* New_OEP = shellcodeP;
	//拷贝代码到shellcodeP,从shellcode开始,拷贝N个字节。
	memcpy(shellcodeP, shellcode, sizeof(shellcode) / sizeof(shellcode[0]));
	//修改E8后面4个字节的地址。
	//E8的地址=messagebox的地址-(E8当前地址+5)
	//E8的地址=messagebox的地址-(shellcodeP+8+5)这个地址是错误的,因为imagebuffer是mallco的,需要切换到运行的地址imagebase。
	//E8的地址=messagebox的地址-(shellcodeP-imagebuffer+imagebase+8+5);
	DWORD E8_address = MessageBox - (shellcodeP - Imagebuffer + optional_header->ImageBase + 8 + 5);

	//把E8的地方放到shellcodeP往后9个字节(4个6A 00+e8)里面去
	*((DWORD*)(shellcodeP + 9)) = E8_address;
	//e9的地址=真正跳转的地址(oep+imagebase)-E9当前的地址的下一条地址(shellcodeP+9+5-Imagebuffer)
	//
	DWORD E9_address = (optional_header->AddressOfEntryPoint + optional_header->ImageBase) - (shellcodeP + 8 + 5 + 5 - Imagebuffer + optional_header->ImageBase);
	*((DWORD*)(shellcodeP + 9 + 5)) = E9_address;

	//EOP还没有修改的。eop=shellcodeP-imagebuffer

	optional_header->AddressOfEntryPoint = DWORD(New_OEP - Imagebuffer);
	return 1;
}
//向任意节中注入代码
int add_shellcode_to_specific_section(char* Imagebuffer, int section_num)
{
	_IMAGE_DOS_HEADER* dos_header = NULL;
	_IMAGE_FILE_HEADER* file_header = NULL;
	_IMAGE_OPTIONAL_HEADER* optional_header = NULL;
	_IMAGE_NT_HEADERS* nt_header = NULL;
	_IMAGE_SECTION_HEADER* section_header = NULL;
	_IMAGE_SECTION_HEADER* last_section_header = NULL;

	dos_header = (_IMAGE_DOS_HEADER*)Imagebuffer;
	nt_header = (_IMAGE_NT_HEADERS*)((char*)dos_header + dos_header->e_lfanew);
	file_header = (_IMAGE_FILE_HEADER*)((char*)nt_header + 4);
	optional_header = (_IMAGE_OPTIONAL_HEADER*)((char*)file_header + 20);
	section_header = (_IMAGE_SECTION_HEADER*)((char*)optional_header + file_header->SizeOfOptionalHeader);
	if (section_num <= 0 || section_num > file_header->NumberOfSections)
	{
		printf("您所输入的节不存在");
		return 0;
	}

	//要注入内容所在节的指针
	_IMAGE_SECTION_HEADER* target_section_header = section_header + section_num - 1;

	//首先判断节中的空白区是否能放的下shellcoded的代码大小。假定sizeofrawdata>vituralsize
	if (target_section_header->SizeOfRawData - target_section_header->Misc.VirtualSize < sizeof(shellcode) / sizeof(shellcode[0]))
	{
		printf("注入的空白区不足");
		return 0;
	}
	//空白区足够的话,就拷贝数据过去,拷贝到虚拟地址中去, 从imagebuffer+sec_>vituraladd+vtsize的地方开始,拷贝shellcode个字节。
	char* shellcodeP = Imagebuffer + target_section_header->VirtualAddress + target_section_header->Misc.VirtualSize;
	char* New_OEP = shellcodeP;
	//拷贝代码到shellcodeP,从shellcode开始,拷贝N个字节。
	memcpy(shellcodeP, shellcode, sizeof(shellcode) / sizeof(shellcode[0]));
	//修改E8后面4个字节的地址。
	//E8的地址=messagebox的地址-(E8当前地址+5)
	//E8的地址=messagebox的地址-(shellcodeP+8+5)这个地址是错误的,因为imagebuffer是mallco的,需要切换到运行的地址imagebase。
	//E8的地址=messagebox的地址-(shellcodeP-imagebuffer+imagebase+8+5);
	DWORD E8_address = MessageBox - (shellcodeP - Imagebuffer + optional_header->ImageBase + 8 + 5);

	//把E8的地方放到shellcodeP往后9个字节(4个6A 00+e8)里面去
	*((DWORD*)(shellcodeP + 9)) = E8_address;
	//e9的地址=真正跳转的地址(oep+imagebase)-E9当前的地址的下一条地址(shellcodeP+9+5-Imagebuffer)
	//
	DWORD E9_address = (optional_header->AddressOfEntryPoint + optional_header->ImageBase) - (shellcodeP + 8 + 5 + 5 - Imagebuffer + optional_header->ImageBase);
	*((DWORD*)(shellcodeP + 9 + 5)) = E9_address;

	//EOP还没有修改的。eop=shellcodeP-imagebuffer
	optional_header->AddressOfEntryPoint = DWORD(New_OEP - Imagebuffer);

	//任意节修改的话, 还需要将属性修改, 否则只可读的节不能写入。用|运算解决。
	target_section_header->Characteristics = target_section_header->Characteristics | 0x60000020;
	return 1;
}
//求最小公倍数
int least_common_multiple(int a, int b)
{
	if (a <= 0 || b <= 0)
	{
		return -1;
	}
	int max = a > b ? a : b;
	while (1)
	{
		if (max % a == 0 && max % b == 0)
		{
			break;
		}
		max++;
	}
	return max;
}
//文件最后新增一个节
char* add_a_section_in_imagebuffer(char* Imagebuffer)
{
	_IMAGE_DOS_HEADER* dos_header = NULL;
	_IMAGE_FILE_HEADER* file_header = NULL;
	_IMAGE_OPTIONAL_HEADER* optional_header = NULL;
	_IMAGE_NT_HEADERS* nt_header = NULL;
	_IMAGE_SECTION_HEADER* section_header = NULL;
	_IMAGE_SECTION_HEADER* last_section_header = NULL;


	dos_header = (_IMAGE_DOS_HEADER*)Imagebuffer;
	nt_header = (_IMAGE_NT_HEADERS*)((char*)dos_header + dos_header->e_lfanew);
	file_header = (_IMAGE_FILE_HEADER*)((char*)nt_header + 4);
	optional_header = (_IMAGE_OPTIONAL_HEADER*)((char*)file_header + 20);
	section_header = (_IMAGE_SECTION_HEADER*)((char*)optional_header + file_header->SizeOfOptionalHeader);

	//malloc一个空间,大小为新增节大小+原来的sizeofimage;并且初始化为0;
	DWORD expand_value = least_common_multiple(optional_header->FileAlignment, optional_header->SectionAlignment);
	char* NewImageBuffer = (char*)malloc(optional_header->SizeOfImage + expand_value);
	if (NewImageBuffer == NULL)
	{
		printf("新增节malloc失败");
		exit(0);
	}

	for (DWORD i = 0; i < optional_header->SizeOfImage + expand_value; i++)
	{
		*(NewImageBuffer + i) = 0x00;
	}
	//接下来,把原来filebuffer的文件拷贝到Newbuffer里面来。
	memcpy(NewImageBuffer, Imagebuffer, optional_header->SizeOfImage);
	//拷贝完成后,把各种头指向新的Newbuffer.进行各种操作。

	dos_header = (_IMAGE_DOS_HEADER*)NewImageBuffer;
	nt_header = (_IMAGE_NT_HEADERS*)((char*)dos_header + dos_header->e_lfanew);
	file_header = (_IMAGE_FILE_HEADER*)((char*)nt_header + 4);
	optional_header = (_IMAGE_OPTIONAL_HEADER*)((char*)file_header + 20);
	section_header = (_IMAGE_SECTION_HEADER*)((char*)optional_header + file_header->SizeOfOptionalHeader);
	//判断一下 是否可以新增节表。 
	if (optional_header->SizeOfHeaders - (dos_header->e_lfanew + 24 + file_header->SizeOfOptionalHeader + file_header->NumberOfSections * 40) < 80)
	{
		printf("节表空白区不足,无法新增节");
		exit(0);
	}
	//判断节表的后面需要有80个字节的大小的数据必须为0.
	for (DWORD i = 0; i < 80; i++)
	{
		if (*((char*)(section_header + file_header->NumberOfSections) + i) != 0)
		{
			printf("节表后80字节数据不全为0x00,有文件数据,无法新增节表");
			exit(0);
		}
	}

	//新增节表
	DWORD old_sizeofimage = optional_header->SizeOfImage;
	//修改sizeofimage;
	optional_header->SizeOfImage += expand_value;


	_IMAGE_SECTION_HEADER* new_section_header = NULL;
	//上面声明的newsection_header
	new_section_header = section_header + file_header->NumberOfSections;

	//复制第一个节表的信息到新增的节表中去
	for (int i = 0; i < 40; i++)
	{
		*((char*)new_section_header + i) = *((char*)section_header + i);
	}
	file_header->NumberOfSections++;

	//节表添加完成后,修改新增节表信息;
	char* name = (char*)new_section_header->Name;
	char* newname = (char*)".newsec";
	strncpy(name, newname, IMAGE_SIZEOF_SHORT_NAME);
	new_section_header->VirtualAddress = old_sizeofimage;
	new_section_header->Misc.VirtualSize = expand_value;
	//PointerToRawData=上一个节表的pointrawdata+sizorawdata

	new_section_header->PointerToRawData = (new_section_header - 1)->PointerToRawData + (new_section_header - 1)->SizeOfRawData;
	new_section_header->SizeOfRawData = expand_value;
	new_section_header->Characteristics = 0x60000020;
	return NewImageBuffer;
}
char* add_a_section_in_filebuffer(char* filebuffer)
{
	_IMAGE_DOS_HEADER* dos_header = NULL;
	_IMAGE_FILE_HEADER* file_header = NULL;
	_IMAGE_OPTIONAL_HEADER* optional_header = NULL;
	_IMAGE_NT_HEADERS* nt_header = NULL;
	_IMAGE_SECTION_HEADER* section_header = NULL;
	_IMAGE_SECTION_HEADER* last_section_header = NULL;


	dos_header = (_IMAGE_DOS_HEADER*)filebuffer;
	nt_header = (_IMAGE_NT_HEADERS*)((char*)dos_header + dos_header->e_lfanew);
	file_header = (_IMAGE_FILE_HEADER*)((char*)nt_header + 4);
	optional_header = (_IMAGE_OPTIONAL_HEADER*)((char*)file_header + 20);
	section_header = (_IMAGE_SECTION_HEADER*)((char*)optional_header + file_header->SizeOfOptionalHeader);

	//malloc一个空间,大小为新增节大小+原来的sizeofimage;并且初始化为0;
	DWORD expand_value = 0x3000;
	//原来的buffersize.
	DWORD filebuffersize = (section_header + file_header->NumberOfSections - 1)->PointerToRawData + (section_header + file_header->NumberOfSections - 1)->SizeOfRawData;

	char* NewFileBuffer = (char*)malloc(filebuffersize + expand_value);
	if (NewFileBuffer == NULL)
	{
		printf("filebuffer新增节malloc失败");
		exit(0);
	}

	for (DWORD i = 0; i < filebuffersize + expand_value; i++)
	{
		*(NewFileBuffer + i) = 0x00;
	}
	//接下来,把原来filebuffer的文件拷贝到Newbuffer里面来。
	memcpy(NewFileBuffer, filebuffer, filebuffersize);
	//拷贝完成后,把各种头指向新的Newbuffer.进行各种操作。

	dos_header = (_IMAGE_DOS_HEADER*)NewFileBuffer;
	nt_header = (_IMAGE_NT_HEADERS*)((char*)dos_header + dos_header->e_lfanew);
	file_header = (_IMAGE_FILE_HEADER*)((char*)nt_header + 4);
	optional_header = (_IMAGE_OPTIONAL_HEADER*)((char*)file_header + 20);
	section_header = (_IMAGE_SECTION_HEADER*)((char*)optional_header + file_header->SizeOfOptionalHeader);
	//判断一下 是否可以新增节表。 
	if (optional_header->SizeOfHeaders - (dos_header->e_lfanew + 24 + file_header->SizeOfOptionalHeader + file_header->NumberOfSections * 40) < 80)
	{
		printf("节表空白区不足,无法新增节");
		exit(0);
	}
	//判断节表的后面需要有80个字节的大小的数据必须为0.
	for (DWORD i = 0; i < 80; i++)
	{
		if (*((char*)(section_header + file_header->NumberOfSections) + i) != 0)
		{
			printf("节表后80字节数据不全为0x00,有文件数据,无法新增节表");
			exit(0);
		}
	}

	//新增节
	DWORD old_sizeofimage = optional_header->SizeOfImage;
	//修改sizeofimage;
	optional_header->SizeOfImage += expand_value;


	_IMAGE_SECTION_HEADER* new_section_header = NULL;
	//上面声明的newsection_header
	new_section_header = section_header + file_header->NumberOfSections;

	//新增节表。复制第一个节表的信息到新增的节表中去
	for (int i = 0; i < 40; i++)
	{
		*((char*)new_section_header + i) = *((char*)section_header + i);
	}
	file_header->NumberOfSections++;

	//节表添加完成后,修改新增节表信息;
	char* name = (char*)new_section_header->Name;
	char* newname = (char*)".newsec";
	strncpy(name, newname, IMAGE_SIZEOF_SHORT_NAME);
	new_section_header->VirtualAddress = old_sizeofimage;
	new_section_header->Misc.VirtualSize = expand_value;
	//PointerToRawData=上一个节表的pointrawdata+sizorawdata

	new_section_header->PointerToRawData = filebuffersize;
	new_section_header->SizeOfRawData = expand_value;
	new_section_header->Characteristics = 0x00000000;
	for (int i = 0; i < file_header->NumberOfSections; i++)
	{
		new_section_header->Characteristics = new_section_header->Characteristics | (section_header + i)->Characteristics;
	}

	return NewFileBuffer;
}
//扩大最后一个节
char* expand_last_section(char* Imagebuffer)
{
	_IMAGE_DOS_HEADER* dos_header = NULL;
	_IMAGE_FILE_HEADER* file_header = NULL;
	_IMAGE_OPTIONAL_HEADER* optional_header = NULL;
	_IMAGE_NT_HEADERS* nt_header = NULL;
	_IMAGE_SECTION_HEADER* section_header = NULL;

	dos_header = (_IMAGE_DOS_HEADER*)Imagebuffer;
	nt_header = (_IMAGE_NT_HEADERS*)((char*)dos_header + dos_header->e_lfanew);
	file_header = (_IMAGE_FILE_HEADER*)((char*)nt_header + 4);
	optional_header = (_IMAGE_OPTIONAL_HEADER*)((char*)file_header + 20);
	section_header = (_IMAGE_SECTION_HEADER*)((char*)optional_header + file_header->SizeOfOptionalHeader);

	//malloc一个空间,大小为扩大节大小+原来的sizeofimage;并且初始化为0;
	DWORD expand_value = least_common_multiple(optional_header->FileAlignment, optional_header->SectionAlignment);
	char* NewImageBuffer = (char*)malloc(optional_header->SizeOfImage + expand_value);
	if (NewImageBuffer == NULL)
	{
		printf("expand_last_section error");
		exit(0);
	}
	for (DWORD i = 0; i < optional_header->SizeOfImage + expand_value; i++)
	{
		*(NewImageBuffer + i) = 0x00;
	}
	//接下来,把原来Imagebuffer的文件拷贝到NewImageBuffer里面来。
	memcpy(NewImageBuffer, Imagebuffer, optional_header->SizeOfImage);
	//拷贝完成后,把各种头指向新的Newbuffer.进行各种操作。

	dos_header = (_IMAGE_DOS_HEADER*)NewImageBuffer;
	nt_header = (_IMAGE_NT_HEADERS*)((char*)dos_header + dos_header->e_lfanew);
	file_header = (_IMAGE_FILE_HEADER*)((char*)nt_header + 4);
	optional_header = (_IMAGE_OPTIONAL_HEADER*)((char*)file_header + 20);
	section_header = (_IMAGE_SECTION_HEADER*)((char*)optional_header + file_header->SizeOfOptionalHeader);

	//扩大节表
	DWORD old_sizeofimage = optional_header->SizeOfImage;
	//修改sizeofimage;
	optional_header->SizeOfImage += expand_value;

	_IMAGE_SECTION_HEADER* last_section_header = section_header + file_header->NumberOfSections - 1;
	//上面声明的修改的最后一个节表 ,指针指向的是节表的最前,所以要-1;

	//节表扩大完成后,修改节表信息;

	last_section_header->Misc.VirtualSize = old_sizeofimage - last_section_header->VirtualAddress + expand_value;
	last_section_header->SizeOfRawData = last_section_header->Misc.VirtualSize;
	last_section_header->Characteristics = last_section_header->Characteristics | 0x60000020;
	return NewImageBuffer;
}
//添加shellcode到新增的地方。
int add_shellcode_to_expanded_section(char* Imagebuffer)
{
	_IMAGE_DOS_HEADER* dos_header = NULL;
	_IMAGE_FILE_HEADER* file_header = NULL;
	_IMAGE_OPTIONAL_HEADER* optional_header = NULL;
	_IMAGE_NT_HEADERS* nt_header = NULL;
	_IMAGE_SECTION_HEADER* section_header = NULL;

	dos_header = (_IMAGE_DOS_HEADER*)Imagebuffer;
	nt_header = (_IMAGE_NT_HEADERS*)((char*)dos_header + dos_header->e_lfanew);
	file_header = (_IMAGE_FILE_HEADER*)((char*)nt_header + 4);
	optional_header = (_IMAGE_OPTIONAL_HEADER*)((char*)file_header + 20);
	section_header = (_IMAGE_SECTION_HEADER*)((char*)optional_header + file_header->SizeOfOptionalHeader);

	if (least_common_multiple(optional_header->SectionAlignment, optional_header->FileAlignment) < (sizeof(shellcode) / sizeof(shellcode[0])))
	{
		printf("扩大节中的空白区不足");
		return 0;
	}
	char* shellcodeP = Imagebuffer + optional_header->SizeOfImage - least_common_multiple(optional_header->SectionAlignment, optional_header->FileAlignment);
	char* New_OEP = shellcodeP;
	//拷贝代码到shellcodeP,从shellcode开始,拷贝N个字节。
	memcpy(shellcodeP, shellcode, sizeof(shellcode) / sizeof(shellcode[0]));
	//修改E8后面4个字节的地址。
	//E8的地址=messagebox的地址-(E8当前地址+5)
	//E8的地址=messagebox的地址-(shellcodeP+8+5)这个地址是错误的,因为imagebuffer是mallco的,需要切换到运行的地址imagebase。
	//E8的地址=messagebox的地址-(shellcodeP-imagebuffer+imagebase+8+5);
	DWORD E8_address = MessageBox - (shellcodeP - Imagebuffer + optional_header->ImageBase + 8 + 5);

	//把E8的地方放到shellcodeP往后9个字节(4个6A 00+e8)里面去
	*((DWORD*)(shellcodeP + 9)) = E8_address;
	//e9的地址=真正跳转的地址(oep+imagebase)-E9当前的地址的下一条地址(shellcodeP+9+5-Imagebuffer)
	//
	DWORD E9_address = (optional_header->AddressOfEntryPoint + optional_header->ImageBase) - (shellcodeP + 8 + 5 + 5 - Imagebuffer + optional_header->ImageBase);
	*((DWORD*)(shellcodeP + 9 + 5)) = E9_address;

	//EOP还没有修改的。eop=shellcodeP-imagebuffer

	optional_header->AddressOfEntryPoint = DWORD(New_OEP - Imagebuffer);


	return 1;
}
//合并节
char* merge_section(char* Imagebuffer)
{
	_IMAGE_DOS_HEADER* dos_header = NULL;
	_IMAGE_FILE_HEADER* file_header = NULL;
	_IMAGE_OPTIONAL_HEADER* optional_header = NULL;
	_IMAGE_NT_HEADERS* nt_header = NULL;
	_IMAGE_SECTION_HEADER* section_header = NULL;

	dos_header = (_IMAGE_DOS_HEADER*)Imagebuffer;
	nt_header = (_IMAGE_NT_HEADERS*)((char*)dos_header + dos_header->e_lfanew);
	file_header = (_IMAGE_FILE_HEADER*)((char*)nt_header + 4);
	optional_header = (_IMAGE_OPTIONAL_HEADER*)((char*)file_header + 20);
	section_header = (_IMAGE_SECTION_HEADER*)((char*)optional_header + file_header->SizeOfOptionalHeader);

	//修改节表信息,要最后修改节表数目,因为前面会用到。
	section_header->Misc.VirtualSize = optional_header->SizeOfImage - section_header->VirtualAddress;
	section_header->SizeOfRawData = section_header->Misc.VirtualSize;

	for (int i = 1; i < file_header->NumberOfSections; i++)//如果一个节表,就不执行,如果两个节表, 就执行1次,如果3个节表,就或两次。
	{
		section_header->Characteristics = section_header->Characteristics | (section_header + i)->Characteristics;
	}

	for (int i = 0; i < (40 * file_header->NumberOfSections); i++)
	{
		*((char*)(section_header + 1) + i) = 0x00;//把第一个节表后面所有节表信息归零。
	}

	file_header->NumberOfSections = 1;


	return Imagebuffer;
}
//定义函数,能够返回对齐后的大小
int aligement_size(int size, int aligment)
{
	if (size < 0 || aligment <= 0)
	{
		printf("所求的对齐的数据不合法");
	}
	return aligment * (size / aligment + 1);
}
char* move_export_table(char* filebuffer)//移动导出表。
{
	char* newfilebuffer = add_a_section_in_filebuffer(filebuffer);

	_IMAGE_DOS_HEADER* dos_header = NULL;
	_IMAGE_FILE_HEADER* file_header = NULL;
	_IMAGE_OPTIONAL_HEADER* optional_header = NULL;
	_IMAGE_NT_HEADERS* nt_header = NULL;
	_IMAGE_SECTION_HEADER* section_header = NULL;
	_IMAGE_DATA_DIRECTORY* data_directory = NULL;
	_IMAGE_EXPORT_DIRECTORY* export_directory = NULL;

	dos_header = (_IMAGE_DOS_HEADER*)newfilebuffer;
	nt_header = (_IMAGE_NT_HEADERS*)((char*)dos_header + dos_header->e_lfanew);
	file_header = (_IMAGE_FILE_HEADER*)((char*)nt_header + 4);
	optional_header = (_IMAGE_OPTIONAL_HEADER*)((char*)file_header + 20);
	section_header = (_IMAGE_SECTION_HEADER*)((char*)optional_header + file_header->SizeOfOptionalHeader);
	data_directory = (_IMAGE_DATA_DIRECTORY*)optional_header->DataDirectory;

	if (data_directory->VirtualAddress == 0)
	{
		printf("此PE没有导出表");
		free(newfilebuffer);//也不知道需不需要free.
		exit(0);
	}
	export_directory = (_IMAGE_EXPORT_DIRECTORY*)(RVA_to_FOA(newfilebuffer, data_directory->VirtualAddress) + newfilebuffer);//指针指向导出表。//我犯了个错误。用pointrawdata+sizeofrawdata,指针指向文件最后了,应该用pointrawdata+newfilebuffer才对。


	char* CopyStart = (section_header + file_header->NumberOfSections - 1)->PointerToRawData + newfilebuffer;//新增节开始的地方。

	/*复制函数地址表*/
	char* fun_add = RVA_to_FOA(filebuffer, export_directory->AddressOfFunctions) + filebuffer;//原节表中的函数地址表。
	memcpy(CopyStart, fun_add, export_directory->NumberOfFunctions * 4);
	char* fun_add_in_newsection = CopyStart;                                                  //新增节函数地址表。
	CopyStart = CopyStart + export_directory->NumberOfFunctions * 4;      //新增节待copy目的地指针。

	/*复制函数序号表*/
	char* orditiona_add = RVA_to_FOA(newfilebuffer, export_directory->AddressOfNameOrdinals) + newfilebuffer; // 原节表中的函数序号表。
	memcpy(CopyStart, orditiona_add, export_directory->NumberOfNames * 2);
	char* orditiona_add_in_newsection = CopyStart;                                                //新增节函数序号表。
	CopyStart = CopyStart + export_directory->NumberOfFunctions * 2;

	/*复制函数名称表*/
	char* names_add = RVA_to_FOA(newfilebuffer, export_directory->AddressOfNames) + newfilebuffer;//原节表中的函数名称表。
	memcpy(CopyStart, names_add, export_directory->NumberOfNames * 4);
	DWORD* names_add_in_newsection = (DWORD*)CopyStart;                                                    //新增节函数名称表。
	CopyStart = CopyStart + export_directory->NumberOfFunctions * 4;

	/*挨个复制函数名字*/
	for (DWORD i = 0; i < export_directory->NumberOfNames; i++)
	{
		char* name = RVA_to_FOA(newfilebuffer, *(DWORD*)names_add) + newfilebuffer;
		memcpy(CopyStart, name, strlen(name) + 1);
		*names_add_in_newsection = FOA_to_RVA(newfilebuffer, (DWORD)(CopyStart - newfilebuffer));

		CopyStart += (strlen(name) + 1);//新增节copy的指针后移;
		names_add = (char*)((DWORD*)names_add + 1);          //原函数名称表指向下一个函数名称地址。
		names_add_in_newsection++;    //新增节h函数名称表指向下一个函数名称地址。
	}

	/*复制导出表*/
	memcpy(CopyStart, (char*)export_directory, 40);//此时copystart指针指向的就是导出表的地址

	/*修改导出表三个地址参数*/
	export_directory->AddressOfFunctions = FOA_to_RVA(newfilebuffer, (DWORD)(fun_add_in_newsection - newfilebuffer));
	export_directory->AddressOfNameOrdinals = FOA_to_RVA(newfilebuffer, (DWORD)(orditiona_add_in_newsection - newfilebuffer));
	export_directory->AddressOfNames = FOA_to_RVA(newfilebuffer, (DWORD)((char*)names_add_in_newsection - newfilebuffer));

	/*修改目录项vitualaddress地址参数*/
	data_directory->VirtualAddress = FOA_to_RVA(newfilebuffer, (DWORD)(CopyStart - newfilebuffer));

	return newfilebuffer;
}
char* move_relocation_table(char* filebuffer)
{
	char* newfilebuffer = add_a_section_in_filebuffer(filebuffer);

	_IMAGE_DOS_HEADER* dos_header = NULL;
	_IMAGE_FILE_HEADER* file_header = NULL;
	_IMAGE_OPTIONAL_HEADER* optional_header = NULL;
	_IMAGE_NT_HEADERS* nt_header = NULL;
	_IMAGE_SECTION_HEADER* section_header = NULL;
	_IMAGE_DATA_DIRECTORY* data_directory = NULL;

	dos_header = (_IMAGE_DOS_HEADER*)newfilebuffer;
	nt_header = (_IMAGE_NT_HEADERS*)((char*)dos_header + dos_header->e_lfanew);
	file_header = (_IMAGE_FILE_HEADER*)((char*)nt_header + 4);
	optional_header = (_IMAGE_OPTIONAL_HEADER*)((char*)file_header + 20);
	section_header = (_IMAGE_SECTION_HEADER*)((char*)optional_header + file_header->SizeOfOptionalHeader);
	data_directory = (_IMAGE_DATA_DIRECTORY*)(optional_header->DataDirectory + 5);//指向重定位表。 这里指针指向的是目录项[16]的首个元素地址。

	if (data_directory->VirtualAddress == 0)
	{
		printf("此PE没有重定位表");
		free(newfilebuffer);//也不知道需不需要free.
		exit(0);
	}
	_IMAGE_BASE_RELOCATION* relocaltion_table = (_IMAGE_BASE_RELOCATION*)(RVA_to_FOA(newfilebuffer, data_directory->VirtualAddress) + newfilebuffer);//重定位表在FOA中的地址。
	_IMAGE_BASE_RELOCATION* relocaltion_table_temp = relocaltion_table;//定义一个新的指针用来计算重定位表的大小。原来的指针要指向被复制的地方,用来复制内容。
	char* CopyStart = (section_header + file_header->NumberOfSections - 1)->PointerToRawData + newfilebuffer;//新增节指针开始的地方。
	int size = 0;
	for (int i = 0; relocaltion_table_temp->VirtualAddress != 0; i++)
	{
		size += relocaltion_table_temp->SizeOfBlock;
		relocaltion_table_temp = (_IMAGE_BASE_RELOCATION*)((char*)relocaltion_table_temp + relocaltion_table_temp->SizeOfBlock);//指针指向下一个块的vitualaddress;
	}
	size += 8;//最后为0的vitualaddress和sizeofblock,共8字节。
	memcpy(CopyStart, (char*)relocaltion_table, size);//copy结束了之后指针不能往后移动,因为后面没有再复制其他内容了。指针还是指向开始的地方。
	data_directory->VirtualAddress = FOA_to_RVA(newfilebuffer, (DWORD)(CopyStart - newfilebuffer));//修复目录项中的vitualaddress;
	return newfilebuffer;
}
void repair_relocation(char* filebuffer)
{
	_IMAGE_DOS_HEADER* dos_header = NULL;
	_IMAGE_FILE_HEADER* file_header = NULL;
	_IMAGE_OPTIONAL_HEADER* optional_header = NULL;
	_IMAGE_NT_HEADERS* nt_header = NULL;
	_IMAGE_SECTION_HEADER* section_header = NULL;
	_IMAGE_DATA_DIRECTORY* data_directory = NULL;

	dos_header = (_IMAGE_DOS_HEADER*)filebuffer;
	nt_header = (_IMAGE_NT_HEADERS*)((char*)dos_header + dos_header->e_lfanew);
	file_header = (_IMAGE_FILE_HEADER*)((char*)nt_header + 4);
	optional_header = (_IMAGE_OPTIONAL_HEADER*)((char*)file_header + 20);
	section_header = (_IMAGE_SECTION_HEADER*)((char*)optional_header + file_header->SizeOfOptionalHeader);
	data_directory = (_IMAGE_DATA_DIRECTORY*)(optional_header->DataDirectory + 5);//指向重定位表。 这里指针指向的是目录项[16]的首个元素地址。
	if (data_directory->VirtualAddress == 0)
	{
		printf("此PE无重定位表");
		exit(0);
	}
	_IMAGE_BASE_RELOCATION* relocation_table = (_IMAGE_BASE_RELOCATION*)(RVA_to_FOA(filebuffer, data_directory->VirtualAddress) + filebuffer);//重定位表地址

	//修改imagebase
	DWORD old_imagebase = optional_header->ImageBase;
	optional_header->ImageBase = 0x02600000;
	int offset = (int)(optional_header->ImageBase - old_imagebase);
	//修改重定位表,挨个进行遍历
	while (relocation_table->VirtualAddress != 0)
	{
		for (DWORD i = 0; i < (relocation_table->SizeOfBlock - 8) / 2; i++)//遍历的具体项个数为 (sizeofblock-8个字节)/2  ;注 每个具体项占两个字节。
		{
			//如果具体项的高四位==0;那么指针往后移动2字节,         
			if (*((WORD*)((char*)relocation_table + 8 + i * 2)) >> 12 == 0)
			{
				continue;   //continue 不在执行循环的下面的语句,而是返回上面的i++。
			}
			//具体项的低12位+reloccation->vituraladdress,   (206+2000)找到他在文件中的位置的偏移,+filebuffer(1600000)  就是该具体项在文件中的偏移。
			DWORD* repaiAddress = (DWORD*)(RVA_to_FOA(filebuffer, (relocation_table->VirtualAddress + (*((WORD*)((char*)relocation_table + 8 + i * 2)) & 0x0FFF))) + filebuffer);//重定位表所指向的偏移指针
			*repaiAddress += offset;//重定位表所指向的偏移的值
		}
		relocation_table = (_IMAGE_BASE_RELOCATION*)((char*)relocation_table + relocation_table->SizeOfBlock);//具体项循环结束后,指针指向下一个块。
	}
}


int main()
{
	//char* FilePath = (char*)"C:\\Windows\\notepad.exe";
	char* FilePath = (char*)"C:\\Users\\Administrator\\Desktop\\NOTEPAD.EXE";
	//char* disk_path= (char*)"C:\\Users\\Administrator\\Desktop\\PETool 1.0.0.5副本.exe";

	//char* FilePath = (char*)"C:\\Users\\Administrator\\Desktop\\Win网络播放器N5-1214.exe";
	//char* FilePath = (char*)"C:\\Users\\Administrator\\Desktop\\16Edit.DLL";
	//char* disk_path = (char*)"C:\\Users\\Administrator\\Desktop\\16Edit副本.DLL";
	char* filebuffer = To_FileBuffer(FilePath);
	Import_table_print(filebuffer);
	//repair_relocation(filebuffer);
	// char* newbuffer = move_export_table(filebuffer);
   //filebuffer =add_a_section_in_filebuffer(filebuffer);   
   //char* funname = (char*)"dbkFCallWrapperAddr";
   //Relocation_print(FilePath);
   //DWORD XXXX=GetFunctionAddrByName(filebuffer, funname);
   //DWORD XXXX = GetFunctionAddrByOrdinals(filebuffer, 1);
   //printf("%x", XXXX);
   //ExportTable_print(FilePath);
   //char* filebuffer=To_FileBuffer(FilePath);
   //char*Imagebuffer=FileBuffer_TO_Imagebuffer(filebuffer);
   //Imagebuffer = expand_last_section(Imagebuffer);
   //Imagebuffer = merge_section(Imagebuffer);
   //add_shellcode_to_expanded_section(Imagebuffer);

   //add_shellcode_to_specific_section(Imagebuffer,3);
   //char* NewBuffer = Imagebuffer_TO_Newbuffer(Imagebuffer);
	//int size = computer_buffersize(filebuffer);
	//int chenggong = Save_to_disk(filebuffer, disk_path, size);
	//int ccc=aligement_size(1001,400);
	//printf("aligement_size:%d", ccc);


	return 0;
}


  • 12
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个基于 Java 的 Android FTP 服务器的示例代码: ```java import android.os.Environment; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; public class FtpServer implements Runnable { private int port; private boolean running; private ServerSocket serverSocket; private String rootDir; public FtpServer(int port) { this.port = port; this.running = false; this.rootDir = Environment.getExternalStorageDirectory().getAbsolutePath(); } @Override public void run() { try { serverSocket = new ServerSocket(port); running = true; System.out.println("FTP Server started on port " + port); while (running) { Socket clientSocket = serverSocket.accept(); System.out.println("Client connected: " + clientSocket.getInetAddress().getHostAddress()); FtpClientHandler clientHandler = new FtpClientHandler(clientSocket, rootDir); new Thread(clientHandler).start(); } } catch (IOException e) { e.printStackTrace(); } } public void stop() { running = false; try { serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } private class FtpClientHandler implements Runnable { private Socket clientSocket; private String rootDir; public FtpClientHandler(Socket clientSocket, String rootDir) { this.clientSocket = clientSocket; this.rootDir = rootDir; } @Override public void run() { try { BufferedInputStream in = new BufferedInputStream(clientSocket.getInputStream()); BufferedOutputStream out = new BufferedOutputStream(clientSocket.getOutputStream()); out.write("220 Service ready for new user.\r\n".getBytes()); out.flush(); byte[] buffer = new byte[1024]; int bytesRead; String command = ""; while ((bytesRead = in.read(buffer)) != -1) { String request = new String(buffer, 0, bytesRead); System.out.print(request); if (request.trim().equals("QUIT")) { out.write("221 Goodbye.\r\n".getBytes()); out.flush(); break; } else if (request.startsWith("USER ")) { out.write("331 User name okay, need password.\r\n".getBytes()); out.flush(); } else if (request.startsWith("PASS ")) { out.write("230 User logged in, proceed.\r\n".getBytes()); out.flush(); } else if (request.startsWith("PWD")) { out.write(("257 \"" + rootDir + "\" is the current directory.\r\n").getBytes()); out.flush(); } else if (request.startsWith("CWD ")) { String[] tokens = request.split(" "); String dir = tokens[1]; File newDir = new File(rootDir + "/" + dir); if (newDir.exists() && newDir.isDirectory()) { rootDir = newDir.getAbsolutePath(); out.write(("250 Changed to directory \"" + rootDir + "\"\r\n").getBytes()); out.flush(); } else { out.write("550 Failed to change directory.\r\n".getBytes()); out.flush(); } } else if (request.startsWith("LIST")) { File dir = new File(rootDir); File[] files = dir.listFiles(); StringBuilder response = new StringBuilder(); for (File file : files) { String name = file.getName(); String type = file.isDirectory() ? "d" : "-"; String size = String.valueOf(file.length()); response.append(type).append("rw-r--r-- 1 owner group ").append(size).append(" Jan 01 00:00 ").append(name).append("\r\n"); } out.write(("150 Opening data connection for directory list\r\n").getBytes()); out.flush(); Socket dataSocket = new Socket(clientSocket.getInetAddress(), 20); BufferedOutputStream dataOut = new BufferedOutputStream(dataSocket.getOutputStream()); dataOut.write(response.toString().getBytes()); dataOut.flush(); dataOut.close(); dataSocket.close(); out.write("226 Directory send OK.\r\n".getBytes()); out.flush(); } else if (request.startsWith("RETR ")) { String[] tokens = request.split(" "); String fileName = tokens[1]; File file = new File(rootDir + "/" + fileName); if (file.exists() && file.isFile()) { out.write(("150 Opening data connection for " + fileName + "\r\n").getBytes()); out.flush(); Socket dataSocket = new Socket(clientSocket.getInetAddress(), 20); BufferedOutputStream dataOut = new BufferedOutputStream(dataSocket.getOutputStream()); BufferedInputStream fileIn = new BufferedInputStream(new FileInputStream(file)); byte[] fileBuffer = new byte[1024]; int fileBytesRead; while ((fileBytesRead = fileIn.read(fileBuffer)) != -1) { dataOut.write(fileBuffer, 0, fileBytesRead); dataOut.flush(); } fileIn.close(); dataOut.close(); dataSocket.close(); out.write("226 Transfer complete.\r\n".getBytes()); out.flush(); } else { out.write(("550 Failed to open file " + fileName + "\r\n").getBytes()); out.flush(); } } else { out.write("502 Command not implemented.\r\n".getBytes()); out.flush(); } buffer = new byte[1024]; } clientSocket.close(); System.out.println("Client disconnected."); } catch (IOException e) { e.printStackTrace(); } } } } ``` 此代码实现了一个简单的 FTP 服务器,支持用户登录、切换目录、列出文件列表、下载文件等基本功能。请注意,此代码仅供参考,实际使用时需要进行适当修改和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值