hook: Update capnhook source files from latest master

https://github.com/decafcode/capnhook
This commit is contained in:
icex2
2020-09-02 19:35:15 +00:00
parent 3a1005f1f8
commit a016f27652
19 changed files with 1720 additions and 757 deletions
+154 -102
View File
@@ -1,90 +1,177 @@
#include <unknwn.h>
#include <windows.h>
#include <unknwn.h>
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include "hook/com-proxy.h"
#include "util/defs.h"
#include "util/mem.h"
static void com_proxy_free(struct com_proxy *proxy);
static HRESULT STDMETHODCALLTYPE com_proxy_query_interface(
IUnknown *unk,
REFIID iid,
void **iface);
static ULONG STDMETHODCALLTYPE com_proxy_addref(IUnknown *unk);
static ULONG STDMETHODCALLTYPE com_proxy_release(IUnknown *unk);
#ifdef _WIN64
#ifdef __amd64
/***** 64-BIT TRAMPOLINE *****/
/***** 64-BIT TRAMPOLINE *****/
#define SLOT_OFFSET 0x0A
static const uint8_t com_proxy_tramp[] = {
/* mov rcx, [rcx+8] ; Replace this with this->real */
0x48,
0x8B,
0x49,
0x08,
/* mov rcx, [rcx+8] ; Get this->real */
0x48, 0x8B, 0x49, 0x08,
/* mov rax, [rcx] ; Get real->vtbl */
0x48,
0x8B,
0x01,
/* mov rax, [rcx] ; Get this->vtbl */
0x48, 0x8B, 0x01,
/* mov rax, [rax+XX] ; Get vtbl->slot_XX */
0x48,
0x8B,
0x80,
-1,
-1,
-1,
-1,
0x48, 0x8B, 0x80, -1, -1, -1, -1,
/* jmp rax ; Continue to slot_XX */
0xFF,
0xE0,
0xFF, 0xE0,
};
#else
/***** 32-BIT TRAMPOLINE *****/
/***** 32-BIT TRAMPOLINE *****/
#define SLOT_OFFSET 0x0F
static const uint8_t com_proxy_tramp[] = {
/* mov eax, [esp+4] ; Get this */
0x8B,
0x44,
0x24,
0x04,
0x8B, 0x44, 0x24, 0x04,
/* mov eax, [eax+4] ; Get this->real */
0x8B,
0x40,
0x04,
0x8B, 0x40, 0x04,
/* mov [esp+4], eax ; Replace this with this->real on stack */
0x89,
0x44,
0x24,
0x04,
0x89, 0x44, 0x24, 0x04,
/* mov ecx, [eax] ; Get real->vtbl */
0x8B,
0x08,
/* mov ecx, [eax] ; Get this->vtbl */
0x8B, 0x08,
/* mov ecx, [ecx+XX] ; Get vtbl->slot_XX */
0x8B,
0x89,
-1,
-1,
-1,
-1,
0x8B, 0x89, -1, -1, -1, -1,
/* jmp ecx ; Continue to slot_XX */
0xFF,
0xE1};
0xFF, 0xE1
};
#endif
static HRESULT STDCALL
com_proxy_query_interface(IUnknown *ptr, REFIID iid, void **iface)
HRESULT com_proxy_wrap(
struct com_proxy **out,
void *real,
size_t vtbl_size)
{
struct com_proxy *self = (struct com_proxy *) ptr;
IUnknown *obj = self->real; /* Not necessarily the real IUnknown* */
struct com_proxy *proxy;
void **vtbl;
uint8_t *cur_tramp;
size_t nslots;
size_t i;
HRESULT hr;
assert(out != NULL);
assert(real != NULL);
*out = NULL;
proxy = calloc(1, sizeof(*proxy));
if (proxy == NULL) {
hr = E_OUTOFMEMORY;
goto end;
}
proxy->vptr = malloc(vtbl_size);
if (proxy->vptr == NULL) {
hr = E_OUTOFMEMORY;
goto end;
}
nslots = vtbl_size / sizeof(void *);
proxy->tramps = VirtualAlloc(
NULL,
sizeof(com_proxy_tramp) * nslots,
MEM_RESERVE | MEM_COMMIT,
PAGE_EXECUTE_READWRITE);
if (proxy->tramps == NULL) {
hr = E_OUTOFMEMORY;
goto end;
}
proxy->real = real;
/* Set up proxied IUnknown impl */
vtbl = proxy->vptr;
vtbl[0] = com_proxy_query_interface;
vtbl[1] = com_proxy_addref;
vtbl[2] = com_proxy_release;
/* Populate trampoline code for remaining vtbl entries */
for (i = 3 /* Skip IUnknown */ ; i < nslots ; i++) {
cur_tramp = proxy->tramps + i * sizeof(com_proxy_tramp);
/* Copy template */
memcpy(cur_tramp, com_proxy_tramp, sizeof(com_proxy_tramp));
/* Patch XX into vtbl lookup (see definition of tramp) */
*((uint32_t *) (cur_tramp + SLOT_OFFSET)) = i * sizeof(void *);
/* Set vtable entry */
vtbl[i] = cur_tramp;
}
*out = proxy;
proxy = NULL;
hr = S_OK;
end:
com_proxy_free(proxy);
return hr;
}
static void com_proxy_free(struct com_proxy *proxy)
{
if (proxy == NULL) {
return;
}
if (proxy->cleanup_ctx != NULL) {
proxy->cleanup_ctx(proxy->ctx);
}
if (proxy->tramps != NULL) {
VirtualFree(proxy->tramps, 0, MEM_RELEASE);
}
free(proxy->vptr);
free(proxy);
}
static HRESULT STDMETHODCALLTYPE com_proxy_query_interface(
IUnknown *unk,
REFIID iid,
void **iface)
{
struct com_proxy *proxy;
IUnknown *obj;
assert(unk != NULL);
proxy = (struct com_proxy *) unk;
obj = proxy->real; /* Not necessarily this object's canonical IUnknown */
/* To some extent, COM is designed to support shennanigans like these.
We can safely pass the call straight through to the underlying
@@ -104,70 +191,35 @@ com_proxy_query_interface(IUnknown *ptr, REFIID iid, void **iface)
return IUnknown_QueryInterface(obj, iid, iface);
}
static ULONG STDCALL com_proxy_addref(IUnknown *ptr)
static ULONG STDMETHODCALLTYPE com_proxy_addref(IUnknown *unk)
{
struct com_proxy *self = (struct com_proxy *) ptr;
IUnknown *obj = self->real;
struct com_proxy *proxy;
IUnknown *obj;
assert(unk != NULL);
proxy = (struct com_proxy *) unk;
obj = proxy->real;
return IUnknown_AddRef(obj);
}
static ULONG STDCALL com_proxy_release(IUnknown *ptr)
static ULONG STDMETHODCALLTYPE com_proxy_release(IUnknown *unk)
{
struct com_proxy *self = (struct com_proxy *) ptr;
IUnknown *obj = self->real;
struct com_proxy *proxy;
IUnknown *real;
ULONG result;
result = IUnknown_Release(obj);
assert(unk != NULL);
proxy = (struct com_proxy *) unk;
real = proxy->real;
result = IUnknown_Release(real);
if (!result) {
/* Last ref to underlying object released */
VirtualFree(self->tramps, 0, MEM_RELEASE);
free(self->vptr);
free(self);
com_proxy_free(proxy);
}
return result;
}
struct com_proxy *com_proxy_wrap(void *iface, size_t vtbl_size)
{
struct com_proxy *self;
void **vtbl;
uint8_t *cur_tramp;
uint32_t nslots;
uint32_t i;
nslots = vtbl_size / sizeof(void *);
self = xmalloc(sizeof(*self));
self->vptr = xmalloc(vtbl_size);
self->real = iface;
self->tramps = VirtualAlloc(
NULL,
sizeof(com_proxy_tramp) * nslots,
MEM_RESERVE | MEM_COMMIT,
PAGE_EXECUTE_READWRITE);
/* Set up proxied IUnknown impl */
vtbl = self->vptr;
vtbl[0] = com_proxy_query_interface;
vtbl[1] = com_proxy_addref;
vtbl[2] = com_proxy_release;
/* Populate trampoline code for remaining vtbl entries */
for (i = 3 /* Skip IUnknown */; i < nslots; i++) {
cur_tramp = self->tramps + i * sizeof(com_proxy_tramp);
/* Copy template */
memcpy(cur_tramp, com_proxy_tramp, sizeof(com_proxy_tramp));
/* Patch XX into vtbl lookup (see definition of tramp) */
*((uint32_t *) (cur_tramp + SLOT_OFFSET)) = i * sizeof(void *);
/* Set vtable entry */
vtbl[i] = cur_tramp;
}
return self;
}