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

import KernelEx-4.0-RC1

This commit is contained in:
UzixLS
2018-11-03 16:18:57 +03:00
commit d4e0420295
295 changed files with 28034 additions and 0 deletions

19
common/is_sorted.hpp Normal file
View File

@ -0,0 +1,19 @@
template<typename FI>
inline bool is_sorted(FI begin, FI end)
{
return is_sorted_until(begin, end) == end;
}
template<typename FI>
FI is_sorted_until(FI begin, FI end)
{
if (begin == end)
return end;
FI next = begin;
for (++next ; next != end ; begin = next, ++next)
if (*next < *begin)
return next;
return end;
}

196
common/kexcoresdk.h Normal file
View File

@ -0,0 +1,196 @@
/*
* 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.
*
*/
/** KernelEx Core SDK. */
#ifndef __KEXCORESDK_H
#define __KEXCORESDK_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef KEXCORE_EXPORTS
#define _KEXCOREIMP __declspec(dllexport)
#else
#define _KEXCOREIMP __declspec(dllimport)
#endif
/*****************************************************************************
*
* Every api library has to export the following functions:
*
*
* const apilib_api_table* get_api_table()
*
* Function should return pointer to api tables provided by the library.
* Function will be called when KernelEx Core builds new api
* configuration table, but only if the library hasn't been loaded yet.
* Named api and ordinal api tables have to be sorted in ascending order,
* according to operator< rules below.
* After the last api table there has to be a closing NULL entry
* (all fields set to zeros).
* Multiple apis with same names and ordinal numbers are allowed in single
* api library. However only one api with given name or ordinal will be
* included in single api configuration. It is possible to specify which
* api should be used in core.ini configuration file.
*
*****************************************************************************/
/** Convenience macro for defining apis. */
#define DECL_API(name_ord,func) { name_ord, (unsigned long) func }
/** Convenience macro for defining tables. */
#define DECL_TAB(lib,named,unnamed) { lib, named, sizeof(named) / sizeof(apilib_named_api), unnamed, sizeof(unnamed) / sizeof(apilib_unnamed_api) }
/** apilib_named_api - named api structure. */
typedef struct _apilib_named_api
{
const char* name; /**< Api name. */
unsigned long addr; /**< Api address. */
} apilib_named_api;
/** apilib_unnamed_api - unnamed api structure. */
typedef struct _apilib_unnamed_api
{
unsigned short ord; /**< Api ordinal number. */
unsigned long addr; /**< Api address. */
} apilib_unnamed_api;
/** apilib_api_table - api table structure. */
typedef struct _apilib_api_table
{
const char* target_library; /**< DLL library for which the apis are defined. */
const apilib_named_api* named_apis; /**< Pointer to table of named apis. */
int named_apis_count; /**< Number of named apis in the table. */
const apilib_unnamed_api* ordinal_apis; /**< Pointer to table of unnamed apis. */
int ordinal_apis_count; /**< Number of unnamed apis in the table. */
} apilib_api_table;
/** Type definition for get_api_table() function. */
typedef const apilib_api_table* (* fgat_t)();
/** kexGetKEXVersion - obtain KernelEx Core version
*
* Returned value is KernelEx version number encoded as follows:
* 0xHHLLRRRR, where:
* HH - major version number
* LL - minor version number
* RRRR - revision number
*/
_KEXCOREIMP unsigned long kexGetKEXVersion();
/** kexDebugPrint - output debug information
*
* Parameters are compatible with printf command,
* maximum output length is limited to 256 bytes.
*/
_KEXCOREIMP void kexDebugPrint(const char* format, ...);
/** kexGetVersion - obtain original Windows version number.
*
* Refer to GetVersion API documentation for parameters and output.
*/
_KEXCOREIMP DWORD kexGetVersion();
/** kexGetProcAddress - obtain original address of DLL library function.
*
* Refer to GetProcAddress API documentation for parameters and output.
*/
_KEXCOREIMP PROC kexGetProcAddress(HMODULE hModule, PCSTR lpProcName);
/** kexPIDtoPDB - obtain pointer to process database entry, given process identifier.
*
* @param pid Process identifier.
* @return Pointer to process database entry on success, NULL on failure.
*/
_KEXCOREIMP void* kexPIDtoPDB(DWORD pid);
/** kexTIDtoTDB - obtain pointer to thread database entry, given thread identifier.
*
* @param tid Thread identifier.
* @return Pointer to thread database entry on success, NULL on failure.
*/
_KEXCOREIMP void* kexTIDtoTDB(DWORD tid);
/** kexGetModuleSettings - Retrieve per module settings.
*
* @param module Module path.
* @param conf_name Receives configuration name, has to be at least 256 bytes long.
* @param ldr_flags Receives flags.
*/
_KEXCOREIMP void kexGetModuleSettings(const char* module,
char* conf_name, BYTE* ldr_flags);
/** kexSetModuleSettings - Set per module settings.
*
* @param module Module path.
* @param conf_name Configuration name to be set for the module.
* @param ldr_flags Flags to be set for the module.
*/
_KEXCOREIMP void kexSetModuleSettings(const char* module,
const char* conf_name, BYTE ldr_flags);
/** kexFlushAppSettings - Reloads all module settings from registy. */
_KEXCOREIMP void kexFlushAppSettings(void);
#ifdef __cplusplus
}; /* extern "C" */
#endif
#ifdef __cplusplus
/** Comparison operator used to order named api entries. */
inline bool operator<(const apilib_named_api& a, const apilib_named_api& b)
{
return strcmp(a.name, b.name) < 0;
}
/** Comparison operator used to order unnamed api entries. */
inline bool operator<(const apilib_unnamed_api& a, const apilib_unnamed_api& b)
{
return a.ord < b.ord;
}
#endif
#endif

435
common/pemanip.cpp Normal file
View File

@ -0,0 +1,435 @@
/*
* KernelEx
* Copyright (C) 2008-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 "pemanip.h"
#include "debug.h"
#include <cstring>
PEmanip::PEmanip()
{
ZeroInit();
}
PEmanip::PEmanip(const char* file_path, int add_size)
{
ZeroInit();
OpenFile(file_path, add_size);
}
PEmanip::PEmanip(void* memory)
{
ZeroInit();
OpenMemory(memory);
}
PEmanip::~PEmanip()
{
if (file_buf)
HeapFree(GetProcessHeap(), 0, file_buf);
if (file_path)
HeapFree(GetProcessHeap(), 0, file_path);
}
void PEmanip::ZeroInit()
{
file_buf = NULL;
file_path = NULL;
MZh = NULL;
PEh = NULL;
section_hdrs = NULL;
target_len = 0;
max_target_len = 0;
image_base = 0;
has_target = false;
}
bool PEmanip::HasTarget()
{
return has_target;
}
IMAGE_NT_HEADERS* PEmanip::GetPEHeader()
{
return PEh;
}
int PEmanip::GetFileSize(const char* file_path)
{
HANDLE file = CreateFile(file_path, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, 0, NULL);
int file_size = -1;
if (file != INVALID_HANDLE_VALUE)
{
file_size = ::GetFileSize(file, NULL);
CloseHandle(file);
}
return file_size;
}
bool PEmanip::LoadFile(const char* file_path, int add_size)
{
void* buf = NULL;
int buf_len;
HANDLE file;
int bytes_read;
bool ret = false;
if (!file_path || add_size < 0)
return false;
buf_len = GetFileSize(file_path);
if (buf_len > 0)
{
buf = HeapAlloc(GetProcessHeap(), 0, buf_len + add_size);
if (buf)
{
file = CreateFile(file_path, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, 0, NULL);
if (file != INVALID_HANDLE_VALUE)
{
if (ReadFile(file, buf, buf_len, (DWORD*) &bytes_read, NULL)
&& bytes_read == buf_len)
{
this->file_path = (char*) HeapAlloc(GetProcessHeap(),
0, strlen(file_path) + 1);
this->target_len = buf_len;
this->file_buf = buf;
this->max_target_len = buf_len + add_size;
if (this->file_path)
{
strcpy(this->file_path, file_path);
ret = true;
}
}
CloseHandle(file);
}
}
}
if (!ret && buf)
HeapFree(GetProcessHeap(), 0, buf);
return ret;
}
bool PEmanip::SaveFile(const char* file_path)
{
HANDLE file;
int bytes_written;
bool ret = false;
if (!file_path || !file_buf)
return false;
file = CreateFile(file_path, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (file != INVALID_HANDLE_VALUE)
{
if (WriteFile(file, file_buf, target_len, (DWORD*) &bytes_written, NULL)
&& bytes_written == target_len)
{
ret = true;
}
CloseHandle(file);
}
return ret;
}
void PEmanip::Close()
{
if (file_buf)
HeapFree(GetProcessHeap(), 0, file_buf);
if (file_path)
HeapFree(GetProcessHeap(), 0, file_path);
ZeroInit();
}
int PEmanip::GetBufferLen()
{
return target_len;
}
bool PEmanip::SetBufferLen(int new_size)
{
if (new_size >= max_target_len)
return false;
if (new_size < target_len)
return false;
target_len = new_size;
return true;
}
unsigned long PEmanip::ALIGN(unsigned long x, unsigned long y)
{
return (x + y - 1) & (~(y - 1));
}
bool PEmanip::OpenFile(const char* file_path, int add_size)
{
if (has_target)
return false;
if (LoadFile(file_path, add_size))
{
MZh = (IMAGE_DOS_HEADER*) file_buf;
if (MZh->e_magic == IMAGE_DOS_SIGNATURE)
{
PEh = (IMAGE_NT_HEADERS*) ((DWORD) MZh + MZh->e_lfanew);
if ((PEh->Signature == IMAGE_NT_SIGNATURE)
&& (PEh->FileHeader.Machine == IMAGE_FILE_MACHINE_I386)
&& (PEh->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR_MAGIC))
{
section_hdrs = (IMAGE_SECTION_HEADER*)
((DWORD) PEh
+ PEh->FileHeader.SizeOfOptionalHeader
+ sizeof(IMAGE_FILE_HEADER)
+ sizeof(DWORD));
image_base = PEh->OptionalHeader.ImageBase;
has_target = true;
return true;
}
}
}
return false;
}
bool PEmanip::OpenMemory(void* memory)
{
if (has_target)
return false;
MZh = (IMAGE_DOS_HEADER*) memory;
if (MZh->e_magic == IMAGE_DOS_SIGNATURE)
{
PEh = (IMAGE_NT_HEADERS*) ((DWORD) MZh + MZh->e_lfanew);
if ((PEh->Signature == IMAGE_NT_SIGNATURE)
&& (PEh->FileHeader.Machine == IMAGE_FILE_MACHINE_I386)
&& (PEh->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR_MAGIC))
{
section_hdrs = (IMAGE_SECTION_HEADER*)
((DWORD) PEh
+ PEh->FileHeader.SizeOfOptionalHeader
+ sizeof(IMAGE_FILE_HEADER)
+ sizeof(DWORD));
image_base = (DWORD)memory;
has_target = true;
target_len = PEh->OptionalHeader.SizeOfImage;
max_target_len = target_len;
return true;
}
}
return false;
}
IMAGE_SECTION_HEADER* PEmanip::RvaToSection(DWORD Rva)
{
IMAGE_SECTION_HEADER* section = section_hdrs;
for (int i = 0 ; i < PEh->FileHeader.NumberOfSections ; i++)
{
if ((Rva >= section->VirtualAddress)
&& (Rva < (section->VirtualAddress + section->Misc.VirtualSize)))
{
return section;
}
section++;
}
return NULL;
}
void* PEmanip::RvaToPointer(DWORD Rva)
{
if (!file_buf)
return (void*)(Rva + image_base);
IMAGE_SECTION_HEADER* section = section_hdrs;
for (int i = 0 ; i < PEh->FileHeader.NumberOfSections ; i++)
{
if ((Rva >= section->VirtualAddress)
&& (Rva < (section->VirtualAddress + section->Misc.VirtualSize)))
{
return (void*) (Rva - section->VirtualAddress
+ section->PointerToRawData + (DWORD) MZh);
}
section++;
}
return 0;
}
DWORD PEmanip::PointerToRva(void* pointer)
{
if (!file_buf)
return (DWORD) pointer - image_base;
IMAGE_SECTION_HEADER* section = section_hdrs;
DWORD offset;
if (pointer < MZh)
return 0;
offset = (DWORD) pointer - (DWORD) MZh;
for (int i = 0 ; i < PEh->FileHeader.NumberOfSections ; i++)
{
if ((offset >= section->PointerToRawData)
&& (offset < (section->PointerToRawData + section->SizeOfRawData)))
{
return offset - section->PointerToRawData
+ section->VirtualAddress;
}
section++;
}
return 0;
}
IMAGE_SECTION_HEADER* PEmanip::FindSectionByName(const char* name)
{
IMAGE_SECTION_HEADER* section = section_hdrs;
for (int i = 0 ; i < PEh->FileHeader.NumberOfSections ; i++)
{
if (!strnicmp((char*) section->Name, name, sizeof(section->Name)))
return section;
section++;
}
return NULL;
}
void* PEmanip::GetSectionByName(const char* name)
{
IMAGE_SECTION_HEADER* section = FindSectionByName(name);
if (section)
return RvaToPointer(section->VirtualAddress);
return NULL;
}
int PEmanip::GetSectionSize(const char* name)
{
IMAGE_SECTION_HEADER* section = FindSectionByName(name);
if (section)
if (file_buf)
return section->SizeOfRawData;
else
return section->Misc.VirtualSize;
return 0;
}
bool PEmanip::AllocSectionSpace(const char* name, int needed_space, void** ptr, int align)
{
IMAGE_SECTION_HEADER* Section = FindSectionByName(name);
if (!Section || align < 1 || needed_space < 0)
return false;
if (!needed_space)
return true;
DWORD current_size = ALIGN(Section->Misc.VirtualSize, align);
DWORD new_size = current_size + needed_space;
DWORD max_size = (Section + 1)->VirtualAddress - Section->VirtualAddress;
int available_space = max_size - current_size;
DBGPRINTF(("Bytes available: %d, ", available_space));
DBGPRINTF(("Bytes needed: %d\n", needed_space));
if (available_space < needed_space)
{
DBGPRINTF(("Not enough space in section!\n"));
return false;
}
if (new_size > Section->SizeOfRawData)
{
int offset = ALIGN(new_size - Section->SizeOfRawData,
PEh->OptionalHeader.FileAlignment);
DBGPRINTF(("Applying offset of %d\n", offset));
void* block_start = RvaToPointer((Section + 1)->VirtualAddress);
int block_size = GetBufferLen() - (Section + 1)->PointerToRawData;
char* tmp = (char*)HeapAlloc(GetProcessHeap(), 0, block_size);
memcpy(tmp, block_start, block_size);
memcpy((void*)((int)block_start + offset), tmp, block_size);
HeapFree(GetProcessHeap(), 0, tmp);
memset(block_start, 0, offset);
// update offsets
for (int i = 0 ; i < PEh->FileHeader.NumberOfSections ; i++)
{
if (&section_hdrs[i] <= Section)
continue;
section_hdrs[i].PointerToRawData += offset;
}
Section->SizeOfRawData += offset;
if (!SetBufferLen(GetBufferLen() + offset))
return false;
}
Section->Misc.VirtualSize = new_size;
if (ptr)
*ptr = RvaToPointer(Section->VirtualAddress + current_size);
return true;
}
DWORD PEmanip::GetExportedAPI(const char* func)
{
IMAGE_EXPORT_DIRECTORY* Exports = (IMAGE_EXPORT_DIRECTORY*)
RvaToPointer(PEh->OptionalHeader
.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
if (Exports)
{
DWORD* Names = (DWORD*) RvaToPointer(Exports->AddressOfNames);
for (DWORD i = 0 ; i < Exports->NumberOfNames ; i++)
{
if (!strcmp(func, (char*) RvaToPointer(*Names)))
{
WORD* OrdinalTable = (WORD*) RvaToPointer(Exports->AddressOfNameOrdinals);
WORD Index = OrdinalTable[i];
DWORD* FunctionTable = (DWORD*) RvaToPointer(Exports->AddressOfFunctions);
DWORD Address = (DWORD) FunctionTable[Index];
return Address;
}
Names++;
}
}
return 0;
}
DWORD PEmanip::GetImageBase()
{
return image_base;
}

70
common/pemanip.h Normal file
View File

@ -0,0 +1,70 @@
/*
* KernelEx
* Copyright (C) 2008-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 _SETUP_PEMANIP_H
#define _SETUP_PEMANIP_H
#include <windows.h>
#include <winnt.h>
class PEmanip
{
private:
bool has_target;
char* file_path;
void* file_buf;
int target_len;
int max_target_len;
IMAGE_DOS_HEADER* MZh;
IMAGE_NT_HEADERS* PEh;
IMAGE_SECTION_HEADER* section_hdrs;
DWORD image_base;
void ZeroInit();
int GetFileSize(const char* file_path);
bool LoadFile(const char* file_path, int add_size);
int GetBufferLen();
bool SetBufferLen(int new_size);
static unsigned long ALIGN(unsigned long x, unsigned long y);
IMAGE_SECTION_HEADER* FindSectionByName(const char* name);
public:
PEmanip();
PEmanip(const char* file_path, int add_size = 0);
PEmanip(void* memory);
~PEmanip();
bool HasTarget();
bool OpenFile(const char* file_path, int add_size = 0);
bool OpenMemory(void* memory);
bool SaveFile(const char* file_path);
void Close();
IMAGE_NT_HEADERS* GetPEHeader();
IMAGE_SECTION_HEADER* RvaToSection(DWORD Rva);
void* RvaToPointer(DWORD Rva);
DWORD PointerToRva(void* pointer);
void* GetSectionByName(const char* name);
int GetSectionSize(const char* name);
bool AllocSectionSpace(const char* name, int needed_space, void** ptr, int align = 1);
DWORD GetExportedAPI(const char* func);
DWORD GetImageBase();
};
#endif

78
common/sstring.hpp Normal file
View File

@ -0,0 +1,78 @@
/*
* 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 __SSTRING_HPP
#define __SSTRING_HPP
#include <string.h>
class sstring
{
public:
sstring(const char* src)
{
len = strlen(src);
storage = new char[len + 1];
strcpy(storage, src);
}
sstring(const sstring& src)
{
len = src.len;
storage = new char[len + 1];
strcpy(storage, src.storage);
}
~sstring()
{
delete [] storage;
}
sstring& operator=(const sstring& src)
{
len = src.len;
delete [] storage;
storage = new char[len + 1];
strcpy(storage, src.storage);
return *this;
}
bool operator<(const sstring& a) const
{
return strcmp(storage, a.storage) < 0;
}
const char* get() const
{
return storage;
}
int length() const
{
return len;
}
private:
int len;
char* storage;
};
#endif