//获得文件buffer
BOOL GetFileBuffer(__in char* m_fileName, __inout char** LPFilebuffer)
{
// 初始化输出参数
*LPFilebuffer = NULL;
if (m_fileName == NULL || LPFilebuffer == NULL)
{
perror("m_fileName OR LPFilebuffer is NULL");
}
FILE* file = (fopen(m_fileName, "rb"));
if (file == NULL)
{
printf("error :%d", GetLastError());
return FALSE;
}
// 从文件头跳转到偏移0x3C位置
if (fseek(file, 0x3C, SEEK_SET) != 0) {
perror("fseek failed");
fclose(file);
return FALSE;
}
//读到e_lfannew的值
//LONG e_lfannew = 0;
//if (fread(&e_lfannew, sizeof(LONG), 1, file) != 1) {
// perror("fread failed");
// fclose(file);
// return FALSE;
//}
从文件开始跳到可选头的imagebase的位置
//fseek(file, e_lfannew + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + 0x38, SEEK_SET);
//DWORD sizeofimage = 0;
//fread(&sizeofimage, sizeof(DWORD), 1, file);
fseek(file, 0, SEEK_END);//到文件尾部
DWORD fileSize = ftell(file);//获得文件的大小
fseek(file, 0, SEEK_SET);//返回文件头部
*LPFilebuffer = malloc(fileSize);
if (*LPFilebuffer == NULL)
{
perror("malloc failed");
fclose(file);
free(*LPFilebuffer);
return FALSE;
}
memset(*LPFilebuffer, 0, fileSize);
fread(*LPFilebuffer, 1, fileSize, file);//将文件读取到内存中
fclose(file);
file = NULL;
return TRUE;
}
//获得imagebuffer
BOOL StrechFileBuffer(__in char* LPFilebuffer, __inout char** LPImageBuffer)
{
if (LPFilebuffer == NULL)
{
perror("Filebuffer is NULL");
return FALSE;
}
PIMAGE_DOS_HEADER pDos =(PIMAGE_DOS_HEADER) LPFilebuffer;
PIMAGE_FILE_HEADER pFileHeader = (PIMAGE_FILE_HEADER)(LPFilebuffer + pDos->e_lfanew + sizeof(DWORD));
DWORD sizeofimage = *(PDWORD)(LPFilebuffer + pDos->e_lfanew + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + 0x38);
//根据imagebase申请拉伸后的内存
char* pImagebuffer = malloc(sizeofimage);
if (pImagebuffer == NULL)
{
perror("malloc failed");
return FALSE;
}
memset(pImagebuffer, 0, sizeofimage);
/
/*已经将PE文件写到内存中了.但是需要分开拷贝,从最后的节开始拷贝数据*/
//看看是多少位的程序
WORD magic = *(WORD*)(LPFilebuffer + pDos->e_lfanew + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER));
//跳到最后一个节区信息结构列表
WORD NumberOfSections = pFileHeader->NumberOfSections;
PIMAGE_SECTION_HEADER PLastSectionTable =(PIMAGE_SECTION_HEADER) (char*)pFileHeader +sizeof(IMAGE_FILE_HEADER)+ (pFileHeader->SizeOfOptionalHeader) + ((NumberOfSections -1) * sizeof(IMAGE_SECTION_HEADER));
// 从最后一个节区开始向前拷贝
PIMAGE_SECTION_HEADER currentSection = PLastSectionTable; // 获取当前节区的指针
for (size_t i = pFileHeader->NumberOfSections; i > 0; i--, currentSection--) {
// 从文件中获取源地址和目标地址
char* src = LPFilebuffer + currentSection->PointerToRawData; // 文件中的数据
char* dest = pImagebuffer + currentSection->VirtualAddress; // 内存中的目标地址
// 计算拷贝的大小
size_t sizeToCopy = currentSection->SizeOfRawData > currentSection->Misc.VirtualSize
? currentSection->SizeOfRawData
: currentSection->Misc.VirtualSize;
// 拷贝数据
memcpy(dest, src, sizeToCopy);
}
//拷贝pe头和节表
size_t sizeToCopy = 0;
if (magic == 0X10B)
{
PIMAGE_OPTIONAL_HEADER32 Poptional =(PIMAGE_OPTIONAL_HEADER32) (LPFilebuffer + pDos->e_lfanew + sizeof(DWORD)) + sizeof(IMAGE_FILE_HEADER);
sizeToCopy = Poptional->SizeOfHeaders;
}
else
{
PIMAGE_OPTIONAL_HEADER64 Poptional = (PIMAGE_OPTIONAL_HEADER64)(LPFilebuffer + pDos->e_lfanew + sizeof(DWORD)) + sizeof(IMAGE_FILE_HEADER);
sizeToCopy = Poptional->SizeOfHeaders;
}
memcpy(pImagebuffer, LPFilebuffer, sizeToCopy);
*LPImageBuffer = pImagebuffer;
return TRUE;
}
//恢复到flieBuffer状态
BOOL RestoreImageToFile( __in char* LPImageBuffer, __inout char** LPFilebuffer, __inout DWORD* BufferSize)
{
if (LPFilebuffer == NULL || LPImageBuffer == NULL)
{
perror("LPFilebuffer OR LPImageBuffer is NULL");
return FALSE;
}
DWORD sizeOfHeader = 0;//头部文件对齐的大小
DWORD sizeOfRawDatas = 0;//所有节需要的内存对齐大小
PIMAGE_DOS_HEADER pDos =(PIMAGE_DOS_HEADER) LPImageBuffer;
PIMAGE_FILE_HEADER pFileHeader =(PIMAGE_FILE_HEADER) (LPImageBuffer + pDos->e_lfanew + sizeof(DWORD));
PIMAGE_SECTION_HEADER pFirstSectionHeader = (PIMAGE_SECTION_HEADER)((char*)pFileHeader + sizeof(IMAGE_FILE_HEADER) + pFileHeader->SizeOfOptionalHeader);
PIMAGE_OPTIONAL_HEADER32 poptionalHeader32 = (PIMAGE_OPTIONAL_HEADER32)((char*)pFileHeader+sizeof(IMAGE_FILE_HEADER));
PIMAGE_OPTIONAL_HEADER64 poptionalHeader64 = (PIMAGE_OPTIONAL_HEADER64)((char*)poptionalHeader32);
//用于保存每个节区的节区FOA 和 文件对齐的大小.这样我就不需要遍历2次了.因为我现在还不知道要申请多大的一块内存
PIMAGE_SECTION_HEADER pCurrentSectionHeader = pFirstSectionHeader;// 保存初始的指针位置
for (size_t i = 0; i < pFileHeader->NumberOfSections; i++) {
sizeOfRawDatas += pCurrentSectionHeader->SizeOfRawData;
pCurrentSectionHeader++;
}
pCurrentSectionHeader--;//不 -- ,将会越界访问
//开始为保存为文件 申请内存
//读一下magic,便于看使用哪个可选头结构体
WORD Magic = *(WORD*)((char*)pFileHeader + sizeof(IMAGE_FILE_HEADER));
if (Magic == 0x10b)
{
sizeOfHeader = poptionalHeader32->SizeOfHeaders;
}
else
{
sizeOfHeader = poptionalHeader64->SizeOfHeaders;
}
//终于开始申请内存了
char* pFileBuffer = (char*)malloc(sizeOfHeader + sizeOfRawDatas);
if (pFileBuffer == NULL)
{
perror("pFileBuffer is faild");
return FALSE;
}
memset(pFileBuffer, 0, sizeOfHeader + sizeOfRawDatas);
for (size_t i = pFileHeader->NumberOfSections; i >0 ; i--)
{
char* source = (LPImageBuffer)+pCurrentSectionHeader->VirtualAddress;//获取到在内存中的位置
char* dst = pFileBuffer + pCurrentSectionHeader->PointerToRawData;//获取到应该在文件中的位置
DWORD copySize = pCurrentSectionHeader->SizeOfRawData;//文件对齐后的大小
memcpy(dst, source, copySize);
pCurrentSectionHeader--;
}
//复制整个头和节表
memcpy(pFileBuffer, LPImageBuffer, sizeOfHeader);
*LPFilebuffer = pFileBuffer;
*BufferSize = sizeOfHeader + sizeOfRawDatas;
return TRUE;
}
//保存到文件
BOOL StoringFile(__in char* SaveFilePath, __in char* FileBuffer ,DWORD BufferSize)
{
if (SaveFilePath == NULL || FileBuffer == NULL)
{
perror("SaveFilePath or FileBuffer is NULL");
return FALSE;
}
FILE* file = fopen(SaveFilePath,"r");
{
if (file) {
// 文件已经存在
fclose(file);
printf("文件 '%s' 已存在,是否覆盖?(y/n): ", SaveFilePath);
char response;
scanf(" %c", &response); // 读取用户输入
if (response != 'Y' && response != 'y') {
printf("操作取消\n");
return FALSE;
}
}
}
FILE* pFile = fopen(SaveFilePath, "wb");
if (!pFile) {
perror("无法打开文件");
return FALSE;
}
// 写入数据到文件
size_t elementsWritten = fwrite(FileBuffer, BufferSize, 1 , pFile);
if (elementsWritten != BufferSize) {
//这里这样判断会出现问题,即使写入成功,也会导致进入这里
perror("写入错误");
fclose(pFile);
return FALSE;
}
// 关闭文件
fclose(pFile);
printf("数据已成功保存到二进制文件\n");
return TRUE;
}
///
//测试拉伸文件,然后恢复文件,最后保存
BOOL TestLoadAndSave(__in char* m_fileName, __in char* SaveFilePath)
{
char* Filebuffer = NULL;
char* NewFielBuffer = NULL;
CHAR* ImageBuffer = NULL;
DWORD size = 0;
do
{
if (!GetFileBuffer(m_fileName, &Filebuffer))break;
if (!StrechFileBuffer(Filebuffer, &ImageBuffer))break;
if (!RestoreImageToFile(ImageBuffer, &NewFielBuffer, &size))break;
if (!StoringFile(SaveFilePath, NewFielBuffer, size))break;
} while (FALSE);
free(Filebuffer);
free(ImageBuffer);
free(NewFielBuffer);
return TRUE;
}
///
//测试添加E8 E9 SHELLCODE 在节的空白区添加shellcode
BOOL AddShellCodeInEmpty(__in char* LPImageBuffer,__in char* Shellcode,DWORD SizeofShellcode)
{
if (LPImageBuffer == NULL || Shellcode == NULL || SizeofShellcode==0)
{
perror("LPImageBuffer or Shellcode or SizeofShellcode is error");
}
PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)LPImageBuffer;
PIMAGE_FILE_HEADER pFileHeader =(PIMAGE_FILE_HEADER) (LPImageBuffer + pDos->e_lfanew+sizeof(DWORD));
PIMAGE_SECTION_HEADER pFirstSectionHeader = (PIMAGE_SECTION_HEADER)((char*)pFileHeader + sizeof(IMAGE_FILE_HEADER) + pFileHeader->SizeOfOptionalHeader);
//尝试在节区某个空白区添加代码
int EmptySize = 0;
DWORD minSize = 0;
BOOL FindIt = FALSE;
//遍历节表
PIMAGE_SECTION_HEADER pCurrent = pFirstSectionHeader;
for (size_t i = 0; i < pFileHeader->NumberOfSections; i++)
{
if (pCurrent->Misc.VirtualSize < pCurrent->SizeOfRawData && (pCurrent->SizeOfRawData - pCurrent->Misc.VirtualSize) >= SizeofShellcode)
{
FindIt = TRUE;
break;
}
pCurrent++;
}
if (FindIt==TRUE)//如果找到了
{
if ((pCurrent->Characteristics & 0x60000020) != 0x60000020)
{
//说明不是代码区,需要修改一下属性
pCurrent->Characteristics |= 0x60000020;
}
//硬编码这一块写的非常烂,毫无兼容性,完全就是垃圾
//硬编码这一块写的非常烂,毫无兼容性,完全就是垃圾
//硬编码这一块写的非常烂,毫无兼容性,完全就是垃圾
PIMAGE_OPTIONAL_HEADER32 pOptional = (PIMAGE_OPTIONAL_HEADER32)(char*)pFileHeader + sizeof(IMAGE_FILE_HEADER);//在使用 EOP和imagebase时,32位和64位是相同的
///修正E8 //754A1060 是messagebox的地址
//offect=要跳转的地址 减去 e8 下一条指令的地址
DWORD offect = 0X754A1060 - (pOptional->ImageBase + pCurrent->VirtualAddress + pCurrent->Misc.VirtualSize + 0XD);
*((PDWORD)&Shellcode[9]) = offect;
//修复e9 要跳转的地址为oep
offect = (pOptional->AddressOfEntryPoint + pOptional->ImageBase) - (pOptional->ImageBase + pCurrent->VirtualAddress + pCurrent->Misc.VirtualSize + 0x12);
*((PDWORD)&Shellcode[14])= offect;
memcpy(LPImageBuffer + pCurrent->VirtualAddress + pCurrent->Misc.VirtualSize, Shellcode, SizeofShellcode);
//设置新的oep
DWORD NewAddressOfPoint = pCurrent->VirtualAddress+ pCurrent->Misc.VirtualSize;
pOptional->AddressOfEntryPoint = NewAddressOfPoint;
}
else
{
//很可惜没有找到
//现在我们可以使用 新增节,扩大节 合并节 这些操作了
}
return TRUE;
}
BOOL TestAddShellCode(__in char* m_fileName, __in char* SaveFilePath)
{
char* Filebuffer = NULL;
char* NewFielBuffer = NULL;
CHAR* ImageBuffer = NULL;
DWORD size = 0;
char shellcode[] = { 0X6A, 0X00,0X6A,0X00,0X6A,0X00,0X6A,0X00,0XE8,0X00,0X00,0X00,0X00,0XE9,0X00,0X00,0X00,0X00 };
DWORD SizeofShellcode = sizeof(shellcode);
do
{
if (!GetFileBuffer(m_fileName, &Filebuffer))break;
if (!StrechFileBuffer(Filebuffer, &ImageBuffer))break;
if (!AddShellCodeInEmpty(ImageBuffer, shellcode, SizeofShellcode))break;
if (!RestoreImageToFile(ImageBuffer, &NewFielBuffer, &size))break;
if (!StoringFile(SaveFilePath, NewFielBuffer, size))break;
} while (FALSE);
free(Filebuffer);
free(ImageBuffer);
free(NewFielBuffer);
return TRUE;
}
PE之拉伸文件添加shellcode并保存文件
最新推荐文章于 2024-11-09 20:57:23 发布