Win2k泄漏源代码赏析——GetProcAddress

    技术2022-05-20  40

     FARPROC GetProcAddress(     HMODULE hModule,     LPCSTR lpProcName     ) {     NTSTATUS Status;     PVOID ProcedureAddress;     STRING ProcedureName;

        if ( (ULONG_PTR)lpProcName > 0xffff ) {         RtlInitString(&ProcedureName,lpProcName);         Status = LdrGetProcedureAddress(                         BasepMapModuleHandle( hModule, FALSE ),                         &ProcedureName,                         0L,                         &ProcedureAddress                         );         }     else {         Status = LdrGetProcedureAddress(                         BasepMapModuleHandle( hModule, FALSE ),                         NULL,                         PtrToUlong((PVOID)lpProcName),                         &ProcedureAddress                         );         }     if ( !NT_SUCCESS(Status) ) {         BaseSetLastNTError(Status);         return NULL;         }     else {         if ( ProcedureAddress == BasepMapModuleHandle( hModule, FALSE ) ) {             if ( (ULONG_PTR)lpProcName > 0xffff ) {                 Status = STATUS_ENTRYPOINT_NOT_FOUND;                 }             else {                 Status = STATUS_ORDINAL_NOT_FOUND;                 }             BaseSetLastNTError(Status);             return NULL;             }         else {             return (FARPROC)ProcedureAddress;             }         } } NTSTATUS LdrGetProcedureAddress (     IN PVOID DllHandle,     IN PANSI_STRING ProcedureName OPTIONAL,     IN ULONG ProcedureNumber OPTIONAL,     OUT PVOID *ProcedureAddress     ) {

        return LdrpGetProcedureAddress(DllHandle,ProcedureName,ProcedureNumber,ProcedureAddress,TRUE);

    } NTSTATUS LdrpGetProcedureAddress (     IN PVOID DllHandle,     IN PANSI_STRING ProcedureName OPTIONAL,     IN ULONG ProcedureNumber OPTIONAL,     OUT PVOID *ProcedureAddress,     IN BOOLEAN RunInitRoutines     )

    /*++

    Routine Description:

        This function locates the address of the specified procedure in the     specified DLL and returns its address.

    --*/

    {     NTSTATUS st;     UCHAR FunctionNameBuffer[64];     PUCHAR src, dst;     ULONG cb, ExportSize;     PLDR_DATA_TABLE_ENTRY LdrDataTableEntry;     IMAGE_THUNK_DATA Thunk;     PVOID ImageBase;     PIMAGE_IMPORT_BY_NAME FunctionName;     PIMAGE_EXPORT_DIRECTORY ExportDirectory;     PLIST_ENTRY Next; #if defined (WX86)     PTEB Teb;     BOOLEAN Wx86KnownDll = FALSE; #endif

        if (ShowSnaps) {         DbgPrint("LDR: LdrGetProcedureAddress by ");     }

    #if defined (WX86)     Teb = NtCurrentTeb();     if (Teb->Wx86Thread.UseKnownWx86Dll) {         Wx86KnownDll = Teb->Wx86Thread.UseKnownWx86Dll;         Teb->Wx86Thread.UseKnownWx86Dll = FALSE;         } #endif         FunctionName = NULL;     if ( ARGUMENT_PRESENT(ProcedureName) ) {

            if (ShowSnaps) {             DbgPrint("NAME - %s/n", ProcedureName->Buffer);         }

            //         // BUGBUG need STRING to PSZ         //

            if (ProcedureName->Length >= sizeof( FunctionNameBuffer )-1 ) {             FunctionName = RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( TEMP_TAG ),ProcedureName->Length+1+sizeof(USHORT));             if ( !FunctionName ) {                 return STATUS_INVALID_PARAMETER;                 }         } else {             FunctionName = (PIMAGE_IMPORT_BY_NAME) FunctionNameBuffer;         }

            FunctionName->Hint = 0;

            cb = ProcedureName->Length;         src = ProcedureName->Buffer;         dst = FunctionName->Name;

            while (cb--) {             *dst++ = *src++;         }         *dst = '{fckeditor}';

            //         // Make sure we don't pass in address with high bit set so we         // can still use it as ordinal flag         //

            ImageBase = FunctionName;         Thunk.u1.AddressOfData = 0;

        } else {             ImageBase = NULL;              if (ShowSnaps) {                  DbgPrint("ORDINAL - %lx/n", ProcedureNumber);              }

                 if (ProcedureNumber) {                  Thunk.u1.Ordinal = ProcedureNumber | IMAGE_ORDINAL_FLAG;              } else {                       return STATUS_INVALID_PARAMETER;                     }           }

        if ( LdrpInLdrInit == FALSE ) {         RtlEnterCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->LoaderLock);         }     try {

            if (!LdrpCheckForLoadedDllHandle(DllHandle, &LdrDataTableEntry)) {             st = STATUS_DLL_NOT_FOUND;             return st;         }

            ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData(                            LdrDataTableEntry->DllBase,                            TRUE,                            IMAGE_DIRECTORY_ENTRY_EXPORT,                            &ExportSize                            );

            if (!ExportDirectory) {             return STATUS_PROCEDURE_NOT_FOUND;         }

            st = LdrpSnapThunk(LdrDataTableEntry->DllBase,                            ImageBase,                            &Thunk,                            &Thunk,                            ExportDirectory,                            ExportSize,                            FALSE,                            NULL                           );

            if ( RunInitRoutines ) {             PLDR_DATA_TABLE_ENTRY LdrInitEntry;

                //             // Look at last entry in init order list. If entry processed             // flag is not set, then a forwarded dll was loaded during the             // getprocaddr call and we need to run init routines             //

                Next = NtCurrentPeb()->Ldr->InInitializationOrderModuleList.Blink;             LdrInitEntry = CONTAINING_RECORD(Next, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks);             if ( !(LdrInitEntry->Flags & LDRP_ENTRY_PROCESSED) ) {                 try {                     st = LdrpRunInitializeRoutines(NULL);                     }                 except( EXCEPTION_EXECUTE_HANDLER ) {                     st = GetExceptionCode();                     }

                    }             }

            if ( NT_SUCCESS(st) ) {             *ProcedureAddress = (PVOID)Thunk.u1.Function; #if defined (WX86)             // For dlls loaded as a Wx86 plugin ...

                if (Wx86ProcessInit && (LdrDataTableEntry->Flags & LDRP_WX86_PLUGIN)) {                 PVOID ExportThunk = NULL;                 USHORT MachineType = RtlImageNtHeader(LdrDataTableEntry->DllBase)->FileHeader.Machine;

                    // and the GetProcAddress call is cross-architecture ...

                    if ((!Wx86KnownDll && (MachineType == IMAGE_FILE_MACHINE_I386))                   || (Wx86KnownDll && (MachineType != IMAGE_FILE_MACHINE_I386))) {                         // Thunk the export

                        st = Wx86ThunkPluginExport(LdrDataTableEntry->DllBase,                                                FunctionName? FunctionName->Name : NULL,                                                ProcedureNumber,                                                (PVOID)(Thunk.u1.Function),                                                &ExportThunk                                                );                     if (NT_SUCCESS(st) && ExportThunk) {                         *ProcedureAddress = ExportThunk;                     } else {                         // Don't let unthunked cross-architecture addresses get out                         *ProcedureAddress = NULL;                         st = STATUS_INVALID_IMAGE_FORMAT;                         }                     }                 } #endif             }     } finally {         if ( FunctionName && (FunctionName != (PIMAGE_IMPORT_BY_NAME) FunctionNameBuffer) ) {             RtlFreeHeap(RtlProcessHeap(),0,FunctionName);             }         if ( LdrpInLdrInit == FALSE ) {             RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->LoaderLock);             }     }     return st; }

     

     


    最新回复(0)