Archive

Posts Tagged ‘injection’

Custom GetProcAddress Implementation

May 11th, 2009

Had to whip together a custom GetProcAddress due to the problems outlined by Nyaeve in his blog (here). Because its probably useful to others, here it is:

// Custom GetProcAddress implementation. Needed because of Vista

// doing potential IAT hooks and generally messing things up for the

// rest of us. (AcLayers/ShimEngine)

FARPROC Injector::CustomGetProcAddress(HMODULE Module, const std::string& FunctionName)

{

try

{

// Guard from structured exceptions

SehGuard Guard;

// Get pointer to DOS header

PIMAGE_DOS_HEADER pDosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(Module);

if (!pDosHeader || pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)

throw InjectorException(”Injector: DOS PE header is invalid.”);

// Get pointer to NT header

PIMAGE_NT_HEADERS pNtHeader = reinterpret_cast<PIMAGE_NT_HEADERS>

(reinterpret_cast<PCHAR>(Module) + pDosHeader->e_lfanew);

if (pNtHeader->Signature != IMAGE_NT_SIGNATURE)

throw InjectorException(”Injector: NT PE header is invalid.”);

// Get pointer to image export directory

PVOID pExportDirTemp = reinterpret_cast<PBYTE>(Module) +

pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;

PIMAGE_EXPORT_DIRECTORY pExportDir =

reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>(pExportDirTemp);

// Get pointer to export names table

PDWORD pNamesRvas = reinterpret_cast<PDWORD>(reinterpret_cast<PBYTE>(Module)

+ pExportDir->AddressOfNames);

// Get pointer to export ordinal table

PWORD pNameOrdinals = reinterpret_cast<PWORD>(reinterpret_cast<PBYTE>(Module)

+ pExportDir->AddressOfNameOrdinals);

// Get pointer to export address table

PDWORD pFunctionAddresses = reinterpret_cast<PDWORD>(reinterpret_cast<PBYTE>(Module)

+ pExportDir->AddressOfFunctions);

// Walk the array of this module’s function names

for (DWORD n = 0; n < pExportDir->NumberOfNames; n++)

{

// Get the function name

PSTR CurrentNameTemp = reinterpret_cast<PSTR>(reinterpret_cast<PBYTE>(Module)

+ pNamesRvas[n]);

// Create string from c-style string

// Note: Throws an access violation if not a valid string

std::string CurrentName(CurrentNameTemp);

// If not the specified function, try the next function

if (CurrentName != FunctionName) continue;

// We found the specified function

// -> Get this function’s Ordinal value

WORD Ordinal = pNameOrdinals[n];

// Get the address of this function’s address

return reinterpret_cast<FARPROC>(reinterpret_cast<PBYTE>(Module)

+ pFunctionAddresses[Ordinal]);

}

}

// Catch custom SEH-proxy exceptions.

catch (const SehException& e)

{

TDBGOUT(e);

}

// Catch Injector exceptions

catch (const InjectorException& e)

{

CDBGOUT(”InjectorException: ” << e.what() << “. File: ” << __FILE__ <<

“Line: ” << __LINE__ << “.”);

}

// Nothing found, return zero

return NULL;

}

Tested and working on Windows Server 2008 x64 on both IA-32 and AMD64 processes.

Credits: Nyaeve (article), Kynox (some of the code), Windows via C/C++ (some of the code)

DLL Injector

April 21st, 2009

Figured I’d release the current build of my loader for an internal project I’m working on:

Compiled and working on both IA-32 and AMD64.
Compiled and working with both Unicode and MBCS/ASCII compiler flags. (Defaults to Unicode for obvious reasons.)

Also supports unloading the module.

Code is written in C++ with full exception handling (none of this annoying C-based return value checking crap).

Only tested on MSVC++. Visual Studio 2008 project files supplied.

Note: The AMD64 version can only inject into AMD64 processes, and the IA-32 version can only inject into IA-32 processes.  It is possible to inject into IA-32 from AMD64 but I didn’t bother because I needed an IA-32 version anyway and the code is much cleaner if I don’t have to support that.

Furthermore, don’t touch the EH compiler settings, they’re set the way they are for a reason and the code won’t work properly if you change it. If you modify it then you can’t mix SEH and C++ EH and so all the SehGuard code will fail and you won’t be able to proxy SEH to C++ EH. In short: If you don’t know what it does, just leave it alone.

Pretty much all the code should be documented but I might have missed some (I didn’t check). It should be very easy to follow though for any Windows programmer.

Obviously you’ll need to change the module name to the name of your module.

Credits:
Kynox
Greyman
Jeffrey M Richter / Christophe Nasarre
jaredpar
All of GD
Anyone I forgot (let me know)

Download:

Injector v20090421a
Injector v20090421b (Thanks Patrick! <3)