Skip to content

Commit e059d78

Browse files
committed
Fix delayload CRT module handle
1 parent 055d836 commit e059d78

File tree

2 files changed

+105
-14
lines changed

2 files changed

+105
-14
lines changed

phlib/include/phutil.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1263,6 +1263,14 @@ PhGetExportNameFromOrdinal(
12631263
_In_opt_ USHORT ProcedureNumber
12641264
);
12651265

1266+
PHLIBAPI
1267+
NTSTATUS
1268+
NTAPI
1269+
PhLoadAllImportsForDll(
1270+
_In_ PWSTR TargetDllName,
1271+
_In_ PSTR ImportDllName
1272+
);
1273+
12661274
PHLIBAPI
12671275
PPH_STRING
12681276
NTAPI

phlib/util.c

Lines changed: 97 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5673,7 +5673,7 @@ NTSTATUS PhGetLoaderEntryImageEntryPoint(
56735673
)
56745674
{
56755675
if (ImageNtHeader->OptionalHeader.AddressOfEntryPoint == 0)
5676-
return STATUS_FAIL_CHECK; // STATUS_ENTRYPOINT_NOT_FOUND
5676+
return STATUS_ENTRYPOINT_NOT_FOUND;
56775677

56785678
*ImageEntryPoint = PTR_ADD_OFFSET(BaseAddress, ImageNtHeader->OptionalHeader.AddressOfEntryPoint);
56795679
return STATUS_SUCCESS;
@@ -5877,6 +5877,7 @@ static NTSTATUS PhpFixupLoaderEntryImageImports(
58775877
if (PhEqualBytesZ(importName, "ProcessHacker.exe", FALSE))
58785878
{
58795879
importBaseAddress = PhInstanceHandle;
5880+
status = STATUS_SUCCESS;
58805881
}
58815882
else
58825883
{
@@ -5998,7 +5999,8 @@ static NTSTATUS PhpFixupLoaderEntryImageImports(
59985999

59996000
static NTSTATUS PhpFixupLoaderEntryImageDelayImports(
60006001
_In_ PVOID BaseAddress,
6001-
_In_ PIMAGE_NT_HEADERS ImageNtHeader
6002+
_In_ PIMAGE_NT_HEADERS ImageNtHeaders,
6003+
_In_ PSTR ImportDllName
60026004
)
60036005
{
60046006
NTSTATUS status;
@@ -6010,7 +6012,7 @@ static NTSTATUS PhpFixupLoaderEntryImageDelayImports(
60106012

60116013
status = PhGetLoaderEntryImageDirectory(
60126014
BaseAddress,
6013-
ImageNtHeader,
6015+
ImageNtHeaders,
60146016
IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT,
60156017
&dataDirectory,
60166018
&delayImportDirectory,
@@ -6027,7 +6029,7 @@ static NTSTATUS PhpFixupLoaderEntryImageDelayImports(
60276029

60286030
status = PhGetLoaderEntryImageSection(
60296031
BaseAddress,
6030-
ImageNtHeader,
6032+
ImageNtHeaders,
60316033
delayImportDirectory,
60326034
&importDirectorySection,
60336035
&importDirectorySize
@@ -6050,15 +6052,54 @@ static NTSTATUS PhpFixupLoaderEntryImageDelayImports(
60506052
for (delayImportDirectory = delayImportDirectory; delayImportDirectory->DllNameRVA; delayImportDirectory++)
60516053
{
60526054
PSTR importName;
6055+
PVOID* importHandle;
60536056
PIMAGE_THUNK_DATA importThunk;
60546057
PIMAGE_THUNK_DATA originalThunk;
6058+
PVOID importBaseAddress;
6059+
BOOLEAN importNeedsFree = FALSE;
60556060

60566061
importName = PTR_ADD_OFFSET(BaseAddress, delayImportDirectory->DllNameRVA);
6062+
importHandle = PTR_ADD_OFFSET(BaseAddress, delayImportDirectory->ModuleHandleRVA);
60576063
importThunk = PTR_ADD_OFFSET(BaseAddress, delayImportDirectory->ImportAddressTableRVA);
60586064
originalThunk = PTR_ADD_OFFSET(BaseAddress, delayImportDirectory->ImportNameTableRVA);
60596065

6060-
if (PhEqualBytesZ(importName, "ProcessHacker.exe", TRUE))
6066+
if (PhEqualBytesZ(importName, ImportDllName, TRUE))
60616067
{
6068+
if (PhEqualBytesZ(importName, "ProcessHacker.exe", FALSE))
6069+
{
6070+
importBaseAddress = PhInstanceHandle;
6071+
status = STATUS_SUCCESS;
6072+
}
6073+
else if (*importHandle)
6074+
{
6075+
importBaseAddress = *importHandle;
6076+
status = STATUS_SUCCESS;
6077+
}
6078+
else
6079+
{
6080+
PPH_STRING importNameSr;
6081+
6082+
importNameSr = PhZeroExtendToUtf16(importName);
6083+
6084+
if (!(importBaseAddress = PhGetLoaderEntryDllBase(importNameSr->Buffer)))
6085+
{
6086+
if (importBaseAddress = LoadLibrary(importNameSr->Buffer))
6087+
{
6088+
importNeedsFree = TRUE;
6089+
status = STATUS_SUCCESS;
6090+
}
6091+
else
6092+
{
6093+
status = PhGetLastWin32ErrorAsNtStatus();
6094+
}
6095+
}
6096+
6097+
PhDereferenceObject(importNameSr);
6098+
}
6099+
6100+
if (!NT_SUCCESS(status))
6101+
break;
6102+
60626103
for (
60636104
originalThunk = originalThunk, importThunk = importThunk;
60646105
originalThunk->u1.AddressOfData;
@@ -6071,7 +6112,7 @@ static NTSTATUS PhpFixupLoaderEntryImageDelayImports(
60716112
PVOID procedureAddress;
60726113

60736114
procedureOrdinal = IMAGE_ORDINAL(originalThunk->u1.Ordinal);
6074-
procedureAddress = PhGetDllBaseProcedureAddress(PhInstanceHandle, NULL, procedureOrdinal);
6115+
procedureAddress = PhGetDllBaseProcedureAddress(importBaseAddress, NULL, procedureOrdinal);
60756116

60766117
importThunk->u1.Function = (ULONG_PTR)procedureAddress;
60776118
}
@@ -6081,11 +6122,16 @@ static NTSTATUS PhpFixupLoaderEntryImageDelayImports(
60816122
PVOID procedureAddress;
60826123

60836124
importByName = PTR_ADD_OFFSET(BaseAddress, originalThunk->u1.AddressOfData);
6084-
procedureAddress = PhGetDllBaseProcedureAddress(PhInstanceHandle, importByName->Name, 0);
6125+
procedureAddress = PhGetDllBaseProcedureAddress(importBaseAddress, importByName->Name, 0);
60856126

60866127
importThunk->u1.Function = (ULONG_PTR)procedureAddress;
60876128
}
60886129
}
6130+
6131+
if ((InterlockedExchangePointer(importHandle, importBaseAddress) == importBaseAddress) && importNeedsFree)
6132+
{
6133+
FreeLibrary(importBaseAddress); // A different thread has already updated the cache.
6134+
}
60896135
}
60906136
}
60916137

@@ -6104,14 +6150,49 @@ static NTSTATUS PhpFixupLoaderEntryImageDelayImports(
61046150
return status;
61056151
}
61066152

6153+
NTSTATUS PhLoaderEntryLoadAllImportsForDll(
6154+
_In_ PVOID BaseAddress,
6155+
_In_ PSTR ImportDllName
6156+
)
6157+
{
6158+
NTSTATUS status;
6159+
PIMAGE_NT_HEADERS imageNtHeaders;
6160+
6161+
status = PhGetLoaderEntryImageNtHeaders(
6162+
BaseAddress,
6163+
&imageNtHeaders
6164+
);
6165+
6166+
if (!NT_SUCCESS(status))
6167+
return status;
6168+
6169+
status = PhpFixupLoaderEntryImageDelayImports(
6170+
BaseAddress,
6171+
imageNtHeaders,
6172+
ImportDllName
6173+
);
6174+
6175+
return status;
6176+
}
6177+
6178+
NTSTATUS PhLoadAllImportsForDll(
6179+
_In_ PWSTR TargetDllName,
6180+
_In_ PSTR ImportDllName
6181+
)
6182+
{
6183+
PVOID imageBaseAddress;
6184+
6185+
if (!(imageBaseAddress = PhGetLoaderEntryDllBase(TargetDllName)))
6186+
return STATUS_INVALID_PARAMETER;
6187+
6188+
return PhLoaderEntryLoadAllImportsForDll(
6189+
imageBaseAddress,
6190+
ImportDllName
6191+
);
6192+
}
6193+
61076194
// dmex: This function and the other LoaderEntryImage functions don't belong in this file
61086195
// and should be moved into mapimg.c at some stage.
6109-
//
6110-
// We use this function to load plugins since we can 'fixup' the import table at runtime which is required when
6111-
// users have renamed the main executable to avoid malware, spyware and other software that targets Process Hacker.
6112-
// This function can only fixup images that have static imports from processhacker.exe,
6113-
// plugins that use LoadLibrary/GetProcAddress will continue to fail when the main executable is renamed.
6114-
// Note: This functionality is a WIP and not be used for anything other than plugins.
61156196
NTSTATUS PhLoadPluginImage(
61166197
_In_ PPH_STRING FileName,
61176198
_Out_opt_ PVOID *BaseAddress
@@ -6153,9 +6234,11 @@ NTSTATUS PhLoadPluginImage(
61536234
if (!NT_SUCCESS(status))
61546235
goto CleanupExit;
61556236

6237+
//status = PhLoaderEntryLoadAllImportsForDll(imageBaseAddress, "ProcessHacker.exe");
61566238
status = PhpFixupLoaderEntryImageDelayImports(
61576239
imageBaseAddress,
6158-
imageHeaders
6240+
imageHeaders,
6241+
"ProcessHacker.exe"
61596242
);
61606243

61616244
if (!NT_SUCCESS(status))

0 commit comments

Comments
 (0)