203 lines
5.7 KiB
C
203 lines
5.7 KiB
C
![]() |
/*
|
||
|
Inject the DLL into the target process by modifying its import descriptor
|
||
|
table. The target process must have been created suspended.
|
||
|
*/
|
||
|
|
||
|
#include "ansicon.h"
|
||
|
|
||
|
|
||
|
// Search for a suitable free area after the main image. (32-bit code could
|
||
|
// really go anywhere, but let's keep it relatively local.)
|
||
|
PVOID FindMem( HANDLE hProcess, PBYTE base, DWORD len )
|
||
|
{
|
||
|
MEMORY_BASIC_INFORMATION minfo;
|
||
|
PBYTE ptr;
|
||
|
PVOID mem;
|
||
|
|
||
|
for (ptr = base;
|
||
|
VirtualQueryEx( hProcess, ptr, &minfo, sizeof(minfo) );
|
||
|
ptr += minfo.RegionSize)
|
||
|
{
|
||
|
if ((minfo.State & MEM_FREE) && minfo.RegionSize >= len)
|
||
|
{
|
||
|
#ifdef _WIN64
|
||
|
if ((PBYTE)minfo.BaseAddress - base > 0xFfFfFfFf - len)
|
||
|
return NULL;
|
||
|
#endif
|
||
|
mem = VirtualAllocEx( hProcess, (PVOID)
|
||
|
(((DWORD_PTR)minfo.BaseAddress + 0xFFFF) & ~0xFFFF),
|
||
|
len, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE );
|
||
|
if (mem != NULL)
|
||
|
return mem;
|
||
|
}
|
||
|
}
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
void InjectDLL( LPPROCESS_INFORMATION ppi, PBYTE pBase )
|
||
|
{
|
||
|
DWORD rva;
|
||
|
PVOID pMem;
|
||
|
DWORD len;
|
||
|
DWORD pr;
|
||
|
IMAGE_DOS_HEADER DosHeader;
|
||
|
IMAGE_NT_HEADERS NTHeader, *pNTHeader;
|
||
|
PIMAGE_IMPORT_DESCRIPTOR pImports, pANSI_ImportDesc;
|
||
|
IMAGE_COR20_HEADER ComHeader, *pComHeader;
|
||
|
union
|
||
|
{
|
||
|
PBYTE pB;
|
||
|
PLONG_PTR pL;
|
||
|
} ip;
|
||
|
|
||
|
ReadProcVar( pBase, &DosHeader );
|
||
|
pNTHeader = (PIMAGE_NT_HEADERS)(pBase + DosHeader.e_lfanew);
|
||
|
ReadProcVar( pNTHeader, &NTHeader );
|
||
|
|
||
|
len = 4 * PTRSZ + ansi_len
|
||
|
+ sizeof(*pANSI_ImportDesc) + NTHeader.IMPORTDIR.Size;
|
||
|
pImports = malloc( len );
|
||
|
if (pImports == NULL)
|
||
|
{
|
||
|
DEBUGSTR( 1, L" Failed to allocate memory." );
|
||
|
return;
|
||
|
}
|
||
|
pMem = FindMem( ppi->hProcess, pBase, len );
|
||
|
if (pMem == NULL)
|
||
|
{
|
||
|
DEBUGSTR( 1, L" Failed to allocate virtual memory." );
|
||
|
free( pImports );
|
||
|
return;
|
||
|
}
|
||
|
rva = (DWORD)((PBYTE)pMem - pBase);
|
||
|
|
||
|
ip.pL = (PLONG_PTR)pImports;
|
||
|
*ip.pL++ = IMAGE_ORDINAL_FLAG + 1;
|
||
|
*ip.pL++ = 0;
|
||
|
*ip.pL++ = IMAGE_ORDINAL_FLAG + 1;
|
||
|
*ip.pL++ = 0;
|
||
|
memcpy( ip.pB, ansi_dll, ansi_len );
|
||
|
ip.pB += ansi_len;
|
||
|
pANSI_ImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)ip.pB;
|
||
|
pANSI_ImportDesc->OriginalFirstThunk = rva + 2 * PTRSZ;
|
||
|
pANSI_ImportDesc->TimeDateStamp = 0;
|
||
|
pANSI_ImportDesc->ForwarderChain = 0;
|
||
|
pANSI_ImportDesc->Name = rva + 4 * PTRSZ;
|
||
|
pANSI_ImportDesc->FirstThunk = rva;
|
||
|
ReadProcMem( pBase + NTHeader.IMPORTDIR.VirtualAddress,
|
||
|
pANSI_ImportDesc + 1, NTHeader.IMPORTDIR.Size );
|
||
|
WriteProcMem( pMem, pImports, len );
|
||
|
free( pImports );
|
||
|
|
||
|
NTHeader.IMPORTDIR.VirtualAddress = rva + 4 * PTRSZ + ansi_len;
|
||
|
NTHeader.IMPORTDIR.Size += sizeof(*pANSI_ImportDesc);
|
||
|
|
||
|
// If there's no IAT, copy the IDT.
|
||
|
if (NTHeader.IATDIR.VirtualAddress == 0)
|
||
|
NTHeader.IATDIR = NTHeader.IMPORTDIR;
|
||
|
|
||
|
// Remove bound imports, so the updated import table is used.
|
||
|
NTHeader.BOUNDDIR.VirtualAddress = 0;
|
||
|
NTHeader.BOUNDDIR.Size = 0;
|
||
|
|
||
|
VirtProtVar( pNTHeader, PAGE_READWRITE );
|
||
|
WriteProcVar( pNTHeader, &NTHeader );
|
||
|
VirtProtVar( pNTHeader, pr );
|
||
|
|
||
|
// Remove the IL-only flag on a managed process.
|
||
|
if (NTHeader.COMDIR.VirtualAddress != 0 && NTHeader.COMDIR.Size != 0)
|
||
|
{
|
||
|
pComHeader = (PIMAGE_COR20_HEADER)(pBase + NTHeader.COMDIR.VirtualAddress);
|
||
|
ReadProcVar( pComHeader, &ComHeader );
|
||
|
if (ComHeader.Flags & COMIMAGE_FLAGS_ILONLY)
|
||
|
{
|
||
|
ComHeader.Flags &= ~COMIMAGE_FLAGS_ILONLY;
|
||
|
VirtProtVar( pComHeader, PAGE_READWRITE );
|
||
|
WriteProcVar( pComHeader, &ComHeader );
|
||
|
VirtProtVar( pComHeader, pr );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
#ifdef _WIN64
|
||
|
void InjectDLL32( LPPROCESS_INFORMATION ppi, PBYTE pBase )
|
||
|
{
|
||
|
DWORD rva;
|
||
|
PVOID pMem;
|
||
|
DWORD len;
|
||
|
DWORD pr;
|
||
|
IMAGE_DOS_HEADER DosHeader;
|
||
|
IMAGE_NT_HEADERS32 NTHeader, *pNTHeader;
|
||
|
PIMAGE_IMPORT_DESCRIPTOR pImports, pANSI_ImportDesc;
|
||
|
IMAGE_COR20_HEADER ComHeader, *pComHeader;
|
||
|
union
|
||
|
{
|
||
|
PBYTE pB;
|
||
|
PLONG pL;
|
||
|
} ip;
|
||
|
|
||
|
ReadProcVar( pBase, &DosHeader );
|
||
|
pNTHeader = (PIMAGE_NT_HEADERS32)(pBase + DosHeader.e_lfanew);
|
||
|
ReadProcVar( pNTHeader, &NTHeader );
|
||
|
|
||
|
len = 16 + ansi_len + sizeof(*pANSI_ImportDesc) + NTHeader.IMPORTDIR.Size;
|
||
|
pImports = malloc( len );
|
||
|
if (pImports == NULL)
|
||
|
{
|
||
|
DEBUGSTR( 1, L" Failed to allocate memory." );
|
||
|
return;
|
||
|
}
|
||
|
pMem = FindMem( ppi->hProcess, pBase, len );
|
||
|
if (pMem == NULL)
|
||
|
{
|
||
|
DEBUGSTR( 1, L" Failed to allocate virtual memory." );
|
||
|
free( pImports );
|
||
|
return;
|
||
|
}
|
||
|
rva = (DWORD)((PBYTE)pMem - pBase);
|
||
|
|
||
|
ip.pL = (PLONG)pImports;
|
||
|
*ip.pL++ = IMAGE_ORDINAL_FLAG32 + 1;
|
||
|
*ip.pL++ = 0;
|
||
|
*ip.pL++ = IMAGE_ORDINAL_FLAG32 + 1;
|
||
|
*ip.pL++ = 0;
|
||
|
memcpy( ip.pB, ansi_dll, ansi_len );
|
||
|
ip.pB += ansi_len;
|
||
|
pANSI_ImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)ip.pB;
|
||
|
pANSI_ImportDesc->OriginalFirstThunk = rva + 8;
|
||
|
pANSI_ImportDesc->TimeDateStamp = 0;
|
||
|
pANSI_ImportDesc->ForwarderChain = 0;
|
||
|
pANSI_ImportDesc->Name = rva + 16;
|
||
|
pANSI_ImportDesc->FirstThunk = rva;
|
||
|
ReadProcMem( pBase + NTHeader.IMPORTDIR.VirtualAddress,
|
||
|
pANSI_ImportDesc + 1, NTHeader.IMPORTDIR.Size );
|
||
|
WriteProcMem( pMem, pImports, len );
|
||
|
free( pImports );
|
||
|
|
||
|
NTHeader.IMPORTDIR.VirtualAddress = rva + 16 + ansi_len;
|
||
|
NTHeader.IMPORTDIR.Size += sizeof(*pANSI_ImportDesc);
|
||
|
if (NTHeader.IATDIR.VirtualAddress == 0)
|
||
|
NTHeader.IATDIR = NTHeader.IMPORTDIR;
|
||
|
NTHeader.BOUNDDIR.VirtualAddress = 0;
|
||
|
NTHeader.BOUNDDIR.Size = 0;
|
||
|
VirtProtVar( pNTHeader, PAGE_READWRITE );
|
||
|
WriteProcVar( pNTHeader, &NTHeader );
|
||
|
VirtProtVar( pNTHeader, pr );
|
||
|
|
||
|
if (NTHeader.COMDIR.VirtualAddress != 0 && NTHeader.COMDIR.Size != 0)
|
||
|
{
|
||
|
pComHeader = (PIMAGE_COR20_HEADER)(pBase + NTHeader.COMDIR.VirtualAddress);
|
||
|
ReadProcVar( pComHeader, &ComHeader );
|
||
|
if (ComHeader.Flags & COMIMAGE_FLAGS_ILONLY)
|
||
|
{
|
||
|
ComHeader.Flags &= ~COMIMAGE_FLAGS_ILONLY;
|
||
|
VirtProtVar( pComHeader, PAGE_READWRITE );
|
||
|
WriteProcVar( pComHeader, &ComHeader );
|
||
|
VirtProtVar( pComHeader, pr );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#endif
|