Giter VIP home page Giter VIP logo

reghookex's Introduction

RegHook/RegHookEx

RegHook is a way of creating your own pointers, copied from registers in a function.
RegHook is for internal usage, RegHookEx is for externals.

More specificly, it's a midfunction hooking library, who's purpose is to retrieve register data at any particular point in a process.

Sample:

RegHook AngleFuncHook(OFFSET_VIEWANGLEFUNC)
((ViewAngle*)AngleFuncHook.GetRegDump().RBX)->Pitch = 0;

regHook.GetRegDump() returns a RegDump class.

class RegDump
{
public:
	char pad_0000[88]; //0x0000
	DWORD64 RBX; //0x0058
	DWORD64 RSP; //0x0060
	DWORD64 RDI; //0x0068
	DWORD64 RSI; //0x0070
	DWORD64 RBP; //0x0078
	DWORD64 RDX; //0x0080
	DWORD64 RCX; //0x0088
	DWORD64 RAX; //0x0090
}; 

Usage

Internal
RegHook AngleFuncHook(OFFSET_VIEWANGLEFUNC);
if (IsValidPtr((LPVOID)AngleFuncHook.GetRegDump().RBX)) {
	((ViewAngle*)AngleFuncHook.GetRegDump().RBX)->Pitch = 0;
	((ViewAngle*)AngleFuncHook.GetRegDump().RBX)->Yaw = 0;
}
External
RegHookEx AngleFuncHook(rpm.hProcess, OFFSET_VIEWANGLEFUNC);
if (rpm.read<RegDump>(AngleFuncHook.GetAddressOfHook()).RBX != 0) {
	//Read
	ViewAngle pViewAngle = rpm.read<ViewAngle>(AngleFuncHook.GetRegDump().RBX);
	//pViewAngle.Yaw, pViewAngle.Pitch
	//Write
	RegDump pRegDump = rpm.read<RegDump>(AngleFuncHook.GetAddressOfHook());
	rpm.write<float>(pRegDump.RBX + offsetof(ViewAngle, ViewAngle::Yaw), 0);
	rpm.write<float>(pRegDump.RBX + offsetof(ViewAngle, ViewAngle::Pitch), 0);
}

fde64

The hook takes 17 bytes to write, and requires RAX to be used for the call.
I'm using fde64 for length dissasembly, so the nearest instruction end after 17 is located automaticlly.

Original Function

Here is the function with RegHookEx installed.

The first thing that happens, is some memory is allocated for the hooked function.
This is where program flow will be redirected to temporarily.

mov [0x2880090], rax    ; save rax to allocated space address + 0x90
mov rax, 0x2880000      ; move allocated space address into rax
call rax

This takes up 17 bytes. Any unused bytes must be NOP'd, in this example none need to be since the function we're overwriting already is 17 bytes.

Hooked Function

Now at the hooked function:

First thing, rax gets restored.

mov rax, [0x2880090]

The next 17 bytes have been copied from the original function, and placed here. The target process doesn't know this ever happened.

This is followed by a shitload of NOPs. This allows for all instructions to get hooked (up to 15 bytes, aka max).

RIP Relative Addressing

Writing all of these manually would be a pain, so I'm using relative addressing. I'm writing it by:

mov [rip + 96], rcx ; ->0x88
mov [rip + 81], rdx ; ->0x80
mov [rip + 66], rbp ; ->0x78
mov [rip + 51], rsi ; ->0x70
mov [rip + 36], rdi ; ->0x68
mov [rip + 21], rsp ; ->0x60
mov [rip + 6], rbx ; ->0x58

This accounts for the RET, as well as the misalignment of the class, thus re-aligning it to the 8'th byte.

Optimization

Due to the wonders of the RIP register, I only need to write one address into the hooked function for it to work. The hook itself requires two in order to preserve RAX. You no longer need to specify a length for RegHookEx to work, that is done for you too.

Full Shellcode

The Hooked Function allocated in memory:

// shellcode for the hkedfunc
byte* hkpatch = new byte[83]{	// using byte* so I don't have to cast when using memcpy
    // use rip relative addressing to make things more efficent
    0x48, 0x8B, 0x05, 0x89, 0x00, 0x00, 0x00,  //  mov rax, [rip + 137]  ;  0x90
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,  //  nop * 26
    0x48, 0x89, 0x0D, 0x60, 0x00, 0x00, 0x00,  //  mov [rip + 96], rcx ; ->0x88
    0x48, 0x89, 0x15, 0x51, 0x00, 0x00, 0x00,  //  mov [rip + 81], rdx ; ->0x80
    0x48, 0x89, 0x2D, 0x42, 0x00, 0x00, 0x00,  //  mov [rip + 66], rbp ; ->0x78
    0x48, 0x89, 0x35, 0x33, 0x00, 0x00, 0x00,  //  mov [rip + 51], rsi ; ->0x70
    0x48, 0x89, 0x3D, 0x24, 0x00, 0x00, 0x00,  //  mov [rip + 36], rdi ; ->0x68
    0x48, 0x89, 0x25, 0x15, 0x00, 0x00, 0x00,  //  mov [rip + 21], rsp ; ->0x60
    0x48, 0x89, 0x1D, 0x06, 0x00, 0x00, 0x00,  //  mov [rip + 6], rbx ; ->0x58
    0xC3  //  ret
};

The hook:

byte* funcpath = new byte[32]{ 
    0x48, 0x89, 0x04, 0x25, 0x90, 0x34, 0x12, 0x00,		// mov [raxpath], rax
    0x48, 0xC7, 0xC0, 0x00, 0x34, 0x12, 0x00,		// mov rax, this->HookedAddress
    0xFF, 0xD0 ,		// call rax ;	0x17
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 }; // extra nops

Unhooking

Unhooking can be done in two different ways.

  1. Per-class
  2. With the static method
  3. Using the static method on exit
Per-class unhooking:

Unhooks and repairs the original function.

AngleFuncHook.DestroyHook();
Static Method:

Unhooks and repairs original functions of all active instances of RegHookEx.

RegHookEx::DestroyAllHooks();
Automated Unhooking:

Use this for externals to Unhook whenever you exit the console.

bool ctrlh(DWORD event)
{
    if (event == CTRL_CLOSE_EVENT) {
        std::cout << "Deleting All Hooks" << std::endl;
        RegHookEx::DestroyAllHooks();
        return TRUE;
    }
    return FALSE;
}

void main() {
    SetConsoleCtrlHandler((PHANDLER_ROUTINE)(ctrlh), TRUE);
    // your stuff
}

For internals, you can call the static function in your DllMain.

BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwAttached, LPVOID lpvReserved)
{
	if (dwAttached == DLL_PROCESS_ATTACH) {
		//...
	}
	if (dwAttached == DLL_PROCESS_DETACH) {
		RegHook::DestroyAllHooks();
		FreeConsole();
	}
	return 1;
}

reghookex's People

Contributors

coltonon avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.