Bemanitools v5.26 release

This commit is contained in:
icex2
2019-09-27 22:36:50 +02:00
commit cbd7720349
718 changed files with 62731 additions and 0 deletions
+9
View File
@@ -0,0 +1,9 @@
libs += hooklib
src_hooklib := \
acp.c \
app.c \
adapter.c \
rs232.c \
setupapi.c \
+62
View File
@@ -0,0 +1,62 @@
#include <windows.h>
#include <stdint.h>
#include <wchar.h>
#include <ntdef.h>
#include <ntstatus.h>
#include "hook/table.h"
#include "hooklib/acp.h"
#include "util/defs.h"
#include "util/codepage.h"
#include "util/log.h"
static NTSTATUS NTAPI my_RtlMultiByteToUnicodeN(
wchar_t *dest, unsigned long destsz, unsigned long *out_destsz,
const char *src, unsigned long srcsz);
static const struct hook_symbol acp_hook_syms[] = {
{
.name = "RtlMultiByteToUnicodeN",
.patch = my_RtlMultiByteToUnicodeN,
},
};
static NTSTATUS NTAPI my_RtlMultiByteToUnicodeN(
wchar_t *dest, unsigned long destsz, unsigned long *out_destsz,
const char *src, unsigned long srcsz)
{
unsigned long result;
result = MultiByteToWideChar(CP_SHIFT_JIS, 0, src, srcsz, dest, destsz);
if (result == 0) {
switch (GetLastError()) {
case ERROR_INSUFFICIENT_BUFFER:
return STATUS_BUFFER_TOO_SMALL;
case ERROR_INVALID_FLAGS:
case ERROR_INVALID_PARAMETER:
return STATUS_INVALID_PARAMETER;
case ERROR_NO_UNICODE_TRANSLATION:
return STATUS_UNMAPPABLE_CHARACTER;
default:
return STATUS_UNSUCCESSFUL;
}
}
if (out_destsz != NULL) {
*out_destsz = result * sizeof(wchar_t);
}
return STATUS_SUCCESS;
}
void acp_hook_init(void)
{
hook_table_apply(NULL, "ntdll.dll", acp_hook_syms, lengthof(acp_hook_syms));
log_info("ACP Hook enabled");
}
+6
View File
@@ -0,0 +1,6 @@
#ifndef HOOKLIB_ACP_H
#define HOOKLIB_ACP_H
void acp_hook_init(void);
#endif
+81
View File
@@ -0,0 +1,81 @@
#include <winsock2.h>
#include <windows.h>
#include <wincrypt.h> /* Required by mingw for some reason */
#include <iphlpapi.h>
#include "hook/table.h"
#include "hooklib/adapter.h"
#include "util/defs.h"
#include "util/codepage.h"
static DWORD WINAPI my_GetAdaptersInfo(
PIP_ADAPTER_INFO adapter_info,
PULONG out_buf_len);
static DWORD(WINAPI *real_GetAdaptersInfo)(PIP_ADAPTER_INFO adapter_info, PULONG out_buf_len);
static const struct hook_symbol adapter_hook_syms[] = {
{
.name = "GetAdaptersInfo",
.patch = my_GetAdaptersInfo,
.link = (void *)&real_GetAdaptersInfo
},
};
static DWORD WINAPI my_GetAdaptersInfo(
PIP_ADAPTER_INFO adapter_info,
PULONG out_buf_len)
{
DWORD ret;
PMIB_IPFORWARDTABLE ip_fwd_table;
DWORD table_size;
DWORD best_adapter;
PIP_ADAPTER_INFO info;
ret = real_GetAdaptersInfo(adapter_info, out_buf_len);
if (ret != 0) {
return ret;
}
ip_fwd_table = (MIB_IPFORWARDTABLE *)malloc(sizeof(MIB_IPFORWARDTABLE));
table_size = 0;
if (GetIpForwardTable(ip_fwd_table, &table_size, 1) ==
ERROR_INSUFFICIENT_BUFFER) {
free(ip_fwd_table);
ip_fwd_table = (MIB_IPFORWARDTABLE *)malloc(table_size);
}
if (GetIpForwardTable(ip_fwd_table, &table_size, 1) != NO_ERROR ||
ip_fwd_table->dwNumEntries == 0) {
return ret;
}
best_adapter = ip_fwd_table->table[0].dwForwardIfIndex;
free(ip_fwd_table);
info = adapter_info;
while (info) {
if (info->Index == best_adapter) {
memcpy(adapter_info, info, sizeof(*info));
adapter_info->Next = 0;
return ret;
}
info = info->Next;
}
return ret;
}
void adapter_hook_init(void)
{
hook_table_apply(
NULL,
"iphlpapi.dll",
adapter_hook_syms,
lengthof(adapter_hook_syms));
}
+6
View File
@@ -0,0 +1,6 @@
#ifndef HOOKLIB_ADAPTER_H
#define HOOKLIB_ADAPTER_H
void adapter_hook_init(void);
#endif
+79
View File
@@ -0,0 +1,79 @@
#include <windows.h>
#include "hook/table.h"
#include "hooklib/app.h"
#include "imports/avs.h"
#include "imports/eapki.h"
#include "util/log.h"
#include "util/str.h"
static dll_entry_init_t hook_dll_entry_init;
static dll_entry_main_t hook_dll_entry_main;
static dll_entry_init_t next_dll_entry_init;
static dll_entry_main_t next_dll_entry_main;
static void *(STDCALL *next_GetProcAddress)(HMODULE mod, const char *sym);
static void * STDCALL my_GetProcAddress(HMODULE mod, const char *sym);
static const struct hook_symbol mod_hooks[] = {
{
.name = "GetProcAddress",
.patch = my_GetProcAddress,
.link = (void **) &next_GetProcAddress,
},
};
static void * STDCALL my_GetProcAddress(HMODULE mod, const char *sym)
{
void *next;
next = next_GetProcAddress(mod, sym);
if (next == NULL || ((intptr_t) sym) <= UINT16_MAX) {
return next;
}
if (str_eq(sym, "dll_entry_init")) {
next_dll_entry_init = next;
if (hook_dll_entry_init != NULL) {
return hook_dll_entry_init;
} else {
return next;
}
} else if (str_eq(sym, "dll_entry_main")) {
next_dll_entry_main = next;
if (hook_dll_entry_main != NULL) {
return hook_dll_entry_main;
} else {
return next;
}
} else {
return next;
}
}
void app_hook_init(dll_entry_init_t init, dll_entry_main_t main_)
{
hook_dll_entry_init = init;
hook_dll_entry_main = main_;
hook_table_apply(NULL, "kernel32.dll", mod_hooks, lengthof(mod_hooks));
}
bool app_hook_invoke_init(char *sidcode, struct property_node *config)
{
log_assert(sidcode != NULL);
log_assert(config != NULL);
return next_dll_entry_init(sidcode, config);
}
bool app_hook_invoke_main(void)
{
return next_dll_entry_main();
}
+13
View File
@@ -0,0 +1,13 @@
#ifndef HOOKLIB_APP_H
#define HOOKLIB_APP_H
#include <stdbool.h>
#include "imports/avs.h"
#include "imports/eapki.h"
void app_hook_init(dll_entry_init_t init, dll_entry_main_t main_);
bool app_hook_invoke_init(char *sidcode, struct property_node *config);
bool app_hook_invoke_main(void);
#endif
+703
View File
@@ -0,0 +1,703 @@
#include <windows.h> /* Usermode API */
#include <ntdef.h> /* Kernel-mode API for ioctls */
#include <devioctl.h>
#include <ntddser.h>
#include <string.h>
#include "hook/iohook.h"
#include "hook/table.h"
#include "util/hr.h"
#include "util/log.h"
/* RS232 API hooks */
static BOOL STDCALL my_ClearCommError(
HANDLE fd,
uint32_t *errors,
COMSTAT *status);
static BOOL STDCALL my_EscapeCommFunction(HANDLE fd, uint32_t func);
static BOOL STDCALL my_GetCommState(HANDLE fd, DCB *dcb);
static BOOL STDCALL my_PurgeComm(HANDLE fd, uint32_t flags);
static BOOL STDCALL my_SetCommMask(HANDLE fd, uint32_t mask);
static BOOL STDCALL my_SetCommState(HANDLE fd, const DCB *dcb);
static BOOL STDCALL my_SetCommTimeouts(HANDLE fd, COMMTIMEOUTS *timeouts);
static BOOL STDCALL my_SetupComm(HANDLE fd, uint32_t in_q, uint32_t out_q);
static BOOL STDCALL my_SetCommBreak(HANDLE fd);
static BOOL STDCALL my_ClearCommBreak(HANDLE fd);
static struct hook_symbol rs232_syms[] = {
{
.name = "ClearCommError",
.patch = my_ClearCommError,
},
{
.name = "EscapeCommFunction",
.patch = my_EscapeCommFunction,
},
{
.name = "GetCommState",
.patch = my_GetCommState,
},
{
.name = "PurgeComm",
.patch = my_PurgeComm,
},
{
.name = "SetCommMask",
.patch = my_SetCommMask,
},
{
.name = "SetCommState",
.patch = my_SetCommState,
},
{
.name = "SetCommTimeouts",
.patch = my_SetCommTimeouts,
},
{
.name = "SetupComm",
.patch = my_SetupComm,
},
{
.name = "SetCommBreak",
.patch = my_SetCommBreak,
},
{
.name = "ClearCommBreak",
.patch = my_ClearCommBreak,
},
};
void rs232_hook_init(void)
{
hook_table_apply(NULL, "kernel32.dll", rs232_syms, lengthof(rs232_syms));
log_info("IO Hook RS232 ioctl subsystem initialized");
}
static BOOL STDCALL my_ClearCommError(
HANDLE fd,
uint32_t *errors,
COMSTAT *status)
{
struct irp irp;
SERIAL_STATUS llstatus;
HRESULT hr;
memset(&irp, 0, sizeof(irp));
irp.op = IRP_OP_IOCTL;
irp.fd = fd;
irp.ioctl = IOCTL_SERIAL_GET_COMMSTATUS;
irp.read.bytes = (uint8_t *) &llstatus;
irp.read.nbytes = sizeof(llstatus);
hr = irp_invoke_next(&irp);
if (FAILED(hr)) {
log_warning(
"%s: IOCTL_SERIAL_GET_COMMSTATUS failed: %lx",
__func__,
hr);
return hr_propagate_win32(hr, FALSE);
}
/* Here we just translate between two structures that carry essentially the
same information, because Windows. */
if (errors != NULL) {
*errors = 0;
if (llstatus.Errors & SERIAL_ERROR_QUEUEOVERRUN) {
*errors |= CE_OVERRUN;
}
if (llstatus.Errors & SERIAL_ERROR_OVERRUN) {
*errors |= CE_RXOVER;
}
if (llstatus.Errors & SERIAL_ERROR_BREAK) {
*errors |= CE_BREAK;
}
if (llstatus.Errors & SERIAL_ERROR_PARITY) {
*errors |= CE_RXPARITY;
}
if (llstatus.Errors & SERIAL_ERROR_FRAMING) {
*errors |= CE_FRAME;
}
}
if (status != NULL) {
memset(status, 0, sizeof(*status));
if (llstatus.HoldReasons & SERIAL_TX_WAITING_FOR_CTS) {
status->fCtsHold = 1;
}
if (llstatus.HoldReasons & SERIAL_TX_WAITING_FOR_DSR) {
status->fDsrHold = 1;
}
if (llstatus.HoldReasons & SERIAL_TX_WAITING_FOR_DCD) {
status->fRlsdHold = 1;
}
if (llstatus.HoldReasons & SERIAL_TX_WAITING_FOR_XON) {
status->fXoffHold = 1;
}
if (llstatus.HoldReasons & SERIAL_TX_WAITING_ON_BREAK) {
/* hrm. No corresponding (documented field). */
}
if (llstatus.HoldReasons & SERIAL_TX_WAITING_XOFF_SENT) {
status->fXoffSent = 1;
}
if (llstatus.EofReceived) {
status->fEof = 1;
}
if (llstatus.WaitForImmediate) {
status->fTxim = 1;
}
status->cbInQue = llstatus.AmountInInQueue;
status->cbOutQue = llstatus.AmountInOutQueue;
}
return TRUE;
}
static BOOL STDCALL my_EscapeCommFunction(HANDLE fd, uint32_t cmd)
{
struct irp irp;
uint32_t ioctl;
HRESULT hr;
switch (cmd) {
case CLRBREAK: ioctl = IOCTL_SERIAL_SET_BREAK_OFF; break;
case CLRDTR: ioctl = IOCTL_SERIAL_CLR_DTR; break;
case CLRRTS: ioctl = IOCTL_SERIAL_CLR_RTS; break;
case SETBREAK: ioctl = IOCTL_SERIAL_SET_BREAK_ON; break;
case SETDTR: ioctl = IOCTL_SERIAL_SET_RTS; break;
case SETRTS: ioctl = IOCTL_SERIAL_SET_RTS; break;
case SETXOFF: ioctl = IOCTL_SERIAL_SET_XOFF; break;
case SETXON: ioctl = IOCTL_SERIAL_SET_XON; break;
default:
log_warning("%s: Invalid comm function %08x", __func__, cmd);
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
memset(&irp, 0, sizeof(irp));
irp.op = IRP_OP_IOCTL;
irp.fd = fd;
irp.ioctl = ioctl;
hr = irp_invoke_next(&irp);
if (FAILED(hr)) {
log_warning("%s: ioctl failed: %lx", __func__, hr);
return hr_propagate_win32(hr, FALSE);
}
return TRUE;
}
static BOOL STDCALL my_GetCommState(HANDLE fd, DCB *dcb)
{
struct irp irp;
SERIAL_BAUD_RATE baud;
SERIAL_CHARS chars;
SERIAL_HANDFLOW handflow;
SERIAL_LINE_CONTROL line_control;
HRESULT hr;
/*
* Validate params
*/
if (dcb == NULL) {
log_warning("%s: DCB pointer is NULL", __func__);
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (dcb->DCBlength != sizeof(*dcb)) {
/* This struct has evolved in the past, but those were the Windows 95
days. So we only support the latest size of this struct. */
log_warning(
"%s: dcb->DCBlength = %d, expected %d",
__func__,
(int) dcb->DCBlength,
(unsigned int) sizeof(*dcb));
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
/*
* Issue ioctls
*/
memset(&irp, 0, sizeof(irp));
irp.op = IRP_OP_IOCTL;
irp.fd = fd;
irp.ioctl = IOCTL_SERIAL_GET_BAUD_RATE;
irp.read.bytes = (uint8_t *) &baud;
irp.read.nbytes = sizeof(baud);
memset(&baud, 0, sizeof(baud));
hr = irp_invoke_next(&irp);
if (FAILED(hr)) {
log_warning("%s: IOCTL_SERIAL_GET_BAUD_RATE failed: %lx", __func__, hr);
return hr_propagate_win32(hr, FALSE);
}
memset(&irp, 0, sizeof(irp));
irp.op = IRP_OP_IOCTL;
irp.fd = fd;
irp.ioctl = IOCTL_SERIAL_GET_HANDFLOW;
irp.read.bytes = (uint8_t *) &handflow;
irp.read.nbytes = sizeof(handflow);
memset(&handflow, 0, sizeof(handflow));
hr = irp_invoke_next(&irp);
if (FAILED(hr)) {
log_warning("%s: IOCTL_SERIAL_GET_HANDFLOW failed: %lx", __func__, hr);
return hr_propagate_win32(hr, FALSE);
}
memset(&irp, 0, sizeof(irp));
irp.op = IRP_OP_IOCTL;
irp.fd = fd;
irp.ioctl = IOCTL_SERIAL_GET_LINE_CONTROL;
irp.read.bytes = (uint8_t *) &line_control;
irp.read.nbytes = sizeof(line_control);
memset(&line_control, 0, sizeof(line_control));
hr = irp_invoke_next(&irp);
if (FAILED(hr)) {
log_warning(
"%s: IOCTL_SERIAL_GET_LINE_CONTROL failed: %lx",
__func__,
hr);
return hr_propagate_win32(hr, FALSE);
}
memset(&irp, 0, sizeof(irp));
irp.op = IRP_OP_IOCTL;
irp.fd = fd;
irp.ioctl = IOCTL_SERIAL_GET_CHARS;
irp.read.bytes = (uint8_t *) &chars;
irp.read.nbytes = sizeof(chars);
memset(&chars, 0, sizeof(chars));
hr = irp_invoke_next(&irp);
if (FAILED(hr)) {
log_warning("%s: IOCTL_SERIAL_GET_CHARS failed: %lx", __func__, hr);
return hr_propagate_win32(hr, FALSE);
}
/*
* Populate output struct
*/
memset(dcb, 0, sizeof(*dcb));
dcb->DCBlength = sizeof(*dcb);
dcb->fBinary = 1;
dcb->BaudRate = baud.BaudRate;
/* Populate fParity somehow? */
if (handflow.ControlHandShake & SERIAL_CTS_HANDSHAKE) {
dcb->fOutxCtsFlow = 1;
}
if (handflow.ControlHandShake & SERIAL_DSR_HANDSHAKE) {
dcb->fOutxDsrFlow = 1;
}
if (handflow.ControlHandShake & SERIAL_DTR_CONTROL) {
dcb->fDtrControl = DTR_CONTROL_ENABLE;
}
if (handflow.ControlHandShake & SERIAL_DTR_HANDSHAKE) {
dcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
}
if (handflow.ControlHandShake & SERIAL_DSR_SENSITIVITY) {
dcb->fDsrSensitivity = 1;
}
if (handflow.ControlHandShake & SERIAL_XOFF_CONTINUE) {
dcb->fTXContinueOnXoff = 1;
}
if (handflow.ControlHandShake & SERIAL_RTS_CONTROL) {
dcb->fRtsControl = RTS_CONTROL_ENABLE;
}
if (handflow.ControlHandShake & SERIAL_RTS_HANDSHAKE) {
dcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
}
if (handflow.ControlHandShake & SERIAL_ERROR_ABORT) {
dcb->fAbortOnError = 1;
}
if (handflow.ControlHandShake & SERIAL_ERROR_CHAR) {
dcb->fErrorChar = 1;
}
if (handflow.ControlHandShake & SERIAL_NULL_STRIPPING) {
dcb->fNull = 1;
}
dcb->XonLim = handflow.XonLimit;
dcb->XoffLim = handflow.XoffLimit;
dcb->ByteSize = line_control.WordLength;
dcb->Parity = line_control.Parity;
dcb->StopBits = line_control.StopBits;
dcb->XonChar = chars.XonChar;
dcb->XoffChar = chars.XoffChar;
dcb->ErrorChar = chars.ErrorChar;
dcb->EofChar = chars.EofChar;
dcb->EvtChar = chars.EventChar;
SetLastError(ERROR_SUCCESS);
return TRUE;
}
static BOOL STDCALL my_PurgeComm(HANDLE fd, uint32_t flags)
{
struct irp irp;
HRESULT hr;
memset(&irp, 0, sizeof(irp));
irp.op = IRP_OP_IOCTL;
irp.fd = fd;
irp.ioctl = IOCTL_SERIAL_PURGE;
irp.write.bytes = (uint8_t *) &flags;
irp.write.nbytes = sizeof(flags);
hr = irp_invoke_next(&irp);
if (FAILED(hr)) {
log_warning("%s: IOCTL_SERIAL_PURGE failed: %lx", __func__, hr);
}
return hr_propagate_win32(hr, SUCCEEDED(hr));
}
static BOOL STDCALL my_SetCommMask(HANDLE fd, uint32_t mask)
{
struct irp irp;
HRESULT hr;
memset(&irp, 0, sizeof(irp));
irp.op = IRP_OP_IOCTL;
irp.fd = fd;
irp.ioctl = IOCTL_SERIAL_SET_WAIT_MASK;
irp.write.bytes = (uint8_t *) &mask;
irp.write.nbytes = sizeof(mask);
hr = irp_invoke_next(&irp);
if (FAILED(hr)) {
log_warning("%s: IOCTL_SERIAL_SET_WAIT_MASK failed: %lx", __func__, hr);
}
return hr_propagate_win32(hr, SUCCEEDED(hr));
}
static BOOL STDCALL my_SetCommState(HANDLE fd, const DCB *dcb)
{
struct irp irp;
SERIAL_BAUD_RATE baud;
SERIAL_CHARS chars;
SERIAL_HANDFLOW handflow;
SERIAL_LINE_CONTROL line_control;
HRESULT hr;
if (dcb == NULL) {
log_warning("%s: DCB pointer is NULL", __func__);
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (dcb->DCBlength != sizeof(*dcb)) {
/* This struct has evolved in the past, but those were the Windows 95
days. So we only support the latest size of this struct. */
log_warning(
"%s: dcb->DCBlength = %d, expected %d",
__func__,
(int) dcb->DCBlength,
(unsigned int) sizeof(*dcb));
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
memset(&baud, 0, sizeof(baud));
baud.BaudRate = dcb->BaudRate;
memset(&handflow, 0, sizeof(handflow));
if (dcb->fOutxCtsFlow) {
handflow.ControlHandShake |= SERIAL_CTS_HANDSHAKE;
}
if (dcb->fOutxDsrFlow) {
handflow.ControlHandShake |= SERIAL_DSR_HANDSHAKE;
}
switch (dcb->fDtrControl) {
case DTR_CONTROL_DISABLE:
break;
case DTR_CONTROL_ENABLE:
handflow.ControlHandShake |= SERIAL_DTR_CONTROL;
break;
case DTR_CONTROL_HANDSHAKE:
handflow.ControlHandShake |= SERIAL_DTR_HANDSHAKE;
break;
default:
log_warning("%s: dcb->fDtrControl value %d is invalid",
__func__, dcb->fDtrControl);
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (dcb->fDsrSensitivity) {
handflow.ControlHandShake |= SERIAL_DSR_SENSITIVITY;
}
if (dcb->fTXContinueOnXoff) {
handflow.ControlHandShake |= SERIAL_XOFF_CONTINUE;
}
switch (dcb->fRtsControl) {
case RTS_CONTROL_DISABLE:
break;
case RTS_CONTROL_ENABLE:
handflow.ControlHandShake |= SERIAL_RTS_CONTROL;
break;
case RTS_CONTROL_HANDSHAKE:
handflow.ControlHandShake |= SERIAL_RTS_HANDSHAKE;
break;
default:
log_warning(
"%s: dcb->fRtsControl value %d is invalid",
__func__,
dcb->fRtsControl);
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
memset(&line_control, 0, sizeof(line_control));
line_control.WordLength = dcb->ByteSize;
line_control.Parity = dcb->Parity;
line_control.StopBits = dcb->StopBits;
memset(&chars, 0, sizeof(chars));
chars.XonChar = dcb->XonChar;
chars.XoffChar = dcb->XoffChar;
chars.ErrorChar = dcb->ErrorChar;
chars.EofChar = dcb->EofChar;
chars.EventChar = dcb->EvtChar;
/* Parameters populated and validated, commit new settings */
memset(&irp, 0, sizeof(irp));
irp.op = IRP_OP_IOCTL;
irp.fd = fd;
irp.ioctl = IOCTL_SERIAL_SET_BAUD_RATE;
irp.write.bytes = (uint8_t *) &baud;
irp.write.nbytes = sizeof(baud);
hr = irp_invoke_next(&irp);
if (FAILED(hr)) {
log_warning("%s: IOCTL_SERIAL_SET_BAUD_RATE failed: %lx", __func__, hr);
return hr_propagate_win32(hr, FALSE);
}
memset(&irp, 0, sizeof(irp));
irp.op = IRP_OP_IOCTL;
irp.fd = fd;
irp.ioctl = IOCTL_SERIAL_SET_HANDFLOW;
irp.write.bytes = (uint8_t *) &handflow;
irp.write.nbytes = sizeof(handflow);
hr = irp_invoke_next(&irp);
if (FAILED(hr)) {
log_warning("%s: IOCTL_SERIAL_SET_HANDFLOW failed: %lx", __func__, hr);
return hr_propagate_win32(hr, FALSE);
}
memset(&irp, 0, sizeof(irp));
irp.op = IRP_OP_IOCTL;
irp.fd = fd;
irp.ioctl = IOCTL_SERIAL_SET_LINE_CONTROL;
irp.write.bytes = (uint8_t *) &line_control;
irp.write.nbytes = sizeof(line_control);
hr = irp_invoke_next(&irp);
if (FAILED(hr)) {
log_warning(
"%s: IOCTL_SERIAL_SET_LINE_CONTROL failed: %lx",
__func__,
hr);
return hr_propagate_win32(hr, FALSE);
}
memset(&irp, 0, sizeof(irp));
irp.op = IRP_OP_IOCTL;
irp.fd = fd;
irp.ioctl = IOCTL_SERIAL_SET_CHARS;
irp.write.bytes = (uint8_t *) &chars;
irp.write.nbytes = sizeof(chars);
hr = irp_invoke_next(&irp);
if (FAILED(hr)) {
log_warning("%s: IOCTL_SERIAL_SET_CHARS failed: %lx", __func__, hr);
return hr_propagate_win32(hr, FALSE);
}
SetLastError(ERROR_SUCCESS);
return TRUE;
}
static BOOL STDCALL my_SetCommTimeouts(HANDLE fd, COMMTIMEOUTS *src)
{
struct irp irp;
SERIAL_TIMEOUTS dest;
HRESULT hr;
dest.ReadIntervalTimeout = src->ReadIntervalTimeout;
dest.ReadTotalTimeoutMultiplier = src->ReadTotalTimeoutMultiplier;
dest.ReadTotalTimeoutConstant = src->ReadTotalTimeoutConstant;
dest.WriteTotalTimeoutMultiplier = src->WriteTotalTimeoutMultiplier;
dest.WriteTotalTimeoutConstant = src->WriteTotalTimeoutConstant;
memset(&irp, 0, sizeof(irp));
irp.op = IRP_OP_IOCTL;
irp.fd = fd;
irp.ioctl = IOCTL_SERIAL_SET_TIMEOUTS;
irp.write.bytes = (uint8_t *) &dest;
irp.write.nbytes = sizeof(dest);
hr = irp_invoke_next(&irp);
if (FAILED(hr)) {
log_warning("%s: IOCTL_SERIAL_SET_TIMEOUTS failed: %lx", __func__, hr);
}
return hr_propagate_win32(hr, SUCCEEDED(hr));
}
static BOOL STDCALL my_SetupComm(HANDLE fd, uint32_t in_q, uint32_t out_q)
{
struct irp irp;
SERIAL_QUEUE_SIZE qs;
HRESULT hr;
qs.InSize = in_q;
qs.OutSize = out_q;
memset(&irp, 0, sizeof(irp));
irp.op = IRP_OP_IOCTL;
irp.fd = fd;
irp.ioctl = IOCTL_SERIAL_SET_QUEUE_SIZE;
irp.write.bytes = (uint8_t *) &qs;
irp.write.nbytes = sizeof(qs);
hr = irp_invoke_next(&irp);
if (FAILED(hr)) {
log_warning("%s: IOCTL_SERIAL_SET_QUEUE_SIZE failed: %lx",__func__, hr);
}
return hr_propagate_win32(hr, SUCCEEDED(hr));
}
static BOOL STDCALL my_SetCommBreak(HANDLE fd)
{
struct irp irp;
HRESULT hr;
memset(&irp, 0, sizeof(irp));
irp.op = IRP_OP_IOCTL;
irp.fd = fd;
irp.ioctl = IOCTL_SERIAL_SET_BREAK_ON;
hr = irp_invoke_next(&irp);
if (FAILED(hr)) {
log_warning("%s: IOCTL_SERIAL_SET_BREAK_ON failed: %lx", __func__, hr);
}
return hr_propagate_win32(hr, SUCCEEDED(hr));
}
static BOOL STDCALL my_ClearCommBreak(HANDLE fd)
{
struct irp irp;
HRESULT hr;
memset(&irp, 0, sizeof(irp));
irp.op = IRP_OP_IOCTL;
irp.fd = fd;
irp.ioctl = IOCTL_SERIAL_SET_BREAK_OFF;
hr = irp_invoke_next(&irp);
if (FAILED(hr)) {
log_warning("%s: IOCTL_SERIAL_SET_BREAK_OFF failed: %lx", __func__, hr);
}
return hr_propagate_win32(hr, SUCCEEDED(hr));
}
+6
View File
@@ -0,0 +1,6 @@
#ifndef HOOKLIB_RS232_H
#define HOOKLIB_RS232_H
void rs232_hook_init(void);
#endif
+330
View File
@@ -0,0 +1,330 @@
#define LOG_MODULE "hook-setupapi"
#include <stdbool.h>
#include <string.h>
#include <wchar.h>
#include "hook/table.h"
#include "hooklib/setupapi.h"
#include "util/defs.h"
#include "util/log.h"
#include "util/str.h"
/* my hooks */
static BOOL STDCALL my_SetupDiDestroyDeviceInfoList(HDEVINFO dev_info);
static BOOL STDCALL my_SetupDiEnumDeviceInfo(
HDEVINFO dev_info, DWORD index, SP_DEVINFO_DATA *info_data);
static BOOL STDCALL my_SetupDiEnumDeviceInterfaces(
HDEVINFO dev_info, SP_DEVINFO_DATA *info_data, const GUID *iface_guid,
DWORD index, SP_DEVICE_INTERFACE_DATA *ifd);
static HDEVINFO STDCALL my_SetupDiGetClassDevsA(
const GUID *class_guid, const char *enumerator, HWND hwnd,
DWORD flags);
static HDEVINFO STDCALL my_SetupDiGetClassDevsW(
const GUID *class_guid, PCWSTR enumerator, HWND hwnd,
DWORD flags);
static BOOL STDCALL my_SetupDiGetDeviceInterfaceDetailA(
HDEVINFO dev_info, SP_DEVICE_INTERFACE_DATA *ifd,
SP_DEVICE_INTERFACE_DETAIL_DATA_A *detail, DWORD size,
DWORD *required_size, SP_DEVINFO_DATA *info_data);
static BOOL STDCALL my_SetupDiGetDeviceInterfaceDetailW(
HDEVINFO dev_info, SP_DEVICE_INTERFACE_DATA *ifd,
SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail, DWORD size,
DWORD *required_size, SP_DEVINFO_DATA *info_data);
static BOOL STDCALL my_SetupDiGetDeviceRegistryPropertyA(
HDEVINFO dev_info, SP_DEVINFO_DATA *info_data, DWORD prop_id,
DWORD *prop_type, void *bytes, DWORD nbytes, DWORD *required_nbytes);
/* real calls */
static BOOL (STDCALL *real_SetupDiDestroyDeviceInfoList)(
HDEVINFO dev_info);
static BOOL (STDCALL *real_SetupDiEnumDeviceInfo)(
HDEVINFO dev_info, DWORD index, SP_DEVINFO_DATA *info_data);
static BOOL (STDCALL *real_SetupDiEnumDeviceInterfaces)(
HDEVINFO dev_info, SP_DEVINFO_DATA *info_data, const GUID *iface_guid,
DWORD index, SP_DEVICE_INTERFACE_DATA *ifd);
static HDEVINFO (STDCALL *real_SetupDiGetClassDevsA)(
const GUID *class_guid, const char *enumerator, HWND hwnd,
DWORD flags);
static HDEVINFO (STDCALL *real_SetupDiGetClassDevsW)(
const GUID *class_guid, PCWSTR enumerator, HWND hwnd,
DWORD flags);
static BOOL (STDCALL *real_SetupDiGetDeviceInterfaceDetailA)(
HDEVINFO dev_info, SP_DEVICE_INTERFACE_DATA *ifd,
SP_DEVICE_INTERFACE_DETAIL_DATA_A *detail, DWORD size,
DWORD *required_size, SP_DEVINFO_DATA *info_data);
static BOOL (STDCALL *real_SetupDiGetDeviceInterfaceDetailW)(
HDEVINFO dev_info, SP_DEVICE_INTERFACE_DATA *ifd,
SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail, DWORD size,
DWORD *required_size, SP_DEVINFO_DATA *info_data);
static BOOL (STDCALL *real_SetupDiGetDeviceRegistryPropertyA)(
HDEVINFO dev_info, SP_DEVINFO_DATA *info_data, DWORD prop_id,
DWORD *prop_type, void *bytes, DWORD nbytes, DWORD *required_nbytes);
static const struct hook_symbol setupapi_hook_syms[] = {
{
.name = "SetupDiDestroyDeviceInfoList",
.patch = my_SetupDiDestroyDeviceInfoList,
.link = (void **) &real_SetupDiDestroyDeviceInfoList
},
{
.name = "SetupDiEnumDeviceInfo",
.patch = my_SetupDiEnumDeviceInfo,
.link = (void **) &real_SetupDiEnumDeviceInfo
},
{
.name = "SetupDiEnumDeviceInterfaces",
.patch = my_SetupDiEnumDeviceInterfaces,
.link = (void **) &real_SetupDiEnumDeviceInterfaces
},
{
.name = "SetupDiGetClassDevsA",
.patch = my_SetupDiGetClassDevsA,
.link = (void **) &real_SetupDiGetClassDevsA
},
{
.name = "SetupDiGetClassDevsW",
.patch = my_SetupDiGetClassDevsW,
.link = (void **) &real_SetupDiGetClassDevsW
},
{
.name = "SetupDiGetDeviceInterfaceDetailA",
.patch = my_SetupDiGetDeviceInterfaceDetailA,
.link = (void **) &real_SetupDiGetDeviceInterfaceDetailA
},
{
.name = "SetupDiGetDeviceInterfaceDetailW",
.patch = my_SetupDiGetDeviceInterfaceDetailW,
.link = (void **) &real_SetupDiGetDeviceInterfaceDetailW
},
{
.name = "SetupDiGetDeviceRegistryPropertyA",
.patch = my_SetupDiGetDeviceRegistryPropertyA,
.link = (void **) &real_SetupDiGetDeviceRegistryPropertyA
},
};
static int hook_setupapi_fake_handle;
static const struct hook_setupapi_data* hook_setupapi_data;
static HDEVINFO STDCALL my_SetupDiGetClassDevsA(
const GUID *class_guid, const char *enumerator, HWND hwnd,
DWORD flags)
{
/* That's how iidx 9-13 detected the old C02 IO. That doesn't work
on iidx 14 anymore... */
/*
if (class_guid != NULL
&& memcmp(class_guid, &hook_setupapi_data->device_guid,
sizeof(hook_setupapi_data->device_guid)) == 0) {
*/
if ((class_guid != NULL
&& !memcmp(class_guid, &hook_setupapi_data->device_guid,
sizeof(hook_setupapi_data->device_guid))) ||
(enumerator != NULL && !strcmp(enumerator, "USB"))) {
SetLastError(ERROR_SUCCESS);
log_misc("SetupDiGetClassDevsA: %s", hook_setupapi_data->device_path);
return &hook_setupapi_fake_handle;
} else {
return real_SetupDiGetClassDevsA(class_guid, enumerator, hwnd, flags);
}
}
static HDEVINFO STDCALL my_SetupDiGetClassDevsW(
const GUID *class_guid, PCWSTR enumerator, HWND hwnd,
DWORD flags)
{
if (class_guid != NULL
&& memcmp(class_guid, &hook_setupapi_data->device_guid,
sizeof(hook_setupapi_data->device_guid)) == 0) {
SetLastError(ERROR_SUCCESS);
log_misc("SetupDiGetClassDevsW: %s", hook_setupapi_data->device_path);
return &hook_setupapi_fake_handle;
} else {
return real_SetupDiGetClassDevsW(class_guid, enumerator, hwnd, flags);
}
}
static BOOL STDCALL my_SetupDiEnumDeviceInfo(
HDEVINFO dev_info, DWORD index, SP_DEVINFO_DATA *info_data)
{
if (dev_info == &hook_setupapi_fake_handle) {
if (index == 0) {
SetLastError(ERROR_SUCCESS);
log_misc("SetupDiEnumDeviceInfo");
return TRUE;
} else {
SetLastError(ERROR_NO_MORE_ITEMS);
return FALSE;
}
} else {
return real_SetupDiEnumDeviceInfo(dev_info, index, info_data);
}
}
static BOOL STDCALL my_SetupDiEnumDeviceInterfaces(
HDEVINFO dev_info, SP_DEVINFO_DATA *info_data, const GUID *iface_guid,
DWORD index, SP_DEVICE_INTERFACE_DATA *ifd)
{
if (dev_info == &hook_setupapi_fake_handle) {
SetLastError(ERROR_SUCCESS);
log_misc("SetupDiEnumDeviceInterfaces");
return index == 0;
} else {
return real_SetupDiEnumDeviceInterfaces(dev_info, info_data,
iface_guid, index, ifd);
}
}
static BOOL STDCALL my_SetupDiGetDeviceRegistryPropertyA(
HDEVINFO dev_info, SP_DEVINFO_DATA *info_data, DWORD prop_id,
DWORD *prop_type, void *bytes, DWORD nbytes, DWORD *required_nbytes)
{
if (dev_info == &hook_setupapi_fake_handle) {
if (prop_id != SPDRP_DEVICEDESC) {
SetLastError(ERROR_BAD_ARGUMENTS);
return FALSE;
}
if (nbytes < MAX_PATH) {
SetLastError(ERROR_INSUFFICIENT_BUFFER);
*required_nbytes = MAX_PATH;
return FALSE;
} else {
SetLastError(ERROR_SUCCESS);
*prop_type = REG_SZ;
if (hook_setupapi_data->device_desc) {
log_misc("SetupDiGetDeviceRegistryPropertyA: %s",
hook_setupapi_data->device_desc);
str_cpy(bytes, nbytes, hook_setupapi_data->device_desc);
}
return TRUE;
}
} else {
return real_SetupDiGetDeviceRegistryPropertyA(
dev_info, info_data, prop_id, prop_type, bytes, nbytes,
required_nbytes);
}
}
static BOOL STDCALL my_SetupDiGetDeviceInterfaceDetailA(
HDEVINFO dev_info, SP_DEVICE_INTERFACE_DATA *ifd,
SP_DEVICE_INTERFACE_DETAIL_DATA_A *detail, DWORD size,
DWORD *required_size, SP_DEVINFO_DATA *info_data)
{
if (dev_info == &hook_setupapi_fake_handle) {
if (size == 0) {
SetLastError(ERROR_INSUFFICIENT_BUFFER);
*required_size = sizeof(DWORD) + sizeof(char) * MAX_PATH;
return FALSE;
} else {
SetLastError(ERROR_SUCCESS);
log_misc("SetupDiGetDeviceInterfaceDetailA: %s",
hook_setupapi_data->device_path);
detail->cbSize = strlen(hook_setupapi_data->device_path);
memcpy(detail->DevicePath, hook_setupapi_data->device_path,
detail->cbSize);
detail->DevicePath[detail->cbSize] = '\0';
return TRUE;
}
} else {
return real_SetupDiGetDeviceInterfaceDetailA(dev_info, ifd, detail,
size, required_size, info_data);
}
}
static BOOL STDCALL my_SetupDiGetDeviceInterfaceDetailW(
HDEVINFO dev_info, SP_DEVICE_INTERFACE_DATA *ifd,
SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail, DWORD size,
DWORD *required_size, SP_DEVINFO_DATA *info_data)
{
if (dev_info == &hook_setupapi_fake_handle) {
if (size == 0) {
SetLastError(ERROR_INSUFFICIENT_BUFFER);
*required_size = sizeof(DWORD) + sizeof(wchar_t) * MAX_PATH;
return FALSE;
} else {
SetLastError(ERROR_SUCCESS);
log_misc("SetupDiGetDeviceInterfaceDetailW: %s",
hook_setupapi_data->device_path);
wchar_t* wstr_path = str_widen(hook_setupapi_data->device_path);
detail->cbSize = strlen(hook_setupapi_data->device_path);
memcpy(detail->DevicePath, wstr_path, (wcslen(wstr_path) + 1) *
sizeof(wchar_t));
detail->DevicePath[detail->cbSize] = '\0';
free(wstr_path);
return TRUE;
}
} else {
return real_SetupDiGetDeviceInterfaceDetailW(dev_info, ifd, detail,
size, required_size, info_data);
}
}
static BOOL STDCALL my_SetupDiDestroyDeviceInfoList(HDEVINFO dev_info)
{
if (dev_info == &hook_setupapi_fake_handle) {
log_misc("SetupDiDestroyDeviceInfoList");
return TRUE;
} else {
return real_SetupDiDestroyDeviceInfoList(dev_info);
}
}
void hook_setupapi_init(const struct hook_setupapi_data* data)
{
hook_table_apply(
NULL,
"setupapi.dll",
setupapi_hook_syms,
lengthof(setupapi_hook_syms));
hook_setupapi_data = data;
log_info("Hooked setupapi for %s, %s", data->device_path,
data->device_desc);
}
+15
View File
@@ -0,0 +1,15 @@
#ifndef HOOKLIB_SETUPAPI_H
#define HOOKLIB_SETUPAPI_H
#include <windows.h>
#include <setupapi.h>
struct hook_setupapi_data {
GUID device_guid;
const char* device_desc;
const char* device_path;
};
void hook_setupapi_init(const struct hook_setupapi_data* data);
#endif