another intersting topic for today. so.there is about 3-4 LoadLibrary? function all called to LoadLibraryExW! this also, call 2 diffrent way's Code: --> to Resource -> option 1 --> to else -> option 2 for resource, it call internal function, that call other couple internal function and also lot of ntdll api. for else, it called LdrLoadDll. example call's with exlpain later. Code: 0x00000010 - LOAD_IGNORE_CODE_AUTHZ_LEVEL LdrLoadDll(1,[Ref]0, 0x000000cae83fda50, 0x000000cae83fda98) 0x00000008 - LOAD_WITH_ALTERED_SEARCH_PATH LdrLoadDll(9,[Ref]0, 0x000000cae7fee930, 0x000000cae7fee978) 0x00000800 - LOAD_LIBRARY_SEARCH_SYSTEM32 LdrLoadDll(2049, [Ref]0, 0x000000cae83fed00, 0x000000cae83fed48 ) 0x00002000 -bor 0x00000008 - LOAD_LIBRARY_SAFE_CURRENT_DIRS & LOAD_WITH_ALTERED_SEARCH_PATH LdrLoadDll(8201, [Ref]0, 0x000000cae85fcbb0, 0x000000cae85fcbf8 ) how it decide, to call Resource or Else ? Code: if ((dwFlags & 0x62) == 0) { local_res8[0] = 0; if ((dwFlags & 1) != 0) { local_res8[0] = 2; uVar3 = 2; } if ((char)dwFlags < '\0') { uVar3 = uVar3 | 0x800000; local_res8[0] = uVar3; } if ((dwFlags & 4) != 0) { uVar3 = uVar3 | 4; local_res8[0] = uVar3; } if ((dwFlags >> 0xf & 1) != 0) { local_res8[0] = uVar3 | 0x80000000; } iVar1 = LdrLoadDll(dwFlags & 0x7f08 | 1,local_res8,local_28,&local_res20); } that mean. Code: (0x00000001 -band 0x7f08) -bor 1 // DONT_RESOLVE_DLL_REFERENCES (0x00000010 -band 0x7f08) -bor 1 // LOAD_IGNORE_CODE_AUTHZ_LEVEL (0x00000200 -band 0x7f08) -bor 1 // LOAD_LIBRARY_SEARCH_APPLICATION_DIR (0x00001000 -band 0x7f08) -bor 1 // LOAD_LIBRARY_SEARCH_DEFAULT_DIRS (0x00000100 -band 0x7f08) -bor 1 // LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR (0x00000800 -band 0x7f08) -bor 1 // LOAD_LIBRARY_SEARCH_SYSTEM32 (0x00000400 -band 0x7f08) -bor 1 // LOAD_LIBRARY_SEARCH_USER_DIRS (0x00000008 -band 0x7f08) -bor 1 // LOAD_WITH_ALTERED_SEARCH_PATH (0x00000080 -band 0x7f08) -bor 1 // LOAD_LIBRARY_REQUIRE_SIGNED_TARGET (0x00002000 -band 0x7f08) -bor 1 // LOAD_LIBRARY_SAFE_CURRENT_DIRS >>> go to ntdll function 0x00000002, LOAD_LIBRARY_AS_DATAFILE 0x00000040, LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE 0x00000020, LOAD_LIBRARY_AS_IMAGE_RESOURCE other Internal function
So, now based on what we know, this is the function, Defination. Code: [In]String\Flags, [In][REF]Flags, [In][REF]UNICODE_STRING, [Out]Handle void LdrLoadDll(ulonglong param_1,uint *param_2,uint *param_3,undefined8 *param_4) https://rextester.com/KCUV42565 RtlInitUnicodeStringStruct (&unicodestring, L"USER32.dll"); LdrLoadDllStruct (NULL, 0, &unicodestring, &hModule); https://doxygen.reactos.org/d7/d55/ldrapi_8c_source.html NTSTATUS NTAPI DECLSPEC_HOTPATCH LdrLoadDll( _In_opt_ PWSTR SearchPath, _In_opt_ PULONG DllCharacteristics, _In_ PUNICODE_STRING DllName, _Out_ PVOID *BaseAddress) { First param can be Value Type (Pointer) or a real directory path. Second params decide by Math algo' of function i share and saved as Pointer -> int Value Code: # parameter [1] Filepath $FilePath = [IntPtr]::new($Flags) # parameter [2] DllCharacteristics [Marshal]::WriteInt32($FlagsPtr, $DllCharacteristics) third params is result of RtlInitUnicodeString(dll_name) last params is output, for place holder pointer
Based on what i shared now, here a complete function, based os PS1 code Check, Data -> goto LoadLibraryExW, else, parse arg's and run LdrLoadDll Function ! Code: enum LOAD_LIBRARY { NO_DLL_REF = 0x00000001 IGNORE_AUTHZ = 0x00000010 AS_DATAFILE = 0x00000002 AS_DATAFILE_EXCL = 0x00000040 AS_IMAGE_RES = 0x00000020 SEARCH_APP = 0x00000200 SEARCH_DEFAULT = 0x00001000 SEARCH_DLL_LOAD = 0x00000100 SEARCH_SYS32 = 0x00000800 SEARCH_USER = 0x00000400 ALTERED_SEARCH = 0x00000008 REQ_SIGNED = 0x00000080 SAFE_CURRENT = 0x00002000 } function Ldr-LoadDll { param ( [Parameter(Mandatory = $true)] [LOAD_LIBRARY]$dwFlags, [Parameter(Mandatory = $false)] [switch]$Log, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$dll ) $HResults = [IntPtr]::Zero $FlagsPtr = [IntPtr]::Zero $unicodeStringPtr = [IntPtr]::Zero if (-not $dwFlags -and $dwFlags.value__ -eq $null) { throw "can't access dwFlags value" } if ($dwFlags.value__ -lt 0) { throw "dwFlags Can't be less than 0" } try { $FlagsPtr = New-IntPtr -Size 4 $unicodeStringPtr = New-IntPtr -Size 16 # Equivalent to: if ((dwFlags & 0x62) == 0) if (($dwFlags.value__ -band 0x62) -eq 0) { $uVar3 = 0 if (($dwFlags.value__ -band 1) -ne 0) { $uVar3 = 2 } if (($dwFlags.value__ -band 0x80) -ne 0) { $uVar3 = $uVar3 -bor 0x800000 } if (($dwFlags.value__ -band 4) -ne 0) { $uVar3 = $uVar3 -bor 4 } if ((($dwFlags.value__ -shr 15) -band 1) -ne 0) { $uVar3 = $uVar3 -bor 0x80000000 } $Flags = ($dwFlags.value__ -band 0x7f08) -bor 1 $DllCharacteristics = $uVar3 if ($Log) { Write-Warning "Flags = $Flags" Write-Warning "SearchPath = $DllCharacteristics" Write-Warning "Function = LdrLoadDll" return } # parameter [1] Filepath $FilePath = [IntPtr]::new($Flags) # parameter [2] DllCharacteristics [Marshal]::WriteInt32($FlagsPtr, $DllCharacteristics) # parameter [3] UnicodeString $null = $Global:ntdll::RtlInitUnicodeString( $unicodeStringPtr, $dll) # Out Results $null = $Global:ntdll::LdrLoadDll( $FilePath, # Flags $FlagsPtr, # NULL / [REF]Long $unicodeStringPtr, # [REF]UnicodeString [ref]$HResults # [Out]Handle ) return $HResults } else { if ($Log) { Write-Warning "Flags = $($dwFlags.value__)" Write-Warning "SearchPath = NULL" Write-Warning "Function = LoadLibraryExW" return } return $Global:kernel32::LoadLibraryExW( $dll, [IntPtr]::Zero, $dwFlags.value__) } } catch { } finally { if ($FlagsPtr -ne $null -and $FlagsPtr -ne [IntPtr]::Zero) { [Marshal]::FreeHGlobal($FlagsPtr) } if ($unicodeStringPtr -ne $null -and $unicodeStringPtr -ne [IntPtr]::Zero) { [Marshal]::FreeHGlobal($unicodeStringPtr) } } return $HResults } Extra Info Code: >>>>>>>>>>>>>>>>>>>>>>>>>>> API-SPY --> SLUI 0x2a ERROR >>>>>>>>>>>>>>>>>>>>>>>>>>> 0x00000010 - LOAD_IGNORE_CODE_AUTHZ_LEVEL LdrLoadDll(1,[Ref]0, 0x000000cae83fda50, 0x000000cae83fda98) 0x00000008 - LOAD_WITH_ALTERED_SEARCH_PATH LdrLoadDll(9,[Ref]0, 0x000000cae7fee930, 0x000000cae7fee978) 0x00000800 - LOAD_LIBRARY_SEARCH_SYSTEM32 LdrLoadDll(2049, [Ref]0, 0x000000cae83fed00, 0x000000cae83fed48 ) 0x00002000 -bor 0x00000008 - LOAD_LIBRARY_SAFE_CURRENT_DIRS & LOAD_WITH_ALTERED_SEARCH_PATH LdrLoadDll(8201, [Ref]0, 0x000000cae85fcbb0, 0x000000cae85fcbf8 ) >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> HMODULE __stdcall LoadLibraryExW(LPCWSTR lpLibFileName,HANDLE hFile,DWORD dwFlags) >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> if ((dwFlags & 0x62) == 0) { local_res8[0] = 0; if ((dwFlags & 1) != 0) { local_res8[0] = 2; uVar3 = 2; } if ((char)dwFlags < '\0') { uVar3 = uVar3 | 0x800000; local_res8[0] = uVar3; } if ((dwFlags & 4) != 0) { uVar3 = uVar3 | 4; local_res8[0] = uVar3; } if ((dwFlags >> 0xf & 1) != 0) { local_res8[0] = uVar3 | 0x80000000; } iVar1 = LdrLoadDll(dwFlags & 0x7f08 | 1,local_res8,local_28,&local_res20); } >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> void LdrLoadDll(ulonglong param_1,uint *param_2,uint *param_3,undefined8 *param_4) >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> if (param_2 == (uint *)0x0) { uVar4 = 0; } else { uVar4 = (*param_2 & 4) * 2; uVar3 = uVar4 | 0x40; if ((*param_2 & 2) == 0) { uVar3 = uVar4; } uVar4 = uVar3 | 0x80; if ((*param_2 & 0x800000) == 0) { uVar4 = uVar3; } uVar3 = uVar4 | 0x100; if ((*param_2 & 0x1000) == 0) { uVar3 = uVar4; } uVar4 = uVar3 | 0x400000; if (-1 < (int)*param_2) { uVar4 = uVar3; } } SearchPath ---------- (0x00000001 -band 0x7f08) -bor 1 // DONT_RESOLVE_DLL_REFERENCES (0x00000010 -band 0x7f08) -bor 1 // LOAD_IGNORE_CODE_AUTHZ_LEVEL (0x00000200 -band 0x7f08) -bor 1 // LOAD_LIBRARY_SEARCH_APPLICATION_DIR (0x00001000 -band 0x7f08) -bor 1 // LOAD_LIBRARY_SEARCH_DEFAULT_DIRS (0x00000100 -band 0x7f08) -bor 1 // LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR (0x00000800 -band 0x7f08) -bor 1 // LOAD_LIBRARY_SEARCH_SYSTEM32 (0x00000400 -band 0x7f08) -bor 1 // LOAD_LIBRARY_SEARCH_USER_DIRS (0x00000008 -band 0x7f08) -bor 1 // LOAD_WITH_ALTERED_SEARCH_PATH (0x00000080 -band 0x7f08) -bor 1 // LOAD_LIBRARY_REQUIRE_SIGNED_TARGET (0x00002000 -band 0x7f08) -bor 1 // LOAD_LIBRARY_SAFE_CURRENT_DIRS This --> will auto bypass to LoadLibraryEx? 0x00000002, LOAD_LIBRARY_AS_DATAFILE 0x00000040, LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE 0x00000020, LOAD_LIBRARY_AS_IMAGE_RESOURCE DllCharacteristics ------------------ Auto deteced by function. According to dwFlag value, who provide by user.
So, back to Origional sample. Code: LdrLoadDll(1,[Ref]0, 0x000000cae83fda50, 0x000000cae83fda98) LdrLoadDll(9,[Ref]0, 0x000000cae7fee930, 0x000000cae7fee978) LdrLoadDll(2049, [Ref]0, 0x000000cae83fed00, 0x000000cae83fed48 ) LdrLoadDll(8201, [Ref]0, 0x000000cae85fcbb0, 0x000000cae85fcbf8 ) 0x00000010 - LOAD_IGNORE_CODE_AUTHZ_LEVEL, after using math algo provided, it become Flags = 1, and Dll Char 0 0x00000008 - LOAD_WITH_ALTERED_SEARCH_PATH after using math algo provided, it become Flags = 9, and Dll Char 0 0x00000800 - LOAD_LIBRARY_SEARCH_SYSTEM32 after using math algo provided, it become Flags = 2049, and Dll Char 0 0x00002000 -bor 0x00000008 - LOAD_LIBRARY_SAFE_CURRENT_DIRS & LOAD_WITH_ALTERED_SEARCH_PATH after using math algo provided, it become Flags = 8201, and Dll Char 0 Code: PS C:\Users\Administrator> Ldr-LoadDll -dwFlag IGNORE_AUTHZ -Log $true WARNING: Flags = 1 WARNING: SearchPath = 0 WARNING: Function = LdrLoadDll PS C:\Users\Administrator> Ldr-LoadDll -dwFlag ALTERED_SEARCH -Log $true WARNING: Flags = 9 WARNING: SearchPath = 0 WARNING: Function = LdrLoadDll PS C:\Users\Administrator> Ldr-LoadDll -dwFlag SEARCH_SYS32 -Log $true WARNING: Flags = 2049 WARNING: SearchPath = 0 WARNING: Function = LdrLoadDll PS C:\Users\Administrator> Ldr-LoadDll -dwFlag ([LOAD_LIBRARY]::SAFE_CURRENT -bor [LOAD_LIBRARY]::ALTERED_SEARCH) -Log $true WARNING: Flags = 8201 WARNING: SearchPath = 0 WARNING: Function = LdrLoadDll
That is more than intersting. full decoded function from ghidra. Code: HMODULE __stdcall LoadLibraryExW( * LPCWSTR lpLibFileName, * HANDLE hFile, * DWORD dwFlags) { ...... ...... if ((dwFlags & 0x62) == 0) { local_res8[0] = 0; if ((dwFlags & 1) != 0) { local_res8[0] = 2; uVar3 = 2; } if ((char)dwFlags < '\0') { uVar3 = uVar3 | 0x800000; local_res8[0] = uVar3; } if ((dwFlags & 4) != 0) { uVar3 = uVar3 | 4; local_res8[0] = uVar3; } if ((dwFlags >> 0xf & 1) != 0) { local_res8[0] = uVar3 | 0x80000000; } ******************* iVar1 = LdrLoadDll( dwFlags & 0x7f08 | 1 local_res8 local_28 &local_res20) ******************* } else { iVar1 = LdrGetDllPath(local_20,dwFlags & 0x7f08,&local_38,&local_30); if (iVar1 < 0) goto LAB_180031e47; iVar1 = FUN_18002f670(local_28,local_38,local_30,dwFlags,(ulonglong *)&local_res20); if (((iVar1 + 0x80000000U & 0x80000000) == 0) && (iVar1 != -0x3ffffff1)) { pHVar2 = (HMODULE)FUN_1800c8449(); return pHVar2; } RtlReleasePath(local_38); } if (-1 < iVar1) { return local_res20; } LAB_180031e47: FUN_1800323e0(); return (HMODULE)0x0; }
In case you wondering resource Case ? OK lot of low level call's like: NtCreateSection, RtlImageNtHeaderEx CreateFileMappingNumaW LdrGetDllHandleByMapping RtlGetActiveActivationContext Code: extracted Using ghidra /* WARNING: Type propagation algorithm not settling */ void FUN_18002f670(uint *param_1,undefined8 param_2,LPCWSTR param_3,uint param_4,ulonglong *param_5) { ........ ........ else { uVar9 = (ushort)*param_1 + 10; if ((0xfffe < uVar9) || (local_1b0 = RtlAllocateHeap(*(undefined8 *)((longlong)ProcessEnvironmentBlock + 0x30),0, uVar9), local_1b0 == 0)) goto LAB_18002f882; local_1b8._2_2_ = (undefined2)uVar9; local_1b8._0_2_ = 0; RtlAppendUnicodeStringToString(&local_1b8,param_1); RtlAppendUnicodeStringToString(&local_1b8,&DAT_180132138); local_1d0 = &local_1b8; } iVar5 = LdrGetDllHandleByName(local_1d0,0,param_5); if (local_1b0 != 0) { RtlFreeHeap(*(undefined8 *)((longlong)ProcessEnvironmentBlock + 0x30),0,local_1b0); } if (iVar5 != -0x3ffffecb) goto LAB_18002f882; goto LAB_18002f815; } iVar5 = LdrGetDllHandleByName(0,local_1d0,param_5); if (iVar5 == -0x3ffffecb) { param_3 = (LPCWSTR)0x0; LAB_18002f8d7: hFile = CreateFileW(*(LPCWSTR *)(local_1d0 + 2),0x80000000,5,(LPSECURITY_ATTRIBUTES)0x0,3, (DWORD)param_3,param_3); if (hFile != (HANDLE)0xffffffffffffffff) { if ((param_4 & 0x20) == 0) { local_1c0 = CreateFileMappingNumaW (hFile,(LPSECURITY_ATTRIBUTES)0x0,2,0,(DWORD)param_3,param_3, 0xffffffff); if (local_1c0 != (HANDLE)0x0) { local_1d8 = param_3; local_1c8 = param_3; iVar5 = NtMapViewOfSection(local_1c0,0xffffffffffffffff,&local_1d8); if (iVar5 < 0) goto LAB_1800c7c5b; iVar5 = RtlImageNtHeaderEx(0,local_1d8,local_1c8,local_170); if ((-1 < iVar5) && (iVar5 = LdrGetDllHandleByMapping(local_1d8,param_5), iVar5 == -0x3ffffecb)) { uVar10 = (ulonglong)local_1d8 | 1; if ((param_4 & 0x40) == 0) { NtClose(hFile); } else { uVar7 = FUN_1801202f4(uVar10,(longlong)hFile); if ((int)uVar7 < 0) goto LAB_1800c7c43; } NtClose(local_1c0); goto LAB_18002fa35; } LAB_1800c7c43: NtUnmapViewOfSection(0xffffffffffffffff,local_1d8); goto LAB_1800c7c5b; } } else { if (((*(byte *)((longlong)ProcessEnvironmentBlock + 3) & 2) != 0) && ((param_4 & 0x42) == 0) ) { FUN_1800c7c13(); return; } iVar5 = NtCreateSection(&local_1c0,5,0); if (-1 < iVar5) { local_1d8 = param_3; local_1c8 = param_3; iVar5 = NtMapViewOfSection(local_1c0,0xffffffffffffffff,&local_1d8); if (-1 < iVar5) { iVar5 = RtlImageNtHeaderEx(0,local_1d8,local_1c8,local_170); if ((iVar5 < 0) || (iVar5 = LdrGetDllHandleByMapping(local_1d8,param_5), iVar5 != -0x3ffffecb)) goto LAB_1800c7c43; NtClose(local_1c0); NtClose(hFile); uVar10 = (ulonglong)local_1d8 | 2; LAB_18002fa35: local_198 = param_3; RtlGetActiveActivationContext(&local_198); LdrAddLoadAsDataTable(uVar10,*(undefined8 *)(local_1d0 + 2),local_1c8,0); if (lStack_1a0 != 0) { RtlFreeUnicodeString(&local_1a8); } *param_5 = uVar10; goto LAB_18002f882; } LAB_1800c7c5b: NtClose(local_1c0); } } NtClose(hFile); } } goto LAB_18002faac; while ((*psVar6 != 0x5c && (*psVar6 != 0x2f))) { joined_r0x00018002f772: psVar6 = psVar6 + -1; if (psVar6 < psVar2) goto LAB_18002f79c; } bVar4 = true; LAB_18002f815: if (param_3 == (LPCWSTR)0x0) { LAB_18002f81e: iVar5 = RtlInitUnicodeStringEx(local_158,param_2); if (iVar5 < 0) goto LAB_18002f882; iVar5 = RtlDosSearchPath_Ustr(6,local_158,param_1); } else { iVar5 = RtlInitUnicodeStringEx(local_168,param_3); if (iVar5 < 0) goto LAB_18002f882; param_3 = (LPCWSTR)0x0; iVar5 = RtlDosSearchPath_Ustr(6,local_168,param_1); if (iVar5 == -0x3ffffff1) goto LAB_18002f81e; } if (iVar5 < 0) goto LAB_18002f882; if ((!bVar4) || (iVar5 = LdrGetDllHandleByName(0,local_1d0,param_5), iVar5 == -0x3ffffecb)) goto LAB_18002f8d7; LAB_18002faac: if (lStack_1a0 != 0) { FUN_1800c7c81(); return; } LAB_18002f882: __security_check_cookie(local_48 ^ (ulonglong)auStackY_228); return; }