/* * @implemented */ HINSTANCE WINAPI LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) { UNICODE_STRING DllName; HINSTANCE hInst; NTSTATUS Status; PWSTR SearchPath; ULONG DllCharacteristics = 0; BOOL FreeString = FALSE; /* Check for any flags LdrLoadDll might be interested in */ if (dwFlags & DONT_RESOLVE_DLL_REFERENCES) { /* Tell LDR to treat it as an EXE */ DllCharacteristics = IMAGE_FILE_EXECUTABLE_IMAGE; } /* Build up a unicode dll name from null-terminated string */ RtlInitUnicodeString(&DllName, (LPWSTR)lpLibFileName); /* Lazy-initialize BasepExeLdrEntry */ if (!BasepExeLdrEntry) LdrEnumerateLoadedModules(0, BasepLocateExeLdrEntry, NtCurrentPeb()->ImageBaseAddress); /* Check if that module is our exe*/ if (BasepExeLdrEntry && !(dwFlags & LOAD_LIBRARY_AS_DATAFILE) && DllName.Length == BasepExeLdrEntry->FullDllName.Length) { /* Lengths match and it's not a datafile, so perform name comparison */ if (RtlEqualUnicodeString(&DllName, &BasepExeLdrEntry->FullDllName, TRUE)) { /* That's us! */ return BasepExeLdrEntry->DllBase; } } /* Check for trailing spaces and remove them if necessary */ if (DllName.Buffer[DllName.Length/sizeof(WCHAR) - 1] == L' ') { RtlCreateUnicodeString(&DllName, (LPWSTR)lpLibFileName); while (DllName.Length > sizeof(WCHAR) && DllName.Buffer[DllName.Length/sizeof(WCHAR) - 1] == L' ') { DllName.Length -= sizeof(WCHAR); } DllName.Buffer[DllName.Length/sizeof(WCHAR)] = UNICODE_NULL; FreeString = TRUE; } /* Compute the load path */ SearchPath = BaseComputeProcessDllPath((dwFlags & LOAD_WITH_ALTERED_SEARCH_PATH) ? DllName.Buffer : NULL, NULL); if (!SearchPath) { /* Getting DLL path failed, so set last error, free mem and return */ BaseSetLastNTError(STATUS_NO_MEMORY); if (FreeString) RtlFreeUnicodeString(&DllName); return NULL; } _SEH2_TRY { if (dwFlags & LOAD_LIBRARY_AS_DATAFILE) { /* If the image is loaded as a datafile, try to get its handle */ Status = LdrGetDllHandleEx(0, SearchPath, NULL, &DllName, (PVOID*)&hInst); if (!NT_SUCCESS(Status)) { /* It's not loaded yet - so load it up */ Status = BasepLoadLibraryAsDatafile(SearchPath, DllName.Buffer, &hInst); } _SEH2_YIELD(goto done;) } /* Call the API Properly */ Status = LdrLoadDll(SearchPath, &DllCharacteristics, &DllName, (PVOID*)&hInst); }
/* * @implemented */ PVOID LoadOle32Export(PVOID * BaseAddress, const PCHAR ProcedureName) { NTSTATUS Status; ANSI_STRING ExportName; PVOID ProcedureAddress; /* First load ole32.dll */ Status = LdrLoadDll(NULL, NULL, &Old32Dll, BaseAddress); if (!NT_SUCCESS(Status)) { RtlRaiseStatus(Status); } RtlInitAnsiString(&ExportName, ProcedureName); /* Look for the procedure */ Status = LdrGetProcedureAddress(*BaseAddress, &ExportName, 0, &ProcedureAddress); if (!NT_SUCCESS(Status)) { RtlRaiseStatus(Status); } /* Return its address */ return ProcedureAddress; }
NTSTATUS NTAPI BaseSrvDelayLoadKernel32(VOID) { NTSTATUS Status; ULONG i; ANSI_STRING ProcedureName; /* Only do this once */ if (BaseSrvKernel32DelayLoadComplete) return STATUS_SUCCESS; /* Loop all imports */ for (i = 0; i < RTL_NUMBER_OF(BaseSrvKernel32Imports); i++) { /* Only look them up once */ if (!*BaseSrvKernel32Imports[i].FunctionPointer) { /* If we haven't loaded the DLL yet, do it now */ if (!BaseSrvKernel32DllHandle) { Status = LdrLoadDll(0, 0, &BaseSrvKernel32DllPath, &BaseSrvKernel32DllHandle); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to load %wZ\n", &BaseSrvKernel32DllPath); return Status; } } /* Get the address of the routine being looked up*/ RtlInitAnsiString(&ProcedureName, BaseSrvKernel32Imports[i].FunctionName); Status = LdrGetProcedureAddress(BaseSrvKernel32DllHandle, &ProcedureName, 0, BaseSrvKernel32Imports[i].FunctionPointer); DPRINT1("NLS: Found %Z at 0x%p\n", &ProcedureName, BaseSrvKernel32Imports[i].FunctionPointer); if (!NT_SUCCESS(Status)) break; } } /* Did we find them all? */ if (i == RTL_NUMBER_OF(BaseSrvKernel32Imports)) { /* Excellent */ BaseSrvKernel32DelayLoadComplete = TRUE; return STATUS_SUCCESS; } /* Nope, fail */ return Status; }
NTSTATUS WINAPI SafeLdrLoadDll(PWCHAR PathToFile,ULONG Flags,PUNICODE_STRING ModuleFileName,PHANDLE ModuleHandle) { NTSTATUS rc; if (CheckOldFunction(&OldLdrLoadDll)) rc=OldLdrLoadDll(PathToFile,Flags,ModuleFileName,ModuleHandle); else rc=LdrLoadDll(PathToFile,Flags,ModuleFileName,ModuleHandle); return rc; }
// my loadlibrary, uses only ntdll functions LPVOID engine_NtLoadLibraryA(LPSTR lpModuleName) { STRING asModuleName; UNICODE_STRING usModuleName; HANDLE hModule; asModuleName.Buffer=(PCHAR)lpModuleName; asModuleName.Length=strlen(lpModuleName); asModuleName.MaximumLength=asModuleName.Length; if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&usModuleName,&asModuleName,TRUE))) return NULL; if (!NT_SUCCESS(LdrLoadDll(NULL,0,&usModuleName,&hModule))) { RtlFreeUnicodeString(&usModuleName); return NULL; } RtlFreeUnicodeString(&usModuleName); return hModule; }
NTSTATUS getAndLoadDllByInput(PVOID* ppDllBase){ WCHAR szDllName[MAX_PATH]; ///It's impossible, that the DLL's image name length exceeds 260 chars, ///since the maximum length of a file path part is limited to ~255 by Windows. ULONGLONG dllStrSize; UNICODE_STRING uDllName; ULONG loadFlags = 0x0; NTSTATUS status = STATUS_HANDLE_NO_LONGER_VALID; status = myfgetws(szDllName, sizeof(szDllName), &dllStrSize); if (status) return status; ///Although we don't want any DllMain() to be called, we intend to use standard PE math ///when walking the EAT at a later time. So we still need to load the DLL as an image file. loadFlags = LOAD_LIBRARY_AS_IMAGE_RESOURCE; loadFlags |= LOAD_LIBRARY_SEARCH_SYSTEM32; loadFlags |= LOAD_LIBRARY_SEARCH_APPLICATION_DIR; RtlInitUnicodeString(&uDllName, szDllName); status = LdrLoadDll(NULL, &loadFlags, &uDllName, ppDllBase); return status; }
HOOKFUNC NTSTATUS NTAPI MyLdrLoadDll(PWCHAR PathToFile, ULONG Flags, PUNICODE_STRING ModuleFileName, PHANDLE ModuleHandle) { //debugprintf(__FUNCTION__ "(ModuleFileName=\"%S\") called.\n", ModuleFileName->Buffer); //cmdprintf("SHORTTRACE: 3,50"); //debugprintf(__FUNCTION__ "(ModuleFileName=\"%S\") called.\n", ModuleFileName->Buffer); //DWORD myEBP; // __asm // { // mov [myEBP], ebp; // } //debugsplatmem(myEBP, "ebp"); #if 1 // new method, get list of loaded dlls from debugger (because LdrLoadDll can load multiple dlls) //_asm{int 3} // to print callstack... debugprintf/cmdprintf can cause problems in this context ThreadLocalStuff* pCurtls = 0; if(tlsIsSafeToUse) { pCurtls = &tls; ThreadLocalStuff& curtls = *pCurtls; if(curtls.callingClientLoadLibrary || curtls.treatDLLLoadsAsClient) { curtls.callingClientLoadLibrary = FALSE; // see MyKiUserCallbackDispatcher watchForCLLApiNum = false; // if we were watching for the apiNum, it must have worked if(!ShouldLoadUserDll(ModuleFileName->Buffer)) { //debuglog(LCF_MODULE, "DENIED loading DLL: %S\n", ModuleFileName->Buffer); //cmdprintf("SHORTTRACE: 3,50"); return /*STATUS_DLL_NOT_FOUND*/0xC0000135; } } // TEST HACK if(WideStringContains(ModuleFileName->Buffer, "dpofeedb.dll")) return /*STATUS_DLL_NOT_FOUND*/0xC0000135; pCurtls->callerisuntrusted++; } //if(tlsIsSafeToUse) //{ // debuglog(LCF_MODULE, "Loaded DLL: %S\n", ModuleFileName->Buffer); // //cmdprintf("SHORTTRACE: 3,50"); //} NTSTATUS rv = LdrLoadDll(PathToFile, Flags, ModuleFileName, ModuleHandle); //if(rv < 0) // debuglog(LCF_MODULE|LCF_ERROR, "FAILED to load DLL: %S (0x%X)\n", ModuleFileName->Buffer, rv); UpdateLoadedOrUnloadedDllHooks(); if(pCurtls) pCurtls->callerisuntrusted--; return rv; #else // for some reason this function is INCREDIBLY fragile. // the slightest bit too much processing will make games fail to load certain critical DLLs. // I'd like to call ShouldAllowDLLLoad to deny certain DLLs from loading, but currently can't. LPWSTR lpFileName = ModuleFileName->Buffer; // store the string first because LdrLoadDll puts garbage in the string (registry keys?) // this way of doing it seems to be more reliable than sprintf(name, "%S", lpFileName); char name [1024]; int i = 0; for(; lpFileName[i] && i != sizeof(name)-1; i++) name[i] = (char)lpFileName[i]; name[i] = 0; //debuglog(LCF_MODULE, __FUNCTION__ "(%S, 0x%X, %S, 0x%X)\n", lpFileName, Flags, PathToFile, ModuleHandle); //if(!ShouldAllowDLLLoad(name)) //{ // //return 0xC0000135; //} NTSTATUS rv = LdrLoadDll(PathToFile, Flags, ModuleFileName, ModuleHandle); //static int inside = 0; //if(inside) if(inside != GetCurrentThreadId()) while(inside) {OutputDebugString("WTFA\n");} //inside = GetCurrentThreadId(); //#if defined(_MSC_VER) && _MSC_VER >= 1400 && _MSC_VER < 1500 // terrible mystery hack! to fix some games from failing to find kernel32.dll when this file is compiled with VS2005 //static bool already = false; //if(!already) // if(lpFileName[0] == 'K' && lpFileName[6] == '3') // { // //already = true; // NTSTATUS rv = LdrLoadDll(PathToFile, Flags, ModuleFileName, ModuleHandle); //// inside = 0; // return rv; // } //#endif // NTSTATUS rv = LdrLoadDll(PathToFile, Flags, ModuleFileName, ModuleHandle); if(rv >= 0) { int namelen = i; if(!(namelen < 4 || !stricmp(name+namelen-4,".exe"))) { char* slash = max(strrchr(name, '\\'), strrchr(name, '/')); const char* dllname = slash ? slash+1 : name; //debuglog(LCF_MODULE, "Rehooking: %s\n", dllname); RetryInterceptAPIs(dllname); // disabled because it will make AVIs captured on different machines be slightly different lengths //// loading DLLs takes time //detTimer.AddDelay(/*10*/15, FALSE, FALSE); // must both be FALSE to signal async delay add, otherwise really weird things will happen like inaccurate thread creation reports to the debugger } } else { //HANDLE handle = GetModuleHandleA(name); //if(handle) //{ // *ModuleHandle = handle; // rv = 0; //} //while(rv < 0) { debuglog(LCF_MODULE|LCF_ERROR, "FAILED to load DLL: %s (0x%X)\n", name, rv); // debuglog(LCF_MODULE|LCF_ERROR, "%S, 0x%X, 0x%X, %S\n", ModuleFileName->Buffer, Flags, ModuleHandle, PathToFile); // rv = LdrLoadDll(PathToFile, Flags, ModuleFileName, ModuleHandle); } //NTSTATUS rv = LdrLoadDll(PathToFile, Flags, ModuleFileName, ModuleHandle); } // inside = 0; return rv; #endif }
BOOL SetConsolePalette( IN HANDLE hConsoleOutput, IN HPALETTE hPalette, IN UINT dwUsage ) /*++ Description: Sets the palette for the console screen buffer. Parameters: hOutput - Supplies a console output handle. hPalette - Supplies a handle to the palette to set. dwUsage - Specifies use of the system palette. SYSPAL_NOSTATIC - System palette contains no static colors except black and white. SYSPAL_STATIC - System palette contains static colors which will not change when an application realizes its logical palette. Return value: TRUE - The operation was successful. FALSE/NULL - The operation failed. Extended error status is available using GetLastError. --*/ { HANDLE hmodGdi; UNICODE_STRING ModuleNameString; NTSTATUS Status; if ( !pfnGdiConvertPalette ) { RtlInitUnicodeString( &ModuleNameString, L"gdi32" ); Status = LdrLoadDll( UNICODE_NULL, NULL, &ModuleNameString, &hmodGdi ); if ( !NT_SUCCESS(Status) ) { SET_LAST_NT_ERROR(Status); return FALSE; } pfnGdiConvertPalette = (PCONVPALFUNC)GetProcAddress(hmodGdi, "GdiConvertPalette"); if (pfnGdiConvertPalette == NULL) { SET_LAST_NT_ERROR(STATUS_PROCEDURE_NOT_FOUND); return FALSE; } } hPalette = (*pfnGdiConvertPalette)(hPalette); return SetConsolePaletteInternal(hConsoleOutput, hPalette, dwUsage); }
ULONG BaseSrvDebugProcess( IN OUT PCSR_API_MSG m, IN OUT PCSR_REPLY_STATUS ReplyStatus ) { NTSTATUS Status; PBASE_DEBUGPROCESS_MSG a = (PBASE_DEBUGPROCESS_MSG)&m->u.ApiMessageData; HANDLE Thread,ProcessHandle,Token; PCSR_PROCESS Process; DWORD ThreadId; PTOKEN_DEFAULT_DACL lpDefaultDacl; TOKEN_DEFAULT_DACL DefaultDacl; ULONG DaclLength; SECURITY_ATTRIBUTES ThreadAttributes; SECURITY_DESCRIPTOR SecurityDescriptor; UNICODE_STRING ModuleNameString_U; PVOID ModuleHandle; STRING ProcedureNameString; PCREATE_REMOTE_THREAD CreateRemoteThreadRoutine; if (a->dwProcessId == -1 && a->AttachCompleteRoutine == NULL) { HANDLE DebugPort; DebugPort = (HANDLE)NULL; Status = NtQueryInformationProcess( NtCurrentProcess(), ProcessDebugPort, (PVOID)&DebugPort, sizeof(DebugPort), NULL ); if ( NT_SUCCESS(Status) && DebugPort ) { return (ULONG)STATUS_ACCESS_DENIED; } return STATUS_SUCCESS; } #if DEVL if (a->dwProcessId != -1) { #endif // DEVL if ( a->AttachCompleteRoutine == NULL ) { Status = CsrLockProcessByClientId((HANDLE)a->dwProcessId,&Process); if ( NT_SUCCESS(Status) ) { ProcessHandle = Process->ProcessHandle; Status = NtOpenProcessToken(ProcessHandle, TOKEN_QUERY, &Token ); if ( !NT_SUCCESS(Status) ) { CsrUnlockProcess(Process); return Status; } lpDefaultDacl = &DefaultDacl; Status = NtQueryInformationToken(Token, TokenDefaultDacl, lpDefaultDacl, sizeof(DefaultDacl), &DaclLength ); if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL) { Status = STATUS_ACCESS_DENIED; } else { Status = STATUS_SUCCESS; } if ( Process->DebugUserInterface.UniqueProcess || Process->DebugUserInterface.UniqueThread ) { Status = STATUS_ACCESS_DENIED; } NtClose(Token); CsrUnlockProcess(Process); } return (ULONG)Status; } // // Can't call base, but I know it is there // RtlInitUnicodeString( &ModuleNameString_U, L"kernel32" ); Status = LdrLoadDll( UNICODE_NULL, NULL, &ModuleNameString_U, &ModuleHandle ); if ( !NT_SUCCESS(Status) ) { return (ULONG)Status; } RtlInitString( &ProcedureNameString, "CreateRemoteThread" ); Status = LdrGetProcedureAddress( ModuleHandle, &ProcedureNameString, (ULONG) NULL, (PVOID *) &CreateRemoteThreadRoutine ); if ( !NT_SUCCESS(Status) ) { LdrUnloadDll( ModuleHandle ); return (ULONG)Status; } Status = CsrLockProcessByClientId((HANDLE)a->dwProcessId,&Process); if ( NT_SUCCESS(Status) ) { ProcessHandle = Process->ProcessHandle; Status = NtOpenProcessToken(ProcessHandle, TOKEN_QUERY, &Token ); if (!NT_SUCCESS(Status)) { CsrUnlockProcess(Process); LdrUnloadDll( ModuleHandle ); return (ULONG)Status; } lpDefaultDacl = &DefaultDacl; Status = NtQueryInformationToken(Token, TokenDefaultDacl, lpDefaultDacl, sizeof(DefaultDacl), &DaclLength ); if (!NT_SUCCESS(Status)) { lpDefaultDacl = RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( TMP_TAG ), DaclLength); if (lpDefaultDacl) { Status = NtQueryInformationToken(Token, TokenDefaultDacl, lpDefaultDacl, DaclLength, &DaclLength ); } else { Status = STATUS_NO_MEMORY; } NtClose(Token); if (!NT_SUCCESS(Status)) { CsrUnlockProcess(Process); LdrUnloadDll( ModuleHandle ); return (ULONG)Status; } } else { NtClose(Token); } ThreadAttributes.nLength = sizeof(ThreadAttributes); RtlCreateSecurityDescriptor(&SecurityDescriptor,SECURITY_DESCRIPTOR_REVISION1); ThreadAttributes.lpSecurityDescriptor = &SecurityDescriptor; SecurityDescriptor.Control = SE_DACL_PRESENT; SecurityDescriptor.Dacl = lpDefaultDacl->DefaultDacl; ThreadAttributes.bInheritHandle = FALSE; CsrUnlockProcess(Process); } #if DEVL } #endif // DEVL // // Set up the specified user-interface as the debugger of the // target process. Whip through the target process and // suspend all threads. Then Send CreateProcess, LoadModule, and // CreateThread Messages. Finally send the attach complete // exception. // Status = CsrDebugProcess( a->dwProcessId, &a->DebuggerClientId, (PCSR_ATTACH_COMPLETE_ROUTINE)a->AttachCompleteRoutine ); #if DEVL if (a->dwProcessId != -1) { #endif // DEVL if ( NT_SUCCESS(Status) ) { Thread = (PVOID)(CreateRemoteThreadRoutine)(ProcessHandle, &ThreadAttributes, 0L, (LPTHREAD_START_ROUTINE)a->AttachCompleteRoutine, 0, 0, &ThreadId ); LdrUnloadDll( ModuleHandle ); if ( lpDefaultDacl != &DefaultDacl ) { RtlFreeHeap(RtlProcessHeap(), 0,lpDefaultDacl); } if ( !Thread ) { return (ULONG)STATUS_UNSUCCESSFUL; } NtClose(Thread); } #if DEVL } #endif // DEVL return (ULONG) Status; }