1
0
mirror of https://github.com/UzixLS/KernelEx.git synced 2025-07-18 15:01:17 +03:00

import KernelEx-4.5.2

This commit is contained in:
UzixLS
2018-11-03 16:24:01 +03:00
parent 2948e23961
commit 37f6b55f9e
54 changed files with 2142 additions and 1505 deletions

View File

@ -128,7 +128,12 @@ void __stdcall log_stub::pre_log(log_data* lgd)
lgd->target, lgd->api_name);
va_list ap = va_list((DWORD*) &lgd + 10);
z += ApiLogParams::inst().decode_parameters(lgd->target, lgd->api_name, ap, msg + z, sizeof(msg)-1 - z);
int limit = sizeof(msg) - 1 - z;
int zz = ApiLogParams::inst().decode_parameters(lgd->target, lgd->api_name, ap, msg + z, limit);
if (zz > limit)
z += limit;
else
z += zz;
strcpy(msg + z, "\n");
writer_fn(msg);

View File

@ -1,3 +1,22 @@
KernelEx v4.5.2 by Xeno86
2011-11-14
removed obsolete SETUPKEX project
moved downgrade detection and detection of pre-4.0 KernelEx from SETUPKEX to the installer
installer: show information about pending reboot before displaying the main window
AppSettings: updated configuration for Firefox 4+ installers
VKrnlEx: added IFSMgr fix, repairing the problem in accessing a locked file through file mapping object
added "VKrnlEx" project which superseeds "SetupKex" project, VKrnlEx makes modification of kernel32.dll file on disk unnecessary by patching the image directly in memory from kernel space before the shell starts
implemented KERNEL32.UnlockFileEx (required for Firefox 7)
fix circular-reference problem in apihook initialization
added SHELL32.IsUserAnAdmin ordinal export - some apps shouldn't complain about not having admin privileges anymore
core: api configuration dump had improper ordinal numbers listed
core: fixed crash if invalid handle was passed to kexGetProcAddress (fixes mysterious crash if UNICOWS.DLL could not be loaded)
apihook/apilog: fixed bug in parameter logging, leading to crashes if resulting string exceeded buffer length
AppSettings: Canon printing manager didn't appear to like working under NT mode
---------------------------------------
KernelEx v4.5.1 by Xeno86
2011-05-06

View File

@ -8,6 +8,8 @@ If you build manually, you need to compile KEXCRT and PREP projects first as oth
To build KEXCONTROL you have to build debug CORE first.
KEXBASES and KEXBASEN projects rely on CORE be built first.
To build VKRNLEX project you need Microsoft Windows 98 Driver Development Kit (DDK) or Microsoft Windows 2000 Driver Development Kit (DDK).
To build installer you need NSIS install system.
-Xeno86

View File

@ -99,18 +99,6 @@ Package=<4>
###############################################################################
Project: "setup"=.\setup\setup.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "sheet"=.\sheet\sheet.dsp - Package Owner=<4>
Package=<5>
@ -135,6 +123,18 @@ Package=<4>
###############################################################################
Project: "VxD"=.\vxd\vxd.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "sdbcreate"=.\util\sdbcreate\sdbcreate.dsp - Package Owner=<4>
Package=<5>

View File

@ -1,4 +1,5 @@
!define _VERSION '4.5.1'
!define _VERSION '4.5.2'
!define _VERSION_CODE 0x04050078
!ifndef _DEBUG
!define FLAVOUR 'Release'
@ -207,48 +208,31 @@ SectionEnd
Section "Install"
SetDetailsView show
ReadRegStr $0 HKLM "Software\Microsoft\Windows\CurrentVersion\RunServicesOnce" "KexNeedsReboot"
IfErrors +5
DetailPrint "Detected unfinished previous installation."
DetailPrint "You have to restart the system in order to complete it before you can proceed."
MessageBox MB_ICONSTOP|MB_OK "You have to restart the system first."
Abort
SetOutPath "$INSTDIR"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\RunServicesOnce" "KexNeedsReboot" ""
;Revert KERNEL32.DLL file patch in case of upgrade
IfFileExists "$WINDIR\SYSBCKUP\KERNEL32.DLL" 0 +7
GetTempFileName $0 "$SYSDIR"
Delete $0
Rename /REBOOTOK "$WINDIR\SYSBCKUP\KERNEL32.DLL" $0
Rename /REBOOTOK $0 "$SYSDIR\kernel32.dll"
Delete "$INSTDIR\kernel32.bak"
Goto Revert_Done
GetTempFileName $R0 "$INSTDIR"
File /oname=$R0 "setup\${FLAVOUR}\setupkex.exe"
StrCpy $R1 "none"
IfFileExists "$INSTDIR\kernel32.bak" 0 +6
StrCpy $R1 "copy"
ClearErrors
CopyFiles /SILENT "$INSTDIR\kernel32.bak" "$WINDIR\SYSBCKUP\KERNEL32.DLL"
IfErrors 0 +2
StrCpy $R1 "exist" ;File already exists
GetTempFileName $0 "$SYSDIR"
Delete $0
Rename /REBOOTOK "$INSTDIR\kernel32.bak" $0
Rename /REBOOTOK $0 "$SYSDIR\kernel32.dll"
Goto Revert_Done
!ifdef _DEBUG
nsExec::ExecToLog '"$R0"'
Pop $0
!else
ExecWait '"$R0"' $0
StrCmp $0 "" 0 +2
StrCpy $0 "error"
!endif
DetailPrint " setup returned: $0"
StrCmp $0 "0" +6
Delete $R0 ;delete temporary setupkex.exe
StrCmp $R1 "copy" 0 +2 ;undo copy
Delete "$WINDIR\SYSBCKUP\KERNEL32.DLL"
RMDir "$INSTDIR"
Abort
Rename /REBOOTOK $R0 "$INSTDIR\setupkex.exe"
StrCmp $R1 "copy" +2 0
StrCmp $R1 "exist" 0 +2
Delete /REBOOTOK "$INSTDIR\kernel32.bak" ;delete deprecated update file
Revert_Done:
Delete /REBOOTOK "$INSTDIR\setupkex.exe"
;Files to install
;UpdateDLL_Func params:
@ -295,6 +279,11 @@ Section "Install"
File license.txt
File "Release Notes.txt"
GetTempFileName $0 "$INSTDIR"
File /oname=$0 "vxd\${FLAVOUR}\VKrnlEx.vxd"
Delete "$INSTDIR\VKrnlEx.vxd"
Rename /REBOOTOK $0 "$INSTDIR\VKrnlEx.vxd"
GetTempFileName $0 "$INSTDIR"
File /oname=$0 auxiliary\msimg32.dll
Delete "$INSTDIR\msimg32.dll"
@ -352,6 +341,7 @@ Section "Install"
WriteRegStr HKLM "Software\KernelEx" "InstallDir" $INSTDIR
;Store run key
WriteRegStr HKLM "System\CurrentControlSet\Services\VxD\VKRNLEX" "StaticVxD" "$INSTDIR\VKrnlEx.vxd"
WriteRegStr HKLM "System\CurrentControlSet\Control\MPRServices\KernelEx" "DLLName" "$INSTDIR\KernelEx.dll"
WriteRegStr HKLM "System\CurrentControlSet\Control\MPRServices\KernelEx" "EntryPoint" "_MprStart@4"
WriteRegDWORD HKLM "System\CurrentControlSet\Control\MPRServices\KernelEx" "StackSize" 0x1000
@ -391,13 +381,6 @@ Section "Uninstall"
SetDetailsView show
ReadRegStr $0 HKLM "Software\Microsoft\Windows\CurrentVersion\RunServicesOnce" "KexNeedsReboot"
IfErrors +5
DetailPrint "Detected unfinished previous installation."
DetailPrint "You have to restart the system in order to complete it before you can proceed."
MessageBox MB_ICONSTOP|MB_OK "You have to restart the system first."
Abort
;Files to uninstall
IfFileExists "$WINDIR\SYSBCKUP\KERNEL32.DLL" 0 +5
GetTempFileName $0 "$SYSDIR"
@ -416,6 +399,8 @@ Section "Uninstall"
Delete "$INSTDIR\license.txt"
Delete "$INSTDIR\Release Notes.txt"
Delete /REBOOTOK "$INSTDIR\VKrnlEx.vxd"
Delete /REBOOTOK "$INSTDIR\msimg32.dll"
DeleteRegValue HKLM "Software\KernelEx\KnownDLLs" "MSIMG32"
Delete /REBOOTOK "$INSTDIR\pdh.dll"
@ -450,6 +435,7 @@ Section "Uninstall"
MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "$(DESC_SETTINGS_PRESERVE)" IDYES +2 IDNO 0
DeleteRegKey HKLM "Software\KernelEx"
DeleteRegKey HKLM "System\CurrentControlSet\Services\VxD\VKRNLEX"
DeleteRegKey HKLM "System\CurrentControlSet\Control\MPRServices\KernelEx"
DeleteRegKey /ifempty HKLM "System\CurrentControlSet\Control\MPRServices"
@ -460,6 +446,35 @@ Section "Uninstall"
SectionEnd
;--------------------------------
; Detect obsolete pre-4.0 KUP or KEX
Function DetectOldKex
System::Call "kernel32::KUPVersion(m .r0)"
StrCmp $0 "" 0 +4
System::Call "kernel32::KEXVersion(m .r0)"
StrCmp $0 "" 0 +2
Return
StrCpy $1 $0 1 0
IntCmp $1 4 +3 0 +3
MessageBox MB_ICONSTOP|MB_OK "Setup has detected previous version of KernelEx ($0) installed on this computer. Please uninstall it before continuing."
Abort
FunctionEnd
;--------------------------------
; We can't predict future... downgrading from higher version is forbidden
Function DetectDowngrade
System::Call "kernelex::kexGetKEXVersion() i.r0 ? u"
StrCmp $0 "" 0 +2
Return
IntCmp $0 ${_VERSION_CODE} +3 +3 0
MessageBox MB_ICONSTOP|MB_OK "Can't downgrade. Please uninstall currently installed version of KernelEx before continuing."
Abort
FunctionEnd
;--------------------------------
;.onInit
@ -475,4 +490,23 @@ Function .onInit
lbl_Ok:
FunctionEnd
ReadRegStr $0 HKLM "Software\Microsoft\Windows\CurrentVersion\RunServicesOnce" "KexNeedsReboot"
IfErrors +3
MessageBox MB_ICONSTOP|MB_OK "Detected unfinished previous installation.$\n\
You have to restart the system in order to complete it before you can proceed further."
Abort
Call DetectOldKex
Call DetectDowngrade
FunctionEnd
Function un.onInit
ReadRegStr $0 HKLM "Software\Microsoft\Windows\CurrentVersion\RunServicesOnce" "KexNeedsReboot"
IfErrors +3
MessageBox MB_ICONSTOP|MB_OK "Detected unfinished previous installation.$\n\
You have to restart the system in order to complete it before you can proceed further."
Abort
FunctionEnd

View File

@ -1,3 +1,19 @@
KernelEx v4.5.2 by Xeno86
2011-11-14
What's new:
----------------------------------
* Added KernelEx Virtual Device (VKrnlEx.vxd) project which makes modification of kernel32.dll file on disk unnecessary by patching the image directly in memory from kernel space before the shell starts
* Implemented a fix for a crash occuring when accessing a locked file through file mapping object
* Some programs shouldn't complain about not having admin privileges anymore
* Various bugfixes
Apps fixed / now working:
-------------------------
* Now working: Mozilla Firefox 8.0
#################################################
KernelEx v4.5.1 by Xeno86
2011-05-06

View File

@ -43,3 +43,21 @@ BOOL WINAPI LockFileEx_new(
return LockFile(hFile, lpOverlapped->Offset, lpOverlapped->OffsetHigh,
nNumberOfBytesToLockLow, nNumberOfBytesToLockHigh);
}
/* MAKE_EXPORT UnlockFileEx_new=UnlockFileEx */
BOOL WINAPI UnlockFileEx_new(
HANDLE hFile,
DWORD dwReserved,
DWORD nNumberOfBytesToUnlockLow,
DWORD nNumberOfBytesToUnlockHigh,
LPOVERLAPPED lpOverlapped
)
{
if (dwReserved)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return UnlockFile(hFile, lpOverlapped->Offset, lpOverlapped->OffsetHigh,
nNumberOfBytesToUnlockLow, nNumberOfBytesToUnlockHigh);
}

View File

@ -214,6 +214,7 @@ static const apilib_named_api kernel32_named_apis[] =
DECL_API("TerminateJobObject", TerminateJobObject_new),
DECL_API("TryEnterCriticalSection", TryEnterCriticalSection_new),
DECL_API("TzSpecificLocalTimeToSystemTime", TzSpecificLocalTimeToSystemTime_new),
DECL_API("UnlockFileEx", UnlockFileEx_new),
DECL_API("VerLanguageNameW", VerLanguageNameW_new),
DECL_API("VerSetConditionMask", VerSetConditionMask_new),
DECL_API("VerifyVersionInfoA", VerifyVersionInfoA_NT2K),

View File

@ -70,6 +70,7 @@ BOOL WINAPI AssignProcessToJobObject_new(HANDLE job, HANDLE process);
BOOL WINAPI IsProcessInJob_new(HANDLE process, HANDLE job, PBOOL result);
void WINAPI KEXVersion(char* out);
BOOL WINAPI LockFileEx_new(HANDLE hFile, DWORD dwFlags, DWORD dwReserved, DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh, LPOVERLAPPED lpOverlapped);
BOOL WINAPI UnlockFileEx_new(HANDLE hFile, DWORD dwReserved, DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh, LPOVERLAPPED lpOverlapped);
LPVOID WINAPI MapViewOfFileEx_new(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap, LPVOID lpBaseAddress);
LPVOID WINAPI MapViewOfFile_new(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap);
BOOL WINAPI MoveFileExA_new(LPCSTR lpExistingFileNameA, LPCSTR lpNewFileNameA, DWORD dwFlags);

View File

@ -22,6 +22,7 @@
#include <windows.h>
/* MAKE_EXPORT IsUserAnAdmin_new=IsUserAnAdmin */
/* MAKE_EXPORT IsUserAnAdmin_new=ordinal680 */
BOOL WINAPI IsUserAnAdmin_new(void)
{
return TRUE;

View File

@ -48,12 +48,11 @@ static const apilib_named_api shell32_named_apis[] =
/*** AUTOGENERATED APILIST NAMED EXPORTS END ***/
};
#if 0
static const apilib_unnamed_api shell32_ordinal_apis[] =
{
/*** AUTOGENERATED APILIST ORDINAL EXPORTS BEGIN ***/
DECL_API(680, IsUserAnAdmin_new),
/*** AUTOGENERATED APILIST ORDINAL EXPORTS END ***/
};
#endif
const apilib_api_table apitable_shell32 = DECL_TAB("SHELL32.DLL", shell32_named_apis, 0 /*shell32_ordinal_apis*/);
const apilib_api_table apitable_shell32 = DECL_TAB("SHELL32.DLL", shell32_named_apis, shell32_ordinal_apis);

View File

@ -7,8 +7,7 @@ REGEDIT4
"*\\UNICOWS.DLL"="DCFG1"
"*\\MFC*U.DLL"="WINXP"
;-Firefox
"*\\FIREFOX SETUP 3*.EXE"="WINXP"
"*\\FIREFOX SETUP 4*.EXE"="WINXP"
"*\\FIREFOX SETUP *.EXE"="WINXP"
"*FIREFOX\\UNINSTALL\\HELPER.EXE"="WINXP"
"*\\FIREFOX*PRE*.INSTALLER.EXE"="WINXP"
"*\\XUL.DLL"="NT2K"
@ -89,4 +88,6 @@ REGEDIT4
"*\\DXWEBSETUP.EXE"=dword:00000001
;-OpenOffice.org
"*\\PROGRAM\\CRASHREP.EXE"=dword:00000001
;Canon PageComposer Queue Manager
"*\\CPC10Q.EXE"=dword:00000001

View File

@ -4,10 +4,9 @@ OBJ = psapi.obj
RES =
DEF = /DEF:psapi.def
BIN = ..\psapi.dll
COMMON_DIR = ../../common
LIBS = -nodefaultlib kernel32.lib $(COMMON_DIR)/kernelex.lib
LDFLAGS = /DLL /OPT:NOWIN98 /ENTRY:DllMain@12 /LIBPATH:$(COMMON_DIR) KernelEx.lib
CFLAGS = /W3 /O2 /Oi /FD /I$(COMMON_DIR)
LIBS = -nodefaultlib kernel32.lib
LDFLAGS = /DLL /OPT:NOWIN98 /ENTRY:DllMain@12 /LIBPATH:../../common KernelEx.lib
CFLAGS = /W3 /O2 /Oi /FD /I../../common
CXXFLAGS = $(CFLAGS)
all : $(BIN)

View File

@ -296,32 +296,6 @@ typedef struct _FILEMAPPING { // Size = 0x28 (from Kernel32)
#pragma pack(pop)
#if defined(__GNUC__)
static inline
PDB98* get_pdb(void)
{
PDB98* pdb;
__asm__(".byte 0x64\n\tmovl (0x30),%0" : "=r" (pdb));
return pdb;
}
static inline
TIB98* get_tib(void)
{
TIB98* tib;
__asm__(".byte 0x64\n\tmovl (0x18),%0" : "=r" (tib));
return tib;
}
static inline
TDB98* get_tdb(void)
{
return (TDB98*) ((unsigned long) get_tib()) - 8;
}
#else
#pragma warning (disable:4035) // turn off no return code warning
static inline
@ -345,6 +319,4 @@ TDB98* get_tdb(void)
#pragma warning (default:4035) // turn on no return code warning
#endif /* defined(__GNUC__) */
#endif /* __KSTRUCTS_H */

View File

@ -22,9 +22,9 @@
#ifndef __VERSION_H
#define __VERSION_H
#define VERSION_STR "4.5.1"
#define VERSION_CODE 0x0405006E
#define RCVERSION 4, 5, 11, 0
#define _RCVERSION_ "4, 5, 11, 0"
#define VERSION_STR "4.5.2"
#define VERSION_CODE 0x04050078
#define RCVERSION 4, 5, 12, 0
#define _RCVERSION_ "4, 5, 12, 0"
#endif

View File

@ -69,9 +69,10 @@ END
STRINGTABLE DISCARDABLE
BEGIN
IDS_NOTREADY "System is not KernelEx-ready.\nPlease reinstall KernelEx."
IDS_NODRIVER "KernelEx was unable to find its kernel driver counterpart.\nPlease reinstall KernelEx."
IDS_STUBMISMATCH "Stub version mismatch (expected: %d, got: %d).\nPlease reinstall KernelEx."
IDS_OLDVER "Another KernelEx version has been detected: %s.\nPlease uninstall all other versions and reinstall latest version."
IDS_DRIVERINITFAIL "KernelEx Virtual Device has failed to initialize."
END
#endif // Neutral resources

View File

@ -552,7 +552,7 @@ void ApiConfiguration::dump()
api_tables[i].named_apis[j].address);
printf("Unnamed apis (count = %d)\n", api_tables[i].unnamed_apis_count);
for (int j = 0 ; j < api_tables[i].unnamed_apis_count ; j++)
printf("\t%-5d %08x\n", j, api_tables[i].unnamed_apis[j]);
printf("\t%-5d %08x\n", j + 1, api_tables[i].unnamed_apis[j]);
printf("\n");
}
printf("\n");

View File

@ -68,7 +68,7 @@ PROC apihook::prepare(BOOL is_static)
if (hApiHookDll)
{
init_once = (init_once_t) GetProcAddress(hApiHookDll, "kexApiHook_initonce");
init_once = (init_once_t) iGetProcAddress(hApiHookDll, "kexApiHook_initonce");
__try
{
if (!init_once || !init_once())
@ -93,7 +93,7 @@ PROC apihook::prepare(BOOL is_static)
}
if (hApiHookDll)
ah_reg = GetProcAddress(hApiHookDll, "kexApiHook_register");
ah_reg = iGetProcAddress(hApiHookDll, "kexApiHook_register");
if (!hApiHookDll || !init_once || !ah_reg)
{

View File

@ -71,7 +71,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" /FI"msvc_quirks.h" /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" /D "_ENABLE_APIHOOK" /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"

View File

@ -27,6 +27,8 @@
#include "pemanip.h"
#include "ModInit.h"
extern "C" int snprintf(char*, size_t, const char*, ...);
#ifdef _DEBUG
#define _D(x) x
#else
@ -72,21 +74,32 @@ void ShowError(UINT id, ...)
MessageBox(NULL, out, "KernelEx Core", MB_OK | MB_ICONERROR);
}
bool rerun_setup()
bool VKernelEx_ioctl(DWORD command, PVOID buffer, DWORD buffer_size)
{
char cmd[MAX_PATH];
STARTUPINFO si;
PROCESS_INFORMATION pi;
BOOL result;
DWORD retlen;
HANDLE VKernelEx;
strcpy(cmd, "\"");
strcat(cmd, kernelex_dir);
strcat(cmd, "setupkex.exe\" /R");
GetStartupInfo(&si);
if (!CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
char vxdpath[MAX_PATH];
snprintf(vxdpath, sizeof(vxdpath), "\\\\.\\%sVKRNLEX.VXD",
(const char*) kernelex_dir);
VKernelEx = CreateFile(vxdpath, 0, 0, 0, 0, FILE_FLAG_DELETE_ON_CLOSE, 0);
if (VKernelEx == INVALID_HANDLE_VALUE)
{
DBGPRINTF(("Failed to connect to VKernelEx!\n"));
return false;
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
result = DeviceIoControl(VKernelEx, command, NULL, 0,
buffer, buffer_size, &retlen, NULL);
CloseHandle(VKernelEx);
if (!result || retlen > buffer_size)
return false;
return true;
}

View File

@ -44,7 +44,7 @@ extern sstring kernelex_dir;
extern sstring own_path;
void ShowError(UINT id, ...);
bool rerun_setup();
bool VKernelEx_ioctl(DWORD command, PVOID buffer, DWORD buffer_size);
bool isWinMe();
typedef MODREF* (__stdcall *MRFromHLib_t)(HMODULE);

View File

@ -26,7 +26,7 @@
#include "apiconf.h"
#include "apiconfmgr.h"
#include "internals.h"
#include "../setup/loadstub.h"
#include "../vxd/interface.h"
#include "thunks.h"
#include "SettingsDB.h"
#include "ModInit.h"
@ -775,6 +775,8 @@ PROC WINAPI iGetProcAddress(HMODULE hModule, LPCSTR lpProcName)
DBGASSERT(ppmteModTable != NULL);
MODREF* mr = MRFromHLib(hModule);
if (mr == NULL)
return NULL;
IMTE* imte = (*ppmteModTable)[mr->mteIndex];
IMAGE_NT_HEADERS* nt_hdr = imte->pNTHdr;
@ -783,25 +785,6 @@ PROC WINAPI iGetProcAddress(HMODULE hModule, LPCSTR lpProcName)
return OriExportFromName(nt_hdr, 0, lpProcName);
}
static IMAGE_SECTION_HEADER* get_data_section()
{
int i;
IMAGE_DOS_HEADER* MZh = (IMAGE_DOS_HEADER*) GetModuleHandle("kernel32");
IMAGE_NT_HEADERS* PEh = (IMAGE_NT_HEADERS*) ((int)MZh + MZh->e_lfanew);
IMAGE_SECTION_HEADER* section = (IMAGE_SECTION_HEADER*)
((int)PEh
+ PEh->FileHeader.SizeOfOptionalHeader
+ sizeof(IMAGE_FILE_HEADER)
+ sizeof(DWORD));
for (i = 0 ; i < PEh->FileHeader.NumberOfSections ; i++)
{
if (!strcmpi((char*) section->Name, ".data"))
return section;
section++;
}
return NULL;
}
static void reset_imtes()
{
DBGPRINTF(("Reseting IMTEs\n"));
@ -863,41 +846,38 @@ void dump_imtes(void)
int resolver_init()
{
DBGPRINTF(("resolver_init()\n"));
DWORD ptr;
KernelEx_dataseg* dseg = NULL;
IMAGE_SECTION_HEADER* section = get_data_section();
DWORD sign_len = sizeof(KEX_SIGNATURE) - 1;
if (!section)
return 0;
ptr = (DWORD) h_kernel32 + section->VirtualAddress + section->Misc.VirtualSize - sign_len;
while (ptr >= (DWORD) h_kernel32 + section->VirtualAddress)
ioctl_connect_params params;
if (!VKernelEx_ioctl(IOCTL_CONNECT, &params, sizeof(params)))
{
if (!memcmp((void*)ptr, KEX_SIGNATURE, sign_len))
{
dseg = (KernelEx_dataseg*) ptr;
break;
}
ptr--;
DBGPRINTF(("IOCTL_Connect failed!\n"));
ShowError(IDS_NODRIVER);
return 0;
}
KernelEx_dataseg* dseg = params.stub_ptr;
if (!params.status)
{
DBGPRINTF(("VKRNLEX failed to initialize!\n"));
ShowError(IDS_DRIVERINITFAIL);
return 0;
}
if (!dseg)
{
DBGPRINTF(("Signature not found\n"));
if (!rerun_setup())
ShowError(IDS_NOTREADY);
DBGPRINTF(("Stub not found\n"));
ShowError(IDS_DRIVERINITFAIL);
return 0;
}
else
DBGPRINTF(("Signature found @ 0x%08x\n", ptr));
DBGPRINTF(("Stub found @ 0x%08x\n", dseg));
if (dseg->version != KEX_STUB_VER)
{
DBGPRINTF(("Wrong stub version, expected: %d, got: %d\n",
KEX_STUB_VER, dseg->version));
if (!rerun_setup())
ShowError(IDS_STUBMISMATCH, KEX_STUB_VER, dseg->version);
ShowError(IDS_STUBMISMATCH, KEX_STUB_VER, dseg->version);
return 0;
}

View File

@ -2,9 +2,10 @@
// Microsoft Developer Studio generated include file.
// Used by Core.rc
//
#define IDS_NOTREADY 1
#define IDS_NODRIVER 1
#define IDS_STUBMISMATCH 2
#define IDS_OLDVER 3
#define IDS_DRIVERINITFAIL 4
// Next default values for new objects
//

View File

@ -23,7 +23,7 @@
#include "thunks.h"
#include "internals.h"
#include "resolver.h"
#include "../setup/loadstub.h"
#include "../vxd/interface.h"
__declspec(naked)
PROC ExportFromOrdinalStatic_thunk(IMAGE_NT_HEADERS* PEh, WORD ordinal)

View File

@ -4,6 +4,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
void _assert(const char *expr, const char *file, unsigned int line)
{

View File

@ -198,11 +198,6 @@ SOURCE=.\memswap.c
# End Source File
# Begin Source File
SOURCE=.\msvc\msvc8.c
# PROP Exclude_From_Build 1
# End Source File
# Begin Source File
SOURCE=.\printf.c
# End Source File
# Begin Source File

View File

@ -1,6 +1,6 @@
OBJ = abort.obj assert.obj atoi.obj atol.obj atoll.obj ctypes.obj memccpy.obj memchr.obj memcmp.obj memcpy.obj memmem.obj memmove.obj memory.obj memory-cpp.obj memrchr.obj memset.obj memswap.obj printf.obj snprintf.obj sprintf.obj sscanf.obj strcat.obj strchr.obj strcmp.obj strcmpi.obj strcpy.obj strdup.obj strlen.obj strncat.obj strncmp.obj strncpy.obj strnicmp.obj strnlen.obj strntoimax.obj strntoumax.obj strpbrk.obj strrchr.obj strsep.obj strstr.obj strtok.obj strtok_r.obj strtol.obj strtoll.obj strtoul.obj strtoull.obj strtoumax.obj strupr.obj strxspn.obj vsnprintf.obj vsprintf.obj vsscanf.obj _vsnprintf.obj write.obj exit.obj \
ctype/isalnum.obj ctype/isalpha.obj ctype/isascii.obj ctype/isblank.obj ctype/iscntrl.obj ctype/isdigit.obj ctype/isgraph.obj ctype/islower.obj ctype/isprint.obj ctype/ispunct.obj ctype/isspace.obj ctype/isupper.obj ctype/isxdigit.obj ctype/tolower.obj ctype/toupper.obj \
msvc/init.obj msvc/dllcrt0.obj msvc/argcargv.obj msvc/concrt0.obj msvc/wincrt0.obj msvc/purecall.obj msvc/msvc8.obj
msvc/init.obj msvc/dllcrt0.obj msvc/argcargv.obj msvc/concrt0.obj msvc/wincrt0.obj msvc/purecall.obj
CFLAGS = /O2 /Oi- /I. /nologo /D_CTYPE_DISABLE_MACROS

View File

@ -1,34 +0,0 @@
#include <windows.h>
#ifndef STATUS_INVALID_CRUNTIME_PARAMETER
#define STATUS_INVALID_CRUNTIME_PARAMETER 0xC0000417
#endif
__declspec(noreturn) void _invoke_watson(
const wchar_t *pszExpression,
const wchar_t *pszFunction,
const wchar_t *pszFile,
unsigned int nLine,
void* pReserved
)
{
MessageBox(NULL, "Invalid argument passed into a CRT function", "CRT error", MB_OK | MB_ICONERROR);
RaiseException( STATUS_INVALID_CRUNTIME_PARAMETER, EXCEPTION_NONCONTINUABLE, 0, NULL );
}
void _invalid_parameter(
const wchar_t *pszExpression,
const wchar_t *pszFunction,
const wchar_t *pszFile,
unsigned int nLine,
void* pReserved
)
{
_invoke_watson(pszExpression, pszFunction, pszFile, nLine, pReserved);
}
void _invalid_parameter_noinfo(void)
{
_invalid_parameter(NULL, NULL, NULL, 0, 0);
}

View File

@ -1,577 +0,0 @@
/*
* KernelEx
* Copyright (C) 2010, Xeno86
*
* This file is part of KernelEx source code.
*
* KernelEx is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; version 2 of the License.
*
* KernelEx is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <windows.h>
#include <cassert>
#include "patch.h"
#include "debug.h"
#include "loadstub.h"
#include "pemanip.h"
#include "resource.h"
#define CODE_SEG ".text"
#define DATA_SEG ".data"
#define INIT_SEG "_INIT"
void ShowError(UINT id, ...);
Patch::Patch(PEmanip& pem) : pefile(pem)
{
}
void Patch::apply()
{
find_ExportFromX();
find_IsKnownDLL();
find_FLoadTreeNotify1();
find_FLoadTreeNotify2();
prepare_subsystem_check();
find_resource_check1();
find_resource_check2();
disable_named_and_rcdata_resources_mirroring();
mod_imte_alloc();
mod_mr_alloc();
mod_pdb_alloc();
KernelEx_codeseg* cseg;
KernelEx_dataseg* dseg;
if (!pefile.AllocSectionSpace(CODE_SEG,
sizeof(KernelEx_codeseg), (void**) &cseg, sizeof(DWORD)))
ShowError(IDS_FAILSEC, CODE_SEG);
if (!pefile.AllocSectionSpace(DATA_SEG,
sizeof(KernelEx_dataseg), (void**) &dseg, sizeof(DWORD)))
ShowError(IDS_FAILSEC, DATA_SEG);
memcpy(cseg->signature, "KrnlEx", 6);
cseg->version = KEX_STUB_VER;
for (int i = 0 ; i < JTAB_SIZE ; i++)
{
cseg->jmp_stub[i].opcode = 0x25ff;
cseg->jmp_stub[i].addr = (DWORD)
pefile.PointerToRva(&dseg->jtab[i]) + pefile.GetImageBase();
cseg->jmp_stub[i].nop = 0x9090;
}
memcpy(dseg->signature, "KrnlEx", 6);
dseg->version = KEX_STUB_VER;
dseg->jtab[JTAB_EFO_DYN] = _ExportFromOrdinal + pefile.GetImageBase();
dseg->jtab[JTAB_EFO_STA] = _ExportFromOrdinal + pefile.GetImageBase();
dseg->jtab[JTAB_EFN_DYN] = _ExportFromName + pefile.GetImageBase();
dseg->jtab[JTAB_EFN_STA] = _ExportFromName + pefile.GetImageBase();
dseg->jtab[JTAB_KNO_DLL] = _IsKnownDLL + pefile.GetImageBase();
dseg->jtab[JTAB_FLD_TRN] = _FLoadTreeNotify + pefile.GetImageBase();
dseg->jtab[JTAB_SYS_CHK] = _SubsysCheckPerform + pefile.GetImageBase();
dseg->jtab[JTAB_RES_CHK] = _GetOrdinal + pefile.GetImageBase();
//exportfromx patch
DWORD code = (DWORD) pefile.GetSectionByName(CODE_SEG);
int code_size = pefile.GetSectionSize(CODE_SEG);
int efo_cnt = 0;
int efn_cnt = 0;
for (DWORD a = code ; a < code + code_size ; a++)
{
if (is_call_ref(a, _ExportFromOrdinal))
{
DWORD file_loc = a;
if (a == EFN_EFO_call)
continue;
if (a == gpa_ExportFromOrdinal_call)
set_call_ref(file_loc, (DWORD) &cseg->jmp_stub[JTAB_EFO_DYN]);
else
set_call_ref(file_loc, (DWORD) &cseg->jmp_stub[JTAB_EFO_STA]);
DBGPRINTF(("%s: address 0x%08x\n", "EFO", pefile.PointerToRva((void*) a)
+ pefile.GetImageBase()));
efo_cnt++;
}
else if (is_call_ref(a, _ExportFromName))
{
DWORD file_loc = a;
if (is_fixupc(a))
continue;
if (a == gpa_ExportFromName_call)
set_call_ref(file_loc, (DWORD) &cseg->jmp_stub[JTAB_EFN_DYN]);
else
set_call_ref(file_loc, (DWORD) &cseg->jmp_stub[JTAB_EFN_STA]);
DBGPRINTF(("%s: address 0x%08x\n", "EFN", pefile.PointerToRva((void*) a)
+ pefile.GetImageBase()));
efn_cnt++;
}
}
if (efo_cnt != 2 || efn_cnt != 2)
ShowError(IDS_ERRCHECK);
//isknowndll patch
set_call_ref(IsKnownDLL_call, (DWORD) &cseg->jmp_stub[JTAB_KNO_DLL]);
DBGPRINTF(("%s: address 0x%08x\n", "KNO_DLL", pefile.PointerToRva((void*) IsKnownDLL_call)
+ pefile.GetImageBase()));
//FLoadTreeNotify patch
set_call_ref(FLoadTreeNotify_call1, (DWORD) &cseg->jmp_stub[JTAB_FLD_TRN]);
DBGPRINTF(("%s: address 0x%08x\n", "FLD_TRN1", pefile.PointerToRva((void*) FLoadTreeNotify_call1)
+ pefile.GetImageBase()));
set_call_ref(FLoadTreeNotify_call2, (DWORD) &cseg->jmp_stub[JTAB_FLD_TRN]);
DBGPRINTF(("%s: address 0x%08x\n", "FLD_TRN2", pefile.PointerToRva((void*) FLoadTreeNotify_call2)
+ pefile.GetImageBase()));
//subsys check patch
set_jmp_ref(SubsysCheck_jmp, (DWORD) &cseg->jmp_stub[JTAB_SYS_CHK]);
DBGPRINTF(("%s: address 0x%08x\n", "SYS_CHK", pefile.PointerToRva((void*) SubsysCheck_jmp)
+ pefile.GetImageBase()));
//resource check patch
set_call_ref(GetOrdinal_call1, (DWORD) &cseg->jmp_stub[JTAB_RES_CHK]);
DBGPRINTF(("%s: address 0x%08x\n", "RES_CHK1", pefile.PointerToRva((void*) GetOrdinal_call1)
+ pefile.GetImageBase()));
set_call_ref(GetOrdinal_call2, (DWORD) &cseg->jmp_stub[JTAB_RES_CHK]);
DBGPRINTF(("%s: address 0x%08x\n", "RES_CHK2", pefile.PointerToRva((void*) GetOrdinal_call2)
+ pefile.GetImageBase()));
}
int Patch::find_pattern(DWORD offset, int size, const short* pattern,
int pat_len, DWORD* found_loc)
{
DWORD end_offset = offset + size - pat_len;
int found = 0;
for (DWORD i = offset ; i <= end_offset ; i++)
{
if (pattern[0] < 0 || *(unsigned char*)i == pattern[0])
{
int j;
for (j = 1 ; j < pat_len ; j++)
{
if (pattern[j] >= 0 && *(unsigned char*)(i + j) != pattern[j])
break;
}
if (j == pat_len) //pattern found
{
*found_loc = i;
found++;
}
}
}
return found;
}
void Patch::set_pattern(DWORD loc, const short* new_pattern, int pat_len)
{
unsigned char* offset = (unsigned char*) loc;
const short* pat_ptr = new_pattern;
while (pat_len--)
{
if (*pat_ptr != -1)
*offset = *pat_ptr & 0xff;
offset++;
pat_ptr++;
}
}
void Patch::prepare_subsystem_check()
{
static const short pattern[] = {
0x66,0x8b,0x46,0x48,0x66,0x3d,0x04,0x00,0x0f,0x87,0x9c,0x01,0x00,0x00,
0x75,0x0b,0x66,0x83,0x7e,0x4a,0x0a,0x0f,0x87,0x8f,0x01,0x00,0x00,0x66,
0x81,0x7e,0x04,0x4c,0x01,
};
static const short after[] = {
0x66,0x83,0x7E,0x48,0x04,0x75,0x05,0x66,0x83,0x7E,0x4A,0x0A,0xE9,0x00,
0x00,0x00,0x00,0x0F,0x87,0x93,0x01,0x00,0x00,0x90,0x90,0x90,0x90,0x66,
0x81,0x7e,0x04,0x4c,0x01,
};
DWORD offset = (DWORD) pefile.GetSectionByName(CODE_SEG);
int size = pefile.GetSectionSize(CODE_SEG);
int length = sizeof(pattern) / sizeof(short);
DWORD found_loc;
int found = find_pattern(offset, size, pattern, length, &found_loc);
if (found != 1)
{
if (!found) ShowError(IDS_NOPAT, "subsystem_check");
else ShowError(IDS_MULPAT, "subsystem_check");
}
DBGPRINTF(("%s: pattern found @ 0x%08x\n", "subsystem_check",
pefile.PointerToRva((void*) found_loc) + pefile.GetImageBase()));
set_pattern(found_loc, after, length);
SubsysCheck_jmp = found_loc + 12;
_SubsysCheckPerform = decode_jmp(SubsysCheck_jmp, 5);
}
void Patch::find_resource_check1()
{
static const short pattern[] = {
0x6A,0x00,0x8D,0x45,0xE0,0x50,0xFF,0x75,0xA4,0xFF,0x75,0xD0,0x8D,0x45,
0xCC,0x50,0xFF,0x75,0x08,0xE8,-2,-2,-2,-2,0x85,0xC0
};
DWORD offset = (DWORD) pefile.GetSectionByName(CODE_SEG);
int size = pefile.GetSectionSize(CODE_SEG);
int length = sizeof(pattern) / sizeof(short);
DWORD found_loc;
int found = find_pattern(offset, size,pattern, length, &found_loc);
if (found != 1)
{
if (!found) ShowError(IDS_NOPAT, "resource_check1");
else ShowError(IDS_MULPAT, "resource_check1");
}
DBGPRINTF(("%s: pattern found @ 0x%08x\n", "resource_check1",
pefile.PointerToRva((void*) found_loc) + pefile.GetImageBase()));
GetOrdinal_call1 = found_loc + 19;
_GetOrdinal = decode_call(GetOrdinal_call1, 5);
}
void Patch::find_resource_check2()
{
static const short pattern[] = {
0x66,0x8B,0x45,0xE0,0x66,0x2D,0x06,0x80,0x66,0x3D,0x01,0x00,0x1B,0xC0,
0xF7,0xD8,0x50,0x8D,0x45,0xDE,0x50,0xFF,0x75, -1,0xFF,0x75,0xD0,0x8D,
0x45,0xCC,0x50,0xFF,0x75,0x08,0xE8, -2, -2, -2, -2,0x85,0xC0
};
DWORD offset = (DWORD) pefile.GetSectionByName(CODE_SEG);
int size = pefile.GetSectionSize(CODE_SEG);
int length = sizeof(pattern) / sizeof(short);
DWORD found_loc;
int found = find_pattern(offset, size,pattern, length, &found_loc);
if (found != 1)
{
if (!found) ShowError(IDS_NOPAT, "resource_check2");
else ShowError(IDS_MULPAT, "resource_check2");
}
DBGPRINTF(("%s: pattern found @ 0x%08x\n", "resource_check2",
pefile.PointerToRva((void*) found_loc) + pefile.GetImageBase()));
GetOrdinal_call2 = found_loc + 34;
}
//no named/rcdata resource types mirroring
void Patch::disable_named_and_rcdata_resources_mirroring()
{
static const short pattern[] = {
0x66,0x8B,0x40,0x0E,0x66,0x89,0x45,0xDA,0x8B,0x45, -1,0x66,0x8B,0x48,
0x0C,0x66,0x89,0x4D,0xD8,0x66,0x8B,0x45,0xE0,0x8B,0x4D,0xD4,0x66,0x89,
0x01,0x83,0x45,0xD4,0x02,0x66,0x8B,0x45,0xDA,0x66,0x03,0x45,0xD8,0x66,
0x89,0x45,0x8C,0x8B,0x4D,0xD4,0x66,0x89,0x01,0x83,0x45,0xD4,0x02
};
static const short after[] = {
0x66,0x8B,0x48,0x0E,0x66,0x03,0x48,0x0C,0x66,0x89,0x4D,0x8C,0x8B,0x45,
0xA4,0x83,0x38,0x0A,0x74,0x40,0x83,0x38,0x00,0x79,0x04,0x3B,0xC0,0xEB,
0x37,0x66,0x8B,0x45,0xE0,0x8B,0x4D,0xD4,0x66,0x89,0x01,0x83,0xC1,0x02,
0x66,0x8B,0x45,0x8C,0x66,0x89,0x01,0x83,0xC1,0x02,0x89,0x4D,0xD4
};
DWORD offset = (DWORD) pefile.GetSectionByName(CODE_SEG);
int size = pefile.GetSectionSize(CODE_SEG);
int length = sizeof(pattern) / sizeof(short);
DWORD found_loc;
int found = find_pattern(offset, size, pattern, length, &found_loc);
if (found != 1)
{
if (!found) ShowError(IDS_NOPAT, "disable_named_and_rcdata_resources_mirroring");
else ShowError(IDS_MULPAT, "disable_named_and_rcdata_resources_mirroring");
}
DBGPRINTF(("%s: pattern found @ 0x%08x\n", "disable_named_and_rcdata_resources_mirroring",
pefile.PointerToRva((void*) found_loc) + pefile.GetImageBase()));
set_pattern(found_loc, after, length);
}
void Patch::mod_imte_alloc()
{
//VA BFF8745C, RVA 1745C, file 15A5C, sec E45C
static const short pattern[] = {
0x66,0xff,0x05,-1,-1,-1,0xbf,0x6a,0x3c,0xe8,
};
static const short after[] = {
0x66,0xff,0x05,-1,-1,-1,0xbf,0x6a,0x40,0xe8,
};
DWORD offset = (DWORD) pefile.GetSectionByName(CODE_SEG);
int size = pefile.GetSectionSize(CODE_SEG);
int length = sizeof(pattern) / sizeof(short);
DWORD found_loc;
int found = find_pattern(offset, size, pattern, length, &found_loc);
if (found != 1)
{
if (!found) ShowError(IDS_NOPAT, "mod_imte_alloc");
else ShowError(IDS_MULPAT, "mod_imte_alloc");
}
DBGPRINTF(("%s: pattern found @ 0x%08x\n", "mod_imte_alloc",
pefile.PointerToRva((void*) found_loc) + pefile.GetImageBase()));
set_pattern(found_loc, after, length);
}
void Patch::mod_mr_alloc()
{
static const short pattern[] = {
0x75,0xF6,0x8D,0x04,-1,0x1C,0x00,0x00,0x00,0x50
};
static const short after[] = {
0x75,0xF6,0x8D,0x04,-1,0x24,0x00,0x00,0x00,0x50
};
DWORD offset = (DWORD) pefile.GetSectionByName(CODE_SEG);
int size = pefile.GetSectionSize(CODE_SEG);
int length = sizeof(pattern) / sizeof(short);
DWORD found_loc;
int found = find_pattern(offset, size, pattern, length, &found_loc);
if (found != 1)
{
if (!found) ShowError(IDS_NOPAT, "mod_mr_alloc");
else ShowError(IDS_MULPAT, "mod_mr_alloc");
}
DBGPRINTF(("%s: pattern found @ 0x%08x\n", "mod_mr_alloc",
pefile.PointerToRva((void*) found_loc) + pefile.GetImageBase()));
set_pattern(found_loc, after, length);
}
void Patch::mod_pdb_alloc()
{
static const short pattern[] = {
0x53,0x56,0x57,0x6A,0x06,0x68,0xC4,0x00,0x00,0x00,0xE8
};
static const short after[] = {
0x53,0x56,0x57,0x6A,0x06,0x68,0xC8,0x00,0x00,0x00,0xE8
};
DWORD offset = (DWORD) pefile.GetSectionByName(CODE_SEG);
int size = pefile.GetSectionSize(CODE_SEG);
int length = sizeof(pattern) / sizeof(short);
DWORD found_loc;
int found = find_pattern(offset, size, pattern, length, &found_loc);
if (found != 1)
{
if (!found) ShowError(IDS_NOPAT, "mod_pdb_alloc");
else ShowError(IDS_MULPAT, "mod_pdb_alloc");
}
DBGPRINTF(("%s: pattern found @ 0x%08x\n", "mod_pdb_alloc",
pefile.PointerToRva((void*) found_loc) + pefile.GetImageBase()));
set_pattern(found_loc, after, length);
}
void Patch::find_ExportFromX()
{
static const short pattern[] = {
0x8B,0x0D,-1,-1,-1,-1,0x0F,0xBF,0x40,0x10,0x8B,0x14,0x81,0x8B,0x44,
0x24,0x14,0x3D,0x00,0x00,0x01,0x00,0x8B,0x4A,0x04,0x73,0x15,-1,0x1D,
-1,-1,-1,-1,0x75,0x04,0x6A,0x32,0xEB,0x3E,0x50,0x51,0xE8,-2,-2,-2,-2,
0xEB,0x0C,0xFF,0x74,0x24,0x14,0x6A,0x00,0x51,0xE8,-2,-2,-2,-2,0x83,
0x7F,0x54,0x00,0x8B,0xF0
};
DWORD offset = (DWORD) pefile.GetSectionByName(CODE_SEG);
int size = pefile.GetSectionSize(CODE_SEG);
int length = sizeof(pattern) / sizeof(short);
DWORD found_loc;
int found = find_pattern(offset, size,pattern, length, &found_loc);
if (found != 1)
{
if (!found) ShowError(IDS_NOPAT, "exportfromX");
else ShowError(IDS_MULPAT, "exportfromX");
}
DBGPRINTF(("%s: pattern found @ 0x%08x\n", "exportfromX",
pefile.PointerToRva((void*) found_loc) + pefile.GetImageBase()));
gpa_ExportFromOrdinal_call = found_loc + 0x29;
gpa_ExportFromName_call = found_loc + 0x37;
_ExportFromOrdinal = decode_call(gpa_ExportFromOrdinal_call, 5);
_ExportFromName = decode_call(gpa_ExportFromName_call, 5);
DWORD start = (DWORD) pefile.RvaToPointer(_ExportFromName);
for (DWORD a = start ; a < start + 0x100 ; a++)
if (is_call_ref(a, _ExportFromOrdinal))
EFN_EFO_call = a;
}
void Patch::find_IsKnownDLL()
{
static const short pattern[] = {
0xFF,0x75,0xFC,0x8D,0x8D,0xF0,0xFE,0xFF,0xFF,0x51,0xE8,-2,-2,-2,-2,
0x85,0xC0,0x75,0x1E,0x8D,0x85,0xE8,0xFD,0xFF,0xFF,
0x8D,0x8D,0xF0,0xFE,0xFF,0xFF,0x50,0x51
};
DWORD offset = (DWORD) pefile.GetSectionByName(CODE_SEG);
int size = pefile.GetSectionSize(CODE_SEG);
int length = sizeof(pattern) / sizeof(short);
DWORD found_loc;
int found = find_pattern(offset, size,pattern, length, &found_loc);
if (found != 1)
{
if (!found) ShowError(IDS_NOPAT, "IsKnownDLL");
else ShowError(IDS_MULPAT, "IsKnownDLL");
}
DBGPRINTF(("%s: pattern found @ 0x%08x\n", "IsKnownDLL",
pefile.PointerToRva((void*) found_loc) + pefile.GetImageBase()));
IsKnownDLL_call = found_loc + 10;
_IsKnownDLL = decode_call(IsKnownDLL_call, 5);
}
void Patch::find_FLoadTreeNotify1()
{
static const short pattern[] = {
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
};
DWORD offset = (DWORD) pefile.GetSectionByName(CODE_SEG);
int size = pefile.GetSectionSize(CODE_SEG);
int length = sizeof(pattern) / sizeof(short);
DWORD found_loc;
int found = find_pattern(offset, size,pattern, length, &found_loc);
if (found != 1)
{
if (!found) ShowError(IDS_NOPAT, "FLoadTreeNotify1");
else ShowError(IDS_MULPAT, "FLoadTreeNotify1");
}
DBGPRINTF(("%s: pattern found @ 0x%08x\n", "FLoadTreeNotify1",
pefile.PointerToRva((void*) found_loc) + pefile.GetImageBase()));
FLoadTreeNotify_call1 = found_loc + 16;
_FLoadTreeNotify = decode_call(FLoadTreeNotify_call1, 5);
}
void Patch::find_FLoadTreeNotify2()
{
static const short pattern[] = {
0x6A,0x00,0x57,0xE8,-1,-1,-1,-1,0x6A,0x00,0x56,0xE8,-2,-2,-2,-2,
0x85,0xC0,0x74,0x12,0x56,0xE8,-1,-1,-1,-1,0x68,0x5A,0x04,0x00,0x00,
0x33,0xF6,0xE8,-1,-1,-1,-1
};
DWORD offset = (DWORD) pefile.GetSectionByName(CODE_SEG);
int size = pefile.GetSectionSize(CODE_SEG);
int length = sizeof(pattern) / sizeof(short);
DWORD found_loc;
int found = find_pattern(offset, size,pattern, length, &found_loc);
if (found != 1)
{
if (!found) ShowError(IDS_NOPAT, "FLoadTreeNotify2");
else ShowError(IDS_MULPAT, "FLoadTreeNotify2");
}
DBGPRINTF(("%s: pattern found @ 0x%08x\n", "FLoadTreeNotify2",
pefile.PointerToRva((void*) found_loc) + pefile.GetImageBase()));
FLoadTreeNotify_call2 = found_loc + 11;
}
DWORD Patch::decode_call(DWORD addr, int len)
{
unsigned char* code = (unsigned char*)addr;
/* CALL rel32 */
if (code[0] == 0xe8)
{
if (len && len == 5 || !len)
return (DWORD)(pefile.PointerToRva(code) + 5 + *(INT32*)(code + 1));
}
/* CALL imm32 */
else if (code[0] == 0xff && code[1] == 0x15)
{
if (len && len == 6 || !len)
return *(DWORD*)(code + 2);
}
/* unmatched */
return 0;
}
DWORD Patch::decode_jmp(DWORD addr, int len)
{
unsigned char* code = (unsigned char*)addr;
/* JMP rel8 */
if (code[0] == 0xeb)
{
if (len && len == 2 || !len)
return (DWORD)(pefile.PointerToRva(code) + 2 + *(INT8*)(code + 1));
}
/* JMP rel32 */
else if (code[0] == 0xe9)
{
if (len && len == 5 || !len)
return (DWORD)(pefile.PointerToRva(code) + 5 + *(INT32*)(code + 1));
}
/* JMP imm32 */
else if (code[0] == 0xff && code[1] == 0x25)
{
if (len && len == 6 || !len)
return *(DWORD*)(code + 2);
}
/* Jxx rel8 */
else if (code[0] >= 0x70 && code[0] < 0x7f || code[0] == 0xe3)
{
if (len && len == 2 || !len)
return (DWORD)(pefile.PointerToRva(code) + 2 + *(INT8*)(code + 1));
}
/* Jxx rel32 */
else if (code[0] == 0x0f && code[1] >= 0x80 && code[1] <= 0x8f)
{
if (len && len == 6 || !len)
return (DWORD)(pefile.PointerToRva(code) + 6 + *(INT32*)(code + 2));
}
/* unmatched */
return 0;
}
bool Patch::is_call_ref(DWORD loc, DWORD target)
{
DWORD addr = decode_call(loc, 5); // size of call imm32 opcode
if (addr == target)
return true;
return false;
}
// Both addresses have to be from the same section!
void Patch::set_call_ref(DWORD loc, DWORD target)
{
DWORD rel;
assert(*(BYTE*) loc == 0xe8);
rel = target - (loc + 5);
*(DWORD*)(loc + 1) = rel;
}
// Both addresses have to be from the same section!
void Patch::set_jmp_ref(DWORD loc, DWORD target)
{
DWORD rel;
unsigned char* code = (unsigned char*)loc;
if (code[0] == 0xe9)
{
rel = target - (loc + 5);
*(DWORD*)(loc + 1) = rel;
}
else if (code[0] == 0x0f && code[1] >= 0x80 && code[1] <= 0x8f)
{
rel = target - (loc + 6);
*(DWORD*)(loc + 2) = rel;
}
else assert(false);
}
bool Patch::is_fixupc(DWORD addr)
{
if (*(DWORD*)(addr - 5) == 0xDAC)
return true;
return false;
}

View File

@ -1,26 +0,0 @@
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by setup.rc
//
#define IDS_OLDKEX 1
#define IDS_NOPAT 2
#define IDS_MULPAT 3
#define IDS_FAILOPEN 4
#define IDS_FAILSEC 5
#define IDS_FAILBAK 6
#define IDS_ERRCHECK 7
#define IDS_FAILOPENBACKUP 8
#define IDS_WINVER 9
#define IDS_DOWNGRADE 10
#define IDS_REBOOT 11
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@ -1,352 +0,0 @@
/*
* KernelEx
* Copyright (C) 2008-2010, Xeno86
*
* This file is part of KernelEx source code.
*
* KernelEx is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; version 2 of the License.
*
* KernelEx is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <windows.h>
#include <tlhelp32.h>
#include <cstdio>
#include <cstdarg>
#include "debug.h"
#include "loadstub.h"
#include "pemanip.h"
#include "setup.h"
#include "wininit.h"
#include "version.h"
#include "resource.h"
#include "patch.h"
#define DATA_SEG ".data"
void ShowError(UINT id, ...)
{
char format[512];
char out[512];
va_list vargs;
va_start(vargs, id);
if (!LoadString(GetModuleHandle(NULL), id, format, sizeof(format)))
sprintf(out, "ERROR: Missing string resource %d", id);
else
_vsnprintf(out, sizeof(out), format, vargs);
va_end(vargs);
DBGPRINTF(("%s\n", out));
MessageBox(NULL, out, "KernelEx Setup", MB_OK | MB_ICONERROR);
exit(id);
}
Setup::Setup(char* _backup_file) : backup_file(strupr(_backup_file))
{
h_kernel32 = GetModuleHandle("KERNEL32");
detect_old_version();
detect_downgrade();
version = get_signature_ver();
OSVERSIONINFOA osv;
osv.dwOSVersionInfoSize = sizeof(osv);
GetVersionEx(&osv);
if ((osv.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS)
|| (osv.dwMajorVersion != 4)
|| (osv.dwMinorVersion != 10 && osv.dwMinorVersion != 90))
ShowError(IDS_WINVER);
//on WinMe and file called "setup.exe" we get 4.10 (lol)
if (osv.dwMinorVersion == 90)
{
DBGPRINTF(("Detected Windows Me\n"));
is_winme = true;
}
else
{
DBGPRINTF(("Detected Windows 98\n"));
is_winme = false;
}
}
bool Setup::detect_old_version()
{
typedef void (WINAPI *KV_t)(char *);
KV_t h_KVersion;
char buf[32];
h_KVersion = (KV_t)GetProcAddress(h_kernel32, "KUPVersion");
if (!h_KVersion)
h_KVersion = (KV_t)GetProcAddress(h_kernel32, "KEXVersion");
if (!h_KVersion)
return false;
h_KVersion(buf);
if (strcmp(buf, "4") < 0)
ShowError(IDS_OLDKEX);
return true;
}
void Setup::detect_downgrade()
{
typedef unsigned long (*kexGetKEXVersion_t)();
kexGetKEXVersion_t kexGetKEXVersion_pfn;
HMODULE h_kernelex;
unsigned long version;
h_kernelex = LoadLibrary("KERNELEX.DLL");
//no KernelEx installed, continue
if (!h_kernelex)
return;
kexGetKEXVersion_pfn = (kexGetKEXVersion_t) GetProcAddress(h_kernelex, "kexGetKEXVersion");
version = kexGetKEXVersion_pfn();
FreeLibrary(h_kernelex);
//trying to downgrade - forbid
if (version > VERSION_CODE)
ShowError(IDS_DOWNGRADE);
}
int Setup::get_signature_ver()
{
DWORD ptr;
KernelEx_dataseg* dseg = NULL;
DWORD sign_len = sizeof(KEX_SIGNATURE) - 1;
PEmanip pemem;
pemem.OpenMemory(h_kernel32);
if (!pemem.HasTarget())
ShowError(IDS_FAILOPEN, "KERNEL32 memory image");
DWORD data = (DWORD) pemem.GetSectionByName(DATA_SEG);
int data_size = pemem.GetSectionSize(DATA_SEG);
ptr = data + data_size - sign_len;
while (ptr >= data)
{
if (!memcmp((void*)ptr, KEX_SIGNATURE, sign_len))
{
dseg = (KernelEx_dataseg*) ptr;
break;
}
ptr--;
}
if (!dseg)
{
DBGPRINTF(("Signature not found\n"));
return -1;
}
else
DBGPRINTF(("Signature found @ 0x%08x\n", ptr));
return dseg->version;
}
void Setup::kill_process(const char* name)
{
PROCESSENTRY32 pe32;
void * h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (h == INVALID_HANDLE_VALUE)
return;
pe32.dwSize = sizeof(PROCESSENTRY32);
Process32First(h, &pe32);
do
{
if (strstr(pe32.szExeFile, name))
{
DBGPRINTF(("Terminating process: %s... ", name));
HANDLE hp = OpenProcess(PROCESS_TERMINATE, FALSE, pe32.th32ProcessID);
if (hp == INVALID_HANDLE_VALUE)
{
DBGPRINTF(("open fail\n"));
continue;
}
if (TerminateProcess(hp, 0))
DBGPRINTF(("ok\n"));
else
DBGPRINTF(("fail\n"));
CloseHandle(hp);
}
}
while (Process32Next(h, &pe32));
CloseHandle(h);
}
sstring Setup::get_temp_file_name()
{
char tmpdir[MAX_PATH];
char target[MAX_PATH];
GetSystemDirectory(tmpdir, sizeof(tmpdir));
GetTempFileName(tmpdir, "kex", 0, target);
return target;
}
void Setup::install()
{
upgrade = false;
if (version >= 0)
{
if (version == KEX_STUB_VER)
{
DBGPRINTF(("No need to upgrade\n"));
return;
}
else
{
upgrade = true;
}
}
char kernel32path[MAX_PATH];
GetModuleFileName(h_kernel32, kernel32path, sizeof(kernel32path));
PEmanip pefile;
pefile.OpenFile(upgrade ? backup_file : kernel32path, 0x10000);
if (!pefile.HasTarget())
{
if (upgrade)
ShowError(IDS_FAILOPENBACKUP, (const char*) backup_file, kernel32path);
else
ShowError(IDS_FAILOPEN, kernel32path);
}
Patch patch(pefile);
patch.apply();
// backup original file
if (!upgrade)
{
if (!CopyFile(kernel32path, backup_file, FALSE))
ShowError(IDS_FAILBAK, (const char*) backup_file);
}
// save patched file
sstring tmp_file = get_temp_file_name();
pefile.SaveFile(tmp_file);
if (is_winme)
{
kill_process("\\STATEMGR.EXE");
kill_process("\\STMGR.EXE");
}
Wininit.add(kernel32path, tmp_file);
if (is_winme)
{
char path[MAX_PATH];
GetWindowsDirectory(path, sizeof(path));
if (path[strlen(path) - 1] != '\\')
strcat(path, "\\");
strcat(path, "WININIT.LOG");
Wininit.add("NUL", path);
path[3] = '\0';
strcat(path, "_RESTORE\\TEMP");
Wininit.add("DIRNUL", path);
}
Wininit.save();
}
void Setup::set_reboot_flag()
{
HKEY hkey;
if (RegCreateKey(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\"
"CurrentVersion\\RunServicesOnce", &hkey) == ERROR_SUCCESS)
{
RegSetValueEx(hkey, "KexNeedsReboot", 0, REG_SZ, (const BYTE*) "", 1);
RegCloseKey(hkey);
}
}
void Setup::register_verify()
{
HKEY hkey;
DWORD type;
char verify_path[MAX_PATH];
DWORD size = sizeof(verify_path);
LONG res;
res = RegOpenKey(HKEY_LOCAL_MACHINE, "Software\\KernelEx", &hkey);
if (res != ERROR_SUCCESS)
return;
res = RegQueryValueEx(hkey, "InstallDir", 0, &type, (BYTE*) verify_path, &size);
RegCloseKey(hkey);
if (res != ERROR_SUCCESS)
return;
strcat(verify_path, "\\verify.exe");
if (RegCreateKey(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\"
"CurrentVersion\\Run", &hkey) == ERROR_SUCCESS)
{
RegSetValueEx(hkey, "KexVerify", 0, REG_SZ, (BYTE*) verify_path,
strlen(verify_path) + 1);
RegCloseKey(hkey);
}
}
void Setup::reboot()
{
char out[512];
if (!LoadString(GetModuleHandle(NULL), IDS_REBOOT, out, sizeof(out)))
sprintf(out, "ERROR: Missing string resource %d", IDS_REBOOT);
int res = MessageBox(NULL, out, "KernelEx Setup", MB_OKCANCEL | MB_ICONQUESTION);
if (res == IDOK)
{
DBGPRINTF(("Rebooting...\n"));
ExitWindowsEx(EWX_REBOOT, 0);
}
}
int main(int argc, char** argv)
{
bool reboot = false;
DBGPRINTF(("KernelEx setup program running\n"));
if (argc != 1 && argc != 2)
return 1;
if (argc == 2 && !strcmp(argv[1], "/R"))
reboot = true;
char backup_path[MAX_PATH];
GetWindowsDirectory(backup_path, MAX_PATH);
if (backup_path[strlen(backup_path)-1] != '\\')
strcat(backup_path, "\\");
strcat(backup_path, "SYSBCKUP\\KERNEL32.DLL");
Setup setup(backup_path);
setup.install();
DBGPRINTF(("Setup finished\n"));
if (reboot)
setup.reboot();
setup.set_reboot_flag();
setup.register_verify();
return 0;
}

View File

@ -1,96 +0,0 @@
//Microsoft Developer Studio generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// Neutral resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU)
#ifdef _WIN32
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
#pragma code_page(1250)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE DISCARDABLE
BEGIN
IDS_OLDKEX "Setup has detected previous version of KernelEx installed on this computer. Please uninstall it before continuing."
IDS_NOPAT "ERROR: %s: pattern not found"
IDS_MULPAT "ERROR: %s: multiple pattern matches"
IDS_FAILOPEN "ERROR: Failed to open %s"
IDS_FAILSEC "ERROR: Failed to allocate %s section memory"
IDS_FAILBAK "ERROR: Failed to create backup in %s"
IDS_ERRCHECK "ERROR: Checksum error"
IDS_FAILOPENBACKUP "ERROR: Failed to open backup file %s.\nPossible causes: previous version not uninstalled correctly or file has been deleted.\nRestore %s manually from install media."
IDS_WINVER "Incompatible Windows version"
IDS_DOWNGRADE "Can't downgrade. Please uninstall currently installed version of KernelEx before continuing."
IDS_REBOOT "KernelEx has to restart this computer in order to complete setup.\nDo you wish to do this now?"
END
#endif // Neutral resources
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// Polish resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_PLK)
#ifdef _WIN32
LANGUAGE LANG_POLISH, SUBLANG_DEFAULT
#pragma code_page(1250)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#endif // Polish resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@ -1,154 +0,0 @@
/*
* KernelEx
* Copyright (C) 2007-2008, 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.
*
*/
/** @file wininit.h
* Class WININIT.
*/
#ifndef __WININIT_H
#define __WININIT_H
#include "sstring.hpp"
#include <queue>
using namespace std;
/** @class WININIT
* Maintains wininit.ini entries.
*/
class WININIT
{
/** @struct _2files
* Helper struct holding two filenames.
*/
struct _2files
{
_2files(const sstring& d, const sstring& s) : dest(d), src(s) {}
sstring dest;
sstring src;
};
/** Stack holding wininit.ini entries. */
std::queue<_2files> que;
/** Holds path to wininit.ini file. */
char InitFile[MAX_PATH];
public:
/** Constructor. */
WININIT()
{
if (GetWindowsDirectory(InitFile, MAX_PATH) > 3) strcat(InitFile, "\\");
strcat(InitFile, "WININIT.INI");
}
/** Destructor. */
~WININIT()
{
clear();
}
/** Deletes all files not saved by save() method. @see save */
void clear()
{
if (!que.empty()) DBGPRINTF(("\nRemoving temporary files ...\n"));
while (!que.empty())
{
DeleteFile(que.front().src);
DBGPRINTF(("... %s\n", que.front().src));
que.pop();
}
}
/** Checks if wininit.ini file exists.
* @return true if exists, false otherwise.
*/
bool exists()
{
return (GetFileAttributes(InitFile) != 0xffffffff);
}
/** Pushes new source-destination pair onto the stack.
* @param dest Destination file name (or 'NUL' for delete).
* @param src Source file name.
*/
void add(const sstring& dest, const sstring& src)
{
_2files t(dest, src);
que.push(t);
}
/** Saves all data from stack to wininit.ini file. */
bool save()
{
char buf[32767];
int buf_len;
if (que.empty())
return true;
buf_len = GetPrivateProfileSection("rename", buf, sizeof(buf), "wininit.ini");
DBGPRINTF(("\nSaving WININIT.INI entries ...\n"));
while (!que.empty())
{
char line[256];
int line_len;
char short_dest[MAX_PATH];
char short_src[MAX_PATH];
if (!GetShortPathName(que.front().dest, short_dest, sizeof(short_dest)))
//if fail, assume destination doesn't exit
//fixme: may not be short path name or be invalid path name
strcpy(short_dest, que.front().dest);
if (!GetShortPathName(que.front().src, short_src, sizeof(short_src)))
strcpy(short_src, que.front().src);
strcpy(line, short_dest);
strcat(line, "=");
strcat(line, short_src);
strcat(line, "\r\n");
line_len = strlen(line);
if (buf_len + line_len + 2 <= sizeof(buf))
{
DBGPRINTF(("... %s => %s\n", (const char*) que.front().src,
(const char*) que.front().dest));
memcpy(&buf[buf_len], line, line_len);
buf_len += line_len;
}
else //buffer overflow
return false;
que.pop();
}
buf[buf_len] = 0;
buf[buf_len + 1] = 0;
if (WritePrivateProfileSection("rename", buf, "wininit.ini"))
return true;
return false;
}
} Wininit;
#endif // __WININIT_H

BIN
util/msvc6chk.zip Executable file

Binary file not shown.

BIN
util/sdbcreate/sdbdb/KernelEx.sdb Executable file

Binary file not shown.

View File

@ -0,0 +1,35 @@
REGEDIT4
[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Custom\{90120000-0020-0409-0000-0000000FF1CE}]
"KernelEx.sdb"="Office 2007 File Format Converters"
[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Custom\{90850409-6000-11D3-8CFE-0150048383C9}]
"KernelEx.sdb"="Word Viewer 2003"
[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Custom\{90840409-6000-11D3-8CFE-0150048383C9}]
"KernelEx.sdb"="Excel Viewer 2003"
[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Custom\{90110409-6000-11D3-8CFE-0150048383C9}]
"KernelEx.sdb"="Office 2003 Professional"
[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Custom\{B59EF430-4849-11DF-B1EC-005056806466}]
"KernelEx.sdb"="Google Earth 5.1"
[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Custom\{C084BC61-E537-11DE-8616-005056806466}]
"KernelEx.sdb"="Google Earth 5.1.7894.7252"
[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Custom\{2EAF7E61-068E-11DF-953C-005056806466}]
"KernelEx.sdb"="Google Earth 5.2"
[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Custom\{4286E640-B5FB-11DF-AC4B-005056C00008}]
"KernelEx.sdb"="Google Earth 5.2.1.1588"
[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Custom\{6DB7AD00-F781-11DF-9EEF-001279CD8240}]
"KernelEx.sdb"="Google Earth 6 beta"
[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Custom\{BE06114F-559D-11E0-B5A1-001D0926B1BF}]
"KernelEx.sdb"="Google Earth 6.0.2.2074"
[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Custom\{AC76BA86-7AD7-1033-7B44-A70900000002}]
"KernelEx.sdb"="Acrobat Reader 7"

View File

@ -0,0 +1,24 @@
REGEDIT4
[-HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Custom\{90120000-0020-0409-0000-0000000FF1CE}]
[-HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Custom\{90850409-6000-11D3-8CFE-0150048383C9}]
[-HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Custom\{90840409-6000-11D3-8CFE-0150048383C9}]
[-HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Custom\{90110409-6000-11D3-8CFE-0150048383C9}]
[-HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Custom\{B59EF430-4849-11DF-B1EC-005056806466}]
[-HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Custom\{C084BC61-E537-11DE-8616-005056806466}]
[-HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Custom\{2EAF7E61-068E-11DF-953C-005056806466}]
[-HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Custom\{4286E640-B5FB-11DF-AC4B-005056C00008}]
[-HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Custom\{6DB7AD00-F781-11DF-9EEF-001279CD8240}]
[-HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Custom\{BE06114F-559D-11E0-B5A1-001D0926B1BF}]
[-HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Custom\{AC76BA86-7AD7-1033-7B44-A70900000002}]

47
vxd/KernelEx.def Executable file
View File

@ -0,0 +1,47 @@
;
; KernelEx
; Copyright (C) 2011, Xeno86
;
; This file is part of KernelEx source code.
;
; KernelEx is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published
; by the Free Software Foundation; version 2 of the License.
;
; KernelEx is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with GNU Make; see the file COPYING. If not, write to
; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
;
VXD VKRNLEX DYNAMIC
DESCRIPTION 'KernelEx Virtual Device'
SEGMENTS
_LPTEXT CLASS 'LCODE' PRELOAD NONDISCARDABLE
_LTEXT CLASS 'LCODE' PRELOAD NONDISCARDABLE
_LDATA CLASS 'LCODE' PRELOAD NONDISCARDABLE
_TEXT CLASS 'LCODE' PRELOAD NONDISCARDABLE
_DATA CLASS 'LCODE' PRELOAD NONDISCARDABLE
CONST CLASS 'LCODE' PRELOAD NONDISCARDABLE
_TLS CLASS 'LCODE' PRELOAD NONDISCARDABLE
_BSS CLASS 'LCODE' PRELOAD NONDISCARDABLE
_ITEXT CLASS 'ICODE' DISCARDABLE
_IDATA CLASS 'ICODE' DISCARDABLE
_PTEXT CLASS 'PCODE' NONDISCARDABLE
_PDATA CLASS 'PDATA' NONDISCARDABLE SHARED
_STEXT CLASS 'SCODE' RESIDENT
_SDATA CLASS 'SCODE' RESIDENT
_DBOSTART CLASS 'DBOCODE' PRELOAD NONDISCARDABLE CONFORMING
_DBOCODE CLASS 'DBOCODE' PRELOAD NONDISCARDABLE CONFORMING
_DBODATA CLASS 'DBOCODE' PRELOAD NONDISCARDABLE CONFORMING
_16ICODE CLASS '16ICODE' PRELOAD DISCARDABLE
_RCODE CLASS 'RCODE'
EXPORTS
_VKRNLEX_DDB @1

42
vxd/debug.cpp Executable file
View File

@ -0,0 +1,42 @@
/*
* 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.
*
*/
extern "C" {
#include <basedef.h>
#include <vmm.h>
};
#include <string.h>
#include <malloc.h>
#include "debug.h"
void debug_printf(const char* fmt, ...)
{
char* newfmt = (char*) alloca(strlen(fmt) + 10);
strcpy(newfmt, "VKRNLEX: ");
strcat(newfmt, fmt);
strcat(newfmt, "\n");
__asm lea eax,(fmt + 4)
__asm push eax
__asm push newfmt
VMMCall(_Debug_Printf_Service)
__asm add esp, 2*4
}

View File

@ -1,6 +1,6 @@
/*
* KernelEx
* Copyright (C) 2009, Xeno86
* Copyright (C) 2011, Xeno86
*
* This file is part of KernelEx source code.
*
@ -23,8 +23,8 @@
#define __DEBUG_H
#ifdef _DEBUG
#include <stdio.h>
#define DBGPRINTF(x) printf x
void debug_printf(const char* fmt, ...);
#define DBGPRINTF(x) debug_printf x
#else
#define DBGPRINTF(x) do {} while (0)
#endif

View File

@ -1,6 +1,6 @@
/*
* KernelEx
* Copyright (C) 2008-2010, Xeno86
* Copyright (C) 2008-2011, Xeno86
*
* This file is part of KernelEx source code.
*
@ -19,25 +19,29 @@
*
*/
#ifndef __LOADSTUB_H
#define __LOADSTUB_H
#ifndef __INTERFACE_H
#define __INTERFACE_H
/* Update this whenever patching functions are changed. */
#define KEX_STUB_VER 11
#define KEX_SIGNATURE "KrnlEx"
/* Update this whenever patching functions are changed. */
#define KEX_STUB_VER 10
#define JTAB_SIZE 8
#define JTAB_EFO_DYN 0
#define JTAB_EFO_STA 1
#define JTAB_EFN_DYN 2
#define JTAB_EFN_STA 3
#define JTAB_KNO_DLL 4
#define JTAB_FLD_TRN 5
#define JTAB_SYS_CHK 6
#define JTAB_RES_CHK 7
enum
{
JTAB_EFO_DYN,
JTAB_EFO_STA,
JTAB_EFN_DYN,
JTAB_EFN_STA,
JTAB_KNO_DLL,
JTAB_FLD_TRN,
JTAB_SYS_CHK,
JTAB_RES_CHK,
JTAB_SIZE
};
#include <pshpack1.h>
typedef struct
struct KernelEx_codeseg
{
char signature[6]; /* "KrnlEx" */
unsigned short version;
@ -47,14 +51,27 @@ typedef struct
DWORD addr; /* address to jtab */
WORD nop; /* dword align */
} jmp_stub[JTAB_SIZE];
} KernelEx_codeseg;
};
typedef struct
struct KernelEx_dataseg
{
char signature[6]; /* "KrnlEx" */
unsigned short version;
DWORD jtab[JTAB_SIZE];
} KernelEx_dataseg;
};
#include <poppack.h>
/*
* IOCTL Support
*/
#define IOCTL_CONNECT 1
struct ioctl_connect_params
{
WORD vxd_version;
bool status;
KernelEx_dataseg* stub_ptr;
};
#endif

223
vxd/patch.cpp Executable file
View File

@ -0,0 +1,223 @@
/*
* KernelEx
* Copyright (C) 2010-2011, Xeno86
*
* This file is part of KernelEx source code.
*
* KernelEx is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; version 2 of the License.
*
* KernelEx is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <windows.h>
#include <cassert>
#include "patch.h"
#include "debug.h"
extern "C" {
#define WANTVXDWRAPS
#include <vmm.h>
#include <vxdwraps.h>
};
#ifdef _DEBUG
const struct
{
MessageID id;
const char* desc;
}
MessageText[] =
{
IDS_NOPAT, "ERROR: %s: pattern not found",
IDS_MULPAT, "ERROR: %s: multiple pattern matches",
IDS_FAILSEC, "ERROR: Failed to allocate %s section memory",
IDS_ERRCHECK, "ERROR: Checksum error",
IDS_WINVER, "Incompatible Windows version",
IDS_DOWNGRADE, "Can't downgrade. Please uninstall currently installed version of KernelEx before continuing.",
};
#endif
void Patch::ShowError(MessageID id, ...)
{
#ifdef _DEBUG
const char* format = NULL;
char out[512];
va_list vargs;
va_start(vargs, id);
for (int i = 0 ; i < sizeof(MessageText) / sizeof(MessageText[0]) ; i++)
{
if (MessageText[i].id == id)
{
format = MessageText[i].desc;
break;
}
}
assert(format != NULL);
_Vsprintf(out, const_cast<char*>(format), vargs);
va_end(vargs);
strcat(out, "\n");
debug_printf(out);
#endif
abort();
}
int Patch::find_pattern(DWORD offset, int size, const short* pattern,
int pat_len, DWORD* found_loc)
{
DWORD end_offset = offset + size - pat_len;
int found = 0;
for (DWORD i = offset ; i <= end_offset ; i++)
{
if (pattern[0] < 0 || *(unsigned char*)i == pattern[0])
{
int j;
for (j = 1 ; j < pat_len ; j++)
{
if (pattern[j] >= 0 && *(unsigned char*)(i + j) != pattern[j])
break;
}
if (j == pat_len) //pattern found
{
*found_loc = i;
found++;
}
}
}
return found;
}
void Patch::set_pattern(DWORD loc, const short* new_pattern, int pat_len)
{
unsigned char* offset = (unsigned char*) loc;
const short* pat_ptr = new_pattern;
while (pat_len--)
{
if (*pat_ptr != -1)
*offset = *pat_ptr & 0xff;
offset++;
pat_ptr++;
}
pagelock(loc, pat_len);
}
DWORD Patch::decode_call(DWORD addr, int len)
{
unsigned char* code = (unsigned char*)addr;
/* CALL rel32 */
if (code[0] == 0xe8)
{
if (len && len == 5 || !len)
return (DWORD)((DWORD)code + 5 + *(INT32*)(code + 1));
}
/* CALL imm32 */
else if (code[0] == 0xff && code[1] == 0x15)
{
if (len && len == 6 || !len)
return *(DWORD*)(code + 2);
}
/* unmatched */
return 0;
}
DWORD Patch::decode_jmp(DWORD addr, int len)
{
unsigned char* code = (unsigned char*)addr;
/* JMP rel8 */
if (code[0] == 0xeb)
{
if (len && len == 2 || !len)
return (DWORD)((DWORD)code + 2 + *(INT8*)(code + 1));
}
/* JMP rel32 */
else if (code[0] == 0xe9)
{
if (len && len == 5 || !len)
return (DWORD)((DWORD)code + 5 + *(INT32*)(code + 1));
}
/* JMP imm32 */
else if (code[0] == 0xff && code[1] == 0x25)
{
if (len && len == 6 || !len)
return *(DWORD*)(code + 2);
}
/* Jxx rel8 */
else if (code[0] >= 0x70 && code[0] < 0x7f || code[0] == 0xe3)
{
if (len && len == 2 || !len)
return (DWORD)((DWORD)code + 2 + *(INT8*)(code + 1));
}
/* Jxx rel32 */
else if (code[0] == 0x0f && code[1] >= 0x80 && code[1] <= 0x8f)
{
if (len && len == 6 || !len)
return (DWORD)((DWORD)code + 6 + *(INT32*)(code + 2));
}
/* unmatched */
return 0;
}
bool Patch::is_call_ref(DWORD loc, DWORD target)
{
DWORD addr = decode_call(loc, 5); // size of call imm32 opcode
if (addr == target)
return true;
return false;
}
// Both addresses have to be from the same section!
void Patch::set_call_ref(DWORD loc, DWORD target)
{
DWORD rel;
assert(*(BYTE*) loc == 0xe8);
rel = target - (loc + 5);
*(DWORD*)(loc + 1) = rel;
pagelock(loc + 1, sizeof(DWORD));
}
// Both addresses have to be from the same section!
void Patch::set_jmp_ref(DWORD loc, DWORD target)
{
DWORD rel;
unsigned char* code = (unsigned char*)loc;
if (code[0] == 0xe9)
{
rel = target - (loc + 5);
*(DWORD*)(loc + 1) = rel;
pagelock(loc + 1, sizeof(DWORD));
}
else if (code[0] == 0x0f && code[1] >= 0x80 && code[1] <= 0x8f)
{
rel = target - (loc + 6);
*(DWORD*)(loc + 2) = rel;
pagelock(loc + 2, sizeof(DWORD));
}
else assert(false);
}
void Patch::pagelock(DWORD addr, DWORD count)
{
_LinPageLock(PAGE(addr), NPAGES((addr & PAGEMASK) + count), 0);
}

53
vxd/patch.h Executable file
View File

@ -0,0 +1,53 @@
/*
* KernelEx
* Copyright (C) 2010-2011, Xeno86
*
* This file is part of KernelEx source code.
*
* KernelEx is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; version 2 of the License.
*
* KernelEx is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef __PATCH_H
#define __PATCH_H
enum MessageID
{
IDS_NOPAT,
IDS_MULPAT,
IDS_FAILSEC,
IDS_ERRCHECK,
IDS_WINVER,
IDS_DOWNGRADE,
};
class Patch
{
public:
Patch() {}
virtual bool apply() = 0;
protected:
void ShowError(MessageID id, ...);
static int find_pattern(DWORD offset, int size, const short* pattern, int pat_len, DWORD* found_loc);
void set_pattern(DWORD loc, const short* new_pattern, int pat_len);
DWORD decode_call(DWORD addr, int len = 0);
DWORD decode_jmp(DWORD addr, int len = 0);
bool is_call_ref(DWORD loc, DWORD target);
void set_call_ref(DWORD loc, DWORD target);
void set_jmp_ref(DWORD loc, DWORD target);
void pagelock(DWORD addr, DWORD count);
};
#endif

178
vxd/patch_ifsmgr.cpp Executable file
View File

@ -0,0 +1,178 @@
/*
* KernelEx
* Copyright (C) 2011, Xeno86
*
* This file is part of KernelEx source code.
*
* KernelEx is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; version 2 of the License.
*
* KernelEx is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
extern "C" {
#define WANTVXDWRAPS
#include <basedef.h>
#include <vmm.h>
#include <vxdwraps.h>
};
#include "patch_ifsmgr.h"
#include "debug.h"
#include "util.h"
#define __IFSMGR_CheckLocks 0x00400056
/*
* This is a fix against a problem where you can't access a locked file
* through memory mapping object.
*
* Why accessing a locked file through memory mapping object doesn't work?
*
* IFSMgr normally checks if the process is an owner of the lock
* and depending on that either allows to access the file or not.
*
* This works fine in case scenario 1. where the file is read directly.
*
* Accessing a file through memory mapping object is a different beast.
* The file is loaded into memory by the system on demand, through a page
* fault trap (see 2.), this causes a read of a page-sized chunk of file.
* However this time it is the system not the application who's reading
* the file, so process ID is set to -1. This value is not checked
* against when the file is verified for access regarding the locks.
*
* The fix is to allow the access to a locked file if PID is -1.
*/
#if 0 /* Test case */
int main()
{
HANDLE file, mapp;
void* view;
char buf[4096];
BOOL ret;
DWORD dw;
file = CreateFileA("File.txt", GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,
NULL);
ret = LockFile(file, 128, 0, 1, 0);
SetFilePointer(file, 32768, 0, 0);
SetEndOfFile(file);
mapp = CreateFileMapping(file, NULL, PAGE_READWRITE, 0, 32768, NULL);
view = MapViewOfFile(mapp, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 32768);
SetFilePointer(file, 0, 0, 0);
//!!!!! 1. This works out of the box
ReadFile(file, buf, 4096, &dw, NULL);
//!!!!! 2. This triggers a crash without the fix
memcpy(buf, view, 4096);
UnmapViewOfFile(view);
CloseHandle(mapp);
UnlockFile(file, 128, 0, 1, 0);
CloseHandle(file);
}
#endif
__declspec(naked)
int IFSMGR_CheckLocks_fixed(
void* handle,
DWORD pos,
DWORD count,
DWORD owner,
DWORD finst,
DWORD flags
)
{
__asm {
push ebp
mov ebp,esp
push ebx
push esi
push edi
mov eax,[ebp+10h]
or eax,eax
jnz _L1
sub eax,eax
jmp _exit_grant
_L1:
mov edi,[ebp+0Ch]
lea ecx,[eax+edi-1]
cmp ecx,edi
jnb _L2
jmp _exit_forbid
_L2:
mov esi,[ebp+8]
sub eax,eax
cmp [esi+0Ch],edi
jb _exit_grant
cmp [esi+8],ecx
ja _exit_grant
mov edx,[esi]
cmp esi,edx
jz _exit_grant
//the fix
mov ebx,[ebp+14h]
cmp ebx,-1
jz _exit_grant
//end of the fix
_loop:
cmp [edx+8],ecx
ja _exit_grant
cmp [edx+0Ch],edi
jb _next
//check lock owner
mov ebx,[ebp+14h]
cmp [edx+14h],ebx
jnz _owner_mismatch
//check file handle
mov ebx,[ebp+18h]
cmp [edx+18h],ebx
jz _next
_owner_mismatch:
mov ebx,[edx+10h]
and ebx,[ebp+1Ch]
test bl,1
jz _exit_forbid
_next:
mov edx,[edx]
cmp esi,edx
jnz _loop
jmp _exit_grant
_exit_forbid:
mov eax,21h
_exit_grant:
pop edi
pop esi
pop ebx
pop ebp
ret
}
}
bool Patch_ifsmgr::apply()
{
DBGPRINTF(("Applying IFSMGR_CheckLocks fix... "));
ULONG serviceid = GetVxDServiceOrdinal(IFSMGR_CheckLocks);
bool ret = Hook_Device_Service(serviceid, (ULONG) IFSMGR_CheckLocks_fixed);
DBGPRINTF((ret ? "... ok" : "... error"));
return ret;
}

View File

@ -1,6 +1,6 @@
/*
* KernelEx
* Copyright (C) 2008-2010, Xeno86
* Copyright (C) 2011, Xeno86
*
* This file is part of KernelEx source code.
*
@ -19,34 +19,15 @@
*
*/
#ifndef __SETUP_H
#define __SETUP_H
#ifndef __PATCH_IFSMGR_H
#define __PATCH_IFSMGR_H
#include "sstring.hpp"
#include "patch.h"
void ShowError(UINT id, ...);
class Setup
class Patch_ifsmgr : public Patch
{
public:
Setup(char* _backup_file);
int get_signature_ver();
void install();
void set_reboot_flag();
void register_verify();
void reboot();
private:
sstring backup_file;
HMODULE h_kernel32;
int version;
bool is_winme;
bool upgrade;
bool detect_old_version();
void detect_downgrade();
void kill_process(const char* name);
sstring get_temp_file_name();
bool apply();
};
#endif

494
vxd/patch_kernel32.cpp Executable file
View File

@ -0,0 +1,494 @@
/*
* KernelEx
* Copyright (C) 2011, Xeno86
*
* This file is part of KernelEx source code.
*
* KernelEx is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; version 2 of the License.
*
* KernelEx is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "pemanip.h"
#include "patch_kernel32.h"
#include "interface.h"
#include "debug.h"
#define CODE_SEG ".text"
#define DATA_SEG ".data"
#define INIT_SEG "_INIT"
Patch_kernel32::Patch_kernel32(PEmanip& pem) : pefile(pem)
{
stub_address = 0;
code_seg_start = (DWORD) pefile.GetSectionByName(CODE_SEG);
code_seg_size = pefile.GetSectionSize(CODE_SEG);
data_seg_start = (DWORD) pefile.GetSectionByName(DATA_SEG);
data_seg_size = pefile.GetSectionSize(DATA_SEG);
}
bool Patch_kernel32::apply()
{
if (find_signature())
{
DBGPRINTF(("KERNEL32 already patched by previous KernelEx version"));
DBGPRINTF(("Make sure pure KERNEL32 is installed before proceeding"));
return false;
}
DBGPRINTF(("Preparing KERNEL32 for KernelEx... "));
if (!find_ExportFromX())
return false;
if (!find_IsKnownDLL())
return false;
if (!find_FLoadTreeNotify1())
return false;
if (!find_FLoadTreeNotify2())
return false;
if (!prepare_subsystem_check())
return false;
if (!find_resource_check1())
return false;
if (!find_resource_check2())
return false;
if (!disable_named_and_rcdata_resources_mirroring())
return false;
if (!mod_imte_alloc())
return false;
if (!mod_mr_alloc())
return false;
if (!mod_pdb_alloc())
return false;
if (!create_stubs())
return false;
DBGPRINTF(("... all done!"));
return true;
}
bool Patch_kernel32::find_signature()
{
DWORD ptr;
KernelEx_dataseg* dseg = NULL;
DWORD sign_len = sizeof(KEX_SIGNATURE) - 1;
ptr = data_seg_start + data_seg_size - sign_len;
ptr = PEmanip::ALIGN(ptr, sizeof(DWORD));
while (ptr >= data_seg_start)
{
if (!memcmp((void*) ptr, KEX_SIGNATURE, sign_len))
{
dseg = (KernelEx_dataseg*) ptr;
break;
}
ptr -= sizeof(DWORD);
}
return dseg != NULL;
}
bool Patch_kernel32::prepare_subsystem_check()
{
static const short pattern[] = {
0x66,0x8b,0x46,0x48,0x66,0x3d,0x04,0x00,0x0f,0x87,0x9c,0x01,0x00,0x00,
0x75,0x0b,0x66,0x83,0x7e,0x4a,0x0a,0x0f,0x87,0x8f,0x01,0x00,0x00,0x66,
0x81,0x7e,0x04,0x4c,0x01,
};
static const short after[] = {
0x66,0x83,0x7E,0x48,0x04,0x75,0x05,0x66,0x83,0x7E,0x4A,0x0A,0xE9,0x00,
0x00,0x00,0x00,0x0F,0x87,0x93,0x01,0x00,0x00,0x90,0x90,0x90,0x90,0x66,
0x81,0x7e,0x04,0x4c,0x01,
};
int length = sizeof(pattern) / sizeof(short);
DWORD found_loc;
int found = find_pattern(code_seg_start, code_seg_size, pattern, length, &found_loc);
if (found != 1)
{
if (!found) ShowError(IDS_NOPAT, "subsystem_check");
else ShowError(IDS_MULPAT, "subsystem_check");
return false;
}
DBGPRINTF(("%s: pattern found @ 0x%08x", "subsystem_check", found_loc));
set_pattern(found_loc, after, length);
SubsysCheck_jmp = found_loc + 12;
_SubsysCheckPerform = decode_jmp(SubsysCheck_jmp, 5);
return true;
}
bool Patch_kernel32::find_resource_check1()
{
static const short pattern[] = {
0x6A,0x00,0x8D,0x45,0xE0,0x50,0xFF,0x75,0xA4,0xFF,0x75,0xD0,0x8D,0x45,
0xCC,0x50,0xFF,0x75,0x08,0xE8,-2,-2,-2,-2,0x85,0xC0
};
int length = sizeof(pattern) / sizeof(short);
DWORD found_loc;
int found = find_pattern(code_seg_start, code_seg_size, pattern, length, &found_loc);
if (found != 1)
{
if (!found) ShowError(IDS_NOPAT, "resource_check1");
else ShowError(IDS_MULPAT, "resource_check1");
return false;
}
DBGPRINTF(("%s: pattern found @ 0x%08x", "resource_check1", found_loc));
GetOrdinal_call1 = found_loc + 19;
_GetOrdinal = decode_call(GetOrdinal_call1, 5);
return true;
}
bool Patch_kernel32::find_resource_check2()
{
static const short pattern[] = {
0x66,0x8B,0x45,0xE0,0x66,0x2D,0x06,0x80,0x66,0x3D,0x01,0x00,0x1B,0xC0,
0xF7,0xD8,0x50,0x8D,0x45,0xDE,0x50,0xFF,0x75, -1,0xFF,0x75,0xD0,0x8D,
0x45,0xCC,0x50,0xFF,0x75,0x08,0xE8, -2, -2, -2, -2,0x85,0xC0
};
int length = sizeof(pattern) / sizeof(short);
DWORD found_loc;
int found = find_pattern(code_seg_start, code_seg_size, pattern, length, &found_loc);
if (found != 1)
{
if (!found) ShowError(IDS_NOPAT, "resource_check2");
else ShowError(IDS_MULPAT, "resource_check2");
return false;
}
DBGPRINTF(("%s: pattern found @ 0x%08x", "resource_check2", found_loc));
GetOrdinal_call2 = found_loc + 34;
return true;
}
//no named/rcdata resource types mirroring
bool Patch_kernel32::disable_named_and_rcdata_resources_mirroring()
{
static const short pattern[] = {
0x66,0x8B,0x40,0x0E,0x66,0x89,0x45,0xDA,0x8B,0x45, -1,0x66,0x8B,0x48,
0x0C,0x66,0x89,0x4D,0xD8,0x66,0x8B,0x45,0xE0,0x8B,0x4D,0xD4,0x66,0x89,
0x01,0x83,0x45,0xD4,0x02,0x66,0x8B,0x45,0xDA,0x66,0x03,0x45,0xD8,0x66,
0x89,0x45,0x8C,0x8B,0x4D,0xD4,0x66,0x89,0x01,0x83,0x45,0xD4,0x02
};
static const short after[] = {
0x66,0x8B,0x48,0x0E,0x66,0x03,0x48,0x0C,0x66,0x89,0x4D,0x8C,0x8B,0x45,
0xA4,0x83,0x38,0x0A,0x74,0x40,0x83,0x38,0x00,0x79,0x04,0x3B,0xC0,0xEB,
0x37,0x66,0x8B,0x45,0xE0,0x8B,0x4D,0xD4,0x66,0x89,0x01,0x83,0xC1,0x02,
0x66,0x8B,0x45,0x8C,0x66,0x89,0x01,0x83,0xC1,0x02,0x89,0x4D,0xD4
};
int length = sizeof(pattern) / sizeof(short);
DWORD found_loc;
int found = find_pattern(code_seg_start, code_seg_size, pattern, length, &found_loc);
if (found != 1)
{
if (!found) ShowError(IDS_NOPAT, "disable_named_and_rcdata_resources_mirroring");
else ShowError(IDS_MULPAT, "disable_named_and_rcdata_resources_mirroring");
return false;
}
DBGPRINTF(("%s: pattern found @ 0x%08x", "disable_named_and_rcdata_resources_mirroring", found_loc));
set_pattern(found_loc, after, length);
return true;
}
bool Patch_kernel32::mod_imte_alloc()
{
//VA BFF8745C, RVA 1745C, file 15A5C, sec E45C
static const short pattern[] = {
0x66,0xff,0x05,-1,-1,-1,0xbf,0x6a,0x3c,0xe8,
};
static const short after[] = {
0x66,0xff,0x05,-1,-1,-1,0xbf,0x6a,0x40,0xe8,
};
int length = sizeof(pattern) / sizeof(short);
DWORD found_loc;
int found = find_pattern(code_seg_start, code_seg_size, pattern, length, &found_loc);
if (found != 1)
{
if (!found) ShowError(IDS_NOPAT, "mod_imte_alloc");
else ShowError(IDS_MULPAT, "mod_imte_alloc");
return false;
}
DBGPRINTF(("%s: pattern found @ 0x%08x", "mod_imte_alloc", found_loc));
set_pattern(found_loc, after, length);
return true;
}
bool Patch_kernel32::mod_mr_alloc()
{
static const short pattern[] = {
0x75,0xF6,0x8D,0x04,-1,0x1C,0x00,0x00,0x00,0x50
};
static const short after[] = {
0x75,0xF6,0x8D,0x04,-1,0x24,0x00,0x00,0x00,0x50
};
int length = sizeof(pattern) / sizeof(short);
DWORD found_loc;
int found = find_pattern(code_seg_start, code_seg_size, pattern, length, &found_loc);
if (found != 1)
{
if (!found) ShowError(IDS_NOPAT, "mod_mr_alloc");
else ShowError(IDS_MULPAT, "mod_mr_alloc");
return false;
}
DBGPRINTF(("%s: pattern found @ 0x%08x", "mod_mr_alloc", found_loc));
set_pattern(found_loc, after, length);
return true;
}
bool Patch_kernel32::mod_pdb_alloc()
{
static const short pattern[] = {
0x53,0x56,0x57,0x6A,0x06,0x68,0xC4,0x00,0x00,0x00,0xE8
};
static const short after[] = {
0x53,0x56,0x57,0x6A,0x06,0x68,0xC8,0x00,0x00,0x00,0xE8
};
int length = sizeof(pattern) / sizeof(short);
DWORD found_loc;
int found = find_pattern(code_seg_start, code_seg_size, pattern, length, &found_loc);
if (found != 1)
{
if (!found) ShowError(IDS_NOPAT, "mod_pdb_alloc");
else ShowError(IDS_MULPAT, "mod_pdb_alloc");
return false;
}
DBGPRINTF(("%s: pattern found @ 0x%08x", "mod_pdb_alloc", found_loc));
set_pattern(found_loc, after, length);
return true;
}
bool Patch_kernel32::find_ExportFromX()
{
static const short pattern[] = {
0x8B,0x0D,-1,-1,-1,-1,0x0F,0xBF,0x40,0x10,0x8B,0x14,0x81,0x8B,0x44,
0x24,0x14,0x3D,0x00,0x00,0x01,0x00,0x8B,0x4A,0x04,0x73,0x15,-1,0x1D,
-1,-1,-1,-1,0x75,0x04,0x6A,0x32,0xEB,0x3E,0x50,0x51,0xE8,-2,-2,-2,-2,
0xEB,0x0C,0xFF,0x74,0x24,0x14,0x6A,0x00,0x51,0xE8,-2,-2,-2,-2,0x83,
0x7F,0x54,0x00,0x8B,0xF0
};
int length = sizeof(pattern) / sizeof(short);
DWORD found_loc;
int found = find_pattern(code_seg_start, code_seg_size, pattern, length, &found_loc);
if (found != 1)
{
if (!found) ShowError(IDS_NOPAT, "exportfromX");
else ShowError(IDS_MULPAT, "exportfromX");
return false;
}
DBGPRINTF(("%s: pattern found @ 0x%08x", "exportfromX", found_loc));
gpa_ExportFromOrdinal_call = found_loc + 0x29;
gpa_ExportFromName_call = found_loc + 0x37;
_ExportFromOrdinal = decode_call(gpa_ExportFromOrdinal_call, 5);
_ExportFromName = decode_call(gpa_ExportFromName_call, 5);
DWORD start = _ExportFromName;
for (DWORD a = start ; a < start + 0x100 ; a++)
{
if (is_call_ref(a, _ExportFromOrdinal))
{
EFN_EFO_call = a;
return true;
}
}
DBGPRINTF(("EFN_EFO_call not found"));
return false;
}
bool Patch_kernel32::find_IsKnownDLL()
{
static const short pattern[] = {
0xFF,0x75,0xFC,0x8D,0x8D,0xF0,0xFE,0xFF,0xFF,0x51,0xE8,-2,-2,-2,-2,
0x85,0xC0,0x75,0x1E,0x8D,0x85,0xE8,0xFD,0xFF,0xFF,
0x8D,0x8D,0xF0,0xFE,0xFF,0xFF,0x50,0x51
};
int length = sizeof(pattern) / sizeof(short);
DWORD found_loc;
int found = find_pattern(code_seg_start, code_seg_size, pattern, length, &found_loc);
if (found != 1)
{
if (!found) ShowError(IDS_NOPAT, "IsKnownDLL");
else ShowError(IDS_MULPAT, "IsKnownDLL");
return false;
}
DBGPRINTF(("%s: pattern found @ 0x%08x", "IsKnownDLL", found_loc));
IsKnownDLL_call = found_loc + 10;
_IsKnownDLL = decode_call(IsKnownDLL_call, 5);
return true;
}
bool Patch_kernel32::find_FLoadTreeNotify1()
{
static const short pattern[] = {
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
};
int length = sizeof(pattern) / sizeof(short);
DWORD found_loc;
int found = find_pattern(code_seg_start, code_seg_size, pattern, length, &found_loc);
if (found != 1)
{
if (!found) ShowError(IDS_NOPAT, "FLoadTreeNotify1");
else ShowError(IDS_MULPAT, "FLoadTreeNotify1");
return false;
}
DBGPRINTF(("%s: pattern found @ 0x%08x", "FLoadTreeNotify1", found_loc));
FLoadTreeNotify_call1 = found_loc + 16;
_FLoadTreeNotify = decode_call(FLoadTreeNotify_call1, 5);
return true;
}
bool Patch_kernel32::find_FLoadTreeNotify2()
{
static const short pattern[] = {
0x6A,0x00,0x57,0xE8,-1,-1,-1,-1,0x6A,0x00,0x56,0xE8,-2,-2,-2,-2,
0x85,0xC0,0x74,0x12,0x56,0xE8,-1,-1,-1,-1,0x68,0x5A,0x04,0x00,0x00,
0x33,0xF6,0xE8,-1,-1,-1,-1
};
int length = sizeof(pattern) / sizeof(short);
DWORD found_loc;
int found = find_pattern(code_seg_start, code_seg_size, pattern, length, &found_loc);
if (found != 1)
{
if (!found) ShowError(IDS_NOPAT, "FLoadTreeNotify2");
else ShowError(IDS_MULPAT, "FLoadTreeNotify2");
return false;
}
DBGPRINTF(("%s: pattern found @ 0x%08x", "FLoadTreeNotify2", found_loc));
FLoadTreeNotify_call2 = found_loc + 11;
return true;
}
bool Patch_kernel32::create_stubs()
{
KernelEx_codeseg* cseg;
KernelEx_dataseg* dseg;
if (!pefile.AllocSectionSpace(CODE_SEG,
sizeof(KernelEx_codeseg), (void**) &cseg, sizeof(DWORD)))
{
ShowError(IDS_FAILSEC, CODE_SEG);
return false;
}
if (!pefile.AllocSectionSpace(DATA_SEG,
sizeof(KernelEx_dataseg), (void**) &dseg, sizeof(DWORD)))
{
ShowError(IDS_FAILSEC, DATA_SEG);
return false;
}
pagelock(pefile.GetImageBase(), 1);
pagelock((DWORD) cseg, sizeof(KernelEx_codeseg));
pagelock((DWORD) dseg, sizeof(KernelEx_dataseg));
stub_address = dseg;
memcpy(cseg->signature, "KrnlEx", 6);
cseg->version = KEX_STUB_VER;
for (int i = 0 ; i < JTAB_SIZE ; i++)
{
cseg->jmp_stub[i].opcode = 0x25ff;
cseg->jmp_stub[i].addr = (DWORD) &dseg->jtab[i];
cseg->jmp_stub[i].nop = 0x9090;
}
memcpy(dseg->signature, "KrnlEx", 6);
dseg->version = KEX_STUB_VER;
dseg->jtab[JTAB_EFO_DYN] = _ExportFromOrdinal;
dseg->jtab[JTAB_EFO_STA] = _ExportFromOrdinal;
dseg->jtab[JTAB_EFN_DYN] = _ExportFromName;
dseg->jtab[JTAB_EFN_STA] = _ExportFromName;
dseg->jtab[JTAB_KNO_DLL] = _IsKnownDLL;
dseg->jtab[JTAB_FLD_TRN] = _FLoadTreeNotify;
dseg->jtab[JTAB_SYS_CHK] = _SubsysCheckPerform;
dseg->jtab[JTAB_RES_CHK] = _GetOrdinal;
//exportfromx patch
int efo_cnt = 0;
int efn_cnt = 0;
for (DWORD a = code_seg_start ; a < code_seg_start + code_seg_size ; a++)
{
if (is_call_ref(a, _ExportFromOrdinal))
{
DWORD file_loc = a;
if (a == EFN_EFO_call)
continue;
if (a == gpa_ExportFromOrdinal_call)
set_call_ref(file_loc, (DWORD) &cseg->jmp_stub[JTAB_EFO_DYN]);
else
set_call_ref(file_loc, (DWORD) &cseg->jmp_stub[JTAB_EFO_STA]);
DBGPRINTF(("%s: address 0x%08x", "EFO", a));
efo_cnt++;
}
else if (is_call_ref(a, _ExportFromName))
{
DWORD file_loc = a;
if (is_fixupc(a))
continue;
if (a == gpa_ExportFromName_call)
set_call_ref(file_loc, (DWORD) &cseg->jmp_stub[JTAB_EFN_DYN]);
else
set_call_ref(file_loc, (DWORD) &cseg->jmp_stub[JTAB_EFN_STA]);
DBGPRINTF(("%s: address 0x%08x", "EFN", a));
efn_cnt++;
}
}
if (efo_cnt != 2 || efn_cnt != 2)
{
ShowError(IDS_ERRCHECK);
return false;
}
//isknowndll patch
set_call_ref(IsKnownDLL_call, (DWORD) &cseg->jmp_stub[JTAB_KNO_DLL]);
DBGPRINTF(("%s: address 0x%08x", "KNO_DLL", IsKnownDLL_call));
//FLoadTreeNotify patch
set_call_ref(FLoadTreeNotify_call1, (DWORD) &cseg->jmp_stub[JTAB_FLD_TRN]);
DBGPRINTF(("%s: address 0x%08x", "FLD_TRN1", FLoadTreeNotify_call1));
set_call_ref(FLoadTreeNotify_call2, (DWORD) &cseg->jmp_stub[JTAB_FLD_TRN]);
DBGPRINTF(("%s: address 0x%08x", "FLD_TRN2", FLoadTreeNotify_call2));
//subsys check patch
set_jmp_ref(SubsysCheck_jmp, (DWORD) &cseg->jmp_stub[JTAB_SYS_CHK]);
DBGPRINTF(("%s: address 0x%08x", "SYS_CHK", SubsysCheck_jmp));
//resource check patch
set_call_ref(GetOrdinal_call1, (DWORD) &cseg->jmp_stub[JTAB_RES_CHK]);
DBGPRINTF(("%s: address 0x%08x", "RES_CHK1", GetOrdinal_call1));
set_call_ref(GetOrdinal_call2, (DWORD) &cseg->jmp_stub[JTAB_RES_CHK]);
DBGPRINTF(("%s: address 0x%08x", "RES_CHK2", GetOrdinal_call2));
return true;
}
bool Patch_kernel32::is_fixupc(DWORD addr)
{
if (*(DWORD*)(addr - 5) == 0xDAC)
return true;
return false;
}

View File

@ -1,6 +1,6 @@
/*
* KernelEx
* Copyright (C) 2010, Xeno86
* Copyright (C) 2011, Xeno86
*
* This file is part of KernelEx source code.
*
@ -19,39 +19,44 @@
*
*/
#ifndef __PATCH_H
#define __PATCH_H
#ifndef __PATCH_KERNEL32_H
#define __PATCH_KERNEL32_H
#include "patch.h"
#include "interface.h"
class PEmanip;
class Patch
class Patch_kernel32 : public Patch
{
public:
Patch(PEmanip& pem);
void apply();
Patch_kernel32(PEmanip& pem);
bool apply();
KernelEx_dataseg* stub_address;
private:
int find_pattern(DWORD offset, int size, const short* pattern, int pat_len, DWORD* found_loc);
void set_pattern(DWORD loc, const short* new_pattern, int pat_len);
void prepare_subsystem_check();
void find_resource_check1();
void find_resource_check2();
void disable_named_and_rcdata_resources_mirroring();
void mod_imte_alloc();
void mod_mr_alloc();
void mod_pdb_alloc();
void find_ExportFromX();
void find_IsKnownDLL();
void find_FLoadTreeNotify1();
void find_FLoadTreeNotify2();
DWORD decode_call(DWORD addr, int len = 0);
DWORD decode_jmp(DWORD addr, int len = 0);
bool is_call_ref(DWORD loc, DWORD target);
void set_call_ref(DWORD loc, DWORD target);
void set_jmp_ref(DWORD loc, DWORD target);
bool find_signature();
bool prepare_subsystem_check();
bool find_resource_check1();
bool find_resource_check2();
bool disable_named_and_rcdata_resources_mirroring();
bool mod_imte_alloc();
bool mod_mr_alloc();
bool mod_pdb_alloc();
bool find_ExportFromX();
bool find_IsKnownDLL();
bool find_FLoadTreeNotify1();
bool find_FLoadTreeNotify2();
bool create_stubs();
bool is_fixupc(DWORD addr);
PEmanip& pefile;
DWORD code_seg_start;
DWORD code_seg_size;
DWORD data_seg_start;
DWORD data_seg_size;
DWORD _GetOrdinal;
DWORD _ExportFromOrdinal;
DWORD _ExportFromName;

200
vxd/pemanip.cpp Executable file
View File

@ -0,0 +1,200 @@
/*
* KernelEx
* Copyright (C) 2008-2009, 2011, Xeno86
*
* This file is part of KernelEx source code.
*
* KernelEx is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; version 2 of the License.
*
* KernelEx is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "pemanip.h"
#include "debug.h"
#include <cstring>
extern "C" {
#define WANTVXDWRAPS
#include <vmm.h>
#include <vxdwraps.h>
};
PEmanip::PEmanip()
{
ZeroInit();
}
PEmanip::PEmanip(void* memory)
{
ZeroInit();
OpenMemory(memory);
}
void PEmanip::ZeroInit()
{
MZh = NULL;
PEh = NULL;
section_hdrs = NULL;
target_len = 0;
image_base = 0;
has_target = false;
}
void PEmanip::Close()
{
ZeroInit();
}
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;
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;
}
IMAGE_SECTION_HEADER* PEmanip::FindSectionByName(const char* name)
{
IMAGE_SECTION_HEADER* section = section_hdrs;
for (int i = 0 ; i < PEh->FileHeader.NumberOfSections ; i++)
{
if (!strncmp((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;
}
DWORD PEmanip::GetSectionSize(const char* name)
{
IMAGE_SECTION_HEADER* section = FindSectionByName(name);
if (section)
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(("Allocating space in section '%s' avail: %d needed: %d",
name, available_space, needed_space));
if (available_space < needed_space)
{
DBGPRINTF(("Not enough space in section!"));
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;
}
void* PEmanip::CreateBackup()
{
if (!has_target)
return NULL;
void* mem = _HeapAllocate(target_len, HEAPSWAP);
memcpy(mem, MZh, target_len);
return mem;
}

91
vxd/pemanip.h Executable file
View File

@ -0,0 +1,91 @@
/*
* KernelEx
* Copyright (C) 2008-2009, 2011, Xeno86
*
* This file is part of KernelEx source code.
*
* KernelEx is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; version 2 of the License.
*
* KernelEx is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef _SETUP_PEMANIP_H
#define _SETUP_PEMANIP_H
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winnt.h>
class PEmanip
{
public:
PEmanip();
PEmanip(void* memory);
bool HasTarget();
bool OpenMemory(void* memory);
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);
DWORD GetSectionSize(const char* name);
bool AllocSectionSpace(const char* name, int needed_space, void** ptr, int align = 1);
DWORD GetExportedAPI(const char* func);
DWORD GetImageBase();
void* CreateBackup();
static unsigned long ALIGN(unsigned long x, unsigned long y);
private:
void ZeroInit();
IMAGE_SECTION_HEADER* FindSectionByName(const char* name);
bool has_target;
int target_len;
IMAGE_DOS_HEADER* MZh;
IMAGE_NT_HEADERS* PEh;
IMAGE_SECTION_HEADER* section_hdrs;
DWORD image_base;
};
inline bool PEmanip::HasTarget()
{
return has_target;
}
inline IMAGE_NT_HEADERS* PEmanip::GetPEHeader()
{
return PEh;
}
inline unsigned long PEmanip::ALIGN(unsigned long x, unsigned long y)
{
return (x + y - 1) & (~(y - 1));
}
inline DWORD PEmanip::GetImageBase()
{
return image_base;
}
inline void* PEmanip::RvaToPointer(DWORD Rva)
{
return (void*)(Rva + image_base);
}
inline DWORD PEmanip::PointerToRva(void* pointer)
{
return (DWORD) pointer - image_base;
}
#endif

50
vxd/util.c Executable file
View File

@ -0,0 +1,50 @@
/*
* KernelEx
* Copyright (C) 2011, Xeno86
*
* This file is part of KernelEx source code.
*
* KernelEx is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; version 2 of the License.
*
* KernelEx is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <basedef.h>
#include <vmm.h>
void __cdecl abort(void)
{
__asm int 3
}
int __cdecl _purecall (void)
{
abort();
return 0;
}
void __cdecl _assert(const char* expr, const char* file, unsigned line)
{
_Debug_Printf_Service("Assertion failed: '%s' in %s line %d", expr, file, line);
abort();
}
void __declspec(naked) _stdcall RtlUnwind(
PVOID TargetFrame,
PVOID TargetIp,
PVOID ExceptionRecord,
PVOID ReturnValue
)
{
VMMJmp(ObsoleteRtlUnwind);
}

72
vxd/util.h Executable file
View File

@ -0,0 +1,72 @@
/*
* KernelEx
* Copyright (C) 2011, Xeno86
*
* This file is part of KernelEx source code.
*
* KernelEx is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; version 2 of the License.
*
* KernelEx is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef __UTIL_H
#define __UTIL_H
#define __STR(x) #x
#define STR(x) __STR(x)
#define EXTERNC extern "C"
#define _Declare_Virtual_Device(name, ver_major, ver_minor, ctrl_proc, device_num, init_order, V86_proc, PM_proc, ref_data) \
BOOL __stdcall ControlDispatcher(DWORD, DWORD, DWORD, DWORD, DWORD, DWORD); \
\
void __declspec(naked) name##_CTRL(void) \
{ \
__asm PUSH EDI \
__asm PUSH ESI \
__asm PUSH EDX \
__asm PUSH ECX \
__asm PUSH EBX \
__asm PUSH EAX \
__asm CALL ctrl_proc \
__asm CMP EAX, TRUE \
__asm RET \
} \
\
EXTERNC struct VxD_Desc_Block name##_DDB = \
{ \
0, DDK_VERSION, device_num, ver_major, ver_minor, 0, \
#name, init_order, (ULONG)name##_CTRL, (ULONG)V86_proc, (ULONG)PM_proc, \
0, 0, ref_data, 0, 0, 0, 'Prev', sizeof(struct VxD_Desc_Block), \
'Rsv1', 'Rsv2', 'Rsv3' \
}
#pragma warning (disable:4035) // turn off no return code warning
static inline
bool Hook_Device_Service(ULONG service, ULONG hookproc)
{
_asm mov eax, [service]
_asm mov esi, [hookproc]
VMMCall(Hook_Device_Service)
_asm setnc al
#ifndef __BOOL_DEFINED
_asm movzx eax, al
#endif
}
#pragma warning (default:4035) // turn on no return code warning
#endif

View File

@ -1,24 +1,24 @@
# Microsoft Developer Studio Project File - Name="setup" - Package Owner=<4>
# Microsoft Developer Studio Project File - Name="VxD" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=setup - Win32 Debug
CFG=VxD - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "setup.mak".
!MESSAGE NMAKE /f "vxd.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "setup.mak" CFG="setup - Win32 Debug"
!MESSAGE NMAKE /f "vxd.mak" CFG="VxD - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "setup - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "setup - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE "VxD - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "VxD - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
@ -28,7 +28,7 @@ CFG=setup - Win32 Debug
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "setup - Win32 Release"
!IF "$(CFG)" == "VxD - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
@ -42,7 +42,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /O2 /I "." /I "../common" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GF /c
# ADD CPP /nologo /W3 /O2 /D "NDEBUG" /FD /GF /c
# ADD BASE RSC /l 0x415 /d "NDEBUG"
# ADD RSC /l 0x415 /d "NDEBUG"
BSC32=bscmake.exe
@ -50,10 +50,10 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib shell32.lib ..\kexcrt\kexcrt.lib libc.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /machine:I386 /nodefaultlib /out:"Release/setupkex.exe" /OPT:NOWIN98
# ADD LINK32 vxdwraps.clb libc.lib /nologo /map /machine:I386 /nodefaultlib /out:"Release/VKrnlEx.vxd" /vxd /ignore:4078 /ignore:4039
# SUBTRACT LINK32 /pdb:none
!ELSEIF "$(CFG)" == "setup - Win32 Debug"
!ELSEIF "$(CFG)" == "VxD - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
@ -67,7 +67,8 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /ZI /Od /I "." /I "../common" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /GF /c
# ADD CPP /nologo /W3 /Gm /Zi /Od /D "_DEBUG" /FD /GF /Gs /c
# SUBTRACT CPP /Gy
# ADD BASE RSC /l 0x415 /d "_DEBUG"
# ADD RSC /l 0x415 /d "_DEBUG"
BSC32=bscmake.exe
@ -75,29 +76,58 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib shell32.lib ..\kexcrt\kexcrt.lib libc.lib /nologo /subsystem:console /debug /machine:I386 /nodefaultlib /out:"Debug/setupkex.exe" /OPT:NOWIN98
# ADD LINK32 vxdwraps.clb libc.lib /nologo /incremental:no /map /debug /machine:I386 /nodefaultlib /out:"Debug/VKrnlEx.vxd" /vxd /ignore:4078 /ignore:4039
# SUBTRACT LINK32 /pdb:none
!ENDIF
# Begin Target
# Name "setup - Win32 Release"
# Name "setup - Win32 Debug"
# Name "VxD - Win32 Release"
# Name "VxD - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\debug.cpp
!IF "$(CFG)" == "VxD - Win32 Release"
# PROP Exclude_From_Build 1
!ELSEIF "$(CFG)" == "VxD - Win32 Debug"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\KernelEx.def
# End Source File
# Begin Source File
SOURCE=.\patch.cpp
# End Source File
# Begin Source File
SOURCE=..\common\pemanip.cpp
SOURCE=.\patch_ifsmgr.cpp
# End Source File
# Begin Source File
SOURCE=.\setup.cpp
SOURCE=.\patch_kernel32.cpp
# End Source File
# Begin Source File
SOURCE=.\pemanip.cpp
# End Source File
# Begin Source File
SOURCE=.\util.c
# End Source File
# Begin Source File
SOURCE=.\vxdmain.cpp
# End Source File
# End Group
# Begin Group "Header Files"
@ -105,11 +135,7 @@ SOURCE=.\setup.cpp
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\debug.h
# End Source File
# Begin Source File
SOURCE=.\loadstub.h
SOURCE=.\interface.h
# End Source File
# Begin Source File
@ -117,28 +143,28 @@ SOURCE=.\patch.h
# End Source File
# Begin Source File
SOURCE=..\common\pemanip.h
SOURCE=.\patch_ifsmgr.h
# End Source File
# Begin Source File
SOURCE=.\resource.h
SOURCE=.\patch_kernel32.h
# End Source File
# Begin Source File
SOURCE=.\setup.h
SOURCE=.\pemanip.h
# End Source File
# Begin Source File
SOURCE=.\wininit.h
SOURCE=.\util.h
# End Source File
# Begin Source File
SOURCE=.\vxdmain.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# Begin Source File
SOURCE=.\setup.rc
# End Source File
# End Group
# End Target
# End Project

244
vxd/vxdmain.cpp Executable file
View File

@ -0,0 +1,244 @@
/*
* KernelEx
* Copyright (C) 2011, Xeno86
*
* This file is part of KernelEx source code.
*
* KernelEx is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; version 2 of the License.
*
* KernelEx is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
extern "C" {
#define WANTVXDWRAPS
#include <vmm.h>
#include <debug.h>
#include <vxdwraps.h>
#include <vwin32.h>
};
#include <winerror.h>
#include "vxdmain.h"
#include "util.h"
#include "debug.h"
#include "pemanip.h"
#include "patch_kernel32.h"
#include "patch_ifsmgr.h"
#include "interface.h"
#define V_MAJOR 1
#define V_MINOR 0
_Declare_Virtual_Device(VKRNLEX, V_MAJOR, V_MINOR, ControlDispatcher, UNDEFINED_DEVICE_ID, UNDEFINED_INIT_ORDER, 0, 0, 0);
DWORD ( _stdcall *VKernelEx_W32_Proc[] )(DWORD, PDIOCPARAMETERS) = {
VKernelEx_IOCTL_Connect
};
#define MAX_VKERNELEX_W32_API (sizeof(VKernelEx_W32_Proc)/sizeof(DWORD))
static ioctl_connect_params s_connect_params;
BOOL __stdcall ControlDispatcher(
DWORD dwControlMessage,
DWORD EBX,
DWORD ECX,
DWORD EDX,
DWORD ESI,
DWORD EDI)
{
switch(dwControlMessage)
{
case SYS_CRITICAL_INIT:
return VKernelEx_Critical_Init();
case DEVICE_INIT:
return VKernelEx_Dynamic_Init();
case SYS_DYNAMIC_DEVICE_INIT:
return VKernelEx_Dynamic_Init();
case SYS_DYNAMIC_DEVICE_EXIT:
return VKernelEx_Dynamic_Exit();
case W32_DEVICEIOCONTROL:
return VKernelEx_W32_DeviceIOControl(ECX, EDX, (PDIOCPARAMETERS) ESI);
case BEGIN_PM_APP:
return VKernelEx_Begin_PM_App(EBX);
case CREATE_PROCESS:
return VKernelEx_Create_Process(EDX);
case DESTROY_PROCESS:
return VKernelEx_Destroy_Process(EDX);
default:
return TRUE;
}
}
/****************************************************************************
VKernelEx_W32_DeviceIOControl
****************************************************************************/
DWORD _stdcall VKernelEx_W32_DeviceIOControl(
DWORD dwService,
DWORD hDevice,
PDIOCPARAMETERS lpDIOCParms
)
{
DWORD dwRetVal = 0;
// DIOC_OPEN is sent when VxD is loaded w/ CreateFile
// (this happens just after SYS_DYNAMIC_INIT)
if (dwService == DIOC_OPEN)
{
DBGPRINTF(("WIN32 DEVIOCTL supported here!"));
// Must return 0 to tell WIN32 that this VxD supports DEVIOCTL
dwRetVal = 0;
}
// DIOC_CLOSEHANDLE is sent when VxD is unloaded w/ CloseHandle
// (this happens just before SYS_DYNAMIC_EXIT)
else if (dwService == DIOC_CLOSEHANDLE)
{
// Dispatch to cleanup proc
dwRetVal = VKernelEx_CleanUp();
}
else if (dwService > MAX_VKERNELEX_W32_API)
{
// Returning a positive value will cause the WIN32 DeviceIOControl
// call to return FALSE, the error code can then be retrieved
// via the WIN32 GetLastError
dwRetVal = ERROR_NOT_SUPPORTED;
}
else
{
// CALL requested service
dwRetVal = (VKernelEx_W32_Proc[dwService-1])(hDevice, lpDIOCParms);
}
return dwRetVal;
}
DWORD _stdcall VKernelEx_IOCTL_Connect(DWORD hDevice, PDIOCPARAMETERS lpDIOCParms)
{
DBGPRINTF(("VKernelEx_IOCTL_Connect"));
if (lpDIOCParms->cbOutBuffer < sizeof(s_connect_params))
return ERROR_INVALID_PARAMETER;
memcpy((void*) lpDIOCParms->lpvOutBuffer, &s_connect_params, sizeof(s_connect_params));
*(DWORD*) lpDIOCParms->lpcbBytesReturned = sizeof(s_connect_params);
return NO_ERROR;
}
BOOL _stdcall VKernelEx_Create_Process(DWORD pid)
{
return VXD_SUCCESS;
}
BOOL _stdcall VKernelEx_Destroy_Process(DWORD pid)
{
return VXD_SUCCESS;
}
BOOL _stdcall VKernelEx_Begin_PM_App(HVM hVM)
{
WORD version;
void* k32ptr;
void* backup = NULL;
bool allOK = false;
if (!Test_Sys_VM_Handle(hVM))
return TRUE;
version = Get_VMM_Version();
if (version >= 0x045A)
k32ptr = (void*) 0xBFF60000; //WINME
else
k32ptr = (void*) 0xBFF70000; //WIN98
__try
{
WORD sign = 0;
__try
{
sign = *(WORD*) k32ptr;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
if (sign == 'ZM')
{
DBGPRINTF(("KERNEL32 located @ 0x%08x", k32ptr));
PEmanip pem;
pem.OpenMemory(k32ptr);
backup = pem.CreateBackup();
Patch_kernel32 patch(pem);
if (patch.apply())
{
allOK = true;
s_connect_params.status = true;
s_connect_params.vxd_version = MAKEWORD(V_MINOR, V_MAJOR);
s_connect_params.stub_ptr = patch.stub_address;
}
}
else
DBGPRINTF(("couldn't locate KERNEL32"));
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
if (!allOK)
{
DBGPRINTF(("KERNEL32 patch failed!"));
if (backup != NULL)
memcpy(k32ptr, backup, _HeapGetSize(backup, 0));
}
if (backup != NULL)
_HeapFree(backup, 0);
return TRUE;
}
BOOL _stdcall VKernelEx_Dynamic_Exit(void)
{
DBGPRINTF(("Exit"));
return VXD_SUCCESS;
}
DWORD _stdcall VKernelEx_CleanUp(void)
{
DBGPRINTF(("Cleaning Up"));
return VXD_SUCCESS;
}
#pragma VxD_ICODE_SEG
#pragma VxD_IDATA_SEG
BOOL _stdcall VKernelEx_Critical_Init(void)
{
DBGPRINTF(("KernelEx Virtual Device v" STR(V_MAJOR) "." STR(V_MINOR)));
DBGPRINTF(("Critical Init"));
Patch_ifsmgr patch;
patch.apply();
return VXD_SUCCESS;
}
BOOL _stdcall VKernelEx_Dynamic_Init(void)
{
DBGPRINTF(("Init"));
return VXD_SUCCESS;
}

35
vxd/vxdmain.h Executable file
View File

@ -0,0 +1,35 @@
/*
* KernelEx
* Copyright (C) 2011, Xeno86
*
* This file is part of KernelEx source code.
*
* KernelEx is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; version 2 of the License.
*
* KernelEx is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef __VXDMAIN_H
#define __VXDMAIN_H
BOOL _stdcall VKernelEx_Critical_Init(void);
BOOL _stdcall VKernelEx_Dynamic_Init(void);
BOOL _stdcall VKernelEx_Dynamic_Exit(void);
DWORD _stdcall VKernelEx_W32_DeviceIOControl(DWORD, DWORD, PDIOCPARAMETERS);
DWORD _stdcall VKernelEx_CleanUp(void);
DWORD _stdcall VKernelEx_IOCTL_Connect(DWORD, PDIOCPARAMETERS);
BOOL _stdcall VKernelEx_Create_Process(DWORD pid);
BOOL _stdcall VKernelEx_Destroy_Process(DWORD pid);
BOOL _stdcall VKernelEx_Begin_PM_App(HVM hVM);
#endif