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:
4
core/Core.rc
Normal file → Executable file
4
core/Core.rc
Normal file → Executable 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
50
core/DebugWindow.cpp
Normal file → Executable 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
12
core/DebugWindow.h
Normal file → Executable 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
103
core/ModInit.cpp
Executable 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
54
core/ModInit.h
Executable 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
95
core/ProcessStorage.cpp
Executable 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
26
core/storage.h → core/ProcessStorage.h
Normal file → Executable 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
11
core/SettingsDB.cpp
Normal file → Executable 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
12
core/SettingsDB.h
Normal file → Executable 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
0
core/apiconf.cpp
Normal file → Executable file
0
core/apiconf.h
Normal file → Executable file
0
core/apiconf.h
Normal file → Executable file
0
core/apiconfmgr.cpp
Normal file → Executable file
0
core/apiconfmgr.cpp
Normal file → Executable file
0
core/apiconfmgr.h
Normal file → Executable file
0
core/apiconfmgr.h
Normal file → Executable file
19
core/apilib.cpp
Normal file → Executable file
19
core/apilib.cpp
Normal file → Executable 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
0
core/apilib.h
Normal file → Executable file
181
core/apilog.cpp
Normal file → Executable file
181
core/apilog.cpp
Normal file → Executable 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
81
core/apilog.h
Normal file → Executable 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
0
core/core.def
Normal file → Executable file
28
core/core.dsp
Normal file → Executable file
28
core/core.dsp
Normal file → Executable 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
0
core/core.ini
Normal file → Executable file
0
core/debug.cpp
Normal file → Executable file
0
core/debug.cpp
Normal file → Executable file
2
core/debug.h
Normal file → Executable file
2
core/debug.h
Normal file → Executable 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
0
core/debugproto.cpp
Normal file → Executable file
0
core/debugproto.h
Normal file → Executable file
0
core/debugproto.h
Normal file → Executable file
142
core/internals.cpp
Normal file → Executable file
142
core/internals.cpp
Normal file → Executable 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
8
core/internals.h
Normal file → Executable 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
48
core/kexcoresdk.cpp
Normal file → Executable 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
0
core/main.cpp
Normal file → Executable file
337
core/resolver.cpp
Normal file → Executable file
337
core/resolver.cpp
Normal file → Executable 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
37
core/resolver.h
Normal file → Executable 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
3
core/resource.h
Normal file → Executable 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
0
core/sharedmem.cpp
Normal file → Executable file
0
core/sharedmem.h
Normal file → Executable file
0
core/sharedmem.h
Normal file → Executable 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
102
core/structs.h
Normal file → Executable 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
6
core/thunks.cpp
Normal file → Executable 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
0
core/thunks.h
Normal file → Executable file
0
core/wildcmp.cpp
Normal file → Executable file
0
core/wildcmp.cpp
Normal file → Executable file
0
core/wildcmp.h
Normal file → Executable file
0
core/wildcmp.h
Normal file → Executable file
Reference in New Issue
Block a user