G
Guest
Hi,
Introduction:
************************************************************
I am working on a project that should encrypt PE files ( Portable executable
), this require me to inject some code to existing PEs.
First, I have tried:
1. to inject some code to the end of the ‘.text’ segment of an existing PE
2. to set the entry point RVA to the address of the injected code
3. at the end of the injected code I have set a jmp to the original entrypoint
The problem:
Opening that file and browsing to the entrypoint address I can see the
injected code BUT when running the application I can see that the IP points
to the correct address ( Base + RVA ) but the injected code is not there (
just some gibberish ), I tried setting the following flags for the section:
‘IMAGE_SCN_MEM_PRELOAD | IMAGE_SCN_CNT_CODE |
IMAGE_SCN_CNT_INITIALIZED_DATA’, BUT still, No good, I get the same results…
A .Any comments remarks or pointers will be appreciated.
B. Any pointers to documentation concerning how the PE loader work will be
appreciated ( e.g. which sections are loaded when, … )
************************************************************
Following is the code I use:
HRESULT InjectCode(char *pSourceName, char *pTargetName)
{
DWORD dwBytesRead = 0;
BYTE *pFileMemImage = 0;
LARGE_INTEGER liSourceSize;
HANDLE hSource = CreateFile(pSourceName, GENERIC_READ,
FILE_SHARE_READ,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
if(0 == hSource)
return HRESULT_FROM_WIN32(GetLastError());
GetFileSizeEx(hSource, &liSourceSize);
pFileMemImage = new BYTE[(DWORD)liSourceSize.QuadPart];
ReadFile(hSource, pFileMemImage,
(DWORD)liSourceSize.QuadPart,
&dwBytesRead, 0);
CloseHandle(hSource);
IMAGE_DOS_HEADER *pdosHeader = (IMAGE_DOS_HEADER*)pFileMemImage;
IMAGE_NT_HEADERS32 *pNtHdr = (IMAGE_NT_HEADERS32*)(pFileMemImage +
pdosHeader->e_lfanew);
IMAGE_SECTION_HEADER *pSecHeader = (IMAGE_SECTION_HEADER*)((PBYTE)pNtHdr +
sizeof(*pNtHdr));
DWORD dwWrittenBytes = 0;
// Copy the new function to the end of the '.text' segment
BYTE *pInjectedCode = pFileMemImage + pSecHeader[1].PointerToRawData +
pSecHeader[1].Misc.VirtualSize -
sizeof(INJECTED_SEGMENT_LIBLOAD);
DWORD *pJumpAddress = (DWORD*)(pInjectedCode +
sizeof(INJECTED_SEGMENT_LIBLOAD) -
sizeof(DWORD));
memcpy(pInjectedCode, INJECTED_SEGMENT_LIBLOAD,
sizeof(INJECTED_SEGMENT_LIBLOAD));
pSecHeader[1].Characteristics |= IMAGE_SCN_MEM_PRELOAD | IMAGE_SCN_CNT_CODE
| IMAGE_SCN_CNT_INITIALIZED_DATA |
IMAGE_SCN_LNK_REMOVE;
*pJumpAddress = pNtHdr->OptionalHeader.AddressOfEntryPoint -
(DWORD)((PBYTE)pJumpAddress - 1);
pNtHdr->OptionalHeader.AddressOfEntryPoint = (DWORD)(pInjectedCode -
pFileMemImage);
HANDLE hTarget = CreateFile(pTargetName, GENERIC_WRITE, 0, 0,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
WriteFile(hTarget, pFileMemImage, (DWORD)liSourceSize.QuadPart,
&dwWrittenBytes, 0);
CloseHandle(hTarget);
return S_OK;
}
Introduction:
************************************************************
I am working on a project that should encrypt PE files ( Portable executable
), this require me to inject some code to existing PEs.
First, I have tried:
1. to inject some code to the end of the ‘.text’ segment of an existing PE
2. to set the entry point RVA to the address of the injected code
3. at the end of the injected code I have set a jmp to the original entrypoint
The problem:
Opening that file and browsing to the entrypoint address I can see the
injected code BUT when running the application I can see that the IP points
to the correct address ( Base + RVA ) but the injected code is not there (
just some gibberish ), I tried setting the following flags for the section:
‘IMAGE_SCN_MEM_PRELOAD | IMAGE_SCN_CNT_CODE |
IMAGE_SCN_CNT_INITIALIZED_DATA’, BUT still, No good, I get the same results…
A .Any comments remarks or pointers will be appreciated.
B. Any pointers to documentation concerning how the PE loader work will be
appreciated ( e.g. which sections are loaded when, … )
************************************************************
Following is the code I use:
HRESULT InjectCode(char *pSourceName, char *pTargetName)
{
DWORD dwBytesRead = 0;
BYTE *pFileMemImage = 0;
LARGE_INTEGER liSourceSize;
HANDLE hSource = CreateFile(pSourceName, GENERIC_READ,
FILE_SHARE_READ,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
if(0 == hSource)
return HRESULT_FROM_WIN32(GetLastError());
GetFileSizeEx(hSource, &liSourceSize);
pFileMemImage = new BYTE[(DWORD)liSourceSize.QuadPart];
ReadFile(hSource, pFileMemImage,
(DWORD)liSourceSize.QuadPart,
&dwBytesRead, 0);
CloseHandle(hSource);
IMAGE_DOS_HEADER *pdosHeader = (IMAGE_DOS_HEADER*)pFileMemImage;
IMAGE_NT_HEADERS32 *pNtHdr = (IMAGE_NT_HEADERS32*)(pFileMemImage +
pdosHeader->e_lfanew);
IMAGE_SECTION_HEADER *pSecHeader = (IMAGE_SECTION_HEADER*)((PBYTE)pNtHdr +
sizeof(*pNtHdr));
DWORD dwWrittenBytes = 0;
// Copy the new function to the end of the '.text' segment
BYTE *pInjectedCode = pFileMemImage + pSecHeader[1].PointerToRawData +
pSecHeader[1].Misc.VirtualSize -
sizeof(INJECTED_SEGMENT_LIBLOAD);
DWORD *pJumpAddress = (DWORD*)(pInjectedCode +
sizeof(INJECTED_SEGMENT_LIBLOAD) -
sizeof(DWORD));
memcpy(pInjectedCode, INJECTED_SEGMENT_LIBLOAD,
sizeof(INJECTED_SEGMENT_LIBLOAD));
pSecHeader[1].Characteristics |= IMAGE_SCN_MEM_PRELOAD | IMAGE_SCN_CNT_CODE
| IMAGE_SCN_CNT_INITIALIZED_DATA |
IMAGE_SCN_LNK_REMOVE;
*pJumpAddress = pNtHdr->OptionalHeader.AddressOfEntryPoint -
(DWORD)((PBYTE)pJumpAddress - 1);
pNtHdr->OptionalHeader.AddressOfEntryPoint = (DWORD)(pInjectedCode -
pFileMemImage);
HANDLE hTarget = CreateFile(pTargetName, GENERIC_WRITE, 0, 0,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
WriteFile(hTarget, pFileMemImage, (DWORD)liSourceSize.QuadPart,
&dwWrittenBytes, 0);
CloseHandle(hTarget);
return S_OK;
}