applied patch #1643633 - 64bit PE support for CResourceEditor
git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@4880 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
parent
bc27ce462e
commit
35ae3cca66
3 changed files with 72 additions and 20 deletions
|
@ -739,6 +739,38 @@ typedef struct _IMAGE_OPTIONAL_HEADER {
|
||||||
DWORD NumberOfRvaAndSizes;
|
DWORD NumberOfRvaAndSizes;
|
||||||
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
|
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
|
||||||
} IMAGE_OPTIONAL_HEADER,*PIMAGE_OPTIONAL_HEADER;
|
} IMAGE_OPTIONAL_HEADER,*PIMAGE_OPTIONAL_HEADER;
|
||||||
|
typedef struct _IMAGE_OPTIONAL_HEADER64 {
|
||||||
|
WORD Magic;
|
||||||
|
BYTE MajorLinkerVersion;
|
||||||
|
BYTE MinorLinkerVersion;
|
||||||
|
DWORD SizeOfCode;
|
||||||
|
DWORD SizeOfInitializedData;
|
||||||
|
DWORD SizeOfUninitializedData;
|
||||||
|
DWORD AddressOfEntryPoint;
|
||||||
|
DWORD BaseOfCode;
|
||||||
|
ULONGLONG ImageBase;
|
||||||
|
DWORD SectionAlignment;
|
||||||
|
DWORD FileAlignment;
|
||||||
|
WORD MajorOperatingSystemVersion;
|
||||||
|
WORD MinorOperatingSystemVersion;
|
||||||
|
WORD MajorImageVersion;
|
||||||
|
WORD MinorImageVersion;
|
||||||
|
WORD MajorSubsystemVersion;
|
||||||
|
WORD MinorSubsystemVersion;
|
||||||
|
DWORD Win32VersionValue;
|
||||||
|
DWORD SizeOfImage;
|
||||||
|
DWORD SizeOfHeaders;
|
||||||
|
DWORD CheckSum;
|
||||||
|
WORD Subsystem;
|
||||||
|
WORD DllCharacteristics;
|
||||||
|
ULONGLONG SizeOfStackReserve;
|
||||||
|
ULONGLONG SizeOfStackCommit;
|
||||||
|
ULONGLONG SizeOfHeapReserve;
|
||||||
|
ULONGLONG SizeOfHeapCommit;
|
||||||
|
DWORD LoaderFlags;
|
||||||
|
DWORD NumberOfRvaAndSizes;
|
||||||
|
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
|
||||||
|
} IMAGE_OPTIONAL_HEADER64,*PIMAGE_OPTIONAL_HEADER64;
|
||||||
#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b
|
#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b
|
||||||
#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
|
#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
|
||||||
typedef struct _IMAGE_NT_HEADERS {
|
typedef struct _IMAGE_NT_HEADERS {
|
||||||
|
|
|
@ -50,8 +50,9 @@ PIMAGE_NT_HEADERS CResourceEditor::GetNTHeaders(BYTE* pbPE) {
|
||||||
if (ntHeaders->Signature != IMAGE_NT_SIGNATURE)
|
if (ntHeaders->Signature != IMAGE_NT_SIGNATURE)
|
||||||
throw runtime_error("PE file missing NT signature");
|
throw runtime_error("PE file missing NT signature");
|
||||||
|
|
||||||
// Make sure this is a 32-bit PE
|
// Make sure this is a supported PE format
|
||||||
if (ntHeaders->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
|
if (ntHeaders->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC &&
|
||||||
|
ntHeaders->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC)
|
||||||
throw runtime_error("Unsupported PE format");
|
throw runtime_error("Unsupported PE format");
|
||||||
|
|
||||||
return ntHeaders;
|
return ntHeaders;
|
||||||
|
@ -64,10 +65,13 @@ PRESOURCE_DIRECTORY CResourceEditor::GetResourceDirectory(
|
||||||
DWORD *pdwResSecVA /*=NULL*/,
|
DWORD *pdwResSecVA /*=NULL*/,
|
||||||
DWORD *pdwSectionIndex /*=NULL*/
|
DWORD *pdwSectionIndex /*=NULL*/
|
||||||
) {
|
) {
|
||||||
if (ConvertEndianness(ntHeaders->OptionalHeader.NumberOfRvaAndSizes) <= IMAGE_DIRECTORY_ENTRY_RESOURCE)
|
PIMAGE_DATA_DIRECTORY dataDirectory = *GetMemberFromOptionalHeader(ntHeaders->OptionalHeader, DataDirectory);
|
||||||
|
DWORD dwNumberOfRvaAndSizes = *GetMemberFromOptionalHeader(ntHeaders->OptionalHeader, NumberOfRvaAndSizes);
|
||||||
|
|
||||||
|
if (ConvertEndianness(dwNumberOfRvaAndSizes) <= IMAGE_DIRECTORY_ENTRY_RESOURCE)
|
||||||
throw runtime_error("No resource section found");
|
throw runtime_error("No resource section found");
|
||||||
// Get resource section virtual address
|
// Get resource section virtual address
|
||||||
DWORD dwResSecVA = ConvertEndianness(ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress);
|
DWORD dwResSecVA = ConvertEndianness(dataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress);
|
||||||
// Pointer to the sections headers array
|
// Pointer to the sections headers array
|
||||||
PIMAGE_SECTION_HEADER sectionHeadersArray = IMAGE_FIRST_SECTION(ntHeaders);
|
PIMAGE_SECTION_HEADER sectionHeadersArray = IMAGE_FIRST_SECTION(ntHeaders);
|
||||||
|
|
||||||
|
@ -124,10 +128,11 @@ CResourceEditor::CResourceEditor(BYTE* pbPE, int iSize) {
|
||||||
m_ntHeaders = GetNTHeaders(m_pbPE);
|
m_ntHeaders = GetNTHeaders(m_pbPE);
|
||||||
|
|
||||||
// No check sum support yet...
|
// No check sum support yet...
|
||||||
if (m_ntHeaders->OptionalHeader.CheckSum)
|
DWORD* pdwCheckSum = GetMemberFromOptionalHeader(m_ntHeaders->OptionalHeader, CheckSum);
|
||||||
|
if (*pdwCheckSum)
|
||||||
{
|
{
|
||||||
// clear checksum (should be [re]calculated after all changes done)
|
// clear checksum (should be [re]calculated after all changes done)
|
||||||
m_ntHeaders->OptionalHeader.CheckSum = 0;
|
pdwCheckSum = 0;
|
||||||
//throw runtime_error("CResourceEditor doesn't yet support check sum");
|
//throw runtime_error("CResourceEditor doesn't yet support check sum");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -405,28 +410,36 @@ DWORD CResourceEditor::Save(BYTE* pbBuf, DWORD &dwSize) {
|
||||||
sectionHeadersArray[m_dwResourceSectionIndex].SizeOfRawData = ConvertEndianness(dwRsrcSizeAligned);
|
sectionHeadersArray[m_dwResourceSectionIndex].SizeOfRawData = ConvertEndianness(dwRsrcSizeAligned);
|
||||||
// Set the virtual size as well (in memory)
|
// Set the virtual size as well (in memory)
|
||||||
sectionHeadersArray[m_dwResourceSectionIndex].Misc.VirtualSize = ConvertEndianness(dwRsrcSize);
|
sectionHeadersArray[m_dwResourceSectionIndex].Misc.VirtualSize = ConvertEndianness(dwRsrcSize);
|
||||||
ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = ConvertEndianness(dwRsrcSize);
|
(*GetMemberFromOptionalHeader(ntHeaders->OptionalHeader, DataDirectory))[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = ConvertEndianness(dwRsrcSize);
|
||||||
|
|
||||||
// Set the new virtual size of the image
|
// Set the new virtual size of the image
|
||||||
ntHeaders->OptionalHeader.SizeOfImage = AlignVA(ntHeaders->OptionalHeader.SizeOfHeaders);
|
DWORD* pdwSizeOfImage = GetMemberFromOptionalHeader(ntHeaders->OptionalHeader, SizeOfImage);
|
||||||
|
*pdwSizeOfImage = AlignVA(*GetMemberFromOptionalHeader(ntHeaders->OptionalHeader, SizeOfHeaders));
|
||||||
for (i = 0; i < wNumberOfSections; i++) {
|
for (i = 0; i < wNumberOfSections; i++) {
|
||||||
DWORD dwSecSize = ConvertEndianness(sectionHeadersArray[i].Misc.VirtualSize);
|
DWORD dwSecSize = ConvertEndianness(sectionHeadersArray[i].Misc.VirtualSize);
|
||||||
ntHeaders->OptionalHeader.SizeOfImage = AlignVA(AdjustVA(ntHeaders->OptionalHeader.SizeOfImage, dwSecSize));
|
*pdwSizeOfImage = AlignVA(AdjustVA(*pdwSizeOfImage, dwSecSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the new AddressOfEntryPoint if needed
|
// Set the new AddressOfEntryPoint if needed
|
||||||
if (ConvertEndianness(ntHeaders->OptionalHeader.AddressOfEntryPoint) > m_dwResourceSectionVA)
|
DWORD* pdwAddressOfEntryPoint = GetMemberFromOptionalHeader(ntHeaders->OptionalHeader, AddressOfEntryPoint);
|
||||||
ntHeaders->OptionalHeader.AddressOfEntryPoint = AdjustVA(ntHeaders->OptionalHeader.AddressOfEntryPoint, dwVAAdjustment);
|
if (ConvertEndianness(*pdwAddressOfEntryPoint) > m_dwResourceSectionVA)
|
||||||
|
*pdwAddressOfEntryPoint = AdjustVA(*pdwAddressOfEntryPoint, dwVAAdjustment);
|
||||||
|
|
||||||
// Set the new BaseOfCode if needed
|
// Set the new BaseOfCode if needed
|
||||||
if (ConvertEndianness(ntHeaders->OptionalHeader.BaseOfCode) > m_dwResourceSectionVA)
|
DWORD* pdwBaseOfCode = GetMemberFromOptionalHeader(ntHeaders->OptionalHeader, BaseOfCode);
|
||||||
ntHeaders->OptionalHeader.BaseOfCode = AdjustVA(ntHeaders->OptionalHeader.BaseOfCode, dwVAAdjustment);
|
if (ConvertEndianness(*pdwBaseOfCode) > m_dwResourceSectionVA)
|
||||||
|
*pdwBaseOfCode = AdjustVA(*pdwBaseOfCode, dwVAAdjustment);
|
||||||
|
|
||||||
// Set the new BaseOfData if needed
|
// Set the new BaseOfData if needed
|
||||||
if (ConvertEndianness(ntHeaders->OptionalHeader.BaseOfData) > m_dwResourceSectionVA)
|
if (ntHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
|
||||||
ntHeaders->OptionalHeader.BaseOfData = AdjustVA(ntHeaders->OptionalHeader.BaseOfData, dwVAAdjustment);
|
DWORD* pdwBaseOfData = &((PIMAGE_OPTIONAL_HEADER32)&ntHeaders->OptionalHeader)->BaseOfData;
|
||||||
|
if (*pdwBaseOfData > m_dwResourceSectionVA)
|
||||||
|
*pdwBaseOfData = AdjustVA(*pdwBaseOfData, dwVAAdjustment);
|
||||||
|
}
|
||||||
|
|
||||||
// Refresh the headers of the sections that come after the resource section, and the data directory
|
// Refresh the headers of the sections that come after the resource section, and the data directory
|
||||||
|
DWORD dwNumberOfRvaAndSizes = *GetMemberFromOptionalHeader(ntHeaders->OptionalHeader, NumberOfRvaAndSizes);
|
||||||
|
PIMAGE_DATA_DIRECTORY pDataDirectory = *GetMemberFromOptionalHeader(ntHeaders->OptionalHeader, DataDirectory);
|
||||||
for (i = m_dwResourceSectionIndex + 1; i < wNumberOfSections; i++) {
|
for (i = m_dwResourceSectionIndex + 1; i < wNumberOfSections; i++) {
|
||||||
if (sectionHeadersArray[i].PointerToRawData) {
|
if (sectionHeadersArray[i].PointerToRawData) {
|
||||||
AdjustVA(sectionHeadersArray[i].PointerToRawData, dwRsrcSizeAligned - dwOldRsrcSize);
|
AdjustVA(sectionHeadersArray[i].PointerToRawData, dwRsrcSizeAligned - dwOldRsrcSize);
|
||||||
|
@ -434,15 +447,15 @@ DWORD CResourceEditor::Save(BYTE* pbBuf, DWORD &dwSize) {
|
||||||
|
|
||||||
// We must find the right data directory entry before we change the virtual address
|
// We must find the right data directory entry before we change the virtual address
|
||||||
unsigned int uDataDirIdx = 0;
|
unsigned int uDataDirIdx = 0;
|
||||||
for (unsigned int j = 0; j < ConvertEndianness(ntHeaders->OptionalHeader.NumberOfRvaAndSizes); j++)
|
for (unsigned int j = 0; j < ConvertEndianness(dwNumberOfRvaAndSizes); j++)
|
||||||
if (ntHeaders->OptionalHeader.DataDirectory[j].VirtualAddress == sectionHeadersArray[i].VirtualAddress)
|
if (pDataDirectory[j].VirtualAddress == sectionHeadersArray[i].VirtualAddress)
|
||||||
uDataDirIdx = j;
|
uDataDirIdx = j;
|
||||||
|
|
||||||
sectionHeadersArray[i].VirtualAddress = AdjustVA(sectionHeadersArray[i].VirtualAddress, dwVAAdjustment);
|
sectionHeadersArray[i].VirtualAddress = AdjustVA(sectionHeadersArray[i].VirtualAddress, dwVAAdjustment);
|
||||||
|
|
||||||
// Change the virtual address in the data directory too
|
// Change the virtual address in the data directory too
|
||||||
if (uDataDirIdx)
|
if (uDataDirIdx)
|
||||||
ntHeaders->OptionalHeader.DataDirectory[uDataDirIdx].VirtualAddress = sectionHeadersArray[i].VirtualAddress;
|
pDataDirectory[uDataDirIdx].VirtualAddress = sectionHeadersArray[i].VirtualAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the resource section
|
// Write the resource section
|
||||||
|
@ -498,7 +511,8 @@ bool CResourceEditor::AddExtraVirtualSize2PESection(const char* pszSectionName,
|
||||||
if (m_dwResourceSectionIndex == (DWORD) k)
|
if (m_dwResourceSectionIndex == (DWORD) k)
|
||||||
{
|
{
|
||||||
// fix the resources virtual address if it changed
|
// fix the resources virtual address if it changed
|
||||||
m_ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = dwSecVA;
|
PIMAGE_DATA_DIRECTORY pDataDirectory = *GetMemberFromOptionalHeader(m_ntHeaders->OptionalHeader, DataDirectory);
|
||||||
|
pDataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = dwSecVA;
|
||||||
m_dwResourceSectionVA = ConvertEndianness(dwSecVA);
|
m_dwResourceSectionVA = ConvertEndianness(dwSecVA);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -712,7 +726,8 @@ DWORD CResourceEditor::AdjustVA(DWORD dwVirtualAddress, DWORD dwAdjustment) {
|
||||||
|
|
||||||
// Aligns a virtual address to the section alignment
|
// Aligns a virtual address to the section alignment
|
||||||
DWORD CResourceEditor::AlignVA(DWORD dwVirtualAddress) {
|
DWORD CResourceEditor::AlignVA(DWORD dwVirtualAddress) {
|
||||||
DWORD dwAlignment = ConvertEndianness(m_ntHeaders->OptionalHeader.SectionAlignment);
|
DWORD dwSectionAlignment = *GetMemberFromOptionalHeader(m_ntHeaders->OptionalHeader, SectionAlignment);
|
||||||
|
DWORD dwAlignment = ConvertEndianness(dwSectionAlignment);
|
||||||
|
|
||||||
dwVirtualAddress = ConvertEndianness(dwVirtualAddress);
|
dwVirtualAddress = ConvertEndianness(dwVirtualAddress);
|
||||||
dwVirtualAddress = RALIGN(dwVirtualAddress, dwAlignment);
|
dwVirtualAddress = RALIGN(dwVirtualAddress, dwAlignment);
|
||||||
|
|
|
@ -102,6 +102,11 @@ typedef struct RESOURCE_DIRECTORY {
|
||||||
MY_IMAGE_RESOURCE_DIRECTORY_ENTRY Entries[1];
|
MY_IMAGE_RESOURCE_DIRECTORY_ENTRY Entries[1];
|
||||||
} *PRESOURCE_DIRECTORY;
|
} *PRESOURCE_DIRECTORY;
|
||||||
|
|
||||||
|
#define GetMemberFromOptionalHeader(optionalHeader, member) \
|
||||||
|
( (optionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) ? \
|
||||||
|
&((PIMAGE_OPTIONAL_HEADER32)&optionalHeader)->member : \
|
||||||
|
&((PIMAGE_OPTIONAL_HEADER64)&optionalHeader)->member \
|
||||||
|
)
|
||||||
class CResourceEditor {
|
class CResourceEditor {
|
||||||
public:
|
public:
|
||||||
CResourceEditor(BYTE* pbPE, int iSize);
|
CResourceEditor(BYTE* pbPE, int iSize);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue