// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "string.h"
#include <malloc.h>
#include <windows.h>
//函数声明
LPVOID ReadPEFile(LPSTR FilePath);
void PrintNTHeaders(LPVOID pfilebuf);
void ImageBufferToFileBuffer(LPVOID ImageBuffer);
int getFileSize(FILE* fileAdress);
FILE* openFile(char* filePath, char* type);
int ReadFileSize(char* FilePath);
LPVOID Code_To_Code(LPVOID imageBuffer);
//DWORD NewSeciton(LPVOID pimageBuffer);
//读取文件大小
int ReadFileSize(char* FilePath)
{
FILE* Pfile;//一般使用FILE*类型变量表示文件句柄,通过它来访问FILE结构体,对文件进行操作。
DWORD len;//定义文件长度;
Pfile = fopen(FilePath, "rb+");//pfile可以拿到文件句柄(指针),那样就可以操作了。fopen函数是打开一个文件,其调用的一般形式为:文件指针名=fopen(文件名,使用文件方式);
if (!Pfile)
{
printf("打开文件错误,错误码01");
return NULL;
}
fseek(Pfile, 0, SEEK_END);//把文件指针位置移动到最后面,用来读取大小。函数原形:int fseek(FILE *stream, long offset, int fromwhere);函数设置文件指针stream的位置。如果执行成功,stream将指向以fromwhere(偏移起始位置:文件头0(SEEK_SET),当前位置1(SEEK_CUR),文件尾2(SEEK_END))为基准,偏移offset(指针偏移量)个字节的位置。如果执行失败(比如offset超过文件自身大小),则不改变stream指向的位置。
len = ftell(Pfile); //用ftell函数拿到大小,ftell原型:long ftell(FILE *stream);函数 ftell 用于得到文件位置指针当前位置相对于文件首的偏移字节数。在随机方式存取文件时,由于文件位置频繁的前后移动,程序不容易确定文件的当前位置。
//printf("这个程序的大小为:%d个字节\n", len);//打印文件大小,单位字节。,读取成功66560个字节
return len;
}
//打开文件,并返回指针,LPVOID是暂时没有类型的指针
LPVOID ReadPEFile(char* FilePath)//LPSTR是一种字符串数据类型。LPSTR被定义成是一个指向以NULL(‘\0’)结尾的32位ANSI字符数组指针
{
FILE* Pfile;//一般使用FILE*类型变量表示文件句柄,通过它来访问FILE结构体,对文件进行操作。
LPVOID pfilebuffer; //定义文件缓冲区指针
DWORD len;//定义文件长度;
Pfile = fopen(FilePath, "rb+");//pfile可以拿到文件句柄(指针),那样就可以操作了。fopen函数是打开一个文件,其调用的一般形式为:文件指针名=fopen(文件名,使用文件方式);
if (!Pfile)
{
printf("打开文件错误,错误码01");
return NULL;
}
fseek(Pfile, 0, SEEK_END);//把文件指针位置移动到最后面,用来读取大小。函数原形:int fseek(FILE *stream, long offset, int fromwhere);函数设置文件指针stream的位置。如果执行成功,stream将指向以fromwhere(偏移起始位置:文件头0(SEEK_SET),当前位置1(SEEK_CUR),文件尾2(SEEK_END))为基准,偏移offset(指针偏移量)个字节的位置。如果执行失败(比如offset超过文件自身大小),则不改变stream指向的位置。
len = ftell(Pfile); //用ftell函数拿到大小,ftell原型:long ftell(FILE *stream);函数 ftell 用于得到文件位置指针当前位置相对于文件首的偏移字节数。在随机方式存取文件时,由于文件位置频繁的前后移动,程序不容易确定文件的当前位置。
//printf("这个程序的大小为:%d个字节\n", len);//打印文件大小,单位字节。,读取成功66560个字节
pfilebuffer = malloc(len);//知道大小了后,我们就把pfilebuffer文件缓冲区指针确定大小,用malloc动态分配
fseek(Pfile, 0, SEEK_SET);//然后把文件游标指针拿到最前面来。
if (!pfilebuffer) //判断pfilebuffer获取成功没
{
printf("分配文件缓冲区空间上失败,错误码02");
pfilebuffer = 0;
fclose(Pfile);
return NULL;
}
size_t filebuffer_count = fread(pfilebuffer, 1, len, Pfile); //把len个字节全部读取到pfilebuffer缓冲区中,这里返回的是一个文件字节大小,用于判断是否读取成功函数原型size_t fread(void *buffer, size_t size, size_t count, FILE *stream);//C99前,从给定输入流stream读取最多count个对象到数组buffer中(相当于以对每个对象调用size次fgetc),把buffer当作unsigned char数组并顺序保存结果。流的文件位置指示器前进读取的字节数。
if (!filebuffer_count)
{
printf("读取文件到缓冲区失败,错误码03");
pfilebuffer = 0;
fclose(Pfile);
return 0;
}
//走到这里就读取成功了,返回一个长度为len个字节(含文件数据流)的pfilebuffer缓冲区指针
fclose(Pfile);
return pfilebuffer;
}
//定义一个打印整个PE头+节表目录信息的函数 ,//
void PrintNTHeaders(LPVOID pfilebuf)
{
LPVOID pfilebuffer;//用来接收 ReadPEFile()函数返回得pfilebuffer缓冲区指针;
PIMAGE_DOS_HEADER pDosHeader = NULL; //DOS头指针
PIMAGE_NT_HEADERS32 pNTHeader = NULL;//NT头指针
PIMAGE_FILE_HEADER pFileHeader = NULL;//标准头指针
PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = NULL;//可选头指针
pfilebuffer = pfilebuf; //传入pfilebuffer缓冲区指针;
if (!pfilebuffer)
{
printf("传入pfilebuffer缓冲区指针失败,错误代码04");
free(pfilebuffer);
return;
}
//PWORD在DOS下(实模式)地址是分段的,每一段的长度为64K字节,刚好是16位(二进制的十六位)DOS头刚好64个字节。
if (*((PWORD)pfilebuffer) != IMAGE_DOS_SIGNATURE)
{
printf("EXE不是有效的程序,错误代码05");
free(pfilebuffer);
return;
}
printf("PIGAMGE_DOS_HEADER-DOS头指针大小:%d个字节\n", sizeof(PIMAGE_DOS_HEADER));
pDosHeader = (PIMAGE_DOS_HEADER)pfilebuffer;
printf("DOS头pDosHeader指针大小:%d个字节\n", sizeof(pDosHeader));
//开始打印DOS头
printf("\n=======即将打印DOS头=======\n");
printf("MZ标志:%x\n", pDosHeader->e_magic);
printf("PE头偏移:%x\n", pDosHeader->e_lfanew);//定位PE文件,PE头相对于文件的偏移量
//开始判断PE标志
//printf("IMAGE_NT_SIGNATURE值为:%x", *PWORD((DWORD)pfilebuffer + pDosHeader->e_lfanew)); 其实这里就可以验证了
if ((*PWORD((DWORD)pfilebuffer + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)//说明:pDosHeader->e_lfanew存的是DOS头开始到PE的偏移量,用(DWORD)pfilebuffer指针加上这个偏移量,那么就可以得到PE头的指针偏移量,就得到IMAGE_NT_SIGNATURE值
{
printf("没有找到PE头标志,错误代码06\n");
free(pfilebuffer);
return;
}
pNTHeader = (PIMAGE_NT_HEADERS32)((DWORD)pfilebuffer + pDosHeader->e_lfanew);
//测试打印下NT头
printf("NT头:%x\n", pNTHeader->Signature);
//拿到标准PE头指针
pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
//打印PE标准头结构
printf("===============PE标准头结构===============\n\n\n");
printf("PE-Machine:%x\n", pFileHeader->Machine);
printf("PE结构中节的数量:%x\n", pFileHeader->NumberOfSections);
printf("PE可选PE结构体大小:%d字节\n\n", pFileHeader->SizeOfOptionalHeader);
//拿到可选PE头
pOptionalHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pFileHeader + 20);
printf("===============PE可选头结构===============\n\n\n");
printf("PE可选头指针:%x\n", pOptionalHeader);
printf("PE-Magic:%x\n", pOptionalHeader->Magic);
printf("程序入口OEP地址:%x\n", pOptionalHeader->AddressOfEntryPoint);
printf("PE可选头-SizeOfHeader值:%xH\n那么节表里面的首节地址也应该是:%xH\n", pOptionalHeader->SizeOfHeaders, pOptionalHeader->SizeOfHeaders);
//拿到节表地址:
PIMAGE_SECTION_HEADER pSection = NULL;
pSection = PIMAGE_SECTION_HEADER((DWORD)pOptionalHeader + 224);
printf("pSection地址:%x\n", pSection);
printf("PE节表-第一个节PointerToRawData地址:%x\n", pSection->PointerToRawData);
printf("PE节区地址:%x\n", pSection->VirtualAddress);
printf("pe节区name:%s\n", pSection->Name);
//pSection = PIMAGE_SECTION_HEADER((DWORD)pSection + 40);
//printf("第二个pe节区name:%s\n", pSection->Name);
//======================================//
DWORD dwSection = pFileHeader->NumberOfSections;//定义节区描述文件个数这里有3个
for (DWORD i = 0; i < dwSection; i++, pSection++)
{
printf("\n================第%d个节区描述============\nName:", i + 1);
for (DWORD j = 0; j < IMAGE_SIZEOF_SHORT_NAME; j++)
{
printf("%c", pSection->Name[j]);
}
printf("\nMISC:%d个字节\n",pSection->Misc);//文件中节区实际含有数据的大小
printf("VirtualAddress:%x\n", pSection->VirtualAddress);//在内存中的地址,需要加上ImageBase;
printf("SizeOfRawData:%d个字节\n", pSection->SizeOfRawData);//文件中的节区大小
printf("PointToRawData:%d偏移字节\n", pSection->PointerToRawData);//文件中节区首地址的偏移
printf("Characteristics:%08x\n",pSection->Characteristics);//节属性
printf("\n================第%d个节区描述结束============\n", i + 1);
}
}
//复制FileBuffer到ImageBuffer的函数
//参数1:Filebuffer指针
LPVOID CopyFileBufferToImageBuffer(LPVOID pFileBuffer)
{
LPVOID TempiamgeBuffer = NULL;
PIMAGE_DOS_HEADER pDosHeader1=NULL;
PIMAGE_NT_HEADERS32 pNTHeader1 = NULL;
PIMAGE_FILE_HEADER pFileHeader1 = NULL;
PIMAGE_OPTIONAL_HEADER32 pOptionHeader1 = NULL;
PIMAGE_SECTION_HEADER pSectionHeader1 = NULL;
if (!pFileBuffer)
{
printf("文件指针未获取到,请检查你的参数设置,错误代码07\n");
pFileBuffer = NULL;
return 0;
}
pDosHeader1 = (PIMAGE_DOS_HEADER)pFileBuffer;
if (*((PWORD)pDosHeader1) != IMAGE_DOS_SIGNATURE) //这里为什么要用(PWORD)呢,第一,pDosHeader1指针是4字节,IMAGE_DOS_SIGNATURE的值是两个字节。第二*的操作数必须是一个指针,所以用指向WORD的指针PWORD
{
printf("没有找到MZ标志,错误代码07\n");
pDosHeader1 = NULL;
pFileBuffer = NULL;
return 0 ;
}
//找到所有头
pNTHeader1 = PIMAGE_NT_HEADERS32((DWORD)pDosHeader1 + pDosHeader1->e_lfanew);
if (*(PDWORD)pNTHeader1 != IMAGE_NT_SIGNATURE)
{
printf("没有找到PE标志,错误代码08\n");
pNTHeader1 = NULL;
pFileBuffer = NULL;
return 0 ;
}
pFileHeader1 = PIMAGE_FILE_HEADER((DWORD)pNTHeader1 + 4);
pOptionHeader1 = PIMAGE_OPTIONAL_HEADER32((DWORD)pFileHeader1 + IMAGE_SIZEOF_FILE_HEADER);
pSectionHeader1 = PIMAGE_SECTION_HEADER((DWORD)pOptionHeader1 + pFileHeader1->SizeOfOptionalHeader);
printf("sizeofimage:%d\n", pOptionHeader1->SizeOfImage);
printf("sizeofHeader:%d\n", pOptionHeader1->SizeOfHeaders);
//申请一块动态内存,并用Tempimagebuffer指向他=======================
TempiamgeBuffer = malloc(pOptionHeader1->SizeOfImage + 0x1000);
printf("pOptionHeader1->ImageBase:%x\n", pOptionHeader1->ImageBase);
printf("pOptionHeader1->FileAlignment:%d\n", pOptionHeader1->FileAlignment);
printf("pOptionHeader1->SectionAlignment:%d\n", pOptionHeader1->SectionAlignment);
//判断是否申请成功
if (!TempiamgeBuffer)
{
printf("动态内存申请失败\n,错误代码09");
TempiamgeBuffer = NULL;
free(TempiamgeBuffer);
return 0;
}
//刷新清空这块内存里面的数据memset(TempiamgeBuffer, 0, pOptionHeader1->SizeOfImage+0x1000);//函数原型:void *memset(void *s, int ch, size_t n);将s中当前位置后面的n个字节 (typedef unsigned int size_t )用 ch 替换并返回 s 。
//然后就可以复制了
//函数原型void *memcpy(void *destin, void *source, unsigned n);destin-- 指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。从源source所指的内存地址的起始位置开始拷贝n个字节到目标destin所指的内存地址的起始位置中。
//destin-- 指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。
//source-- 指向要复制的数据源,类型强制转换为 void* 指针。
//n-- 要被复制的字节数。
//复制整个PE头
memcpy(TempiamgeBuffer, pDosHeader1, pOptionHeader1->SizeOfHeaders); //函数原型void *memcpy(void *destin, void *source, unsigned n);destin-- 指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。
//
DWORD dwSection = pFileHeader1->NumberOfSections;//节的个数
PIMAGE_SECTION_HEADER pTempSectionHeader = pSectionHeader1;
for (DWORD i = 0; i < dwSection; i++)
{
memcpy((void*)((DWORD)TempiamgeBuffer + (pTempSectionHeader->VirtualAddress)),((void*)((DWORD)pFileBuffer + pTempSectionHeader->PointerToRawData)), pTempSectionHeader->SizeOfRawData);
//pSectionHeader1 = (PIMAGE_SECTION_HEADER)(pSectionHeader1+sizeof(_IMAGE_SECTION_HEADER));
//PIMAGE_SECTION_HEADER pTempSectionHeader = pSectionHeader1;
pTempSectionHeader++;
}
printf("复制数据到ImageBuffer成功\n");
//memset(TempiamgeBuffer, 0, pOptionHeader1->SizeOfImage); //清空
//free(TempiamgeBuffer);//释放内存
//TempiamgeBuffer = NULL;
// TempiamgeBuffer = Code_To_Code(TempiamgeBuffer);
//printf("TempiamgeBuffer:%x\n", TempiamgeBuffer);
//=========================新增节=====================
PIMAGE_SECTION_HEADER NewSection;
//pSection--;
NewSection = pTempSectionHeader;
pTempSectionHeader--;
NewSection->Name[0] = 'a'; NewSection->Name[1] = 'b'; NewSection->Name[2] = 'c'; NewSection->Name[3] = 'd';
NewSection->Misc.VirtualSize = 0x1000;
NewSection->VirtualAddress = pTempSectionHeader->VirtualAddress + pTempSectionHeader->SizeOfRawData;
NewSection->PointerToRawData = pTempSectionHeader->PointerToRawData + pTempSectionHeader->SizeOfRawData;
NewSection->SizeOfRawData = 0x1000;
int n = (pTempSectionHeader - (pFileHeader1->NumberOfSections - 1))->Characteristics; //这里是取到第一个节表的属性
pFileHeader1->NumberOfSections += 1;
NewSection->Characteristics = n;
pOptionHeader1->SizeOfImage += 0x1000;
memcpy(TempiamgeBuffer, pDosHeader1, pOptionHeader1->SizeOfHeaders);
//在代码节添加代码
TempiamgeBuffer = Code_To_Code(TempiamgeBuffer);
return TempiamgeBuffer;
}
//imagebuffer 到filebuffer
DWORD ImagebufferToFilebuffer(LPVOID imagebuffer)
{
LPVOID TempFileBuffer = NULL;
PIMAGE_DOS_HEADER pDosHeader2 = NULL;
PIMAGE_NT_HEADERS32 pNTHeader2 = NULL;
PIMAGE_FILE_HEADER pFileHeader2 = NULL;
PIMAGE_OPTIONAL_HEADER32 pOptionHeader2 = NULL;
PIMAGE_SECTION_HEADER pSectionHeader2 = NULL;
if (!imagebuffer)
{
printf("ImagebufferToFilebuffer函数没有获取到imagebuffer指针,错误码20");
return 0;
}
if (*(PWORD)((PIMAGE_DOS_HEADER)imagebuffer) != IMAGE_DOS_SIGNATURE)
{
printf("imagebuffer不是有效的MZ");
return 0;
}
pDosHeader2=(PIMAGE_DOS_HEADER)imagebuffer;
pNTHeader2 = (PIMAGE_NT_HEADERS32)((DWORD)pDosHeader2 + pDosHeader2->e_lfanew);
pFileHeader2 = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader2 + 4);
pOptionHeader2 = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pFileHeader2 + IMAGE_SIZEOF_FILE_HEADER);
pSectionHeader2 = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader2 + pFileHeader2->SizeOfOptionalHeader);
//先拿到文件buffer大小
int File_size = ReadFileSize("D:\\ipmsg.exe");
File_size += 0x1000;
pOptionHeader2->SizeOfImage += 0x1000;
//申请内存
TempFileBuffer = malloc(File_size+0x1000);
//清空内存中的数据
memset(TempFileBuffer, 0, File_size);
//复制PE头
memcpy(TempFileBuffer, imagebuffer, pOptionHeader2->SizeOfHeaders);
//获得节个数
int DwSetion = pFileHeader2->NumberOfSections;
//imageBase加1000个字节
//申请一个节变量,用于自增
PIMAGE_SECTION_HEADER pSection = pSectionHeader2;
//开始复制节到文件内存里
for (int i = 0; i < DwSetion; i++)
{
memcpy((VOID*)((DWORD)TempFileBuffer + pSection->PointerToRawData), (void*)((DWORD)imagebuffer + pSection->VirtualAddress), pSection->SizeOfRawData);
pSection++;
}
printf("sizeofimage:%d", pOptionHeader2->SizeOfImage);
printf("imagebuffer到FileBuffer成功了"); //好吧,真的成功了。接下来要存盘了。
//====================开始存盘,看看能不能用========================
char Save_exe[] = "D:\\ipmsg_NewSection.exe";
FILE* Save_file = fopen(Save_exe, "wb+");
fwrite(TempFileBuffer,File_size,1,Save_file);
if (!Save_file)
{
printf("拷贝失败了,错误代码22\n");
fclose(Save_file);
return 0;
}
fclose(Save_file);
return 0;
}
//imagebuffer直接存盘函数
DWORD ImagebufferToFilebuffer2(LPVOID imagebuffer)
{
LPVOID TempFileBuffer = NULL;
PIMAGE_DOS_HEADER pDosHeader2 = NULL;
PIMAGE_NT_HEADERS32 pNTHeader2 = NULL;
PIMAGE_FILE_HEADER pFileHeader2 = NULL;
PIMAGE_OPTIONAL_HEADER32 pOptionHeader2 = NULL;
PIMAGE_SECTION_HEADER pSectionHeader2 = NULL;
if (!imagebuffer)
{
printf("ImagebufferToFilebuffer函数没有获取到imagebuffer指针,错误码20");
return 0;
}
if (*(PWORD)((PIMAGE_DOS_HEADER)imagebuffer) != IMAGE_DOS_SIGNATURE)
{
printf("imagebuffer不是有效的MZ");
return 0;
}
pDosHeader2 = (PIMAGE_DOS_HEADER)imagebuffer;
pNTHeader2 = (PIMAGE_NT_HEADERS32)((DWORD)pDosHeader2 + pDosHeader2->e_lfanew);
pFileHeader2 = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader2 + 4);
pOptionHeader2 = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pFileHeader2 + IMAGE_SIZEOF_FILE_HEADER);
pSectionHeader2 = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader2 + pFileHeader2->SizeOfOptionalHeader);
//申请内存
TempFileBuffer = malloc(pOptionHeader2->SizeOfImage);
//清空内存中的数据
memset(TempFileBuffer, 0, pOptionHeader2->SizeOfImage);
//复制PE头
memcpy(TempFileBuffer, imagebuffer, pOptionHeader2->SizeOfImage);
//获得节个数
int DwSetion = pFileHeader2->NumberOfSections;
//申请一个节变量,用于自增
PIMAGE_SECTION_HEADER pSection = pSectionHeader2;
//开始复制节到文件内存里
for (int i = 0; i < DwSetion; i++)
{
memcpy((VOID*)((DWORD)TempFileBuffer + pSection->PointerToRawData), (void*)((DWORD)imagebuffer + pSection->VirtualAddress), pSection->SizeOfRawData);
pSection++;
}
printf("sizeofimage:%d", pOptionHeader2->SizeOfImage);
printf("imagebuffer到FileBuffer成功了"); //好吧,真的成功了。接下来要存盘了。
//====================开始存盘,看看能不能用========================
char Save_exe[] = "D:\\ipmsg_NewSection2222.exe";
FILE* Save_file = fopen(Save_exe, "wb+");
fwrite(TempFileBuffer, pOptionHeader2->SizeOfImage, 1, Save_file);
if (!Save_file)
{
printf("拷贝失败了,错误代码22\n");
fclose(Save_file);
return 0;
}
fclose(Save_file);
return 0;
}
//代码节添加代码
LPVOID Code_To_Code(LPVOID pImageBuffer)
{
char Code[] =
{
0x6A, 0x00, 0x6A, 0x00, 0x6A, 0x00, 0x6A, 0x00,
0xE8, 0x00, 0x00, 0x00, 0x00,
0xE9, 0x00, 0x00, 0x00, 0x00
};
DWORD MessageBoxAddress = 0x762d1e80 ;
PIMAGE_DOS_HEADER pDosHeader3 = NULL;
PIMAGE_NT_HEADERS32 pNTHeader3 = NULL;
PIMAGE_FILE_HEADER pFileHeader3 = NULL;
PIMAGE_OPTIONAL_HEADER32 pOptionHeader3 = NULL;
PIMAGE_SECTION_HEADER pSectionHeader3 = NULL;
pDosHeader3 = (PIMAGE_DOS_HEADER)pImageBuffer;
pNTHeader3 = (PIMAGE_NT_HEADERS32)((DWORD)pDosHeader3 + pDosHeader3->e_lfanew);
pFileHeader3 = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader3 + 4);
pOptionHeader3 = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pFileHeader3 + IMAGE_SIZEOF_FILE_HEADER);
pSectionHeader3 = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader3 + pFileHeader3->SizeOfOptionalHeader);
//添加代码,首先找到代码节的空白区,用imagebase(这里是)+VirtualAddress+SizeOfRawData拿到空白区地址,这个空白区开始的地址就是 我们保存代码的开始地址 CodeBegin
PBYTE CodeBebin = PBYTE((DWORD)pImageBuffer + pSectionHeader3->VirtualAddress + pSectionHeader3->Misc.VirtualSize);
//然后把Code代码复制进去
memcpy(CodeBebin, Code, sizeof(Code));
//计算E8后的地址,,,,((DWORD)CodeBebin + 0xD) - (DWORD)pImageBuffer)是在imagebuffer里的值(就是个偏移)(不是真正运行中)
int E8ShellCode = MessageBoxAddress - (pOptionHeader3->ImageBase + ((DWORD)CodeBebin + 0xd) - (DWORD)pImageBuffer);//得到E8 后4个字节的硬编码
//修改
*(PDWORD)(CodeBebin + 9) = E8ShellCode;
//计算E9后的地址
int E9ShellCode = (pOptionHeader3->ImageBase + pOptionHeader3->AddressOfEntryPoint) - (pOptionHeader3->ImageBase + ((DWORD)CodeBebin + 0x12)-(DWORD)pImageBuffer);
//修改
*(PDWORD)(CodeBebin + 0xe) = E9ShellCode;
//修改AddressOfEntryPoint(OEP)里面存的值为 E8开始的地方
pOptionHeader3->AddressOfEntryPoint = (DWORD)CodeBebin - (DWORD)pImageBuffer;
printf("COde to code:%x\n", pImageBuffer);
return pImageBuffer;
}
//扩大节
//传入Imagebuffer(这里由于我比较懒,传入的就是一个拉伸后的imagebuffer),对其最后一个节区进行扩大1000个字节
LPVOID ExpSection(LPVOID imagebuffer)
{
PIMAGE_DOS_HEADER ExpDos = (PIMAGE_DOS_HEADER)imagebuffer;
PIMAGE_NT_HEADERS ExpNT = PIMAGE_NT_HEADERS((DWORD)imagebuffer + (DWORD)ExpDos->e_lfanew);
PIMAGE_FILE_HEADER ExpFile = PIMAGE_FILE_HEADER((DWORD)ExpNT + 4);
PIMAGE_OPTIONAL_HEADER ExpOption= PIMAGE_OPTIONAL_HEADER((DWORD)ExpFile + 20);
PIMAGE_SECTION_HEADER ExpSec = PIMAGE_SECTION_HEADER((DWORD)ExpOption + (DWORD)ExpFile->SizeOfOptionalHeader);
LPVOID ExpTempP = NULL;
if (*(PDWORD)ExpNT != IMAGE_NT_SIGNATURE)
{
printf("没有传入拉伸后的内存指针,请检查代码,060");
return 0;
}
//申请动态内存
ExpTempP = malloc(ExpOption->SizeOfImage + 0x1000);
//把imagebuffer的数据复制进去
memcpy(ExpTempP, imagebuffer, ExpOption->SizeOfImage);
PIMAGE_DOS_HEADER ExpDos2 = (PIMAGE_DOS_HEADER)ExpTempP;
PIMAGE_NT_HEADERS ExpNT2 = PIMAGE_NT_HEADERS((DWORD)ExpTempP + (DWORD)ExpDos2->e_lfanew);
PIMAGE_FILE_HEADER ExpFile2 = PIMAGE_FILE_HEADER((DWORD)ExpNT2 + 4);
PIMAGE_OPTIONAL_HEADER ExpOption2 = PIMAGE_OPTIONAL_HEADER((DWORD)ExpFile2 + 20);
PIMAGE_SECTION_HEADER ExpSec2 = PIMAGE_SECTION_HEADER((DWORD)ExpOption2 + (DWORD)ExpFile2->SizeOfOptionalHeader);
//修改节表里面最后一个节的部分属性
for (int i = 1; i < ExpFile2->NumberOfSections; i++,ExpSec2++);
ExpSec2->SizeOfRawData += 0x1000; //把节区增大1000个字节
ExpSec2->Misc.VirtualSize += 0x1000;//在内存中大小加0x1000字节
ExpOption2->SizeOfImage += 0x1000;
return ExpTempP;
}
//得到文件大小函数 返回文件大小
int getFileSize(FILE* fileAdress)
{
int size;
//定位文件末尾
fseek(fileAdress, NULL, SEEK_END);
//得到文件流大小
size = ftell(fileAdress);
//重定位文件开头
fseek(fileAdress, NULL, SEEK_SET);
returnsize;
}
FILE* openFile(char* filePath, char* type)
{
FILE* fileAdress;
//通过传入的文件地址以及读写类型打开文件创建文件流
if (!(fileAdress = fopen(filePath, type)))
{
printf("获取文件出错!\n");
return 0;
}
return fileAdress;
}
int main()
{
char FilePath[] = "D:\\ipmsg.exe";
LPVOID p = CopyFileBufferToImageBuffer(ReadPEFile(FilePath));
LPVOID p2 = ExpSection(p);
//ImagebufferToFilebuffer(p);
//Code_To_Code(p);
ImagebufferToFilebuffer2(p2);
//NewSeciton(ReadPEFile(FilePath));
getchar();
return 1;
}
代码节添加代码,新增节,再把新增节扩大
最新推荐文章于 2024-01-17 18:37:13 发布