~moody/dllcpf

d9d572ac1b7aa76e5a1e5cf34169bef8efc0e81f — Jacob Moody 7 months ago ff5ea1e
Add hooking files
2 files changed, 236 insertions(+), 0 deletions(-)

A hook.c
A hook.h
A hook.c => hook.c +225 -0
@@ 0,0 1,225 @@
#include "hook.h"

#define NAKED __attribute__((naked))

NTSTATUS NAKED
NtAllocateVirtualMemory10(
		HANDLE ProcessHandle,
		PVOID *BaseAddress,
		ULONG_PTR ZeroBits,
		PSIZE_T RegionSize,
		ULONG AllocationType,
		ULONG protect)
{
	asm volatile (
		"mov %rcx, %r10;"
		"mov $0x18, %eax;"
		"syscall;"
		"ret;"
		     );
}


NTSTATUS NAKED
NtFreeVirtualMemory10(HANDLE ProcessHandle,
		PVOID *BaseAddress,
		IN OUT PSIZE_T RegionSize,
		ULONG FreeType)
{
	asm volatile (
		"mov %rcx, %r10;"
		"mov $0x1E, %eax;"
		"syscall;"
		"ret;"
		     );
}

NTSTATUS NAKED
ZwWriteVirtualMemory10(
		HANDLE hProcess,
		PVOID lpBaseAddress,
		PVOID lpBuffer,
		SIZE_T NumberOfBytesToRead,
		PSIZE_T NumberOfBytesRead)
{
	asm volatile (
		"mov %rcx, %r10;"
		"mov $0x3a, %eax;"
		"syscall;"
		"ret;"
		     );
}

NTSTATUS NAKED
ZwProtectVirtualMemory10(IN HANDLE ProcessHandle,
		IN PVOID *BaseAddress,
		IN SIZE_T* NumberOfBytesToProtect,
		IN ULONG NewAccessProtection,
		OUT PULONG OldAccessProtection)
{
	asm volatile (
		"mov %rcx, %r10;"
		"mov $0x50, %eax;"
		"syscall;"
		"ret;"
		     );
}

NTSTATUS NAKED
NtCreateThreadEx10(
		OUT PHANDLE hThread,
		IN ACCESS_MASK DesiredAccess,
		IN PVOID ObjectAttributes,
		IN HANDLE ProcessHandle,
		IN PVOID lpStartAddress,
		IN PVOID lpParameter,
		IN ULONG Flags,
		IN SIZE_T StackZeroBits,
		IN SIZE_T SizeOfStackCommit,
		IN SIZE_T SizeOfStackReserve,
		OUT PVOID lpBytesBuffer)
{
	asm volatile (
		"mov %rcx, %r10;"
		"mov $0xC1, %eax;"
		"syscall;"
		"ret;"
		     );
}

struct {
	HANDLE *mutex;
	LPTHREAD_START_ROUTINE lpStartAddress;
	LPVOID lpParamater;
	BOOL launched;
} BouncerInfo;

static BOOL UsePivot;

void
SetupPivot(void)
{
	BouncerInfo.mutex = CreateMutexA(NULL, FALSE, NULL);
	BouncerInfo.launched = TRUE;
	UsePivot = TRUE;
}

DWORD __stdcall
ThreadPivot(void *param){
	WaitForSingleObject(BouncerInfo.mutex, INFINITE);
	LPTHREAD_START_ROUTINE f = BouncerInfo.lpStartAddress;
	LPVOID p = BouncerInfo.lpParamater;
	BouncerInfo.launched = TRUE;
	ReleaseMutex(BouncerInfo.mutex);
	printf("[*] Pivoting to passed function on threadId: %lu\n", GetCurrentThreadId());
	return f(p);
}

HANDLE __stdcall
HookedCreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParamater, DWORD dwCreationFlags, LPDWORD lpThreadId)
{
	HANDLE ThreadHandle = NULL;
	WaitForSingleObject(BouncerInfo.mutex, INFINITE);
	//It's possible that we get two CreateThread calls before a pivot
	//occurs, this is a bad way of dealing with it but it shouldn't happen often
	while(BouncerInfo.launched == FALSE){
		printf("[!] Double entry detected, spin locking...\n");
		ReleaseMutex(BouncerInfo.mutex);
		WaitForSingleObject(BouncerInfo.mutex, INFINITE);
	}
	BouncerInfo.lpStartAddress = lpStartAddress;
	BouncerInfo.lpParamater = lpParamater;
	BouncerInfo.launched = FALSE;
	ThreadHandle = CreateRemoteThreadEx(GetCurrentProcess(), lpThreadAttributes, dwStackSize, ThreadPivot, lpParamater, dwCreationFlags, NULL, lpThreadId);
	ReleaseMutex(BouncerInfo.mutex);
	return ThreadHandle;
}

LPVOID __stdcall
HookedVirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect)
{
	NTSTATUS a;
	a = NtAllocateVirtualMemory10(GetCurrentProcess(), &lpAddress, 0, &dwSize, flAllocationType, flProtect);
	if(NT_ERROR(a)){
		printf("[!] HookedVirtualAlloc error: %lx\n", a);
		return NULL;
	}
	return lpAddress;
}

BOOL __stdcall
HookedVirtualProtect(LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpfOldProtect)
{
	NTSTATUS a;
	a = ZwProtectVirtualMemory10(GetCurrentProcess(), &lpAddress, &dwSize, flNewProtect, lpfOldProtect);
	if(NT_ERROR(a)){
		printf("[!] HookedVirtualAlloc error: %lx\n", a);
		return FALSE;
	}
	return TRUE;
}

BOOL __stdcall
HookedVirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType)
{
	NTSTATUS a;
	a = NtFreeVirtualMemory10(GetCurrentProcess(), &lpAddress, &dwSize, dwFreeType);
	if(NT_ERROR(a)){
		printf("[!] HookedVirtualFree error: %lx\n", a);
		return FALSE;
	}
	return TRUE;
}

int
UnhookApi(void (*sneakyFunc)(void), char *dll, char *functionName)
{
	printf("[*] Patching %s\n", functionName);
	BYTE patch[] = {0x68, 0x00, 0x00, 0x00, 0x00, 0xC3};
	memcpy(patch+1, &sneakyFunc, 4);
	LPVOID lpProcAddress = GetProcAddress(LoadLibrary(dll), functionName);

	LPVOID lpBaseAddress = lpProcAddress;
	ULONG OldProtection, NewProtection;
	SIZE_T uSize = sizeof patch;
	NTSTATUS status = ZwProtectVirtualMemory10(GetCurrentProcess(), &lpBaseAddress, &uSize, PAGE_EXECUTE_READWRITE, &OldProtection);
	if (status != STATUS_SUCCESS) {
		return 1;
	}

	status = ZwWriteVirtualMemory10(GetCurrentProcess(), lpProcAddress, (PVOID)patch, sizeof(patch), NULL);
	if (status != STATUS_SUCCESS) {
		return 2;
	}

	status = ZwProtectVirtualMemory10(GetCurrentProcess(), &lpBaseAddress, &uSize, OldProtection, &NewProtection);
	if (status != STATUS_SUCCESS) {
		return 3;
	}

	return 0;
}

int
UnhookAll(void)
{
	int res;

	res = UnhookApi((void (*)(void))HookedCreateThread, "kernel32.dll", "CreateThread");
	if(res != 0)
		return res;

	res = UnhookApi((void (*)(void))HookedVirtualAlloc, "kernel32.dll", "VirtualAlloc");
	if(res != 0)
		return res;

	res = UnhookApi((void (*)(void))HookedVirtualProtect, "kernel32.dll", "VirtualProtect");
	if(res != 0)
		return res;

	res = UnhookApi((void (*)(void))HookedVirtualFree, "kernel32.dll", "VirtualFree");
	if(res != 0)
		return res;

	return 0;
}

A hook.h => hook.h +11 -0
@@ 0,0 1,11 @@
#pragma once

#include <windows.h>
#include <winnt.h>
#include <ntstatus.h>
#include <process.h>
#include <Ntdef.h>
#include <stdio.h>

int UnhookAll(void);
void SetupPivot(void);