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

import KernelEx-4.5-Beta1

This commit is contained in:
UzixLS
2018-11-03 16:21:13 +03:00
parent d6aad6c6c5
commit 09929b2b7d
392 changed files with 17832 additions and 2491 deletions

4
core/Core.rc Normal file → Executable file
View File

@ -98,7 +98,7 @@ BEGIN
VALUE "FileDescription", "KernelEx Core\0"
VALUE "FileVersion", _RCVERSION_ "\0"
VALUE "InternalName", "KernelEx\0"
VALUE "LegalCopyright", "Copyright <20> 2009, Xeno86\0"
VALUE "LegalCopyright", "Copyright <20> 2009-2010, Xeno86\0"
VALUE "OriginalFilename", "KernelEx.dll\0"
VALUE "ProductName", "KernelEx\0"
VALUE "ProductVersion", VERSION_STR "\0"
@ -151,6 +151,8 @@ IDR_LOGMENU MENU DISCARDABLE
BEGIN
POPUP ""
BEGIN
MENUITEM "Enabled", IDM_ENABLE, CHECKED
MENUITEM SEPARATOR
MENUITEM "Save to file", IDM_TOFILE
MENUITEM "Clear", IDM_CLEAR
MENUITEM "Filter", IDM_FILTER

50
core/DebugWindow.cpp Normal file → Executable file
View File

@ -27,6 +27,8 @@
#include "internals.h"
#include "debug.h"
extern bool apilog_enabled;
const unsigned short WM_KEXSTOPDEBUG = 0x6eee;
const unsigned short WM_KEXAPPENDLOG = 0x6eef;
@ -39,6 +41,8 @@ char* strtok_r(char* s, const char* delim, char** holder);
DebugWindow::DebugWindow()
{
DWORD tid;
DBGPRINTF(("Creating DebugWindow\n"));
hwnd = (HWND) -1;
//we're interested in everything
@ -50,12 +54,14 @@ DebugWindow::DebugWindow()
excludes.push_back("Interlocked");
InitializeCriticalSection(&cs);
InitCommonControls();
MakeCriticalSectionGlobal(&cs);
LoadLibrary("COMCTL32.DLL");
hThread = CreateThread(NULL, 0, thread, (void*) this, 0, &tid);
}
DebugWindow::~DebugWindow()
{
DBGPRINTF(("Destroying DebugWindow\n"));
DeleteCriticalSection(&cs);
SendMessage(hwnd, WM_KEXSTOPDEBUG, 0, 0);
}
@ -118,30 +124,25 @@ void DebugWindow::InitDialog(HWND hwnd)
LV_COLUMN col;
memset(&col, 0, sizeof(col));
col.mask = LVCF_TEXT | LVCF_SUBITEM | LVCF_WIDTH;
col.mask = LVCF_TEXT | LVCF_SUBITEM | LVCF_WIDTH | LVCF_FMT;
col.cx = 20;
col.pszText = "Depth";
col.fmt = LVCFMT_RIGHT;
ListView_InsertColumn(hList, 0, &col);
col.cx = 60;
col.fmt = LVCFMT_LEFT;
col.pszText = "Thread";
ListView_InsertColumn(hList, 1, &col);
col.cx = 90;
col.pszText = "Source";
col.cx = 310;
col.pszText = "Info";
ListView_InsertColumn(hList, 2, &col);
col.cx = 90;
col.pszText = "Dest";
ListView_InsertColumn(hList, 3, &col);
col.cx = 130;
col.pszText = "Function";
ListView_InsertColumn(hList, 4, &col);
col.cx = 60;
col.mask |= LVCF_FMT;
col.fmt = LVCFMT_RIGHT;
col.pszText = "Return";
ListView_InsertColumn(hList, 5, &col);
ListView_InsertColumn(hList, 3, &col);
#define NUM_COLS 6
#define NUM_COLS 4
menu = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_LOGMENU));
menu = GetSubMenu(menu, 0);
@ -156,6 +157,10 @@ void DebugWindow::HandleMenu()
p.x, p.y, 0, hwnd, NULL);
switch (res)
{
case IDM_ENABLE:
apilog_enabled = !apilog_enabled;
CheckMenuItem(menu, IDM_ENABLE, apilog_enabled ? MF_CHECKED : MF_UNCHECKED);
break;
case IDM_TOFILE:
WriteToFile();
break;
@ -316,13 +321,15 @@ void DebugWindow::WriteToFile()
HMODULE hComDlg32;
BOOL (WINAPI* pGetSaveFileName)(OPENFILENAME*);
hComDlg32 = LoadLibrary("COMDLG32.DLL");
hComDlg32 = GetModuleHandle("COMDLG32.DLL");
if (!hComDlg32)
hComDlg32 = LoadLibrary("COMDLG32.DLL");
if (!hComDlg32)
return;
pGetSaveFileName = (BOOL (WINAPI*)(OPENFILENAME*))
GetProcAddress(hComDlg32, "GetSaveFileNameA");
if (!pGetSaveFileName)
goto __fini;
return;
filename[0] = '\0';
memset(&ofn, 0, sizeof(ofn));
@ -335,11 +342,11 @@ void DebugWindow::WriteToFile()
ofn.nMaxFile = sizeof(filename);
ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
if (!pGetSaveFileName(&ofn))
goto __fini;
return;
hFile = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
goto __fini;
return;
//write column headers
col.mask = LVCF_TEXT;
@ -351,7 +358,7 @@ void DebugWindow::WriteToFile()
DWORD len;
ListView_GetColumn(hList, j, &col);
len = strlen(buf);
if (j) WriteFile(hFile, "|", 1, &wlen, NULL);
if (j) WriteFile(hFile, " ", 1, &wlen, NULL);
WriteFile(hFile, buf, len, &wlen, NULL);
}
WriteFile(hFile, "\r\n", 2, &wlen, NULL);
@ -365,7 +372,8 @@ void DebugWindow::WriteToFile()
DWORD len; DWORD wlen;
ListView_GetItemText(hList, i, j, buf, sizeof(buf));
len = strlen(buf);
if (j) WriteFile(hFile, "|", 1, &wlen, NULL);
if (j == 1 || j == 2) WriteFile(hFile, " ", 1, &wlen, NULL);
else if (j == 3 && len) WriteFile(hFile, " = ", 3, &wlen, NULL);
WriteFile(hFile, buf, len, &wlen, NULL);
}
WriteFile(hFile, "\r\n", 2, &wlen, NULL);
@ -374,9 +382,6 @@ void DebugWindow::WriteToFile()
CloseHandle(hFile);
MessageBox(hwnd, "File written successfully", "Information", MB_ICONINFORMATION | MB_OK);
__fini:
FreeLibrary(hComDlg32);
}
DWORD WINAPI DebugWindow::thread(void* param)
@ -468,4 +473,5 @@ void DebugWindow::destroy()
{
if (instance)
delete instance;
instance = NULL;
}

12
core/DebugWindow.h Normal file → Executable file
View File

@ -29,23 +29,23 @@
using namespace std;
class DebugWindow
class DebugWindow
{
public:
DebugWindow();
~DebugWindow();
static bool create();
static void destroy();
static DebugWindow* get();
void append(const char* str);
private:
DebugWindow();
~DebugWindow();
static DebugWindow* instance;
HWND hwnd;
HWND hList;
HANDLE hThread;
int max_entries;
static DebugWindow* instance;
CRITICAL_SECTION cs;
HMENU menu;
list<sstring> includes;

103
core/ModInit.cpp Executable file
View File

@ -0,0 +1,103 @@
/*
* KernelEx
* Copyright (C) 2009, 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 <windows.h>
#include <stdlib.h>
#include <new>
#include "ModInit.h"
#include "ProcessStorage.h"
#include "internals.h"
#include "resolver.h"
#include "debug.h"
static int modinit_index;
bool ModuleInitializer_init()
{
modinit_index = ProcessStorage::allocate();
return modinit_index != -1;
}
ModuleInitializer::ModuleInitializer()
{
size = 0;
init = 0;
memset(data, 0, sizeof(data));
}
void ModuleInitializer::add_module(MODREF* mr)
{
data[size++] = mr;
DBGASSERT(size < countof(data));
}
DWORD ModuleInitializer::get_handle_for_index(WORD idx)
{
IMTE** pmteModTable = *ppmteModTable;
for (int i = 0 ; i < size ; i++)
{
IMTE_KEX* imte = (IMTE_KEX*) pmteModTable[data[i]->mteIndex];
if (imte->mod_index == idx)
return imte->pNTHdr->OptionalHeader.ImageBase;
}
return 0;
}
bool ModuleInitializer::initialize_modules()
{
while (init < size)
{
DBGPRINTF(("Post-Initializing %s [PID=%08x]\n",
(*ppmteModTable)[data[init]->mteIndex]->pszModName,
GetCurrentProcessId()));
init++;
if (FLoadTreeNotify(data[init-1], TRUE))
return false;
}
return true;
}
ModuleInitializer* ModuleInitializer::get_instance(bool alloc)
{
ProcessStorage* store = ProcessStorage::get_instance();
ModuleInitializer* mi = (ModuleInitializer*) store->get(modinit_index);
if (!mi && alloc)
{
mi = (ModuleInitializer*) HeapAlloc(_GetProcessHeap(), 0, sizeof(ModuleInitializer));
DBGASSERT(mi != NULL);
new (mi) ModuleInitializer;
store->set(modinit_index, mi);
}
return mi;
}
void ModuleInitializer::destroy()
{
ProcessStorage* store = ProcessStorage::get_instance();
HeapFree(_GetProcessHeap(), 0, this);
store->set(modinit_index, NULL);
}

54
core/ModInit.h Executable file
View File

@ -0,0 +1,54 @@
/*
* KernelEx
* Copyright (C) 2009, 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 __MODINIT_H
#define __MODINIT_H
#include "structs.h"
bool ModuleInitializer_init();
class ModuleInitializer
{
public:
void add_module(MODREF* mr);
DWORD get_handle_for_index(WORD idx);
bool has_initialize();
bool initialize_modules();
void destroy();
static ModuleInitializer* get_instance(bool alloc);
private:
int size;
int init;
MODREF* data[64];
ModuleInitializer();
~ModuleInitializer();
};
inline bool ModuleInitializer::has_initialize()
{
return init < size;
}
#endif

95
core/ProcessStorage.cpp Executable file
View File

@ -0,0 +1,95 @@
/*
* KernelEx
* Copyright (C) 2009, 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 <windows.h>
#include <new>
#include "ProcessStorage.h"
#include "internals.h"
#include "debug.h"
long ProcessStorage::count;
struct PDB_KEX : PDB98
{
void* kex_storage;
};
ProcessStorage::ProcessStorage()
{
for (int i = 0 ; i < PS_MAX_INDEX ; i++)
data[i] = NULL;
}
ProcessStorage* ProcessStorage::get_instance()
{
PDB_KEX* pdb = (PDB_KEX*) *pppdbCur;
if (!pdb->kex_storage)
return create_instance();
return (ProcessStorage*) pdb->kex_storage;
}
void* ProcessStorage::get(int index)
{
if (index >= 0 && index < PS_MAX_INDEX)
return data[index];
else
return NULL;
}
bool ProcessStorage::set(int index, void* value)
{
if (index >= 0 && index < PS_MAX_INDEX)
data[index] = value;
else
return false;
return true;
}
int ProcessStorage::allocate()
{
if (count >= PS_MAX_INDEX - 1)
return -1;
return InterlockedIncrement(&count);
}
ProcessStorage* ProcessStorage::create_instance()
{
ProcessStorage* ret;
PDB_KEX* pdb = (PDB_KEX*) *pppdbCur;
_EnterSysLevel(krnl32lock);
//double check - we might have been waiting on krnl32lock for create_instance
if (pdb->kex_storage)
{
_LeaveSysLevel(krnl32lock);
return (ProcessStorage*) pdb->kex_storage;
}
pdb->kex_storage = HeapAlloc(_GetProcessHeap(), 0, sizeof(ProcessStorage));
ret = new (pdb->kex_storage) ProcessStorage();
_LeaveSysLevel(krnl32lock);
DBGASSERT(pdb->kex_storage != NULL && ret != NULL);
return ret;
}

26
core/storage.h → core/ProcessStorage.h Normal file → Executable file
View File

@ -19,18 +19,26 @@
*
*/
#ifndef __STORAGE_H
#define __STORAGE_H
#ifndef __PROCESSSTORAGE_H
#define __PROCESSSTORAGE_H
class storage
#define PS_MAX_INDEX 64
class ProcessStorage
{
public:
int size;
void* data[1]; //dummy table
static const int storage_size;
static storage* get_storage(bool alloc);
static void return_storage();
static ProcessStorage* get_instance();
void* get(int index);
bool set(int index, void* value);
static int allocate();
private:
static long count;
void* data[PS_MAX_INDEX];
static ProcessStorage* create_instance();
ProcessStorage();
~ProcessStorage();
};
#endif

11
core/SettingsDB.cpp Normal file → Executable file
View File

@ -66,6 +66,7 @@ void SettingsDB::parse_configs()
HKEY key;
DWORD index = 0;
char path[MAX_PATH];
char epath[MAX_PATH];
DWORD path_len;
char name[256];
DWORD name_len;
@ -98,13 +99,17 @@ void SettingsDB::parse_configs()
if (!as.conf)
continue;
strupr(path);
if (strchr(path, '*') || strchr(path, '?'))
int ret = ExpandEnvironmentStrings(path, epath, MAX_PATH);
if (ret > MAX_PATH || ret == 0)
continue;
strupr(epath);
if (strchr(epath, '*') || strchr(epath, '?'))
pdb = &db_wild;
else
pdb = &db;
pdb->insert(pair<sstring, appsetting>(path, as));
pdb->insert(pair<sstring, appsetting>(epath, as));
}
RegCloseKey(key);
}

12
core/SettingsDB.h Normal file → Executable file
View File

@ -22,23 +22,13 @@
#ifndef __SETTINGSDB_H
#define __SETTINGSDB_H
#ifdef _MSC_VER
#pragma warning(disable:4786)
#endif
#include "sstring.hpp"
#include <map>
#include "resolver.h"
#include "apiconf.h"
using namespace std;
struct appsetting
{
appsetting() : conf(NULL), flags(0) {}
ApiConfiguration* conf;
unsigned long flags;
};
class SettingsDB
{
public:

0
core/apiconf.cpp Normal file → Executable file
View File

0
core/apiconf.h Normal file → Executable file
View File

0
core/apiconfmgr.cpp Normal file → Executable file
View File

0
core/apiconfmgr.h Normal file → Executable file
View File

19
core/apilib.cpp Normal file → Executable file
View File

@ -186,8 +186,7 @@ bool ApiLibraryManager::load_apilib(const char* apilib_name)
// DBGPRINTF((" * %s\n", p->target_library));
if (!add_overridden_module(p->target_library))
{
DBGPRINTF(("Failed to add overridden module %s\n", p->target_library));
goto __error;
DBGPRINTF(("Failed to add overridden module %s. Skipping\n", p->target_library));
}
}
@ -375,6 +374,13 @@ bool ApiLibraryManager::add_overridden_module(const char* mod)
return true;
}
apilib_api_table table;
if (!parse_system_dll(mod, &table))
{
DBGPRINTF(("Failed to parse system DLL: %s\n", mod));
return false;
}
//allocate space for new overridden modules
if (overridden_module_count % ALLOC_CAPACITY == 0)
{
@ -396,11 +402,7 @@ bool ApiLibraryManager::add_overridden_module(const char* mod)
std_api_table = (apilib_api_table*) new_block;
}
if (!parse_system_dll(mod, &std_api_table[overridden_module_count]))
{
DBGPRINTF(("Failed to parse system DLL: %s\n", mod));
return false;
}
std_api_table[overridden_module_count] = table;
//add to table of overridden modules
overridden_module_names[overridden_module_count]
@ -529,7 +531,10 @@ bool ApiLibraryManager::parse_system_dll(const char* dll_name, apilib_api_table*
char* new_mod = (char*) malloc(strlen(dll_name) + 1);
if (!new_mod)
{
free(mem);
return false;
}
strcpy(new_mod, dll_name);
strupr(new_mod);

0
core/apilib.h Normal file → Executable file
View File

181
core/apilog.cpp Normal file → Executable file
View File

@ -21,48 +21,16 @@
#include <new>
#include <windows.h>
#include <stdio.h>
#include "apilog.h"
#include "debug.h"
#include "internals.h"
#include "DebugWindow.h"
#include "ProcessStorage.h"
#define APILOG_TLS_INDEX 78
void* get_process_env_data(const char* env, void* (*creator)())
{
//environment variable: ENV=ProcessID:DATA
char buf[20];
DWORD ret;
DWORD ProcID;
void* data = NULL;
ret = GetEnvironmentVariable(env, buf, sizeof(buf));
if (ret == 0 || ret > sizeof(buf)
|| sscanf(buf, "%x:%x", &ProcID, &data) != 2
|| ProcID != GetCurrentProcessId())
{
//invalid/missing value - create new data
data = creator();
if (data)
{
sprintf(buf, "%x:%x", GetCurrentProcessId(), data);
SetEnvironmentVariable(env, buf);
}
}
return data;
}
void* heap_creator()
{
return HeapCreate(0, 0, 0);
}
HANDLE get_process_debug_heap()
{
return get_process_env_data("KEXDBGH", heap_creator);
}
static int apilog_ps_index = -1;
bool apilog_enabled = true;
void* tls_creator()
{
@ -73,43 +41,20 @@ void* tls_creator()
return (void*) APILOG_TLS_INDEX;
}
DWORD get_process_debug_tls()
void get_process_debug_tls()
{
return (DWORD) get_process_env_data("KEXDBGT", tls_creator);
ProcessStorage* ps = ProcessStorage::get_instance();
if (apilog_ps_index == -1)
apilog_ps_index = ps->allocate();
if (APILOG_TLS_INDEX != (DWORD) ps->get(apilog_ps_index))
{
ps->set(apilog_ps_index, tls_creator());
}
}
extern "C"
int snprintf(char *buffer, size_t n, const char* format, ...);
DWORD __stdcall log_api(const char* source, const char* target, const char* api_name, DWORD depth, DWORD ret)
{
DebugWindow* dw = DebugWindow::get();
if (!dw)
return 0;
char msg[DEBUGMSG_MAXLEN];
//fancy call stack depth indicator
if (depth < DEBUGMSG_MAXLEN / 2)
{
for (int i = 0 ; i < depth ; i++)
msg[i] = 'l';
}
else
{
msg[0] = 'E';
msg[1] = 'E';
depth = 2;
}
snprintf(msg + depth, sizeof(msg) - depth, "|%x|%s|%s|%s|%x",
GetCurrentThreadId(), source, target, api_name, ret);
dw->append(msg);
return ret;
}
ThreadAddrStack::ThreadAddrStack()
{
pos = 0;
@ -117,49 +62,121 @@ ThreadAddrStack::ThreadAddrStack()
void __stdcall ThreadAddrStack::push_ret_addr(DWORD addr)
{
//TlsGetValue clears last error value so remember & restore it
DWORD lasterr = GetLastError();
ThreadAddrStack* tas = (ThreadAddrStack*) TlsGetValue(APILOG_TLS_INDEX);
SetLastError(lasterr);
if (!tas)
{
void* mem = HeapAlloc(get_process_debug_heap(), 0, sizeof(ThreadAddrStack));
void* mem = HeapAlloc(_GetProcessHeap(), 0, sizeof(ThreadAddrStack));
tas = new (mem) ThreadAddrStack;
TlsSetValue(APILOG_TLS_INDEX, mem);
}
tas->stack[tas->pos++] = addr;
DBGASSERT(tas->pos < sizeof(tas->stack) / sizeof(tas->stack[0]));
DBGASSERT(tas->pos < countof(tas->stack));
}
DWORD __stdcall ThreadAddrStack::pop_ret_addr()
{
//TlsGetValue clears last error value so remember & restore it
DWORD lasterr = GetLastError();
ThreadAddrStack* tas = (ThreadAddrStack*) TlsGetValue(APILOG_TLS_INDEX);
SetLastError(lasterr);
DBGASSERT(tas->pos > 0);
return tas->stack[--tas->pos];
}
DWORD __stdcall ThreadAddrStack::get_level()
{
//TlsGetValue clears last error value so remember & restore it
DWORD lasterr = GetLastError();
ThreadAddrStack* tas = (ThreadAddrStack*) TlsGetValue(APILOG_TLS_INDEX);
SetLastError(lasterr);
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*) &lgd + 9);
last_err = GetLastError();
ThreadAddrStack::push_ret_addr(caller_addr);
DebugWindow* dw = DebugWindow::get();
if (dw && apilog_enabled)
{
DWORD level;
char msg[DEBUGMSG_MAXLEN];
level = ThreadAddrStack::get_level();
snprintf(msg, sizeof(msg), "%-2d|%x|%*s[%s]%08x:<%s>%s",
level,
GetCurrentThreadId(),
(level-1) * 2, "",
lgd->source, caller_addr,
lgd->target, lgd->api_name);
dw->append(msg);
}
SetLastError(last_err);
}
void __stdcall log_stub::post_log(log_data* lgd, DWORD retval)
{
DWORD last_err;
DWORD& caller_addr = *((DWORD*) &retval + 9);
last_err = GetLastError();
caller_addr = ThreadAddrStack::pop_ret_addr();
DebugWindow* dw = DebugWindow::get();
if (dw && apilog_enabled)
{
DWORD level;
char msg[DEBUGMSG_MAXLEN];
level = ThreadAddrStack::get_level();
snprintf(msg, sizeof(msg), "%-2d|%x|%*s[%s]%08x:<%s>%s|%x",
level,
GetCurrentThreadId(),
(level-1) * 2, "",
lgd->source, caller_addr,
lgd->target, lgd->api_name,
retval);
dw->append(msg);
}
SetLastError(last_err);
}
PROC create_log_stub(const char* caller, const char* target, const char* api, PROC orig)
{
HANDLE heap = get_process_debug_heap();
char* new_api = (char*) HeapAlloc(heap, 0, strlen(api) + 1);
char* new_api = (char*) HeapAlloc(_GetProcessHeap(), 0, strlen(api) + 1);
strcpy(new_api, api);
get_process_debug_tls();
void* mem = HeapAlloc(heap, 0, sizeof(log_stub));
void* mem = HeapAlloc(_GetProcessHeap(), 0, sizeof(log_stub));
return (PROC) new (mem) log_stub(caller,
target, new_api, (unsigned long) orig,
(unsigned long) log_api);
target, new_api, (unsigned long) orig);
}
PROC create_log_stub(const char* caller, const char* target, WORD ord, PROC orig)

81
core/apilog.h Normal file → Executable file
View File

@ -45,41 +45,58 @@ class log_stub
{
public:
log_stub(const char* source, const char* target, const char* name,
unsigned long proc, unsigned long log_fun)
: call_orig(proc, true), jmp_logfun(log_fun),
tas_store((unsigned long) ThreadAddrStack::push_ret_addr, true),
tas_restore((unsigned long) ThreadAddrStack::pop_ret_addr, true),
tas_depth((unsigned long) ThreadAddrStack::get_level, true)
{
c_push2 = c_push3 = c_push4 = 0x68;
v_source = source;
v_target = target;
v_name = name;
c_pusheax1 = c_pusheax2 = c_pusheax3 = c_pusheax4 = 0x50;
c_popeax4 = 0x58;
c_pushecx = 0x51;
c_popecx = 0x59;
}
unsigned long proc);
private:
unsigned char c_popeax4; //caller ret
unsigned char c_pushecx;
unsigned char c_pusheax4; //caller ret
redir_stub tas_store;
unsigned char c_popecx;
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;
unsigned char c_pusheax1; //orig ret
redir_stub tas_depth;
unsigned char c_pusheax3; //call stack depth
unsigned char c_push2; //api name
const char* v_name;
unsigned char c_push3; //target module
const char* v_target;
unsigned char c_push4; //calling module
const char* v_source;
redir_stub tas_restore;
unsigned char c_pusheax2; //caller return address
redir_stub jmp_logfun; //jump to log_fun
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)

0
core/core.def Normal file → Executable file
View File

28
core/core.dsp Normal file → Executable file
View File

@ -43,7 +43,7 @@ RSC=rc.exe
# 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 "KERNELEX_EXPORTS" /YX /FD /c
# ADD CPP /nologo /W3 /O2 /I "." /I "../common" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "KEXCORE_EXPORTS" /YX /FD /GF /c
# ADD CPP /nologo /W3 /O2 /I "." /I "../common" /FI"msvc_quirks.h" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "KEXCORE_EXPORTS" /YX /FD /GF /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x415 /d "NDEBUG"
@ -70,7 +70,7 @@ LINK32=link.exe
# 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 "KERNELEX_EXPORTS" /YX /FD /GZ /c
# ADD CPP /nologo /ML /W3 /Gm /Zi /Od /I "." /I "../common" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "KEXCORE_EXPORTS" /YX /FD /GZ /GF /c
# ADD CPP /nologo /ML /W3 /Gm /Zi /Od /I "." /I "../common" /FI"msvc_quirks.h" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "KEXCORE_EXPORTS" /YX /FD /GZ /GF /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x415 /d "_DEBUG"
@ -209,10 +209,18 @@ SOURCE=.\main.cpp
# End Source File
# Begin Source File
SOURCE=.\ModInit.cpp
# End Source File
# Begin Source File
SOURCE=..\common\pemanip.cpp
# End Source File
# Begin Source File
SOURCE=.\ProcessStorage.cpp
# End Source File
# Begin Source File
SOURCE=.\resolver.cpp
# End Source File
# Begin Source File
@ -225,10 +233,6 @@ SOURCE=.\sharedmem.cpp
# End Source File
# Begin Source File
SOURCE=.\storage.cpp
# End Source File
# Begin Source File
SOURCE=.\thunks.cpp
# End Source File
# Begin Source File
@ -290,10 +294,18 @@ SOURCE=..\common\kexcoresdk.h
# End Source File
# Begin Source File
SOURCE=.\ModInit.h
# End Source File
# Begin Source File
SOURCE=..\common\pemanip.h
# End Source File
# Begin Source File
SOURCE=.\ProcessStorage.h
# End Source File
# Begin Source File
SOURCE=.\resolver.h
# End Source File
# Begin Source File
@ -310,10 +322,6 @@ SOURCE=..\common\sstring.hpp
# End Source File
# Begin Source File
SOURCE=.\storage.h
# End Source File
# Begin Source File
SOURCE=.\structs.h
# End Source File
# Begin Source File

0
core/core.ini Normal file → Executable file
View File

0
core/debug.cpp Normal file → Executable file
View File

2
core/debug.h Normal file → Executable file
View File

@ -47,6 +47,4 @@
void dbgvprintf(const char* format, void* _argp);
void dbgprintf(const char* format, ...);
#include "apilog.h"
#endif

0
core/debugproto.cpp Normal file → Executable file
View File

0
core/debugproto.h Normal file → Executable file
View File

142
core/internals.cpp Normal file → Executable file
View File

@ -25,6 +25,13 @@
#include "resolver.h"
#include "debug.h"
#include "pemanip.h"
#include "ModInit.h"
#ifdef _DEBUG
#define _D(x) x
#else
#define _D(x) NULL
#endif
static bool is_winme;
HINSTANCE hInstance;
@ -39,7 +46,6 @@ MRFromHLib_t MRFromHLib = NULL;
TIDtoTDB_t TIDtoTDB = NULL;
MRLoadTree_t MRLoadTree = NULL;
FreeLibTree_t FreeLibTree = NULL;
FLoadTreeNotify_t FLoadTreeNotify = NULL;
FreeLibRemove_t FreeLibRemove = NULL;
AllocHandle_t AllocHandle = NULL;
@ -59,7 +65,7 @@ void ShowError(UINT id, ...)
va_start(vargs, id);
if (!LoadString(hInstance, id, format, sizeof(format)))
sprintf(out, "ERROR: Missing string resource %d", id);
sprintf(out, "ERROR: %d [Missing error description]", id);
else
_vsnprintf(out, sizeof(out), format, vargs);
va_end(vargs);
@ -181,14 +187,32 @@ HANDLE _OpenThread(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId)
return ret;
}
HANDLE _GetProcessHeap()
{
HANDLE hp = GetProcessHeap();
if (!hp)
{
PDB98* pdb = *pppdbCur;
IMAGE_NT_HEADERS* nth = (*ppmteModTable)[pdb->pExeMODREF->mteIndex]->pNTHdr;
//create new default heap
hp = pdb->DefaultHeap = HeapCreate(0, nth->OptionalHeader.SizeOfHeapCommit, 0);
//this will prevent the system from creating another default heap
nth->OptionalHeader.SizeOfHeapReserve = 0;
}
DBGASSERT(hp != NULL);
return hp;
}
/* find win32 mutex */
static CRITICAL_SECTION* find_krnl32lock()
{
CRITICAL_SECTION* ret;
static const char* pat_name = _D("Win32 lock");
static const short pat[] = {0x55,0xA1,-2,-2,-2,-2,0x8B,0xEC,0x56,0x57,0x33,0xF6,0x50,0xE8};
static const int pat_len = sizeof(pat) / sizeof(short);
const char* pat_name = "Win32 lock";
short pat[] = {0x55,0xA1,-2,-2,-2,-2,0x8B,0xEC,0x56,0x57,0x33,0xF6,0x50,0xE8};
int pat_len = sizeof(pat) / sizeof(short);
CRITICAL_SECTION* ret;
DWORD* res = find_unique_pattern((void*) iGetProcAddress(h_kernel32, "VirtualQueryEx"), pat_len, pat, pat_len, pat_name);
if (!res)
@ -202,11 +226,11 @@ static CRITICAL_SECTION* find_krnl32lock()
/* find current process PDB */
static PDB98** find_curPDB()
{
PDB98** ret;
static const char* pat_name = _D("pppdbCur");
static const short pat[] = {0xA1,-2,-2,-2,-2,0xFF,0x30,0xE8,-1,-1,-1,-1,0xC3};
static const int pat_len = sizeof(pat) / sizeof(short);
const char* pat_name = "pppdbCur";
short pat[] = {0xA1,-2,-2,-2,-2,0xFF,0x30,0xE8,-1,-1,-1,-1,0xC3};
int pat_len = sizeof(pat) / sizeof(short);
PDB98** ret;
DWORD* res = find_unique_pattern((void*) iGetProcAddress(h_kernel32, "GetCurrentProcessId"), pat_len, pat, pat_len, pat_name);
if (!res)
@ -220,12 +244,12 @@ static PDB98** find_curPDB()
/* find global module tables */
static IMTE*** find_mod_table()
{
static const char* pat_name = _D("Module table");
static const short pat[] = {0x8B,0x0D,-2,-2,-2,-2};
static const int pat_len = sizeof(pat) / sizeof(short);
IMTE*** ret;
const char* pat_name = "Module table";
short pat[] = {0x8B,0x0D,-2,-2,-2,-2};
int pat_len = sizeof(pat) / sizeof(short);
DWORD* res = find_unique_pattern((void*) iGetProcAddress(h_kernel32, (LPSTR)23), 0x20, pat, pat_len, pat_name);
ret = (IMTE***)*res;
@ -235,11 +259,11 @@ static IMTE*** find_mod_table()
static MRFromHLib_t find_MRFromHLib()
{
MRFromHLib_t ret;
static const char* pat_name = _D("MRFromHLib");
static const short pat[] = {0xE8,-2,-2,-2,-2};
static const int pat_len = sizeof(pat) / sizeof(short);
const char* pat_name = "MRFromHLib";
short pat[] = {0xE8,-2,-2,-2,-2};
int pat_len = sizeof(pat) / sizeof(short);
MRFromHLib_t ret;
DWORD* res = find_unique_pattern((void*) iGetProcAddress(h_kernel32, (LPSTR)23), 0x20, pat, pat_len, pat_name);
if (!res)
@ -252,16 +276,16 @@ static MRFromHLib_t find_MRFromHLib()
static WORD* find_pimteMax()
{
static const char* pat_name = _D("pimteMax");
static const short pat[] = {0x66,0x8B,0x44,0x24,0x04,0x66,-1,0x05,-2,-2,-2,-2,-1,0x17,0x8B,0x0D,-1,-1,-1,-1,0x0F,0xBF,0xC0,0x8B,0x04,0x81,0x85,0xC0,0x74,0x07,0x8B,0x40,0x04,0x85,0xC0,0x75,0x09};
static const int pat_len = sizeof(pat) / sizeof(short);
static const char* sec_name = ".text";
WORD* ret;
PEmanip pe(h_kernel32);
if (!pe.HasTarget())
return NULL;
const char* pat_name = "pimteMax";
short pat[] = {0x66,0x8B,0x44,0x24,0x04,0x66,-1,0x05,-2,-2,-2,-2,-1,0x17,0x8B,0x0D,-1,-1,-1,-1,0x0F,0xBF,0xC0,0x8B,0x04,0x81,0x85,0xC0,0x74,0x07,0x8B,0x40,0x04,0x85,0xC0,0x75,0x09};
int pat_len = sizeof(pat) / sizeof(short);
const char* sec_name = ".text";
DWORD* res = find_unique_pattern(pe.GetSectionByName(sec_name), pe.GetSectionSize(sec_name), pat, pat_len, pat_name);
if (!res)
return NULL;
@ -273,16 +297,16 @@ static WORD* find_pimteMax()
static TIDtoTDB_t find_TIDtoTDB()
{
static const char* pat_name = _D("TIDtoTDB");
static const short pat[] = {0x89,-1,0xFF,0x75,0xFC,0xFF,0x77,0x14,0xE8,-2,-2,-2,-2,0x50};
static const int pat_len = sizeof(pat) / sizeof(short);
static const char* sec_name = ".text";
TIDtoTDB_t ret;
PEmanip pe(h_kernel32);
if (!pe.HasTarget())
return NULL;
const char* pat_name = "TIDtoTDB";
short pat[] = {0x89,-1,0xFF,0x75,0xFC,0xFF,0x77,0x14,0xE8,-2,-2,-2,-2,0x50};
int pat_len = sizeof(pat) / sizeof(short);
const char* sec_name = ".text";
DWORD* res = find_unique_pattern(pe.GetSectionByName(sec_name), pe.GetSectionSize(sec_name), pat, pat_len, pat_name);
if (!res)
return NULL;
@ -294,16 +318,16 @@ static TIDtoTDB_t find_TIDtoTDB()
static MRLoadTree_t find_MRLoadTree()
{
static const char* pat_name = _D("MRLoadTree");
static const short pat[] = {0x33,0xF6,0xE8,-1,-1,-1,-1,0x39,0x35,-1,-1,-1,-1,0x74,0x11,0xA1,-1,-1,-1,-1,0x50,0xE8,-1,-1,-1,-1,0x89,0x35,-1,-1,-1,-1,0xFF,0x74,0x24,0x14,0xE8,-2,-2,-2,-2,0x8B,0xF0,0x85,0xF6};
static const int pat_len = sizeof(pat) / sizeof(short);
static const char* sec_name = ".text";
MRLoadTree_t ret;
PEmanip pe(h_kernel32);
if (!pe.HasTarget())
return NULL;
const char* pat_name = "MRLoadTree";
short pat[] = {0x33,0xF6,0xE8,-1,-1,-1,-1,0x39,0x35,-1,-1,-1,-1,0x74,0x11,0xA1,-1,-1,-1,-1,0x50,0xE8,-1,-1,-1,-1,0x89,0x35,-1,-1,-1,-1,0xFF,0x74,0x24,0x14,0xE8,-2,-2,-2,-2,0x8B,0xF0,0x85,0xF6};
int pat_len = sizeof(pat) / sizeof(short);
const char* sec_name = ".text";
DWORD* res = find_unique_pattern(pe.GetSectionByName(sec_name), pe.GetSectionSize(sec_name), pat, pat_len, pat_name);
if (!res)
return NULL;
@ -315,11 +339,11 @@ static MRLoadTree_t find_MRLoadTree()
static FreeLibTree_t find_FreeLibTree()
{
FreeLibTree_t ret;
static const char* pat_name = _D("FreeLibTree");
static const short pat[] = {0x75,0x09,0x6A,0x06,0xE8,-1,-1,-1,-1,0xEB,0x08,0x50,0xE8,-2,-2,-2,-2,0x8B,0xF0};
static const int pat_len = sizeof(pat) / sizeof(short);
const char* pat_name = "FreeLibTree";
short pat[] = {0x75,0x09,0x6A,0x06,0xE8,-1,-1,-1,-1,0xEB,0x08,0x50,0xE8,-2,-2,-2,-2,0x8B,0xF0};
int pat_len = sizeof(pat) / sizeof(short);
FreeLibTree_t ret;
DWORD* res = find_unique_pattern((void*) iGetProcAddress(h_kernel32, "FreeLibrary"), 0x80, pat, pat_len, pat_name);
if (!res)
@ -330,39 +354,18 @@ static FreeLibTree_t find_FreeLibTree()
return ret;
}
static FLoadTreeNotify_t find_FLoadTreeNotify()
{
FLoadTreeNotify_t ret;
PEmanip pe(h_kernel32);
if (!pe.HasTarget())
return NULL;
const char* pat_name = "FLoadTreeNotify";
short pat[] = {0x56,0xA1,-1,-1,-1,-1,0x6A,0x01,0x8B,0x08,0xFF,0xB1,0x98,0x00,0x00,0x00,0xE8,-2,-2,-2,-2,0x83,0xF8,0x01,0x1B,0xF6,0xF7,0xDE,0x85,0xF6};
int pat_len = sizeof(pat) / sizeof(short);
const char* sec_name = ".text";
DWORD* res = find_unique_pattern(pe.GetSectionByName(sec_name), pe.GetSectionSize(sec_name), pat, pat_len, pat_name);
if (!res)
return NULL;
ret = (FLoadTreeNotify_t)decode_calljmp(res);
DBGPRINTF(("%s @ 0x%08x\n", pat_name, ret));
return ret;
}
static FreeLibRemove_t find_FreeLibRemove()
{
static const char* pat_name = _D("FreeLibRemove");
static const short pat[] = {0x8B,0xF0,0x85,0xF6,0x75,0x05,0xE8,-2,-2,-2,-2,0xA1,-1,-1,-1,-1,0x50};
static const int pat_len = sizeof(pat) / sizeof(short);
static const char* sec_name = ".text";
FreeLibRemove_t ret;
PEmanip pe(h_kernel32);
if (!pe.HasTarget())
return NULL;
const char* pat_name = "FreeLibRemove";
short pat[] = {0x8B,0xF0,0x85,0xF6,0x75,0x05,0xE8,-2,-2,-2,-2,0xA1,-1,-1,-1,-1,0x50};
int pat_len = sizeof(pat) / sizeof(short);
const char* sec_name = ".text";
DWORD* res = find_unique_pattern(pe.GetSectionByName(sec_name), pe.GetSectionSize(sec_name), pat, pat_len, pat_name);
if (!res)
return NULL;
@ -374,11 +377,11 @@ static FreeLibRemove_t find_FreeLibRemove()
static AllocHandle_t find_AllocHandle()
{
AllocHandle_t ret;
static const char* pat_name = _D("AllocHandle");
static const short pat[] = {0x83,0xD1,0xFF,0x81,0xE2,0xFF,0x0F,0x1F,0x00,0x81,0xE1,0x00,0x00,0x00,0x80,0x0B,0xCA,0x8B,0x15,-1,-1,-1,-1,0x51,0x50,0xFF,0x32,0xE8,-2,-2,-2,-2};
static const int pat_len = sizeof(pat) / sizeof(short);
const char* pat_name = "AllocHandle";
short pat[] = {0x83,0xD1,0xFF,0x81,0xE2,0xFF,0x0F,0x1F,0x00,0x81,0xE1,0x00,0x00,0x00,0x80,0x0B,0xCA,0x8B,0x15,-1,-1,-1,-1,0x51,0x50,0xFF,0x32,0xE8,-2,-2,-2,-2};
int pat_len = sizeof(pat) / sizeof(short);
AllocHandle_t ret;
DWORD* res = find_unique_pattern((void*) iGetProcAddress(h_kernel32, "OpenProcess"), 0x80, pat, pat_len, pat_name);
if (!res)
@ -445,15 +448,16 @@ int internals_init()
TIDtoTDB = find_TIDtoTDB();
MRLoadTree = find_MRLoadTree();
FreeLibTree = find_FreeLibTree();
FLoadTreeNotify = find_FLoadTreeNotify();
FreeLibRemove = find_FreeLibRemove();
AllocHandle = find_AllocHandle();
bool instdir_rslt = find_kernelex_install_dir();
is_winme = (GetVersion() == 0xc0005a04);
bool modinit_rslt = ModuleInitializer_init();
if (!h_kernel32 || !ppmteModTable || !krnl32lock || !pppdbCur || !MRFromHLib
|| !pimteMax || !TIDtoTDB || !MRLoadTree || !FreeLibTree
|| !FLoadTreeNotify || !FreeLibRemove || !AllocHandle || !instdir_rslt)
|| !FreeLibRemove || !AllocHandle || !instdir_rslt
|| !modinit_rslt)
return 0;
return 1;
}

8
core/internals.h Normal file → Executable file
View File

@ -28,12 +28,7 @@
#include "resource.h"
#include "k32ord.h"
/** MSVC 6.0 for-loop workaround. */
#ifdef _MSC_VER
#if _MSC_VER < 1201
#define for if (0); else for
#endif
#endif
#define countof(x) (sizeof(x)/sizeof(x[0]))
#define IS_SHARED(x) (((DWORD)x) >= 0x80000000)
@ -75,5 +70,6 @@ extern AllocHandle_t AllocHandle;
MODREF* MRfromCallerAddr(DWORD addr);
HANDLE _OpenThread(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId);
HANDLE _GetProcessHeap();
#endif

48
core/kexcoresdk.cpp Normal file → Executable file
View File

@ -27,6 +27,8 @@
#include "internals.h"
#include "SettingsDB.h"
#include "debug.h"
#undef MAKE_PS_TAG
#include "ProcessStorage.h"
unsigned long kexGetKEXVersion()
{
@ -73,24 +75,60 @@ BOOL kexAreExtensionsEnabled()
}
void kexGetModuleSettings(const char* module,
char* conf_name, BYTE* ldr_flags)
char* conf_name, DWORD* mod_flags)
{
appsetting as = SettingsDB::instance.get_appsetting(module);
if (!as.conf)
{
conf_name[0] = '\0';
}
else
{
strncpy(conf_name, as.conf->get_name(), 256);
*ldr_flags = as.flags;
conf_name[255] = '\0';
conf_name[255] = '\0';
}
DWORD flags = 0;
if (as.flags & LDR_KEX_DISABLE) flags |= KRF_KEX_DISABLE;
if (as.flags & LDR_OVERRIDE_PROC_MOD) flags |= KRF_OVERRIDE_PROC_MOD;
if (as.flags & LDR_LOG_APIS) flags |= KRF_LOG_APIS;
if (as.flags & LDR_NO_INHERIT) flags |= KRF_NO_INHERIT;
if (as.flags & LDR_VALID_FLAG) flags |= KRF_VALID_FLAG;
*mod_flags = flags;
}
void kexSetModuleSettings(const char* module,
const char* conf_name, BYTE ldr_flags)
const char* conf_name, DWORD mod_flags)
{
SettingsDB::instance.write_single(module, conf_name, ldr_flags);
BYTE flags = 0;
if (mod_flags & KRF_KEX_DISABLE) flags |= LDR_KEX_DISABLE;
if (mod_flags & KRF_OVERRIDE_PROC_MOD) flags |= LDR_OVERRIDE_PROC_MOD;
if (mod_flags & KRF_LOG_APIS) flags |= LDR_LOG_APIS;
if (mod_flags & KRF_NO_INHERIT) flags |= LDR_NO_INHERIT;
SettingsDB::instance.write_single(module, conf_name, flags);
}
void kexFlushAppSettings(void)
{
SettingsDB::instance.flush_all();
}
int kexPsAllocIndex(void)
{
return ProcessStorage::allocate();
}
void* kexPsGetValue(int index)
{
return ProcessStorage::get_instance()->get(index);
}
int kexPsSetValue(int index, void* value)
{
return ProcessStorage::get_instance()->set(index, value);
}
void* kexGetK32Lock()
{
return krnl32lock;
}

0
core/main.cpp Normal file → Executable file
View File

337
core/resolver.cpp Normal file → Executable file
View File

@ -29,7 +29,10 @@
#include "../setup/loadstub.h"
#include "thunks.h"
#include "SettingsDB.h"
#include "storage.h"
#include "ModInit.h"
#ifdef _DEBUG
#include "apilog.h"
#endif
using namespace std;
@ -40,6 +43,8 @@ static PLONG jtab;
static LONG old_jtab[JTAB_SIZE];
static HKEY known_dlls_key;
FLoadTreeNotify_t FLoadTreeNotify;
/** Get API configuration for selected module.
* @param module Target module.
@ -50,86 +55,102 @@ static bool get_config(MODREF* moduleMR, config_params& cp)
{
IMTE** pmteModTable = *ppmteModTable;
PDB98* ppdbCur = *pppdbCur;
IMTE_KEX* module = (IMTE_KEX*) pmteModTable[moduleMR->mteIndex];
IMTE_KEX* process = (IMTE_KEX*) pmteModTable[ppdbCur->pExeMODREF->mteIndex];
ApiConfiguration* conf;
BYTE flags;
volatile MODREF_KEX module(moduleMR);
MODREF_KEX process(ppdbCur->pExeMODREF);
//shared modules should use standard api
if (IS_SHARED(module->baseAddress))
if (IS_SHARED(pmteModTable[module.mr.mteIndex]->baseAddress))
return false;
//unless override flag is set try to get module configuration first
if (!(process->flags & LDR_OVERRIDE_PROC_MOD))
{
if (!(module->flags & LDR_VALID_FLAG))
{
appsetting as = SettingsDB::instance.get_appsetting(module->pszFileName);
module->config = as.conf;
module->flags = as.flags;
}
conf = module->config;
flags = module->flags;
//if settings are already known, exit immediatelly
if (module.as.flags & LDR_VALID_FLAG)
goto __end;
if (flags & LDR_KEX_DISABLE)
return false;
//we need process settings to know if process.LDR_OVERRIDE_PROC_MOD is set
if (!(process.as.flags & LDR_VALID_FLAG))
{
//try to take settings from database...
pmteModTable = *ppmteModTable;
process.as = SettingsDB::instance
.get_appsetting(pmteModTable[process.mr.mteIndex]->pszFileName);
//...if settings are not there, take them from parent process...
if (!(process.as.flags & LDR_VALID_FLAG))
{
PDB98* ppdbParent = ppdbCur->ParentPDB;
//...IF there is parent process and...
if (ppdbParent && !(ppdbParent->Flags & (fTerminated | fTerminating |
fNearlyTerminating | fDosProcess | fWin16Process)))
{
MODREF_KEX parent(ppdbParent->pExeMODREF);
//...unless parent disallows us to inherit them
if ((parent.as.flags & LDR_VALID_FLAG) && !(parent.as.flags & LDR_NO_INHERIT))
{
process.as = parent.as;
#ifdef _DEBUG //don't inherit log flag
process.as.flags &= ~LDR_LOG_APIS;
#endif
}
}
}
}
//at this point we know whether override is enabled or not
if ((process.as.flags & LDR_VALID_FLAG))
{
//if it is then take process settings
if (process.as.flags & LDR_OVERRIDE_PROC_MOD)
{
module.as = process.as;
goto __end;
}
}
//if process still doesn't have settings, set some reasonable defaults
else
conf = NULL;
//if above failed or override flag was set try to get process configuration
if (!conf)
{
if (!(process->flags & LDR_VALID_FLAG))
{
appsetting as = SettingsDB::instance.get_appsetting(process->pszFileName);
process->config = as.conf;
process->flags = as.flags;
}
conf = process->config;
flags = process->flags;
if (flags & LDR_KEX_DISABLE)
return false;
}
//if no process configuration then get parent configuration
if (!conf)
{
PDB98* ppdbParent = ppdbCur->ParentPDB;
if (ppdbParent && !(ppdbParent->Flags & (fTerminated | fTerminating |
fNearlyTerminating | fDosProcess | fWin16Process)))
{
pmteModTable = *ppmteModTable;
IMTE_KEX* parent = (IMTE_KEX*) pmteModTable[ppdbParent->pExeMODREF->mteIndex];
conf = parent->config;
flags = parent->flags;
flags &= ~LDR_LOG_APIS; //don't inherit LOG flag
if (flags & LDR_KEX_DISABLE)
return false;
}
}
if (flags & LDR_FILTER_APIS)
{
//TODO: not implemented yet
DBGPRINTF(("Resolver flag LDR_FILTER_APIS not implemented\n"));
}
//finally if everything else fails take default configuration
if (!conf)
{
if (apiconfmgr.are_extensions_disabled())
return false;
conf = apiconfmgr.get_default_configuration();
{
process.as.flags = LDR_VALID_FLAG | LDR_KEX_DISABLE;
}
else
{
process.as.conf = apiconfmgr.get_default_configuration();
process.as.flags = LDR_VALID_FLAG;
}
}
DBGASSERT(conf != NULL);
cp.apiconf = conf;
//if module == process then we've already got everything we need
if (&module.as == &process.as)
goto __end;
//lookup module settings in database
pmteModTable = *ppmteModTable;
module.as = SettingsDB::instance
.get_appsetting(pmteModTable[module.mr.mteIndex]->pszFileName);
if (module.as.flags & LDR_VALID_FLAG)
{
#ifdef _DEBUG //copy log flag from process to module
if (process.as.flags & LDR_LOG_APIS)
module.as.flags |= LDR_LOG_APIS;
#endif
goto __end;
}
//if module has no settings, take them from process
module.as = process.as;
__end:
DBGASSERT(module.as.flags & LDR_VALID_FLAG);
if (module.as.flags & LDR_KEX_DISABLE)
return false;
DBGASSERT(module.as.conf != NULL);
cp.apiconf = module.as.conf;
#ifdef _DEBUG
cp.log_apis = (process->flags & LDR_LOG_APIS) != 0;
cp.log_apis = (module.as.flags & LDR_LOG_APIS) != 0;
#endif
return true;
}
@ -163,10 +184,10 @@ static WORD resolve_mod_index(IMTE_KEX* target)
* (static resolve).
* @param addr Encoded api library ID + offset in this api library
* @param caller Module that requests api from api library.
* @param refmod
* @param is_static True if implicit (static), false if explicit (GetProcAddress) resolve
* @return Valid address to function for calling process.
*/
static PROC resolve_nonshared_addr(DWORD addr, MODREF* caller, PMODREF** refmod)
static PROC resolve_nonshared_addr(DWORD addr, MODREF* caller, BOOL is_static)
{
MODREF* mr;
WORD idx;
@ -175,9 +196,8 @@ static PROC resolve_nonshared_addr(DWORD addr, MODREF* caller, PMODREF** refmod)
char dllpath[MAX_PATH];
ApiLibrary* apilib;
IMTE** pmteModTable = *ppmteModTable;
static MODREF* buffer[1024];
ModuleInitializer* mi = ModuleInitializer::get_instance(true);
DBGASSERT(addr >= 0xc0000000);
api_lib_num = (addr >> 24) - 0xc0;
DBGASSERT(api_lib_num > 0); //ensure apilib ID isn't STD's
apilib = apilibmgr.get_apilib_by_index(api_lib_num);
@ -186,19 +206,9 @@ static PROC resolve_nonshared_addr(DWORD addr, MODREF* caller, PMODREF** refmod)
idx = 0xff00 + api_lib_num;
//first check if api library has already been loaded
mr = (*pppdbCur)->MODREFList;
do
{
IMTE_KEX* imte = (IMTE_KEX*) pmteModTable[mr->mteIndex];
if (imte->mod_index == idx)
{
IMAGE_NT_HEADERS* nthdr = imte->pNTHdr;
img_base = nthdr->OptionalHeader.ImageBase;
return (PROC)(img_base + (addr & 0x00ffffff));
}
mr = mr->pNextModRef;
}
while (mr);
img_base = mi->get_handle_for_index(idx);
if (img_base != 0)
return (PROC)(img_base + (addr & 0x00ffffff));
//if not - load it
@ -216,46 +226,15 @@ static PROC resolve_nonshared_addr(DWORD addr, MODREF* caller, PMODREF** refmod)
_LeaveSysLevel(krnl32lock);
return 0;
}
mi->add_module(mr);
_LeaveSysLevel(krnl32lock);
if (refmod) //static resolve (implicit)
{
//FIXME: this will cause problems if apilib references another non-shared apilib!!
//it is okay to use global buffer because static resolve code is protected by k32 lock
//not buffered yet?
if (!(*refmod >= buffer && *refmod < buffer + sizeof(buffer)))
{
//make a copy
for (int i = 0 ; i < caller->cImportedModules ; i++)
buffer[i] = caller->ImplicitImports[i].pMR;
//set reference to copy - copy will be seen by continuing resolve process
*refmod += buffer - &caller->ImplicitImports[0].pMR;
}
DBGPRINTF(("Implicit load: replacing tree %s => %s [PID=%08x]\n",
(*ppmteModTable)[caller->ImplicitImports[*refmod - buffer].pMR->mteIndex]
->pszModName, apilib->apilib_name,
GetCurrentProcessId()));
//remember tree which we overwrite - we will initialize it ourselves
//in resolver_process_attach as a result of initializing our tree
//requirement: Core is in IAT of the apilib !!!
storage* s = storage::get_storage(true);
DBGASSERT(s != NULL);
s->data[s->size++] = (void*) caller->ImplicitImports[*refmod - buffer].pMR;
//modify original - modifications will be seen by dll initializer
//which will initialize our mr tree
caller->ImplicitImports[*refmod - buffer].pMR = mr;
}
else //dynamic resolve (GetProcAddress)
if (!is_static)
{
DBGPRINTF(("Explicit load: initializing tree %s [PID=%08x]\n",
apilib->apilib_name, GetCurrentProcessId()));
if (FLoadTreeNotify(mr, 0))
if (FLoadTreeNotify(mr, FALSE))
{
FreeLibTree(mr);
return 0;
@ -280,27 +259,6 @@ static PROC resolve_nonshared_addr(DWORD addr, MODREF* caller, PMODREF** refmod)
*/
BOOL resolver_process_attach()
{
//initialize all modules replaced by api libraries
bool loaded = false;
storage* s = storage::get_storage(false);
if (!s)
return TRUE;
for (int i = 0 ; i < s->size ; i++)
{
DBGPRINTF(("Post-Initializing %s [PID=%08x]\n",
(*ppmteModTable)[((MODREF*) s->data[i])->mteIndex]->pszModName,
GetCurrentProcessId()));
if (FLoadTreeNotify((MODREF*) s->data[i], 1))
return FALSE;
loaded = true;
}
storage::return_storage();
if (!loaded)
return TRUE;
//reference all shared api libraries
ApiLibrary* lib;
int i = 1;
@ -310,13 +268,15 @@ BOOL resolver_process_attach()
{
char dllpath[MAX_PATH];
lib->get_dll_path(dllpath);
LoadLibrary(dllpath);
if (!LoadLibrary(dllpath))
return FALSE;
}
}
return TRUE;
}
/** Original ExportFromOrdinal function. @see ExportFromOrdinal */
static PROC WINAPI OriExportFromOrdinal(IMAGE_NT_HEADERS* PEh, WORD ordinal)
{
DWORD img_base;
@ -381,6 +341,7 @@ static PROC WINAPI OriExportFromOrdinal(IMAGE_NT_HEADERS* PEh, WORD ordinal)
return (PROC) addr;
}
/** Original ExportFromName function. @see ExportFromName */
static PROC WINAPI OriExportFromName(IMAGE_NT_HEADERS* PEh, WORD hint, LPCSTR name)
{
DWORD img_base;
@ -453,6 +414,12 @@ static PROC WINAPI OriExportFromName(IMAGE_NT_HEADERS* PEh, WORD hint, LPCSTR na
return 0;
}
/** Encode function pointer + API library information into single dword.
* @see decode_address
* @param addr Absolute address.
* @param apilib Pointer to API library.
* @return Encoded pointer.
*/
DWORD encode_address(DWORD addr, const ApiLibrary* apilib)
{
//note: rules have to be the same as in decode_address
@ -472,7 +439,7 @@ DWORD encode_address(DWORD addr, const ApiLibrary* apilib)
//extremely rare scenario: driver hijacked apis so the address is now
//above 0xc0000000 and we use these for encoded apilib addresses
//so we have to create a stub in shared arena with proper address
return (DWORD) new redir_stub(addr);
return (DWORD) new redir_stub(addr, false);
}
//non-shared apilib
@ -487,7 +454,15 @@ DWORD encode_address(DWORD addr, const ApiLibrary* apilib)
return addr;
}
inline PROC decode_address(DWORD p, IMAGE_NT_HEADERS* target_NThdr, MODREF* caller, PMODREF** refmod)
/** Decodes pointers created with encode_address.
* @see encode_address
* @param p Encoded pointer.
* @param target_NThdr Target module NT header.
* @param caller Calling module ref.
* @param is_static True if implicit resolve, false if explicit.
* @return Decoded function pointer.
*/
inline PROC decode_address(DWORD p, IMAGE_NT_HEADERS* target_NThdr, MODREF* caller, BOOL is_static)
{
//note: rules have to be the same as in encode_address
//zero address
@ -501,12 +476,19 @@ inline PROC decode_address(DWORD p, IMAGE_NT_HEADERS* target_NThdr, MODREF* call
return (PROC)(p + target_NThdr->OptionalHeader.ImageBase);
//non-shared api library
if (p >= 0xc0000000)
return resolve_nonshared_addr(p, caller, refmod);
return resolve_nonshared_addr(p, caller, is_static);
//shared system or api library
return (PROC) p;
}
PROC WINAPI ExportFromOrdinal(IMTE_KEX* target, MODREF* caller, PMODREF** refmod, WORD ordinal)
/** Performs function resolve by ordinal number.
* @param target Target module, module from which we want function.
* @param caller Calling module, module which wants function.
* @param is_static True if static resolve, false if dynamic.
* @param ordinal Function ordinal number.
* @return Function pointer.
*/
PROC WINAPI ExportFromOrdinal(IMTE_KEX* target, MODREF* caller, BOOL is_static, WORD ordinal)
{
PROC ret;
@ -527,13 +509,13 @@ PROC WINAPI ExportFromOrdinal(IMTE_KEX* target, MODREF* caller, PMODREF** refmod
if (!cp.apiconf->is_table_empty(mod_index))
ret = decode_address(cp.apiconf->get(mod_index, ordinal),
target->pNTHdr, caller, refmod);
target->pNTHdr, caller, is_static);
else
ret = OriExportFromOrdinal(target->pNTHdr, ordinal);
#ifdef _DEBUG
if (ret && cp.log_apis)
{
IMTE_KEX* icaller = (IMTE_KEX*)((*ppmteModTable)[caller->mteIndex]);
IMTE* icaller = (*ppmteModTable)[caller->mteIndex];
if (DWORD(ret) < target->pNTHdr->OptionalHeader.ImageBase
+ target->pNTHdr->OptionalHeader.BaseOfData)
ret = create_log_stub(icaller->pszModName, target->pszModName, ordinal, ret);
@ -543,7 +525,7 @@ PROC WINAPI ExportFromOrdinal(IMTE_KEX* target, MODREF* caller, PMODREF** refmod
else
ret = OriExportFromOrdinal(target->pNTHdr, ordinal);
if (!ret && refmod)
if (!ret && is_static)
{
DBGPRINTF(("%s: unresolved export %s:%d\n",
((*ppmteModTable)[caller->mteIndex])->pszModName,
@ -553,7 +535,15 @@ PROC WINAPI ExportFromOrdinal(IMTE_KEX* target, MODREF* caller, PMODREF** refmod
return ret;
}
PROC WINAPI ExportFromName(IMTE_KEX* target, MODREF* caller, PMODREF** refmod, WORD hint, LPCSTR name)
/** Performs function resolve by name.
* @param target Target module, module from which we want function.
* @param caller Calling module, module which wants function.
* @param is_static True if static resolve, false if dynamic.
* @param hint Hint number, tells resolver where to start search.
* @param name Function name.
* @return Function pointer.
*/
PROC WINAPI ExportFromName(IMTE_KEX* target, MODREF* caller, BOOL is_static, WORD hint, LPCSTR name)
{
PROC ret;
@ -574,13 +564,13 @@ PROC WINAPI ExportFromName(IMTE_KEX* target, MODREF* caller, PMODREF** refmod, W
if (!cp.apiconf->is_table_empty(mod_index))
ret = decode_address(cp.apiconf->get(mod_index, hint, name),
target->pNTHdr, caller, refmod);
target->pNTHdr, caller, is_static);
else
ret = OriExportFromName(target->pNTHdr, hint, name);
#ifdef _DEBUG
if (ret && cp.log_apis)
{
IMTE_KEX* icaller = (IMTE_KEX*)((*ppmteModTable)[caller->mteIndex]);
IMTE* icaller = (*ppmteModTable)[caller->mteIndex];
if (DWORD(ret) < target->pNTHdr->OptionalHeader.ImageBase
+ target->pNTHdr->OptionalHeader.BaseOfData)
ret = create_log_stub(icaller->pszModName, target->pszModName, name, ret);
@ -590,7 +580,7 @@ PROC WINAPI ExportFromName(IMTE_KEX* target, MODREF* caller, PMODREF** refmod, W
else
ret = OriExportFromName(target->pNTHdr, hint, name);
if (!ret && refmod)
if (!ret && is_static)
{
DBGPRINTF(("%s: unresolved export %s:%s\n",
((*ppmteModTable)[caller->mteIndex])->pszModName,
@ -600,10 +590,12 @@ PROC WINAPI ExportFromName(IMTE_KEX* target, MODREF* caller, PMODREF** refmod, W
return ret;
}
/** Determines whether process has API extensions enabled. */
bool are_extensions_enabled()
{
config_params cp;
MODREF* exe = (*pppdbCur)->pExeMODREF;
DBGASSERT(exe != NULL);
return get_config(exe, cp);
}
@ -619,6 +611,9 @@ static BOOL WINAPI IsKnownKexDLL(char* name, const char* ext)
if (ext && strcmp(ext, "DLL") != 0)
return FALSE;
if ((*pppdbCur)->pExeMODREF == NULL)
return FALSE;
if (are_extensions_enabled())
{
//workaround windows bug
@ -644,6 +639,15 @@ static BOOL WINAPI IsKnownKexDLL(char* name, const char* ext)
}
}
static BOOL WINAPI KexLoadTreeNotify(MODREF* mr, BOOL is_static)
{
ModuleInitializer* mi = ModuleInitializer::get_instance(false);
if (mi && mi->has_initialize() && !mi->initialize_modules())
return TRUE;
return FLoadTreeNotify(mr, is_static);
}
PROC WINAPI iGetProcAddress(HMODULE hModule, LPCSTR lpProcName)
{
IMAGE_DOS_HEADER* dos_hdr;
@ -688,9 +692,13 @@ static void reset_imtes()
IMTE_KEX* imte = (IMTE_KEX*) pmteModTable[i];
if (imte)
{
imte->config = NULL;
imte->flags = 0;
imte->mod_index = 0;
for (MODREF* mr = imte->pMR ; mr != NULL ; mr = mr->pNextMteMR)
{
MODREF_KEX kmr(mr);
kmr.as.conf = NULL;
kmr.as.flags = 0;
}
}
}
@ -706,17 +714,22 @@ void dump_imtes(void)
int total = 0;
dbgprintf("Dumping IMTEs...\n");
dbgprintf("%-4s %-12s %-7s %s %s\n", "No.", "Process", "Config", "Fl", "Module");
for (WORD i = 0 ; i < imteMax ; i++)
{
IMTE_KEX* imte = (IMTE_KEX*) pmteModTable[i];
if (imte)
{
dbgprintf("#%-3d %-12s %-7s %02x %s\n", i,
pmteModTable[imte->pMR->ppdb->pExeMODREF->mteIndex]->pszSModName,
imte->config ? imte->config->get_name() : "unknown",
imte->flags,
imte->pszFileName);
dbgprintf("%s\n", imte->pszFileName);
for (MODREF* mr = imte->pMR ; mr != NULL ; mr = mr->pNextMteMR)
{
MODREF_KEX kmr(mr);
dbgprintf("\t%02x %-7s %-12s\n",
kmr.as.flags,
kmr.as.conf ? kmr.as.conf->get_name() : "none",
pmteModTable[mr->ppdb->pExeMODREF->mteIndex]->pszModName);
}
total++;
}
}
@ -765,6 +778,7 @@ int resolver_init()
}
jtab = (PLONG) dseg->jtab;
FLoadTreeNotify = (FLoadTreeNotify_t) jtab[JTAB_FLD_TRN];
system_path_len = GetSystemDirectory(system_path, sizeof(system_path));
RegOpenKey(HKEY_LOCAL_MACHINE, "Software\\KernelEx\\KnownDLLs", &known_dlls_key);
@ -790,6 +804,7 @@ void resolver_hook()
old_jtab[JTAB_EFN_DYN] = InterlockedExchange(jtab + JTAB_EFN_DYN, (LONG) ExportFromNameDynamic_thunk);
old_jtab[JTAB_EFN_STA] = InterlockedExchange(jtab + JTAB_EFN_STA, (LONG) ExportFromNameStatic_thunk);
old_jtab[JTAB_KNO_DLL] = InterlockedExchange(jtab + JTAB_KNO_DLL, (LONG) IsKnownKexDLL);
old_jtab[JTAB_FLD_TRN] = InterlockedExchange(jtab + JTAB_FLD_TRN, (LONG) KexLoadTreeNotify);
}
void resolver_unhook()

37
core/resolver.h Normal file → Executable file
View File

@ -30,6 +30,7 @@
#define LDR_OVERRIDE_PROC_MOD 2 /* use same configuration and flags for all modules in a process */
#define LDR_LOG_APIS 4 /* enable API tracing */
#define LDR_FILTER_APIS 8 /* allow to control single APIs - enable, disable, switch */
#define LDR_NO_INHERIT 16 /* don't inherit configuration and flags to child processes */
#define LDR_VALID_FLAG 128 /* denotes that flags field is valid */
#pragma pack(push,1)
@ -38,26 +39,40 @@ class ApiConfiguration;
struct IMTE_KEX : public IMTE
{
ApiConfiguration* config; /* pointer to API configuration required by the module
* 0 - not checked */
BYTE flags; /* loader flags */
BYTE unused; /* unused */
WORD mod_index; /* this value minus 1 is index into MODAPI table in API configurations
* 0xff00-0xfffe - api libraries
* 0 - not checked, 0xffff - not an overridden module */
};
struct appsetting
{
appsetting() : conf(NULL), flags(0) {}
ApiConfiguration* conf; /* pointer to API configuration used by the module */
unsigned long flags; /* resolver flags */
};
struct MODREF_KEX
{
MODREF_KEX(PMODREF pmr) : mr(*pmr),
as(*(appsetting*)(mr.ImplicitImports + mr.cImportedModules)) {}
MODREF& mr;
appsetting& as;
};
/* Creates a stub that calls address specified in the constructor. */
class redir_stub
{
public:
redir_stub(unsigned long target, bool make_call = false) : c_eax(0xb8),
v_eax(target), c_jmp(make_call ? 0xd0ff : 0xe0ff) {}
redir_stub(unsigned long target, bool make_call = true)
{
op = make_call ? 0xe8 : 0xe9;
addr = target - (unsigned long(this) + 5);
}
private:
unsigned char c_eax;
unsigned long v_eax;
unsigned short c_jmp;
unsigned char op;
unsigned long addr;
};
struct config_params
@ -73,8 +88,8 @@ struct config_params
bool are_extensions_enabled();
DWORD encode_address(DWORD addr, const ApiLibrary* apilib);
PROC WINAPI iGetProcAddress(HMODULE hModule, LPCSTR lpProcName);
PROC WINAPI ExportFromOrdinal(IMTE_KEX* target, MODREF* caller, PMODREF** refmod, WORD ordinal);
PROC WINAPI ExportFromName(IMTE_KEX* target, MODREF* caller, PMODREF** refmod, WORD hint, LPCSTR name);
PROC WINAPI ExportFromOrdinal(IMTE_KEX* target, MODREF* caller, BOOL is_static, WORD ordinal);
PROC WINAPI ExportFromName(IMTE_KEX* target, MODREF* caller, BOOL is_static, WORD hint, LPCSTR name);
#ifdef _DEBUG
void dump_imtes(void);

3
core/resource.h Normal file → Executable file
View File

@ -14,13 +14,14 @@
#define IDM_TOFILE 40001
#define IDM_CLEAR 40002
#define IDM_FILTER 40003
#define IDM_ENABLE 40004
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 104
#define _APS_NEXT_COMMAND_VALUE 40004
#define _APS_NEXT_COMMAND_VALUE 40005
#define _APS_NEXT_CONTROL_VALUE 1006
#define _APS_NEXT_SYMED_VALUE 101
#endif

0
core/sharedmem.cpp Normal file → Executable file
View File

0
core/sharedmem.h Normal file → Executable file
View File

View File

@ -1,61 +0,0 @@
/*
* KernelEx
* Copyright (C) 2009, 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 <windows.h>
#include "storage.h"
#include "internals.h"
#include "debug.h"
struct PDB_KEX : PDB98
{
void* kex_data_storage;
};
const int storage::storage_size = 0x1000;
storage* storage::get_storage(bool alloc)
{
PDB_KEX* pdb = (PDB_KEX*) *pppdbCur;
storage* s = (storage*) pdb->kex_data_storage;
if (!s && alloc)
{
pdb->kex_data_storage = VirtualAlloc(NULL, storage_size,
MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
DBGASSERT(pdb->kex_data_storage != NULL);
memset(pdb->kex_data_storage, 0, storage_size);
s = (storage*) pdb->kex_data_storage;
s->size = 0;
}
return s;
}
void storage::return_storage()
{
PDB_KEX* pdb = (PDB_KEX*) *pppdbCur;
if (pdb->kex_data_storage)
{
BOOL ret = VirtualFree(pdb->kex_data_storage, 0, MEM_RELEASE);
DBGASSERT(ret != FALSE);
pdb->kex_data_storage = NULL;
}
}

102
core/structs.h Normal file → Executable file
View File

@ -58,6 +58,21 @@ typedef struct _HANDLE_TABLE {
HANDLE_TABLE_ENTRY array[1]; // An array (number is given by cEntries)
} HANDLE_TABLE, *PHANDLE_TABLE;
// List node
typedef struct _NODE
{
struct _NODE* next;
struct _NODE* prev;
PVOID data;
} NODE, *PNODE;
// List
typedef struct _LIST {
PNODE firstNode;
PNODE lastNode;
PNODE currentNode;
} LIST, *PLIST;
struct _PDB98;
// MODREF
@ -145,16 +160,15 @@ typedef struct _PDB98 { // Size = 0xC4 (from Kernel32)
PHANDLE_TABLE pHandleTable; // 44 Pointer to Handle Table
struct _PDB98* ParentPDB; // 48 Pointer to parent process (PDB)
PMODREF MODREFList; // 4C Pointer to list of modules
DWORD ThreadList; // 50 Pointer to list of threads
PLIST ThreadList; // 50 Pointer to list of threads
DWORD DebuggeeCB; // 54 Debuggee context block
DWORD LocalHeapFreeHead; // 58 Free list for process default heap
DWORD InitialRing0ID; // 5C Meaning unknown
CRITICAL_SECTION CriticalSection; // 60 For synchronizing threads
DWORD Unknown4[3]; // 78
DWORD pConsole; // 84 Output console
DWORD tlsInUseBits1; // 88 Status of TLS indexes 0 - 31
DWORD tlsInUseBits2; // 8C Status of TLS indexes 32 - 63
DWORD ProcessDWORD; // 90 Undocumented API GetProcessDword, meaning unknown
DWORD Unknown4[2]; // 78
DWORD pConsole; // 80 Output console
DWORD tlsInUseBits[3]; // 84 Status of TLS indexes
DWORD ProcessDWORD; // 90 Undocumented API GetProcessDword - user data
struct _PDB98* ProcessGroup; // 94 Master process PDB (in debugging)
PMODREF pExeMODREF; // 98 Points to exe's module structure
DWORD TopExcFilter; // 9C SetUnhandledExceptionFilter
@ -171,60 +185,6 @@ typedef struct _PDB98 { // Size = 0xC4 (from Kernel32)
DWORD Unknown6; // C0
} PDB98, *PPDB98;
// Process Database
typedef struct _PDBME { // Size = 0xC4 (from Kernel32)
BYTE Type; // 00 Kernel object type = K32OBJ_PROCESS (6)
BYTE Unknown_A; // 01 (align ?)
WORD cReference; // 02 Number of references to process
DWORD Unknown_B; // 04 Pointer to ???
DWORD Unknown1; // 08 (zero)
DWORD pEvent; // 0C Event for process waiting
DWORD TerminationStatus; // 10 GetExitCodeProcess
DWORD Unknown2; // 14 May be used for private purposes
DWORD DefaultHeap; // 18 GetProcessHeap
DWORD MemoryContext; // 1C Pointer to process context
DWORD Flags; // 20 Flags
DWORD pPSP; // 24 Linear address of DOS PSP
WORD PSPSelector; // 28 Selector to DOS PSP
WORD MTEIndex; // 2A Index into global module table
WORD cThreads; // 2C Threads.ItemCount
WORD cNotTermThreads; // 2E Threads.ItemCount
WORD Unknown3; // 30 (zero)
WORD cRing0Threads; // 32 Normally Threads.ItemCount (except kernel32)
HANDLE HeapHandle; // 34 Kernel32 shared heap
DWORD w16TDB; // 38 Win16 task database selector
DWORD MemMappedFiles; // 3C List of memory mapped files
PEDB pEDB; // 40 Pointer to Environment Database
PHANDLE_TABLE pHandleTable; // 44 Pointer to Handle Table
struct _PDBME* ParentPDB; // 48 Pointer to parent process (PDB)
PMODREF MODREFList; // 4C Pointer to list of modules
DWORD ThreadList; // 50 Pointer to list of threads
DWORD DebuggeeCB; // 54 Debuggee context block
DWORD LocalHeapFreeHead; // 58 Free list for process default heap
DWORD InitialRing0ID; // 5C Meaning unknown
CRITICAL_SECTION CriticalSection; // 60 For synchronizing threads
DWORD Unknown4[2]; // 78
DWORD pConsole; // 80 Output console
DWORD tlsInUseBits1; // 84 Status of TLS indexes 0 - 31
DWORD tlsInUseBits2; // 88 Status of TLS indexes 32 - 63
DWORD ProcessDWORD; // 8C Undocumented API GetProcessDword, meaning unknown
DWORD Unknown_C; // 90 Unknown
struct _PDBME* ProcessGroup; // 94 Master process PDB (in debugging)
PMODREF pExeMODREF; // 98 Points to exe's module structure
DWORD TopExcFilter; // 9C SetUnhandledExceptionFilter
DWORD PriorityClass; // A0 PriorityClass (8 = NORMAL)
DWORD HeapList; // A4 List of heaps
DWORD HeapHandleList; // A8 List of moveable memory blocks
DWORD HeapPointer; // AC Pointer to one moveable memory block, meaning unknown
DWORD pConsoleProvider; // B0 Console for DOS apps
WORD EnvironSelector; // B4 Environment database selector
WORD ErrorMode; // B6 SetErrorMode
DWORD pEventLoadFinished; // B8 Signaled when the process has finished loading
WORD UTState; // BC Universal thunking, meaning unknown
WORD Unknown5; // BE (zero)
DWORD Unknown6; // C0
} PDBME, *PPDBME;
// Thread Information Block (FS:[0x18])
typedef struct _TIB98 { // Size = 0x38
PSEH pvExcept; // 00 Head of exception record list
@ -240,8 +200,8 @@ typedef struct _TIB98 { // Size = 0x38
DWORD DebugContext; // 20 Pointer to debug context structure
DWORD pCurrentPriority; // 24 Pointer to DWORD containing current priority level
DWORD pvQueue; // 28 Message Queue selector
PVOID *pvTLSArray; // 2C Thread Local Storage (TLS) array
PVOID *pProcess; // 30 Pointer to owning process database (PDB)
DWORD *pvTLSArray; // 2C Pointer to TDB.TlsSlots
PDB98 *pProcess; // 30 Pointer to owning process database (PDB)
DWORD Unknown; // 34 Pointer to ???
} TIB98, *PTIB98;
@ -262,8 +222,13 @@ typedef struct _TDB98 { // Size = 0x228 (from Kernel32)
DWORD cHandles; // 50 Handle count
DWORD Ring0Thread; // 54 R0 thread control block (TCB)
TDBX98 *pTDBX; // 58 R0 thread database extension (TDBX)
DWORD un1[109]; // 5C
DWORD un1[3]; // 5C
DWORD LastError; // 68 GetLastError code value
DWORD un2[9]; // 6C
LPVOID TlsSlots[80]; // 90 Thread Local Storage
DWORD un3[16]; // 1D0
DWORD APISuspendCount; // 210 Count of SuspendThread's minus ResumeThread's
DWORD un4[5]; // 214
} TDB98, *PTDB98;
typedef struct _TDBME { // Size = 0x228 (from Kernel32)
@ -280,10 +245,15 @@ typedef struct _TDBME { // Size = 0x228 (from Kernel32)
DWORD cHandles; // 50 Handle count
DWORD Ring0Thread; // 54 R0 thread control block (TCB)
DWORD Unknown3; // 58 Selector for ???
DWORD un1[11]; // 5C
TDBX98 *pTDBX; // 88
DWORD un2[97]; // 8C
DWORD un1[8]; // 5C
DWORD LastError; // 7C GetLastError code value
DWORD un2[2]; // 80
TDBX98 *pTDBX; // 88 R0 thread database extension (TDBX)
DWORD Unknown4; // 8C
DWORD TlsSlots[80]; // 90 Thread Local Storage
DWORD un3[16]; // 1D0
DWORD APISuspendCount; // 210 Count of SuspendThread's minus ResumeThread's
DWORD un4[5]; // 214
} TDBME, *PTDBME;
// Thread database extension

6
core/thunks.cpp Normal file → Executable file
View File

@ -39,8 +39,7 @@ __asm {
push dword ptr [esp+4] //return address
mov eax, [ebp+8]
mov [esp+8], eax //caller MODREF
lea eax, [ebp-4Ch]
mov dword ptr [esp+12], eax
mov dword ptr [esp+12], 1
jmp ExportFromOrdinal
}
}
@ -60,8 +59,7 @@ __asm {
push dword ptr [esp+4] //return address
mov eax, [ebp+8]
mov [esp+8], eax //caller MODREF
lea eax, [ebp-4Ch]
mov dword ptr [esp+12], eax
mov dword ptr [esp+12], 1
jmp ExportFromName
}
}

0
core/thunks.h Normal file → Executable file
View File

0
core/wildcmp.cpp Normal file → Executable file
View File

0
core/wildcmp.h Normal file → Executable file
View File