1
0
mirror of https://github.com/UzixLS/KernelEx.git synced 2025-07-19 07:21:20 +03:00

import KernelEx-4.5.1

This commit is contained in:
UzixLS
2018-11-03 16:23:39 +03:00
parent 7571e3c60d
commit 2948e23961
77 changed files with 2603 additions and 883 deletions

133
ApiHook/ApiLog/ApiLog.dsp Executable file
View File

@ -0,0 +1,133 @@
# Microsoft Developer Studio Project File - Name="ApiLog" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=ApiLog - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "ApiLog.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "ApiLog.mak" CFG="ApiLog - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "ApiLog - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "ApiLog - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "ApiLog - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "APILOG_EXPORTS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /O2 /I "." /I "../../common" /FI"msvc_quirks.h" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "APILOG_EXPORTS" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x415 /d "NDEBUG"
# ADD RSC /l 0x415 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib ../../kexcrt/kexcrt.lib libc.lib /nologo /entry:"DllMain@12" /dll /machine:I386 /nodefaultlib /OPT:NOWIN98
# SUBTRACT LINK32 /pdb:none
!ELSEIF "$(CFG)" == "ApiLog - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "APILOG_EXPORTS" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /I "." /I "../../common" /FI"msvc_quirks.h" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "APILOG_EXPORTS" /YX /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x415 /d "_DEBUG"
# ADD RSC /l 0x415 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib ../../kexcrt/kexcrt.lib libc.lib /nologo /entry:"DllMain@12" /dll /debug /machine:I386 /nodefaultlib /OPT:NOWIN98
# SUBTRACT LINK32 /pdb:none
!ENDIF
# Begin Target
# Name "ApiLog - Win32 Release"
# Name "ApiLog - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\apilog.cpp
# End Source File
# Begin Source File
SOURCE=.\apilog.def
# End Source File
# Begin Source File
SOURCE=.\apilog_params.cpp
# End Source File
# Begin Source File
SOURCE=.\writer.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\apilog.h
# End Source File
# Begin Source File
SOURCE=.\apilog_params.h
# End Source File
# Begin Source File
SOURCE=.\writer.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project

38
ApiHook/ApiLog/README.txt Executable file
View File

@ -0,0 +1,38 @@
API logging DLL for KernelEx Core API hook infrastructure
Make sure to disable API extensions for this module or else the DLL
will try to hooks its own imports.
By default you have to rename the DLL to kexApiHook.dll and place it either in C:\Windows\KernelEx or somewhere in DLL search path.
Alternatively you can set the 'ApiHookPath' value under 'HKEY_LOCAL_MACHINE\Software\KernelEx' to full path to the DLL.
Search path takes precedence over other methods.
The DLL can output logs using different methods, set 'KEXAPILOG_OUTPUT' environment variable to change:
file - API logs are written to a file named as module but with '.log' extension (default)
window - API logs are output to DebugWindow application
debug - API logs are output via OutputDebugString API to system debugger
The DLL will also try to load the file called 'signature.dat' in the directory where the DLL is located.
This file contains API function signatures for parameter logging.
Syntax of the file:
[MODULENAME.DLL]
ApiName=format
where format is a sequence of letters from printf format specifiers:
p - pointer in the form of: 0x1234abcd
d - decimal number
x - hexadecimal number
s - ansi string
S - unicode string
f - float
Example:
[KERNEL32.DLL]
GetProcAddress=ps
Errors related to API hook DLL loading are written to debug output.

334
ApiHook/ApiLog/apilog.cpp Executable file
View File

@ -0,0 +1,334 @@
/*
* KernelEx
* Copyright (C) 2011, Xeno86
*
* This file is part of KernelEx source code.
*
* KernelEx is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; version 2 of the License.
*
* KernelEx is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/*
* API logging DLL for KernelEx Core API hook infrastructure
*
* Make sure to disable API extensions for this module or else the DLL
* will try to hooks its own imports.
*/
#include "apilog.h"
#include "apilog_params.h"
#include "writer.h"
extern "C" void * _AddressOfReturnAddress(void);
#pragma intrinsic(_AddressOfReturnAddress)
#define countof(x) (sizeof(x)/sizeof(x[0]))
#ifdef _DEBUG
#define DBGASSERT(e) ((e) ? 0 : DebugBreak())
#else
#define DBGASSERT(e) ((void)0)
#endif
extern "C"
int snprintf(char *buffer, size_t n, const char* format, ...);
int tlsindex = -1;
const bool apilog_enabled = true;
HINSTANCE hInst;
ThreadAddrStack::ThreadAddrStack()
{
pos = 0;
}
void __stdcall ThreadAddrStack::push_ret_addr(DWORD addr)
{
DBGASSERT(tlsindex != -1);
ThreadAddrStack* tas = (ThreadAddrStack*) TlsGetValue(tlsindex);
if (!tas)
{
tas = new ThreadAddrStack;
TlsSetValue(tlsindex, tas);
}
tas->stack[tas->pos++] = addr;
DBGASSERT(tas->pos < countof(tas->stack));
}
DWORD __stdcall ThreadAddrStack::pop_ret_addr()
{
DBGASSERT(tlsindex != -1);
ThreadAddrStack* tas = (ThreadAddrStack*) TlsGetValue(tlsindex);
DBGASSERT(tas->pos > 0);
return tas->stack[--tas->pos];
}
DWORD __stdcall ThreadAddrStack::get_level()
{
DBGASSERT(tlsindex != -1);
ThreadAddrStack* tas = (ThreadAddrStack*) TlsGetValue(tlsindex);
return tas->pos;
}
log_stub::log_stub(const char* source, const char* target, const char* name,
unsigned long proc)
: call_prelog(DWORD(pre_log)), call_postlog(DWORD(post_log)),
call_orig(proc)
{
c_pushad1 = c_pushad2 = 0x60;
c_popad1 = c_popad2 = 0x61;
c_ret = 0xc3;
c_push1 = c_push2 = 0x68;
v_lgd1 = &lgd;
v_lgd2 = &lgd;
c_push_eax = 0x50;
c_add_esp = 0xc483;
c_sub_esp = 0xec83;
c_byte_4 = c_byte_4_1 = 4;
lgd.source = source;
lgd.target = target;
lgd.api_name = name;
}
void __stdcall log_stub::pre_log(log_data* lgd)
{
DWORD last_err;
DWORD caller_addr;
caller_addr = *((DWORD*) _AddressOfReturnAddress() + 10);
last_err = GetLastError();
ThreadAddrStack::push_ret_addr(caller_addr);
if (apilog_enabled)
{
DWORD level;
char msg[DEBUGMSG_MAXLEN];
level = ThreadAddrStack::get_level();
int z = snprintf(msg, sizeof(msg)-1, "%-2d|%x|%*s[%s]%08x:<%s>%s",
level,
GetCurrentThreadId(),
(level-1) * 2, "",
lgd->source, caller_addr,
lgd->target, lgd->api_name);
va_list ap = va_list((DWORD*) &lgd + 10);
z += ApiLogParams::inst().decode_parameters(lgd->target, lgd->api_name, ap, msg + z, sizeof(msg)-1 - z);
strcpy(msg + z, "\n");
writer_fn(msg);
}
SetLastError(last_err);
}
void __stdcall log_stub::post_log(log_data* lgd, DWORD retval)
{
DWORD last_err;
DWORD& caller_addr = *((DWORD*) _AddressOfReturnAddress() + 11);
last_err = GetLastError();
caller_addr = ThreadAddrStack::pop_ret_addr();
if (apilog_enabled)
{
DWORD level;
char msg[DEBUGMSG_MAXLEN];
level = ThreadAddrStack::get_level() + 1;
snprintf(msg, sizeof(msg), "%-2d|%x|%*s[%s]%08x:<%s>%s|%x\n",
level,
GetCurrentThreadId(),
(level-1) * 2, "",
lgd->source, caller_addr,
lgd->target, lgd->api_name,
retval);
writer_fn(msg);
}
SetLastError(last_err);
}
HMODULE GetCurrentModule()
{
MEMORY_BASIC_INFORMATION mbi;
static int dummy;
VirtualQuery(&dummy, &mbi, sizeof(mbi));
return (HMODULE)mbi.AllocationBase;
}
void load_signature()
{
char signature_file[MAX_PATH];
GetModuleFileName(hInst, signature_file, MAX_PATH);
char* p = strrchr(signature_file, '\\');
if (!p) p = signature_file;
else p++;
*p = '\0';
strcat(signature_file, "signature.dat");
OutputDebugString("Loading apilog signatures... ");
bool res = ApiLogParams::inst().load_signatures(signature_file);
OutputDebugString(res ? "done.\n" : "error.\n");
}
bool filter_out(const char* target, const char* api)
{
static const char* filtered_apis[] =
{
"HeapAlloc",
"HeapFree",
"HeapReAlloc",
"HeapSize",
"GetProcessHeap",
"TlsGetValue",
"TlsSetValue",
"InitializeCriticalSection",
"ReinitializeCriticalSection",
"DeleteCriticalSection",
"EnterCriticalSection",
"LeaveCriticalSection",
"InterlockedIncrement",
"InterlockedDecrement",
"InterlockedExchange",
"InterlockedExchangeAdd",
"InterlockedCompareExchange",
};
if (HIWORD(api) && !strcmp(target, "KERNEL32.DLL"))
{
for (int i = 0 ; i < countof(filtered_apis) ; i++)
{
if (!strcmp(api, filtered_apis[i]))
return true;
}
}
return false;
}
/*
* This function is called before any call to _register and BEFORE DllMain
* in order to let you prepare your API hooks.
*
* Return:
* 1 for success
* 0 in case of error - this will trigger unloading of the DLL
*
* WARNING: This function is called inside Kernel32Lock
* so you have to be VERY careful what you call here if you don't want
* to crash the system.
*/
int kexApiHook_initonce(void)
{
hInst = GetCurrentModule();
DBGASSERT(hInst != NULL);
load_signature();
return 1;
}
/*
* This function is called by the resolver for each API imported by a module.
* This function is called before DllMain.
*
* Parameters:
* caller - the module which imports the API (full path)
* target - the module from which API is imported (full path)
* api - the name of the API or ordinal number of the API (if upper word is zero)
* orig - address of the API being hooked, can be NULL if resolver found no API
*
* Return:
* orig - if you don't want to hook the API
* address of the hook - if you want to intercept the API
* NULL - if you want to disable the API altogether
*
* WARNING: This function is called inside Kernel32Lock
* so you have to be VERY careful what you call here if you don't want
* to crash the system.
*/
PROC kexApiHook_register(const char* caller, const char* target, const char* api, PROC orig)
{
char* new_api;
if (orig == NULL)
return orig;
//extract DLL file names
char* p;
p = strrchr(caller, '\\');
if (p) caller = p + 1;
p = strrchr(target, '\\');
if (p) target = p + 1;
if (filter_out(target, api))
return orig;
if (HIWORD(api)) //named export
{
new_api = strdup(api);
}
else //ordinal export
{
char ord_name[32];
snprintf(ord_name, sizeof(ord_name), "Ordinal:%u", (unsigned) api);
new_api = strdup(ord_name);
}
return (PROC) new log_stub(caller, target, new_api, (unsigned long) orig);
}
void prologue()
{
char path[MAX_PATH];
GetModuleFileName(NULL, path, MAX_PATH);
char msg[DEBUGMSG_MAXLEN];
snprintf(msg, sizeof(msg) -1, "0 |KernelEx API Log start for %s\n", path);
writer_fn(msg);
}
void epilogue()
{
writer_fn("0 |End of API log\n");
}
/*
* Called at DLL initialization/unload time, outside of Kernel32Lock.
* All static variables are initialized at this point.
* Also all DLLs on which this DLL depends are initialized here.
* This DLL's module tree is initialized before DLLs belonging to the process
* so be careful what you do.
*/
BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID lpReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
tlsindex = TlsAlloc();
if (tlsindex == -1)
return 0;
DisableThreadLibraryCalls(hModule);
if (!init_writer())
return FALSE;
prologue();
}
else if (dwReason == DLL_PROCESS_DETACH)
{
epilogue();
}
return TRUE;
}

4
ApiHook/ApiLog/apilog.def Executable file
View File

@ -0,0 +1,4 @@
LIBRARY ApiLog.dll BASE=0x77000000
EXPORTS
kexApiHook_initonce
kexApiHook_register

122
ApiHook/ApiLog/apilog.h Executable file
View File

@ -0,0 +1,122 @@
/*
* KernelEx
* Copyright (C) 2011, Xeno86
*
* This file is part of KernelEx source code.
*
* KernelEx is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; version 2 of the License.
*
* KernelEx is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef _APILOG_APILOG_H
#define _APILOG_APILOG_H
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
class ThreadAddrStack
{
public:
ThreadAddrStack();
static void __stdcall push_ret_addr(DWORD addr);
static DWORD __stdcall pop_ret_addr();
static DWORD __stdcall get_level();
private:
int pos;
DWORD stack[1023];
};
#pragma pack(push,1)
/* Creates a stub that calls address specified in the constructor. */
class redir_stub
{
public:
redir_stub(unsigned long target, bool make_call = true)
{
op = make_call ? 0xe8 : 0xe9;
addr = target - ((unsigned long)(this) + 5);
}
private:
unsigned char op;
unsigned long addr;
};
/* Creates a stub for api logging. */
class log_stub
{
public:
log_stub(const char* source, const char* target, const char* name,
unsigned long proc);
private:
struct log_data
{
const char* source;
const char* target;
const char* api_name;
};
static void __stdcall pre_log(log_data* lgd);
static void __stdcall post_log(log_data* lgd, DWORD retval);
/*
pushad
push lgd
call pre_log@4
popad
add esp, 4
call orig
sub esp, 4
pushad
push eax
push lgd
call post_log@8
popad
ret
*/
BYTE c_pushad1;
BYTE c_push1;
log_data* v_lgd1;
redir_stub call_prelog;
BYTE c_popad1;
WORD c_add_esp;
BYTE c_byte_4;
redir_stub call_orig;
WORD c_sub_esp;
BYTE c_byte_4_1;
BYTE c_pushad2;
BYTE c_push_eax;
BYTE c_push2;
log_data* v_lgd2;
redir_stub call_postlog;
BYTE c_popad2;
BYTE c_ret;
log_data lgd;
};
#pragma pack(pop)
#endif

172
ApiHook/ApiLog/apilog_params.cpp Executable file
View File

@ -0,0 +1,172 @@
/*
* KernelEx
* Copyright (C) 2010, Xeno86
*
* This file is part of KernelEx source code.
*
* KernelEx is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; version 2 of the License.
*
* KernelEx is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <malloc.h>
#include "apilog_params.h"
extern "C"
int vsnprintf(char *buffer, size_t n, const char *format, va_list ap);
//singleton instance
ApiLogParams* ApiLogParams::inst_;
ApiLogParams::ApiLogParams() : empty_signature("")
{
}
ApiLogParams::~ApiLogParams()
{
}
int ApiLogParams::decode_parameters(const char* lib, const char* fn, va_list ap,
char* buf, int len)
{
const sstring& sign = get_signature(lib, fn);
if (sign.empty())
return 0;
int slen = sign.length();
int extra = 0;
for (int i = 0 ; i < slen ; i++)
{
if (sign[i] == 's' || sign[i] == 'S') extra += 2;
}
char* format = (char*) alloca(slen * 3 + 3);
char* p = format;
*p++ = '(';
for (int i = 0 ; i < slen ; i++)
{
bool wide = false;
char fc = sign[i];
if (i != 0)
*p++ = ' ';
if (fc == 's' || fc == 'S') *p++ = '\"';
*p++ = '%';
*p++ = fc;
if (fc == 's' || fc == 'S') *p++ = '\"';
}
*p++ = ')';
*p++ = '\0';
__try
{
return vsnprintf(buf, len, format, ap);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
//better output nothing than crash
return 0;
}
}
size_t ApiLogParams::readline(HANDLE file, char* buf, size_t size)
{
char c;
DWORD nr;
size_t pos = 0;
bool cmt = false;
bool read_sth = false;
//fill buffer with a line, skipping comments, trimming line to buffer size
while (ReadFile(file, &c, 1, &nr, NULL) && nr == 1)
{
read_sth = true;
if (c == '\r')
continue;
if (c == '\n')
break;
if (c == ';' || cmt)
{
cmt = true;
continue;
}
if (pos < size-1)
buf[pos++] = c;
}
if (read_sth)
buf[pos++] = '\0';
return pos;
}
bool ApiLogParams::load_signatures(const char* file_name)
{
char buf[256];
sstring lib;
HANDLE file = CreateFile(file_name, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, 0, NULL);
if (file == INVALID_HANDLE_VALUE)
return false;
while (readline(file, buf, sizeof(buf)) != 0)
{
char* p;
char* fun;
char* sig;
//library name
if (buf[0] == '[')
{
p = strchr(buf, ']');
if (!p) continue;
*p = '\0';
strupr(buf);
lib = buf + 1;
}
//function definition
else
{
fun = buf;
p = strchr(buf, '=');
if (!p) continue;
*p++ = '\0';
sig = p;
if (!lib.empty())
signatures[lib][fun] = sig;
}
}
CloseHandle(file);
return true;
}
const sstring& ApiLogParams::get_signature(const char* lib, const char* fn)
{
std::map<sstring, std::map<sstring, sstring> >::iterator outer;
std::map<sstring, sstring>::iterator inner;
outer = signatures.find(lib);
if (outer == signatures.end())
return empty_signature;
inner = outer->second.find(fn);
if (inner == outer->second.end())
return empty_signature;
return inner->second;
}

54
ApiHook/ApiLog/apilog_params.h Executable file
View File

@ -0,0 +1,54 @@
/*
* KernelEx
* Copyright (C) 2010, Xeno86
*
* This file is part of KernelEx source code.
*
* KernelEx is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; version 2 of the License.
*
* KernelEx is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef __APILOGPARAMS_H
#define __APILOGPARAMS_H
#include <map>
#include <stdarg.h>
#include <windows.h>
#include "sstring.hpp"
class ApiLogParams
{
public:
~ApiLogParams();
int decode_parameters(const char* lib, const char* fn, va_list ap, char* buf, int len);
bool load_signatures(const char* file_name);
static ApiLogParams& inst();
private:
ApiLogParams();
const sstring& get_signature(const char* lib, const char* fn);
size_t readline(HANDLE file, char* buf, size_t size);
static ApiLogParams* inst_;
const sstring empty_signature;
std::map<sstring, std::map<sstring, sstring> > signatures;
};
inline ApiLogParams& ApiLogParams::inst()
{
if (!inst_) inst_ = new ApiLogParams;
return *inst_;
}
#endif // __APILOGPARAMS_H

37
ApiHook/ApiLog/test.cpp Executable file
View File

@ -0,0 +1,37 @@
#include <windows.h>
#include <stdio.h>
typedef PROC (*al_register_t)(const char*, const char*, const char*, PROC);
typedef int (*init_once_t)(void);
typedef int (WINAPI *MessageBox_t)(HWND, LPCWSTR, LPCWSTR, UINT);
int main()
{
MessageBox_t msgbox;
HMODULE hUser32 = LoadLibrary("user32.dll");
msgbox = (MessageBox_t) GetProcAddress(hUser32, "MessageBoxW");
al_register_t al_register;
init_once_t init_once;
HMODULE hApiHookDll = LoadLibrary("ApiLog.dll");
init_once = (init_once_t) GetProcAddress(hApiHookDll, "kexApiHook_initonce");
al_register = (al_register_t) GetProcAddress(hApiHookDll, "kexApiHook_register");
if (!init_once || !al_register)
{
puts("Failed to load api hook dll");
return 1;
}
if (!init_once())
{
puts("Failed to init api hook dll");
return 1;
}
msgbox = (MessageBox_t) al_register("SOURCE", "TARGET", "TestApi", (PROC) msgbox);
msgbox(NULL, L"This is a test message", L"Caption", MB_OK | MB_ICONINFORMATION);
FreeLibrary(hUser32);
FreeLibrary(hApiHookDll);
return 0;
}

121
ApiHook/ApiLog/writer.cpp Executable file
View File

@ -0,0 +1,121 @@
/*
* KernelEx
* Copyright (C) 2011, Xeno86
*
* This file is part of KernelEx source code.
*
* KernelEx is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; version 2 of the License.
*
* KernelEx is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "writer.h"
#define VA_SHARED 0x8000000
const unsigned short WM_KEXAPPENDLOG = 0x6eef;
static HANDLE hFile;
static char* shbuf;
static HWND hwnd;
static CRITICAL_SECTION windows_cs;
typedef bool (*initfn_t)();
initfn_t init_fn;
writerfn_t writer_fn;
bool init_file()
{
char path[MAX_PATH];
char* p;
GetModuleFileName(NULL, path, sizeof(path));
p = strrchr(path, '.');
if (p) *p = '\0';
strcat(path, ".log");
hFile = CreateFile(path, GENERIC_WRITE, FILE_SHARE_READ, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
return false;
return true;
}
void write_file(const char* msg)
{
DWORD written;
WriteFile(hFile, msg, strlen(msg), &written, NULL);
}
bool init_window()
{
shbuf = (char*) VirtualAlloc(NULL, DEBUGMSG_MAXLEN,
VA_SHARED | MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
hwnd = FindWindow(NULL, "KernelEx Debug Console");
InitializeCriticalSection(&windows_cs);
if (hwnd == NULL)
return false;
return true;
}
void write_window(const char* msg)
{
EnterCriticalSection(&windows_cs);
strcpy(shbuf, msg);
int i = strlen(shbuf);
if (i > 0) shbuf[i-1] = 0;
SendMessage(hwnd, WM_KEXAPPENDLOG, 0, (LPARAM) shbuf);
LeaveCriticalSection(&windows_cs);
}
bool init_debug()
{
return true;
}
void write_debug(const char* msg)
{
OutputDebugString(msg);
}
bool init_writer()
{
char output[100];
output[0] = 0;
if (GetEnvironmentVariable("KEXAPILOG_OUTPUT", output, sizeof(output)))
{
if (!strcmp(output, "file"))
{
init_fn = init_file;
writer_fn = write_file;
}
else if (!strcmp(output, "window"))
{
init_fn = init_window;
writer_fn = write_window;
}
else if (!strcmp(output, "debug"))
{
init_fn = init_debug;
writer_fn = write_debug;
}
}
//default fallback
if (!writer_fn)
{
init_fn = init_file;
writer_fn = write_file;
}
return init_fn();
}

32
ApiHook/ApiLog/writer.h Executable file
View File

@ -0,0 +1,32 @@
/*
* KernelEx
* Copyright (C) 2011, Xeno86
*
* This file is part of KernelEx source code.
*
* KernelEx is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; version 2 of the License.
*
* KernelEx is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef _APILOG_WRITER_H
#define _APILOG_WRITER_H
#define DEBUGMSG_MAXLEN 256
typedef void (*writerfn_t)(const char* msg);
extern writerfn_t writer_fn;
bool init_writer();
#endif