现在的位置: 首页 > 综合 > 正文

Win2k泄漏源代码赏析——GetProcAddress

2013年01月25日 ⁄ 综合 ⁄ 共 6969字 ⁄ 字号 评论关闭

 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;
}

 

 

抱歉!评论已关闭.