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:
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
24
KernelEx.dsw
24
KernelEx.dsw
@ -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>
|
||||
|
126
KernelEx.nsi
126
KernelEx.nsi
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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);
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <windows.h>
|
||||
|
||||
/* MAKE_EXPORT IsUserAnAdmin_new=IsUserAnAdmin */
|
||||
/* MAKE_EXPORT IsUserAnAdmin_new=ordinal680 */
|
||||
BOOL WINAPI IsUserAnAdmin_new(void)
|
||||
{
|
||||
return TRUE;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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, ¶ms, 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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
//
|
||||
|
@ -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)
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
void _assert(const char *expr, const char *file, unsigned int line)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
577
setup/patch.cpp
577
setup/patch.cpp
@ -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;
|
||||
}
|
||||
|
@ -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
|
352
setup/setup.cpp
352
setup/setup.cpp
@ -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;
|
||||
}
|
@ -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
|
||||
|
154
setup/wininit.h
154
setup/wininit.h
@ -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
BIN
util/msvc6chk.zip
Executable file
Binary file not shown.
BIN
util/sdbcreate/sdbdb/KernelEx.sdb
Executable file
BIN
util/sdbcreate/sdbdb/KernelEx.sdb
Executable file
Binary file not shown.
35
util/sdbcreate/sdbdb/kexsdb.i.reg
Executable file
35
util/sdbcreate/sdbdb/kexsdb.i.reg
Executable 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"
|
||||
|
24
util/sdbcreate/sdbdb/kexsdb.u.reg
Executable file
24
util/sdbcreate/sdbdb/kexsdb.u.reg
Executable 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
47
vxd/KernelEx.def
Executable 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
42
vxd/debug.cpp
Executable 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
|
||||
}
|
@ -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
|
@ -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
223
vxd/patch.cpp
Executable 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
53
vxd/patch.h
Executable 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
178
vxd/patch_ifsmgr.cpp
Executable 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;
|
||||
}
|
@ -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
494
vxd/patch_kernel32.cpp
Executable 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;
|
||||
}
|
@ -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
200
vxd/pemanip.cpp
Executable 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
91
vxd/pemanip.h
Executable 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
50
vxd/util.c
Executable 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
72
vxd/util.h
Executable 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
|
@ -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
244
vxd/vxdmain.cpp
Executable 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
35
vxd/vxdmain.h
Executable 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
|
Reference in New Issue
Block a user