diff --git a/ApiHook/ApiLog/apilog.cpp b/ApiHook/ApiLog/apilog.cpp index e08d6d3..d12422a 100755 --- a/ApiHook/ApiLog/apilog.cpp +++ b/ApiHook/ApiLog/apilog.cpp @@ -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); diff --git a/CHANGELOG.txt b/CHANGELOG.txt index a3b3da3..77cd5d9 100755 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -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 diff --git a/COMPILE.TXT b/COMPILE.TXT index 8b7b891..1ddd818 100755 --- a/COMPILE.TXT +++ b/COMPILE.TXT @@ -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 diff --git a/KernelEx.dsw b/KernelEx.dsw index 09fc045..8a596a6 100755 --- a/KernelEx.dsw +++ b/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> diff --git a/KernelEx.nsi b/KernelEx.nsi index 301c45a..5ad5b5c 100755 --- a/KernelEx.nsi +++ b/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 diff --git a/Release Notes.txt b/Release Notes.txt index 6fb7a84..997aca8 100755 --- a/Release Notes.txt +++ b/Release Notes.txt @@ -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 diff --git a/apilibs/kexbases/Kernel32/LockFileEx.c b/apilibs/kexbases/Kernel32/LockFileEx.c index 6ae8c3a..73a626c 100755 --- a/apilibs/kexbases/Kernel32/LockFileEx.c +++ b/apilibs/kexbases/Kernel32/LockFileEx.c @@ -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); +} diff --git a/apilibs/kexbases/Kernel32/_kernel32_apilist.c b/apilibs/kexbases/Kernel32/_kernel32_apilist.c index 55b51e4..f06cad2 100755 --- a/apilibs/kexbases/Kernel32/_kernel32_apilist.c +++ b/apilibs/kexbases/Kernel32/_kernel32_apilist.c @@ -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), diff --git a/apilibs/kexbases/Kernel32/_kernel32_apilist.h b/apilibs/kexbases/Kernel32/_kernel32_apilist.h index f63a154..ee88f57 100755 --- a/apilibs/kexbases/Kernel32/_kernel32_apilist.h +++ b/apilibs/kexbases/Kernel32/_kernel32_apilist.h @@ -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); diff --git a/apilibs/kexbases/shell32/IsUserAnAdmin.c b/apilibs/kexbases/shell32/IsUserAnAdmin.c index b804f34..a3685f9 100755 --- a/apilibs/kexbases/shell32/IsUserAnAdmin.c +++ b/apilibs/kexbases/shell32/IsUserAnAdmin.c @@ -22,6 +22,7 @@ #include /* MAKE_EXPORT IsUserAnAdmin_new=IsUserAnAdmin */ +/* MAKE_EXPORT IsUserAnAdmin_new=ordinal680 */ BOOL WINAPI IsUserAnAdmin_new(void) { return TRUE; diff --git a/apilibs/kexbases/shell32/_shell32_apilist.c b/apilibs/kexbases/shell32/_shell32_apilist.c index eca400e..6557bf8 100755 --- a/apilibs/kexbases/shell32/_shell32_apilist.c +++ b/apilibs/kexbases/shell32/_shell32_apilist.c @@ -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); diff --git a/apilibs/settings.reg b/apilibs/settings.reg index a4252bf..5cd3794 100755 --- a/apilibs/settings.reg +++ b/apilibs/settings.reg @@ -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 diff --git a/auxiliary/psapi/makefile.msv b/auxiliary/psapi/makefile.msv index 99ff3ee..dd9e5c1 100755 --- a/auxiliary/psapi/makefile.msv +++ b/auxiliary/psapi/makefile.msv @@ -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) diff --git a/common/kstructs.h b/common/kstructs.h index 698b82a..2103bda 100755 --- a/common/kstructs.h +++ b/common/kstructs.h @@ -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 */ diff --git a/common/version.h b/common/version.h index 16ab5a2..5b68ce5 100755 --- a/common/version.h +++ b/common/version.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 diff --git a/core/Core.rc b/core/Core.rc index 4b24057..faab28d 100755 --- a/core/Core.rc +++ b/core/Core.rc @@ -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 diff --git a/core/apiconf.cpp b/core/apiconf.cpp index 97e624a..0b16a8e 100755 --- a/core/apiconf.cpp +++ b/core/apiconf.cpp @@ -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"); diff --git a/core/apihook.cpp b/core/apihook.cpp index d50ab78..37ad8af 100755 --- a/core/apihook.cpp +++ b/core/apihook.cpp @@ -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) { diff --git a/core/core.dsp b/core/core.dsp index c8d6ddb..1c62ed2 100755 --- a/core/core.dsp +++ b/core/core.dsp @@ -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" diff --git a/core/internals.cpp b/core/internals.cpp index 6a6ce3d..8067bde 100755 --- a/core/internals.cpp +++ b/core/internals.cpp @@ -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; } diff --git a/core/internals.h b/core/internals.h index 862892c..722e928 100755 --- a/core/internals.h +++ b/core/internals.h @@ -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); diff --git a/core/resolver.cpp b/core/resolver.cpp index 4ef7e16..905e468 100755 --- a/core/resolver.cpp +++ b/core/resolver.cpp @@ -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; } diff --git a/core/resource.h b/core/resource.h index ac88191..681ccbc 100755 --- a/core/resource.h +++ b/core/resource.h @@ -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 // diff --git a/core/thunks.cpp b/core/thunks.cpp index 81ec762..04a382a 100755 --- a/core/thunks.cpp +++ b/core/thunks.cpp @@ -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) diff --git a/kexcrt/assert.c b/kexcrt/assert.c index 348425c..30cc9d8 100755 --- a/kexcrt/assert.c +++ b/kexcrt/assert.c @@ -4,6 +4,7 @@ #include #include +#include void _assert(const char *expr, const char *file, unsigned int line) { diff --git a/kexcrt/kexcrt.dsp b/kexcrt/kexcrt.dsp index 245ef7a..d930ab5 100755 --- a/kexcrt/kexcrt.dsp +++ b/kexcrt/kexcrt.dsp @@ -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 diff --git a/kexcrt/makefile.msv b/kexcrt/makefile.msv index af894a5..a9596be 100755 --- a/kexcrt/makefile.msv +++ b/kexcrt/makefile.msv @@ -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 diff --git a/kexcrt/msvc/msvc8.c b/kexcrt/msvc/msvc8.c deleted file mode 100755 index aae3832..0000000 --- a/kexcrt/msvc/msvc8.c +++ /dev/null @@ -1,34 +0,0 @@ -#include - -#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); -} - diff --git a/setup/patch.cpp b/setup/patch.cpp deleted file mode 100755 index 3b6ed27..0000000 --- a/setup/patch.cpp +++ /dev/null @@ -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 -#include -#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; -} - diff --git a/setup/resource.h b/setup/resource.h deleted file mode 100755 index 1f4f369..0000000 --- a/setup/resource.h +++ /dev/null @@ -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 diff --git a/setup/setup.cpp b/setup/setup.cpp deleted file mode 100755 index 7e37f03..0000000 --- a/setup/setup.cpp +++ /dev/null @@ -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 -#include -#include -#include -#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; -} diff --git a/setup/setup.rc b/setup/setup.rc deleted file mode 100755 index dda319f..0000000 --- a/setup/setup.rc +++ /dev/null @@ -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 - diff --git a/setup/wininit.h b/setup/wininit.h deleted file mode 100755 index 89cd2ab..0000000 --- a/setup/wininit.h +++ /dev/null @@ -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 - -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 diff --git a/util/msvc6chk.zip b/util/msvc6chk.zip new file mode 100755 index 0000000..793eaad Binary files /dev/null and b/util/msvc6chk.zip differ diff --git a/util/sdbcreate/sdbdb/KernelEx.sdb b/util/sdbcreate/sdbdb/KernelEx.sdb new file mode 100755 index 0000000..994a1e7 Binary files /dev/null and b/util/sdbcreate/sdbdb/KernelEx.sdb differ diff --git a/util/sdbcreate/sdbdb/kexsdb.i.reg b/util/sdbcreate/sdbdb/kexsdb.i.reg new file mode 100755 index 0000000..bd3c779 --- /dev/null +++ b/util/sdbcreate/sdbdb/kexsdb.i.reg @@ -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" + diff --git a/util/sdbcreate/sdbdb/kexsdb.u.reg b/util/sdbcreate/sdbdb/kexsdb.u.reg new file mode 100755 index 0000000..5e17705 --- /dev/null +++ b/util/sdbcreate/sdbdb/kexsdb.u.reg @@ -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}] + diff --git a/vxd/KernelEx.def b/vxd/KernelEx.def new file mode 100755 index 0000000..233cfbb --- /dev/null +++ b/vxd/KernelEx.def @@ -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 diff --git a/vxd/debug.cpp b/vxd/debug.cpp new file mode 100755 index 0000000..1950102 --- /dev/null +++ b/vxd/debug.cpp @@ -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 +#include +}; +#include +#include +#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 +} diff --git a/setup/debug.h b/vxd/debug.h similarity index 85% rename from setup/debug.h rename to vxd/debug.h index 4dc422c..65d3261 100755 --- a/setup/debug.h +++ b/vxd/debug.h @@ -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 -#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 diff --git a/setup/loadstub.h b/vxd/interface.h similarity index 69% rename from setup/loadstub.h rename to vxd/interface.h index 527d6bc..a0ba3b7 100755 --- a/setup/loadstub.h +++ b/vxd/interface.h @@ -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 -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 +/* + * IOCTL Support + */ + +#define IOCTL_CONNECT 1 + +struct ioctl_connect_params +{ + WORD vxd_version; + bool status; + KernelEx_dataseg* stub_ptr; +}; + #endif diff --git a/vxd/patch.cpp b/vxd/patch.cpp new file mode 100755 index 0000000..480bb1a --- /dev/null +++ b/vxd/patch.cpp @@ -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 +#include +#include "patch.h" +#include "debug.h" + +extern "C" { +#define WANTVXDWRAPS +#include +#include +}; + +#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(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); +} diff --git a/vxd/patch.h b/vxd/patch.h new file mode 100755 index 0000000..d24ab14 --- /dev/null +++ b/vxd/patch.h @@ -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 diff --git a/vxd/patch_ifsmgr.cpp b/vxd/patch_ifsmgr.cpp new file mode 100755 index 0000000..72cab69 --- /dev/null +++ b/vxd/patch_ifsmgr.cpp @@ -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 +#include +#include +}; +#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; +} diff --git a/setup/setup.h b/vxd/patch_ifsmgr.h similarity index 58% rename from setup/setup.h rename to vxd/patch_ifsmgr.h index 6644da5..7de0fa6 100755 --- a/setup/setup.h +++ b/vxd/patch_ifsmgr.h @@ -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 diff --git a/vxd/patch_kernel32.cpp b/vxd/patch_kernel32.cpp new file mode 100755 index 0000000..418eb7f --- /dev/null +++ b/vxd/patch_kernel32.cpp @@ -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 +#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; +} diff --git a/setup/patch.h b/vxd/patch_kernel32.h similarity index 57% rename from setup/patch.h rename to vxd/patch_kernel32.h index 0fd3b64..8283951 100755 --- a/setup/patch.h +++ b/vxd/patch_kernel32.h @@ -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; diff --git a/vxd/pemanip.cpp b/vxd/pemanip.cpp new file mode 100755 index 0000000..b608310 --- /dev/null +++ b/vxd/pemanip.cpp @@ -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 + +extern "C" { +#define WANTVXDWRAPS +#include +#include +}; + +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; +} diff --git a/vxd/pemanip.h b/vxd/pemanip.h new file mode 100755 index 0000000..32db89a --- /dev/null +++ b/vxd/pemanip.h @@ -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 +#include + +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 diff --git a/vxd/util.c b/vxd/util.c new file mode 100755 index 0000000..2176a89 --- /dev/null +++ b/vxd/util.c @@ -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 +#include + +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); +} diff --git a/vxd/util.h b/vxd/util.h new file mode 100755 index 0000000..c6815e2 --- /dev/null +++ b/vxd/util.h @@ -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 diff --git a/setup/setup.dsp b/vxd/vxd.dsp similarity index 67% rename from setup/setup.dsp rename to vxd/vxd.dsp index 67d462e..ab54695 100755 --- a/setup/setup.dsp +++ b/vxd/vxd.dsp @@ -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 diff --git a/vxd/vxdmain.cpp b/vxd/vxdmain.cpp new file mode 100755 index 0000000..ad38dea --- /dev/null +++ b/vxd/vxdmain.cpp @@ -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 +extern "C" { +#define WANTVXDWRAPS +#include +#include +#include +#include +}; +#include +#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; +} diff --git a/vxd/vxdmain.h b/vxd/vxdmain.h new file mode 100755 index 0000000..4f52afa --- /dev/null +++ b/vxd/vxdmain.h @@ -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