-
Notifications
You must be signed in to change notification settings - Fork 63
/
WorkItemLoadLibrary.c
81 lines (65 loc) · 2.19 KB
/
WorkItemLoadLibrary.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/* WorkItemLoadLibrary.c by @rad9800
* Credit goes to:
* - Peter Winter-Smith (@peterwintrsmith)
* - Proofpoint threatinsight team for their detailed analysis
*
* Loads a DLL by queuing a work item (RtlQueueWorkItem/) with
* the address of LoadLibraryW and a pointer to the buffer
*
*/
#include <Windows.h>
#include <winternl.h>
#include <stdio.h>
#define NtCurrentProcess() ( ( HANDLE ) ( LONG_PTR ) -1 )
#define IMPORTAPI( DLLFILE, FUNCNAME, RETTYPE, ...)\
typedef RETTYPE( WINAPI* type##FUNCNAME )( __VA_ARGS__ );\
type##FUNCNAME FUNCNAME = (type##FUNCNAME)GetProcAddress((LoadLibraryW(DLLFILE), GetModuleHandleW(DLLFILE)), #FUNCNAME);
HMODULE getModuleHandle(LPCWSTR libraryName)
{
const LIST_ENTRY* head = &NtCurrentTeb()->ProcessEnvironmentBlock->Ldr->InMemoryOrderModuleList;
LIST_ENTRY* next = head->Flink;
while (next != head)
{
LDR_DATA_TABLE_ENTRY* entry =
CONTAINING_RECORD(next, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
const UNICODE_STRING* basename = (UNICODE_STRING*)((BYTE*)&entry->FullDllName
+ sizeof(UNICODE_STRING));
if (_wcsicmp(libraryName, basename->Buffer) == 0)
{
return entry->DllBase;
}
next = next->Flink;
}
return NULL;
}
HMODULE queueLoadLibrary(WCHAR* libraryName, BOOL swtch)
{
IMPORTAPI(L"NTDLL.dll", NtWaitForSingleObject, NTSTATUS, HANDLE, BOOLEAN, PLARGE_INTEGER);
if (swtch)
{
IMPORTAPI(L"NTDLL.dll", RtlQueueWorkItem, NTSTATUS, PVOID, PVOID, ULONG);
if (NT_SUCCESS(RtlQueueWorkItem(&LoadLibraryW, (PVOID)libraryName, WT_EXECUTEDEFAULT)))
{
LARGE_INTEGER timeout;
timeout.QuadPart = -500000;
NtWaitForSingleObject(NtCurrentProcess(), FALSE, &timeout);
}
}
else
{
IMPORTAPI(L"NTDLL.dll", RtlRegisterWait, NTSTATUS, PHANDLE, HANDLE, WAITORTIMERCALLBACKFUNC, PVOID, ULONG, ULONG);
HANDLE newWaitObject;
HANDLE eventObject = CreateEventW(NULL, FALSE, FALSE, NULL);
if (NT_SUCCESS(RtlRegisterWait(&newWaitObject, eventObject, LoadLibraryW, (PVOID)libraryName, 0, WT_EXECUTEDEFAULT)))
{
WaitForSingleObject(eventObject, 500);
}
}
return getModuleHandle(libraryName);
}
int main()
{
WCHAR libraryName[] = L"DBGHELP.dll";
HMODULE moduleHandle = queueLoadLibrary(libraryName, TRUE);
printf("0x%p", moduleHandle);
}