如何解决PE可执行文件在添加新部分时损坏
我试图在可移植可执行文件中添加一个新部分,在这里我需要写一些数据,在这种情况下是整个文件。
第二个文件能够解析自身并从我在其中创建的部分读取数据,但是由于某些原因,当我使用下面的代码修改它时,它会损坏。
此消息框应出现。
但是我收到此错误消息:“此应用程序无法在您的PC上运行。”
新部分已正确添加到PE中:
新部分中的数据:
我真的无法分辨出这里出了什么问题。
#include <iostream>
#include <Windows.h>
#include <ShlObj.h>
#include <Shlwapi.h>
#pragma comment(lib,"Shell32.lib")
#pragma comment(lib,"Shlwapi.lib")
DWORD align(DWORD size,DWORD align,DWORD addr) {
if (!(size % align))
return addr + size;
return addr + (size / align + 1) * align;
}
int main(int argc,char* argv[])
{
if (argc < 3)
{
std::cout << "Argomenti insufficienti.\n";
return 0;
}
char PathToSave[MAX_PATH];
if (SUCCEEDED(SHGetFolderPathA(NULL,CSIDL_COMMON_DOCUMENTS,NULL,PathToSave)))
{
PathAppendA(PathToSave,"Bind.exe");
}
HANDLE fOutput = CreateFileA(PathToSave,GENERIC_WRITE,FILE_SHARE_WRITE,CREATE_ALWAYS,NULL); // Unused
HANDLE FirstFile = CreateFileA(argv[5],GENERIC_READ,FILE_SHARE_READ,OPEN_EXISTING,NULL); // File to read data from
if (FirstFile == INVALID_HANDLE_VALUE)
{
std::cout << "Impossibile aprire il file passato come primo argomento.\n";
return 0;
}
HANDLE SecFile = CreateFileA(argv[5],GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_WRITE,NULL); // File to write the read data in
if (SecFile == INVALID_HANDLE_VALUE)
{
std::cout << "Impossibile aprire il file passato come secondo argomento.\n";
return 0;
}
DWORD FirstFS = GetFileSize(FirstFile,0); // First file dimension
DWORD SecondFS = GetFileSize(SecFile,0); // Second file dimension
BYTE* FirstFB = (BYTE*)VirtualAlloc(NULL,FirstFS,MEM_COMMIT | MEM_RESERVE,PAGE_READWRITE); // Allocates memory for the first file
BYTE* SecondFB = (BYTE*)VirtualAlloc(NULL,SecondFS,PAGE_READWRITE); // Allocates memory for the second file
DWORD BytesRead = 0;
DWORD BytesWritten = 0;
if (bool Read = ReadFile(FirstFile,FirstFB,&BytesRead,NULL) == FALSE) // Reads the first file
{
std::cout << "Impossibile leggere primo file.\n";
return 0;
}
else
{
std::cout << "Letti " << BytesRead << " dal primo file.\n";
BytesRead = 0;
}
if (bool Read = ReadFile(SecFile,SecondFB,NULL) == FALSE) // Reads the second file
{
std::cout << "Impossibile leggere secondo file.\n";
return 0;
}
else
{
std::cout << "Letti " << BytesRead << " bytes dal secondo file.\n";
BytesRead = 0;
}
/*
*
* The code is problematic beyond this point!
*
* SecondFB = Pointer to the second file's data buffer that needs to be modified by adding the new section.
* FirstFB = Pointer to the first file's data buffer that will be written inside the ".sdata" section.
* Both of them have been loaded in memory using VirtualAlloc.
*
* Ask me anything for further info and many,many thanks :D
*/
// Here I add a new section to the second file.
PIMAGE_DOS_HEADER sIDH = (IMAGE_DOS_HEADER*)SecondFB;
PIMAGE_NT_HEADERS sINH = (IMAGE_NT_HEADERS*)(SecondFB + sIDH->e_lfanew);
PIMAGE_FILE_HEADER sIFH = (PIMAGE_FILE_HEADER)(SecondFB + sIDH->e_lfanew + sizeof(DWORD));
PIMAGE_OPTIONAL_HEADER sIOH = (PIMAGE_OPTIONAL_HEADER)(SecondFB + sIDH->e_lfanew + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER));
PIMAGE_SECTION_HEADER sISH = (PIMAGE_SECTION_HEADER)(SecondFB + sIDH->e_lfanew + sizeof(IMAGE_NT_HEADERS));
// Here I name the new section inside the file
ZeroMemory(sISH,sizeof(IMAGE_SECTION_HEADER));
copyMemory(sISH[sIFH->NumberOfSections].Name,".scode",8);
/*
0xE00000E0 = IMAGE_SCN_MEM_WRITE |
IMAGE_SCN_CNT_CODE |
IMAGE_SCN_CNT_UNINITIALIZED_DATA |
IMAGE_SCN_MEM_EXECUTE |
IMAGE_SCN_CNT_INITIALIZED_DATA |
IMAGE_SCN_MEM_READ
*/
// Here all the required information gets filled in
sISH[sIFH->NumberOfSections].VirtualAddress = align(sISH[sIFH->NumberOfSections - 1].Misc.VirtualSize,sIOH->SectionAlignment,sISH[sIFH->NumberOfSections - 1].VirtualAddress);
sISH[sIFH->NumberOfSections].SizeOfRawData = align(FirstFS,0);
sISH[sIFH->NumberOfSections].Misc.VirtualSize = align(FirstFS,0);
sISH[sIFH->NumberOfSections].PointerToRawData = align(sISH[sIFH->NumberOfSections - 1].SizeOfRawData,sIOH->FileAlignment,sISH[sIFH->NumberOfSections - 1].PointerToRawData);
sISH[sIFH->NumberOfSections].characteristics = 0xE00000E0;
// Here the changes are written to the second file
SetFilePointer(SecFile,sISH[sIFH->NumberOfSections].PointerToRawData + sISH[sIFH->NumberOfSections].SizeOfRawData,FILE_BEGIN);
SetEndOfFile(SecFile);
sIOH->SizeOfImage = sISH[sIFH->NumberOfSections].VirtualAddress + sISH[sIFH->NumberOfSections].Misc.VirtualSize;
sIFH->NumberOfSections += 1;
SetFilePointer(SecFile,FILE_BEGIN);
BytesWritten = 0;
bool W = WriteFile(SecFile,&BytesWritten,NULL);
if (W == FALSE)
{
std::cout << "Impossibile aggiungere sezione alla stub.\n";
return 0;
}
else
{
std::cout << "Scritti " << BytesWritten << " bytes nella stub. (Aggiunta nuova sezione.)\n";
BytesWritten = 0;
}
// Here I write the data inside the new section
SetFilePointer(SecFile,sISH[sIFH->NumberOfSections - 1].PointerToRawData,FILE_BEGIN);
if (bool Write = WriteFile(SecFile,NULL) == FALSE)
{
std::cout << "Impossibile aggiungere sezione alla stub.\n";
}
else
{
std::cout << "Scritti " << BytesWritten << " bytes nella stub.\n";
BytesWritten = 0;
}
// Here I close all the handles
VirtualFree(FirstFB,MEM_RELEASE);
CloseHandle(FirstFile);
VirtualFree(SecondFB,MEM_RELEASE);
CloseHandle(SecFile);
std::cout << "Binding completato.\n";
return 0;
}
解决方法
问题出在ZeroMemory(sISH,sizeof(IMAGE_SECTION_HEADER));
您删除了第一节的内存,这导致exe的节结构出现问题。这就是exe无法运行的原因。
解决方案:
=> ZeroMemory(&sISH[sIFH->NumberOfSections],sizeof(IMAGE_SECTION_HEADER)); //Clear the memory behind the last section
请不要忘记为第一个FILE_SHARE_WRITE
添加CreateFileA
,否则将导致第二个CreateFileA
无法写入。
=> HANDLE FirstFile = CreateFileA(argv[5],GENERIC_READ,FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_EXISTING,NULL); // File to read data from
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。