ansicon/injdll.c

203 lines
5.7 KiB
C
Raw Normal View History

/*
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