mirror of
https://github.com/UzixLS/KernelEx.git
synced 2025-07-19 07:21:20 +03:00
import KernelEx-4.5.2
This commit is contained in:
47
vxd/KernelEx.def
Executable file
47
vxd/KernelEx.def
Executable file
@ -0,0 +1,47 @@
|
||||
;
|
||||
; KernelEx
|
||||
; Copyright (C) 2011, Xeno86
|
||||
;
|
||||
; This file is part of KernelEx source code.
|
||||
;
|
||||
; KernelEx is free software; you can redistribute it and/or modify
|
||||
; it under the terms of the GNU General Public License as published
|
||||
; by the Free Software Foundation; version 2 of the License.
|
||||
;
|
||||
; KernelEx is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with GNU Make; see the file COPYING. If not, write to
|
||||
; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
;
|
||||
|
||||
VXD VKRNLEX DYNAMIC
|
||||
|
||||
DESCRIPTION 'KernelEx Virtual Device'
|
||||
|
||||
SEGMENTS
|
||||
_LPTEXT CLASS 'LCODE' PRELOAD NONDISCARDABLE
|
||||
_LTEXT CLASS 'LCODE' PRELOAD NONDISCARDABLE
|
||||
_LDATA CLASS 'LCODE' PRELOAD NONDISCARDABLE
|
||||
_TEXT CLASS 'LCODE' PRELOAD NONDISCARDABLE
|
||||
_DATA CLASS 'LCODE' PRELOAD NONDISCARDABLE
|
||||
CONST CLASS 'LCODE' PRELOAD NONDISCARDABLE
|
||||
_TLS CLASS 'LCODE' PRELOAD NONDISCARDABLE
|
||||
_BSS CLASS 'LCODE' PRELOAD NONDISCARDABLE
|
||||
_ITEXT CLASS 'ICODE' DISCARDABLE
|
||||
_IDATA CLASS 'ICODE' DISCARDABLE
|
||||
_PTEXT CLASS 'PCODE' NONDISCARDABLE
|
||||
_PDATA CLASS 'PDATA' NONDISCARDABLE SHARED
|
||||
_STEXT CLASS 'SCODE' RESIDENT
|
||||
_SDATA CLASS 'SCODE' RESIDENT
|
||||
_DBOSTART CLASS 'DBOCODE' PRELOAD NONDISCARDABLE CONFORMING
|
||||
_DBOCODE CLASS 'DBOCODE' PRELOAD NONDISCARDABLE CONFORMING
|
||||
_DBODATA CLASS 'DBOCODE' PRELOAD NONDISCARDABLE CONFORMING
|
||||
_16ICODE CLASS '16ICODE' PRELOAD DISCARDABLE
|
||||
_RCODE CLASS 'RCODE'
|
||||
|
||||
EXPORTS
|
||||
_VKRNLEX_DDB @1
|
42
vxd/debug.cpp
Executable file
42
vxd/debug.cpp
Executable file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* KernelEx
|
||||
* Copyright (C) 2009, Xeno86
|
||||
*
|
||||
* This file is part of KernelEx source code.
|
||||
*
|
||||
* KernelEx is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* KernelEx is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
extern "C" {
|
||||
#include <basedef.h>
|
||||
#include <vmm.h>
|
||||
};
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include "debug.h"
|
||||
|
||||
void debug_printf(const char* fmt, ...)
|
||||
{
|
||||
char* newfmt = (char*) alloca(strlen(fmt) + 10);
|
||||
strcpy(newfmt, "VKRNLEX: ");
|
||||
strcat(newfmt, fmt);
|
||||
strcat(newfmt, "\n");
|
||||
|
||||
__asm lea eax,(fmt + 4)
|
||||
__asm push eax
|
||||
__asm push newfmt
|
||||
VMMCall(_Debug_Printf_Service)
|
||||
__asm add esp, 2*4
|
||||
}
|
32
vxd/debug.h
Executable file
32
vxd/debug.h
Executable file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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 __DEBUG_H
|
||||
#define __DEBUG_H
|
||||
|
||||
#ifdef _DEBUG
|
||||
void debug_printf(const char* fmt, ...);
|
||||
#define DBGPRINTF(x) debug_printf x
|
||||
#else
|
||||
#define DBGPRINTF(x) do {} while (0)
|
||||
#endif
|
||||
|
||||
#endif
|
77
vxd/interface.h
Executable file
77
vxd/interface.h
Executable file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* KernelEx
|
||||
* Copyright (C) 2008-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 __INTERFACE_H
|
||||
#define __INTERFACE_H
|
||||
|
||||
/* Update this whenever patching functions are changed. */
|
||||
#define KEX_STUB_VER 11
|
||||
|
||||
#define KEX_SIGNATURE "KrnlEx"
|
||||
|
||||
enum
|
||||
{
|
||||
JTAB_EFO_DYN,
|
||||
JTAB_EFO_STA,
|
||||
JTAB_EFN_DYN,
|
||||
JTAB_EFN_STA,
|
||||
JTAB_KNO_DLL,
|
||||
JTAB_FLD_TRN,
|
||||
JTAB_SYS_CHK,
|
||||
JTAB_RES_CHK,
|
||||
JTAB_SIZE
|
||||
};
|
||||
|
||||
#include <pshpack1.h>
|
||||
struct KernelEx_codeseg
|
||||
{
|
||||
char signature[6]; /* "KrnlEx" */
|
||||
unsigned short version;
|
||||
struct
|
||||
{
|
||||
WORD opcode; /* 0xFF 0x25 */
|
||||
DWORD addr; /* address to jtab */
|
||||
WORD nop; /* dword align */
|
||||
} jmp_stub[JTAB_SIZE];
|
||||
};
|
||||
|
||||
struct KernelEx_dataseg
|
||||
{
|
||||
char signature[6]; /* "KrnlEx" */
|
||||
unsigned short version;
|
||||
DWORD jtab[JTAB_SIZE];
|
||||
};
|
||||
#include <poppack.h>
|
||||
|
||||
/*
|
||||
* IOCTL Support
|
||||
*/
|
||||
|
||||
#define IOCTL_CONNECT 1
|
||||
|
||||
struct ioctl_connect_params
|
||||
{
|
||||
WORD vxd_version;
|
||||
bool status;
|
||||
KernelEx_dataseg* stub_ptr;
|
||||
};
|
||||
|
||||
#endif
|
223
vxd/patch.cpp
Executable file
223
vxd/patch.cpp
Executable file
@ -0,0 +1,223 @@
|
||||
/*
|
||||
* KernelEx
|
||||
* Copyright (C) 2010-2011, Xeno86
|
||||
*
|
||||
* This file is part of KernelEx source code.
|
||||
*
|
||||
* KernelEx is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* KernelEx is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include <cassert>
|
||||
#include "patch.h"
|
||||
#include "debug.h"
|
||||
|
||||
extern "C" {
|
||||
#define WANTVXDWRAPS
|
||||
#include <vmm.h>
|
||||
#include <vxdwraps.h>
|
||||
};
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
||||
const struct
|
||||
{
|
||||
MessageID id;
|
||||
const char* desc;
|
||||
}
|
||||
MessageText[] =
|
||||
{
|
||||
IDS_NOPAT, "ERROR: %s: pattern not found",
|
||||
IDS_MULPAT, "ERROR: %s: multiple pattern matches",
|
||||
IDS_FAILSEC, "ERROR: Failed to allocate %s section memory",
|
||||
IDS_ERRCHECK, "ERROR: Checksum error",
|
||||
IDS_WINVER, "Incompatible Windows version",
|
||||
IDS_DOWNGRADE, "Can't downgrade. Please uninstall currently installed version of KernelEx before continuing.",
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
void Patch::ShowError(MessageID id, ...)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
const char* format = NULL;
|
||||
char out[512];
|
||||
va_list vargs;
|
||||
|
||||
va_start(vargs, id);
|
||||
for (int i = 0 ; i < sizeof(MessageText) / sizeof(MessageText[0]) ; i++)
|
||||
{
|
||||
if (MessageText[i].id == id)
|
||||
{
|
||||
format = MessageText[i].desc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(format != NULL);
|
||||
|
||||
_Vsprintf(out, const_cast<char*>(format), vargs);
|
||||
va_end(vargs);
|
||||
strcat(out, "\n");
|
||||
debug_printf(out);
|
||||
#endif
|
||||
abort();
|
||||
}
|
||||
|
||||
int Patch::find_pattern(DWORD offset, int size, const short* pattern,
|
||||
int pat_len, DWORD* found_loc)
|
||||
{
|
||||
DWORD end_offset = offset + size - pat_len;
|
||||
int found = 0;
|
||||
|
||||
for (DWORD i = offset ; i <= end_offset ; i++)
|
||||
{
|
||||
if (pattern[0] < 0 || *(unsigned char*)i == pattern[0])
|
||||
{
|
||||
int j;
|
||||
for (j = 1 ; j < pat_len ; j++)
|
||||
{
|
||||
if (pattern[j] >= 0 && *(unsigned char*)(i + j) != pattern[j])
|
||||
break;
|
||||
}
|
||||
if (j == pat_len) //pattern found
|
||||
{
|
||||
*found_loc = i;
|
||||
found++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
void Patch::set_pattern(DWORD loc, const short* new_pattern, int pat_len)
|
||||
{
|
||||
unsigned char* offset = (unsigned char*) loc;
|
||||
const short* pat_ptr = new_pattern;
|
||||
|
||||
while (pat_len--)
|
||||
{
|
||||
if (*pat_ptr != -1)
|
||||
*offset = *pat_ptr & 0xff;
|
||||
offset++;
|
||||
pat_ptr++;
|
||||
}
|
||||
|
||||
pagelock(loc, pat_len);
|
||||
}
|
||||
|
||||
DWORD Patch::decode_call(DWORD addr, int len)
|
||||
{
|
||||
unsigned char* code = (unsigned char*)addr;
|
||||
|
||||
/* CALL rel32 */
|
||||
if (code[0] == 0xe8)
|
||||
{
|
||||
if (len && len == 5 || !len)
|
||||
return (DWORD)((DWORD)code + 5 + *(INT32*)(code + 1));
|
||||
}
|
||||
/* CALL imm32 */
|
||||
else if (code[0] == 0xff && code[1] == 0x15)
|
||||
{
|
||||
if (len && len == 6 || !len)
|
||||
return *(DWORD*)(code + 2);
|
||||
}
|
||||
/* unmatched */
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD Patch::decode_jmp(DWORD addr, int len)
|
||||
{
|
||||
unsigned char* code = (unsigned char*)addr;
|
||||
|
||||
/* JMP rel8 */
|
||||
if (code[0] == 0xeb)
|
||||
{
|
||||
if (len && len == 2 || !len)
|
||||
return (DWORD)((DWORD)code + 2 + *(INT8*)(code + 1));
|
||||
}
|
||||
/* JMP rel32 */
|
||||
else if (code[0] == 0xe9)
|
||||
{
|
||||
if (len && len == 5 || !len)
|
||||
return (DWORD)((DWORD)code + 5 + *(INT32*)(code + 1));
|
||||
}
|
||||
/* JMP imm32 */
|
||||
else if (code[0] == 0xff && code[1] == 0x25)
|
||||
{
|
||||
if (len && len == 6 || !len)
|
||||
return *(DWORD*)(code + 2);
|
||||
}
|
||||
/* Jxx rel8 */
|
||||
else if (code[0] >= 0x70 && code[0] < 0x7f || code[0] == 0xe3)
|
||||
{
|
||||
if (len && len == 2 || !len)
|
||||
return (DWORD)((DWORD)code + 2 + *(INT8*)(code + 1));
|
||||
}
|
||||
/* Jxx rel32 */
|
||||
else if (code[0] == 0x0f && code[1] >= 0x80 && code[1] <= 0x8f)
|
||||
{
|
||||
if (len && len == 6 || !len)
|
||||
return (DWORD)((DWORD)code + 6 + *(INT32*)(code + 2));
|
||||
}
|
||||
/* unmatched */
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Patch::is_call_ref(DWORD loc, DWORD target)
|
||||
{
|
||||
DWORD addr = decode_call(loc, 5); // size of call imm32 opcode
|
||||
if (addr == target)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Both addresses have to be from the same section!
|
||||
void Patch::set_call_ref(DWORD loc, DWORD target)
|
||||
{
|
||||
DWORD rel;
|
||||
|
||||
assert(*(BYTE*) loc == 0xe8);
|
||||
|
||||
rel = target - (loc + 5);
|
||||
*(DWORD*)(loc + 1) = rel;
|
||||
pagelock(loc + 1, sizeof(DWORD));
|
||||
}
|
||||
|
||||
// Both addresses have to be from the same section!
|
||||
void Patch::set_jmp_ref(DWORD loc, DWORD target)
|
||||
{
|
||||
DWORD rel;
|
||||
unsigned char* code = (unsigned char*)loc;
|
||||
|
||||
if (code[0] == 0xe9)
|
||||
{
|
||||
rel = target - (loc + 5);
|
||||
*(DWORD*)(loc + 1) = rel;
|
||||
pagelock(loc + 1, sizeof(DWORD));
|
||||
}
|
||||
else if (code[0] == 0x0f && code[1] >= 0x80 && code[1] <= 0x8f)
|
||||
{
|
||||
rel = target - (loc + 6);
|
||||
*(DWORD*)(loc + 2) = rel;
|
||||
pagelock(loc + 2, sizeof(DWORD));
|
||||
}
|
||||
else assert(false);
|
||||
}
|
||||
|
||||
void Patch::pagelock(DWORD addr, DWORD count)
|
||||
{
|
||||
_LinPageLock(PAGE(addr), NPAGES((addr & PAGEMASK) + count), 0);
|
||||
}
|
53
vxd/patch.h
Executable file
53
vxd/patch.h
Executable file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* KernelEx
|
||||
* Copyright (C) 2010-2011, Xeno86
|
||||
*
|
||||
* This file is part of KernelEx source code.
|
||||
*
|
||||
* KernelEx is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* KernelEx is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __PATCH_H
|
||||
#define __PATCH_H
|
||||
|
||||
enum MessageID
|
||||
{
|
||||
IDS_NOPAT,
|
||||
IDS_MULPAT,
|
||||
IDS_FAILSEC,
|
||||
IDS_ERRCHECK,
|
||||
IDS_WINVER,
|
||||
IDS_DOWNGRADE,
|
||||
};
|
||||
|
||||
class Patch
|
||||
{
|
||||
public:
|
||||
Patch() {}
|
||||
virtual bool apply() = 0;
|
||||
|
||||
protected:
|
||||
void ShowError(MessageID id, ...);
|
||||
static int find_pattern(DWORD offset, int size, const short* pattern, int pat_len, DWORD* found_loc);
|
||||
void set_pattern(DWORD loc, const short* new_pattern, int pat_len);
|
||||
DWORD decode_call(DWORD addr, int len = 0);
|
||||
DWORD decode_jmp(DWORD addr, int len = 0);
|
||||
bool is_call_ref(DWORD loc, DWORD target);
|
||||
void set_call_ref(DWORD loc, DWORD target);
|
||||
void set_jmp_ref(DWORD loc, DWORD target);
|
||||
void pagelock(DWORD addr, DWORD count);
|
||||
};
|
||||
|
||||
#endif
|
178
vxd/patch_ifsmgr.cpp
Executable file
178
vxd/patch_ifsmgr.cpp
Executable file
@ -0,0 +1,178 @@
|
||||
/*
|
||||
* KernelEx
|
||||
* Copyright (C) 2011, Xeno86
|
||||
*
|
||||
* This file is part of KernelEx source code.
|
||||
*
|
||||
* KernelEx is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* KernelEx is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
extern "C" {
|
||||
#define WANTVXDWRAPS
|
||||
#include <basedef.h>
|
||||
#include <vmm.h>
|
||||
#include <vxdwraps.h>
|
||||
};
|
||||
#include "patch_ifsmgr.h"
|
||||
#include "debug.h"
|
||||
#include "util.h"
|
||||
|
||||
#define __IFSMGR_CheckLocks 0x00400056
|
||||
|
||||
/*
|
||||
* This is a fix against a problem where you can't access a locked file
|
||||
* through memory mapping object.
|
||||
*
|
||||
* Why accessing a locked file through memory mapping object doesn't work?
|
||||
*
|
||||
* IFSMgr normally checks if the process is an owner of the lock
|
||||
* and depending on that either allows to access the file or not.
|
||||
*
|
||||
* This works fine in case scenario 1. where the file is read directly.
|
||||
*
|
||||
* Accessing a file through memory mapping object is a different beast.
|
||||
* The file is loaded into memory by the system on demand, through a page
|
||||
* fault trap (see 2.), this causes a read of a page-sized chunk of file.
|
||||
* However this time it is the system not the application who's reading
|
||||
* the file, so process ID is set to -1. This value is not checked
|
||||
* against when the file is verified for access regarding the locks.
|
||||
*
|
||||
* The fix is to allow the access to a locked file if PID is -1.
|
||||
*/
|
||||
|
||||
#if 0 /* Test case */
|
||||
|
||||
int main()
|
||||
{
|
||||
HANDLE file, mapp;
|
||||
void* view;
|
||||
char buf[4096];
|
||||
BOOL ret;
|
||||
DWORD dw;
|
||||
|
||||
file = CreateFileA("File.txt", GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
|
||||
ret = LockFile(file, 128, 0, 1, 0);
|
||||
|
||||
SetFilePointer(file, 32768, 0, 0);
|
||||
SetEndOfFile(file);
|
||||
|
||||
mapp = CreateFileMapping(file, NULL, PAGE_READWRITE, 0, 32768, NULL);
|
||||
view = MapViewOfFile(mapp, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 32768);
|
||||
|
||||
SetFilePointer(file, 0, 0, 0);
|
||||
|
||||
//!!!!! 1. This works out of the box
|
||||
ReadFile(file, buf, 4096, &dw, NULL);
|
||||
|
||||
//!!!!! 2. This triggers a crash without the fix
|
||||
memcpy(buf, view, 4096);
|
||||
|
||||
UnmapViewOfFile(view);
|
||||
CloseHandle(mapp);
|
||||
|
||||
UnlockFile(file, 128, 0, 1, 0);
|
||||
|
||||
CloseHandle(file);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
__declspec(naked)
|
||||
int IFSMGR_CheckLocks_fixed(
|
||||
void* handle,
|
||||
DWORD pos,
|
||||
DWORD count,
|
||||
DWORD owner,
|
||||
DWORD finst,
|
||||
DWORD flags
|
||||
)
|
||||
{
|
||||
__asm {
|
||||
push ebp
|
||||
mov ebp,esp
|
||||
push ebx
|
||||
push esi
|
||||
push edi
|
||||
mov eax,[ebp+10h]
|
||||
or eax,eax
|
||||
jnz _L1
|
||||
sub eax,eax
|
||||
jmp _exit_grant
|
||||
_L1:
|
||||
mov edi,[ebp+0Ch]
|
||||
lea ecx,[eax+edi-1]
|
||||
cmp ecx,edi
|
||||
jnb _L2
|
||||
jmp _exit_forbid
|
||||
_L2:
|
||||
mov esi,[ebp+8]
|
||||
sub eax,eax
|
||||
cmp [esi+0Ch],edi
|
||||
jb _exit_grant
|
||||
cmp [esi+8],ecx
|
||||
ja _exit_grant
|
||||
mov edx,[esi]
|
||||
cmp esi,edx
|
||||
jz _exit_grant
|
||||
//the fix
|
||||
mov ebx,[ebp+14h]
|
||||
cmp ebx,-1
|
||||
jz _exit_grant
|
||||
//end of the fix
|
||||
_loop:
|
||||
cmp [edx+8],ecx
|
||||
ja _exit_grant
|
||||
cmp [edx+0Ch],edi
|
||||
jb _next
|
||||
//check lock owner
|
||||
mov ebx,[ebp+14h]
|
||||
cmp [edx+14h],ebx
|
||||
jnz _owner_mismatch
|
||||
//check file handle
|
||||
mov ebx,[ebp+18h]
|
||||
cmp [edx+18h],ebx
|
||||
jz _next
|
||||
_owner_mismatch:
|
||||
mov ebx,[edx+10h]
|
||||
and ebx,[ebp+1Ch]
|
||||
test bl,1
|
||||
jz _exit_forbid
|
||||
_next:
|
||||
mov edx,[edx]
|
||||
cmp esi,edx
|
||||
jnz _loop
|
||||
jmp _exit_grant
|
||||
_exit_forbid:
|
||||
mov eax,21h
|
||||
_exit_grant:
|
||||
pop edi
|
||||
pop esi
|
||||
pop ebx
|
||||
pop ebp
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
bool Patch_ifsmgr::apply()
|
||||
{
|
||||
DBGPRINTF(("Applying IFSMGR_CheckLocks fix... "));
|
||||
ULONG serviceid = GetVxDServiceOrdinal(IFSMGR_CheckLocks);
|
||||
bool ret = Hook_Device_Service(serviceid, (ULONG) IFSMGR_CheckLocks_fixed);
|
||||
DBGPRINTF((ret ? "... ok" : "... error"));
|
||||
return ret;
|
||||
}
|
33
vxd/patch_ifsmgr.h
Executable file
33
vxd/patch_ifsmgr.h
Executable file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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 __PATCH_IFSMGR_H
|
||||
#define __PATCH_IFSMGR_H
|
||||
|
||||
#include "patch.h"
|
||||
|
||||
class Patch_ifsmgr : public Patch
|
||||
{
|
||||
public:
|
||||
bool apply();
|
||||
};
|
||||
|
||||
#endif
|
494
vxd/patch_kernel32.cpp
Executable file
494
vxd/patch_kernel32.cpp
Executable file
@ -0,0 +1,494 @@
|
||||
/*
|
||||
* KernelEx
|
||||
* Copyright (C) 2011, Xeno86
|
||||
*
|
||||
* This file is part of KernelEx source code.
|
||||
*
|
||||
* KernelEx is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* KernelEx is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include "pemanip.h"
|
||||
#include "patch_kernel32.h"
|
||||
#include "interface.h"
|
||||
#include "debug.h"
|
||||
|
||||
#define CODE_SEG ".text"
|
||||
#define DATA_SEG ".data"
|
||||
#define INIT_SEG "_INIT"
|
||||
|
||||
Patch_kernel32::Patch_kernel32(PEmanip& pem) : pefile(pem)
|
||||
{
|
||||
stub_address = 0;
|
||||
|
||||
code_seg_start = (DWORD) pefile.GetSectionByName(CODE_SEG);
|
||||
code_seg_size = pefile.GetSectionSize(CODE_SEG);
|
||||
|
||||
data_seg_start = (DWORD) pefile.GetSectionByName(DATA_SEG);
|
||||
data_seg_size = pefile.GetSectionSize(DATA_SEG);
|
||||
}
|
||||
|
||||
bool Patch_kernel32::apply()
|
||||
{
|
||||
if (find_signature())
|
||||
{
|
||||
DBGPRINTF(("KERNEL32 already patched by previous KernelEx version"));
|
||||
DBGPRINTF(("Make sure pure KERNEL32 is installed before proceeding"));
|
||||
return false;
|
||||
}
|
||||
|
||||
DBGPRINTF(("Preparing KERNEL32 for KernelEx... "));
|
||||
|
||||
if (!find_ExportFromX())
|
||||
return false;
|
||||
if (!find_IsKnownDLL())
|
||||
return false;
|
||||
if (!find_FLoadTreeNotify1())
|
||||
return false;
|
||||
if (!find_FLoadTreeNotify2())
|
||||
return false;
|
||||
if (!prepare_subsystem_check())
|
||||
return false;
|
||||
if (!find_resource_check1())
|
||||
return false;
|
||||
if (!find_resource_check2())
|
||||
return false;
|
||||
if (!disable_named_and_rcdata_resources_mirroring())
|
||||
return false;
|
||||
if (!mod_imte_alloc())
|
||||
return false;
|
||||
if (!mod_mr_alloc())
|
||||
return false;
|
||||
if (!mod_pdb_alloc())
|
||||
return false;
|
||||
if (!create_stubs())
|
||||
return false;
|
||||
|
||||
DBGPRINTF(("... all done!"));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Patch_kernel32::find_signature()
|
||||
{
|
||||
DWORD ptr;
|
||||
KernelEx_dataseg* dseg = NULL;
|
||||
DWORD sign_len = sizeof(KEX_SIGNATURE) - 1;
|
||||
|
||||
ptr = data_seg_start + data_seg_size - sign_len;
|
||||
ptr = PEmanip::ALIGN(ptr, sizeof(DWORD));
|
||||
|
||||
while (ptr >= data_seg_start)
|
||||
{
|
||||
if (!memcmp((void*) ptr, KEX_SIGNATURE, sign_len))
|
||||
{
|
||||
dseg = (KernelEx_dataseg*) ptr;
|
||||
break;
|
||||
}
|
||||
ptr -= sizeof(DWORD);
|
||||
}
|
||||
|
||||
return dseg != NULL;
|
||||
}
|
||||
|
||||
bool Patch_kernel32::prepare_subsystem_check()
|
||||
{
|
||||
static const short pattern[] = {
|
||||
0x66,0x8b,0x46,0x48,0x66,0x3d,0x04,0x00,0x0f,0x87,0x9c,0x01,0x00,0x00,
|
||||
0x75,0x0b,0x66,0x83,0x7e,0x4a,0x0a,0x0f,0x87,0x8f,0x01,0x00,0x00,0x66,
|
||||
0x81,0x7e,0x04,0x4c,0x01,
|
||||
};
|
||||
static const short after[] = {
|
||||
0x66,0x83,0x7E,0x48,0x04,0x75,0x05,0x66,0x83,0x7E,0x4A,0x0A,0xE9,0x00,
|
||||
0x00,0x00,0x00,0x0F,0x87,0x93,0x01,0x00,0x00,0x90,0x90,0x90,0x90,0x66,
|
||||
0x81,0x7e,0x04,0x4c,0x01,
|
||||
};
|
||||
|
||||
int length = sizeof(pattern) / sizeof(short);
|
||||
DWORD found_loc;
|
||||
int found = find_pattern(code_seg_start, code_seg_size, pattern, length, &found_loc);
|
||||
if (found != 1)
|
||||
{
|
||||
if (!found) ShowError(IDS_NOPAT, "subsystem_check");
|
||||
else ShowError(IDS_MULPAT, "subsystem_check");
|
||||
return false;
|
||||
}
|
||||
DBGPRINTF(("%s: pattern found @ 0x%08x", "subsystem_check", found_loc));
|
||||
set_pattern(found_loc, after, length);
|
||||
|
||||
SubsysCheck_jmp = found_loc + 12;
|
||||
_SubsysCheckPerform = decode_jmp(SubsysCheck_jmp, 5);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Patch_kernel32::find_resource_check1()
|
||||
{
|
||||
static const short pattern[] = {
|
||||
0x6A,0x00,0x8D,0x45,0xE0,0x50,0xFF,0x75,0xA4,0xFF,0x75,0xD0,0x8D,0x45,
|
||||
0xCC,0x50,0xFF,0x75,0x08,0xE8,-2,-2,-2,-2,0x85,0xC0
|
||||
};
|
||||
|
||||
int length = sizeof(pattern) / sizeof(short);
|
||||
DWORD found_loc;
|
||||
int found = find_pattern(code_seg_start, code_seg_size, pattern, length, &found_loc);
|
||||
if (found != 1)
|
||||
{
|
||||
if (!found) ShowError(IDS_NOPAT, "resource_check1");
|
||||
else ShowError(IDS_MULPAT, "resource_check1");
|
||||
return false;
|
||||
}
|
||||
DBGPRINTF(("%s: pattern found @ 0x%08x", "resource_check1", found_loc));
|
||||
GetOrdinal_call1 = found_loc + 19;
|
||||
_GetOrdinal = decode_call(GetOrdinal_call1, 5);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Patch_kernel32::find_resource_check2()
|
||||
{
|
||||
static const short pattern[] = {
|
||||
0x66,0x8B,0x45,0xE0,0x66,0x2D,0x06,0x80,0x66,0x3D,0x01,0x00,0x1B,0xC0,
|
||||
0xF7,0xD8,0x50,0x8D,0x45,0xDE,0x50,0xFF,0x75, -1,0xFF,0x75,0xD0,0x8D,
|
||||
0x45,0xCC,0x50,0xFF,0x75,0x08,0xE8, -2, -2, -2, -2,0x85,0xC0
|
||||
};
|
||||
|
||||
int length = sizeof(pattern) / sizeof(short);
|
||||
DWORD found_loc;
|
||||
int found = find_pattern(code_seg_start, code_seg_size, pattern, length, &found_loc);
|
||||
if (found != 1)
|
||||
{
|
||||
if (!found) ShowError(IDS_NOPAT, "resource_check2");
|
||||
else ShowError(IDS_MULPAT, "resource_check2");
|
||||
return false;
|
||||
}
|
||||
DBGPRINTF(("%s: pattern found @ 0x%08x", "resource_check2", found_loc));
|
||||
GetOrdinal_call2 = found_loc + 34;
|
||||
return true;
|
||||
}
|
||||
|
||||
//no named/rcdata resource types mirroring
|
||||
bool Patch_kernel32::disable_named_and_rcdata_resources_mirroring()
|
||||
{
|
||||
static const short pattern[] = {
|
||||
0x66,0x8B,0x40,0x0E,0x66,0x89,0x45,0xDA,0x8B,0x45, -1,0x66,0x8B,0x48,
|
||||
0x0C,0x66,0x89,0x4D,0xD8,0x66,0x8B,0x45,0xE0,0x8B,0x4D,0xD4,0x66,0x89,
|
||||
0x01,0x83,0x45,0xD4,0x02,0x66,0x8B,0x45,0xDA,0x66,0x03,0x45,0xD8,0x66,
|
||||
0x89,0x45,0x8C,0x8B,0x4D,0xD4,0x66,0x89,0x01,0x83,0x45,0xD4,0x02
|
||||
};
|
||||
static const short after[] = {
|
||||
0x66,0x8B,0x48,0x0E,0x66,0x03,0x48,0x0C,0x66,0x89,0x4D,0x8C,0x8B,0x45,
|
||||
0xA4,0x83,0x38,0x0A,0x74,0x40,0x83,0x38,0x00,0x79,0x04,0x3B,0xC0,0xEB,
|
||||
0x37,0x66,0x8B,0x45,0xE0,0x8B,0x4D,0xD4,0x66,0x89,0x01,0x83,0xC1,0x02,
|
||||
0x66,0x8B,0x45,0x8C,0x66,0x89,0x01,0x83,0xC1,0x02,0x89,0x4D,0xD4
|
||||
};
|
||||
|
||||
int length = sizeof(pattern) / sizeof(short);
|
||||
DWORD found_loc;
|
||||
int found = find_pattern(code_seg_start, code_seg_size, pattern, length, &found_loc);
|
||||
if (found != 1)
|
||||
{
|
||||
if (!found) ShowError(IDS_NOPAT, "disable_named_and_rcdata_resources_mirroring");
|
||||
else ShowError(IDS_MULPAT, "disable_named_and_rcdata_resources_mirroring");
|
||||
return false;
|
||||
}
|
||||
DBGPRINTF(("%s: pattern found @ 0x%08x", "disable_named_and_rcdata_resources_mirroring", found_loc));
|
||||
set_pattern(found_loc, after, length);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Patch_kernel32::mod_imte_alloc()
|
||||
{
|
||||
//VA BFF8745C, RVA 1745C, file 15A5C, sec E45C
|
||||
static const short pattern[] = {
|
||||
0x66,0xff,0x05,-1,-1,-1,0xbf,0x6a,0x3c,0xe8,
|
||||
};
|
||||
static const short after[] = {
|
||||
0x66,0xff,0x05,-1,-1,-1,0xbf,0x6a,0x40,0xe8,
|
||||
};
|
||||
|
||||
int length = sizeof(pattern) / sizeof(short);
|
||||
DWORD found_loc;
|
||||
int found = find_pattern(code_seg_start, code_seg_size, pattern, length, &found_loc);
|
||||
if (found != 1)
|
||||
{
|
||||
if (!found) ShowError(IDS_NOPAT, "mod_imte_alloc");
|
||||
else ShowError(IDS_MULPAT, "mod_imte_alloc");
|
||||
return false;
|
||||
}
|
||||
DBGPRINTF(("%s: pattern found @ 0x%08x", "mod_imte_alloc", found_loc));
|
||||
set_pattern(found_loc, after, length);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Patch_kernel32::mod_mr_alloc()
|
||||
{
|
||||
static const short pattern[] = {
|
||||
0x75,0xF6,0x8D,0x04,-1,0x1C,0x00,0x00,0x00,0x50
|
||||
};
|
||||
static const short after[] = {
|
||||
0x75,0xF6,0x8D,0x04,-1,0x24,0x00,0x00,0x00,0x50
|
||||
};
|
||||
|
||||
int length = sizeof(pattern) / sizeof(short);
|
||||
DWORD found_loc;
|
||||
int found = find_pattern(code_seg_start, code_seg_size, pattern, length, &found_loc);
|
||||
if (found != 1)
|
||||
{
|
||||
if (!found) ShowError(IDS_NOPAT, "mod_mr_alloc");
|
||||
else ShowError(IDS_MULPAT, "mod_mr_alloc");
|
||||
return false;
|
||||
}
|
||||
DBGPRINTF(("%s: pattern found @ 0x%08x", "mod_mr_alloc", found_loc));
|
||||
set_pattern(found_loc, after, length);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Patch_kernel32::mod_pdb_alloc()
|
||||
{
|
||||
static const short pattern[] = {
|
||||
0x53,0x56,0x57,0x6A,0x06,0x68,0xC4,0x00,0x00,0x00,0xE8
|
||||
};
|
||||
static const short after[] = {
|
||||
0x53,0x56,0x57,0x6A,0x06,0x68,0xC8,0x00,0x00,0x00,0xE8
|
||||
};
|
||||
|
||||
int length = sizeof(pattern) / sizeof(short);
|
||||
DWORD found_loc;
|
||||
int found = find_pattern(code_seg_start, code_seg_size, pattern, length, &found_loc);
|
||||
if (found != 1)
|
||||
{
|
||||
if (!found) ShowError(IDS_NOPAT, "mod_pdb_alloc");
|
||||
else ShowError(IDS_MULPAT, "mod_pdb_alloc");
|
||||
return false;
|
||||
}
|
||||
DBGPRINTF(("%s: pattern found @ 0x%08x", "mod_pdb_alloc", found_loc));
|
||||
set_pattern(found_loc, after, length);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Patch_kernel32::find_ExportFromX()
|
||||
{
|
||||
static const short pattern[] = {
|
||||
0x8B,0x0D,-1,-1,-1,-1,0x0F,0xBF,0x40,0x10,0x8B,0x14,0x81,0x8B,0x44,
|
||||
0x24,0x14,0x3D,0x00,0x00,0x01,0x00,0x8B,0x4A,0x04,0x73,0x15,-1,0x1D,
|
||||
-1,-1,-1,-1,0x75,0x04,0x6A,0x32,0xEB,0x3E,0x50,0x51,0xE8,-2,-2,-2,-2,
|
||||
0xEB,0x0C,0xFF,0x74,0x24,0x14,0x6A,0x00,0x51,0xE8,-2,-2,-2,-2,0x83,
|
||||
0x7F,0x54,0x00,0x8B,0xF0
|
||||
};
|
||||
|
||||
int length = sizeof(pattern) / sizeof(short);
|
||||
DWORD found_loc;
|
||||
int found = find_pattern(code_seg_start, code_seg_size, pattern, length, &found_loc);
|
||||
if (found != 1)
|
||||
{
|
||||
if (!found) ShowError(IDS_NOPAT, "exportfromX");
|
||||
else ShowError(IDS_MULPAT, "exportfromX");
|
||||
return false;
|
||||
}
|
||||
DBGPRINTF(("%s: pattern found @ 0x%08x", "exportfromX", found_loc));
|
||||
gpa_ExportFromOrdinal_call = found_loc + 0x29;
|
||||
gpa_ExportFromName_call = found_loc + 0x37;
|
||||
_ExportFromOrdinal = decode_call(gpa_ExportFromOrdinal_call, 5);
|
||||
_ExportFromName = decode_call(gpa_ExportFromName_call, 5);
|
||||
DWORD start = _ExportFromName;
|
||||
for (DWORD a = start ; a < start + 0x100 ; a++)
|
||||
{
|
||||
if (is_call_ref(a, _ExportFromOrdinal))
|
||||
{
|
||||
EFN_EFO_call = a;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
DBGPRINTF(("EFN_EFO_call not found"));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Patch_kernel32::find_IsKnownDLL()
|
||||
{
|
||||
static const short pattern[] = {
|
||||
0xFF,0x75,0xFC,0x8D,0x8D,0xF0,0xFE,0xFF,0xFF,0x51,0xE8,-2,-2,-2,-2,
|
||||
0x85,0xC0,0x75,0x1E,0x8D,0x85,0xE8,0xFD,0xFF,0xFF,
|
||||
0x8D,0x8D,0xF0,0xFE,0xFF,0xFF,0x50,0x51
|
||||
};
|
||||
|
||||
int length = sizeof(pattern) / sizeof(short);
|
||||
DWORD found_loc;
|
||||
int found = find_pattern(code_seg_start, code_seg_size, pattern, length, &found_loc);
|
||||
if (found != 1)
|
||||
{
|
||||
if (!found) ShowError(IDS_NOPAT, "IsKnownDLL");
|
||||
else ShowError(IDS_MULPAT, "IsKnownDLL");
|
||||
return false;
|
||||
}
|
||||
DBGPRINTF(("%s: pattern found @ 0x%08x", "IsKnownDLL", found_loc));
|
||||
IsKnownDLL_call = found_loc + 10;
|
||||
_IsKnownDLL = decode_call(IsKnownDLL_call, 5);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Patch_kernel32::find_FLoadTreeNotify1()
|
||||
{
|
||||
static const short pattern[] = {
|
||||
0x56,0xA1,-1,-1,-1,-1,0x6A,0x01,0x8B,0x08,0xFF,0xB1,0x98,0x00,0x00,
|
||||
0x00,0xE8,-2,-2,-2,-2,0x83,0xF8,0x01,0x1B,0xF6,0xF7,0xDE
|
||||
};
|
||||
|
||||
int length = sizeof(pattern) / sizeof(short);
|
||||
DWORD found_loc;
|
||||
int found = find_pattern(code_seg_start, code_seg_size, pattern, length, &found_loc);
|
||||
if (found != 1)
|
||||
{
|
||||
if (!found) ShowError(IDS_NOPAT, "FLoadTreeNotify1");
|
||||
else ShowError(IDS_MULPAT, "FLoadTreeNotify1");
|
||||
return false;
|
||||
}
|
||||
DBGPRINTF(("%s: pattern found @ 0x%08x", "FLoadTreeNotify1", found_loc));
|
||||
FLoadTreeNotify_call1 = found_loc + 16;
|
||||
_FLoadTreeNotify = decode_call(FLoadTreeNotify_call1, 5);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Patch_kernel32::find_FLoadTreeNotify2()
|
||||
{
|
||||
static const short pattern[] = {
|
||||
0x6A,0x00,0x57,0xE8,-1,-1,-1,-1,0x6A,0x00,0x56,0xE8,-2,-2,-2,-2,
|
||||
0x85,0xC0,0x74,0x12,0x56,0xE8,-1,-1,-1,-1,0x68,0x5A,0x04,0x00,0x00,
|
||||
0x33,0xF6,0xE8,-1,-1,-1,-1
|
||||
};
|
||||
|
||||
int length = sizeof(pattern) / sizeof(short);
|
||||
DWORD found_loc;
|
||||
int found = find_pattern(code_seg_start, code_seg_size, pattern, length, &found_loc);
|
||||
if (found != 1)
|
||||
{
|
||||
if (!found) ShowError(IDS_NOPAT, "FLoadTreeNotify2");
|
||||
else ShowError(IDS_MULPAT, "FLoadTreeNotify2");
|
||||
return false;
|
||||
}
|
||||
DBGPRINTF(("%s: pattern found @ 0x%08x", "FLoadTreeNotify2", found_loc));
|
||||
FLoadTreeNotify_call2 = found_loc + 11;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Patch_kernel32::create_stubs()
|
||||
{
|
||||
KernelEx_codeseg* cseg;
|
||||
KernelEx_dataseg* dseg;
|
||||
if (!pefile.AllocSectionSpace(CODE_SEG,
|
||||
sizeof(KernelEx_codeseg), (void**) &cseg, sizeof(DWORD)))
|
||||
{
|
||||
ShowError(IDS_FAILSEC, CODE_SEG);
|
||||
return false;
|
||||
}
|
||||
if (!pefile.AllocSectionSpace(DATA_SEG,
|
||||
sizeof(KernelEx_dataseg), (void**) &dseg, sizeof(DWORD)))
|
||||
{
|
||||
ShowError(IDS_FAILSEC, DATA_SEG);
|
||||
return false;
|
||||
}
|
||||
|
||||
pagelock(pefile.GetImageBase(), 1);
|
||||
pagelock((DWORD) cseg, sizeof(KernelEx_codeseg));
|
||||
pagelock((DWORD) dseg, sizeof(KernelEx_dataseg));
|
||||
|
||||
stub_address = dseg;
|
||||
|
||||
memcpy(cseg->signature, "KrnlEx", 6);
|
||||
cseg->version = KEX_STUB_VER;
|
||||
for (int i = 0 ; i < JTAB_SIZE ; i++)
|
||||
{
|
||||
cseg->jmp_stub[i].opcode = 0x25ff;
|
||||
cseg->jmp_stub[i].addr = (DWORD) &dseg->jtab[i];
|
||||
cseg->jmp_stub[i].nop = 0x9090;
|
||||
}
|
||||
|
||||
memcpy(dseg->signature, "KrnlEx", 6);
|
||||
dseg->version = KEX_STUB_VER;
|
||||
dseg->jtab[JTAB_EFO_DYN] = _ExportFromOrdinal;
|
||||
dseg->jtab[JTAB_EFO_STA] = _ExportFromOrdinal;
|
||||
dseg->jtab[JTAB_EFN_DYN] = _ExportFromName;
|
||||
dseg->jtab[JTAB_EFN_STA] = _ExportFromName;
|
||||
dseg->jtab[JTAB_KNO_DLL] = _IsKnownDLL;
|
||||
dseg->jtab[JTAB_FLD_TRN] = _FLoadTreeNotify;
|
||||
dseg->jtab[JTAB_SYS_CHK] = _SubsysCheckPerform;
|
||||
dseg->jtab[JTAB_RES_CHK] = _GetOrdinal;
|
||||
|
||||
//exportfromx patch
|
||||
int efo_cnt = 0;
|
||||
int efn_cnt = 0;
|
||||
|
||||
for (DWORD a = code_seg_start ; a < code_seg_start + code_seg_size ; a++)
|
||||
{
|
||||
if (is_call_ref(a, _ExportFromOrdinal))
|
||||
{
|
||||
DWORD file_loc = a;
|
||||
if (a == EFN_EFO_call)
|
||||
continue;
|
||||
if (a == gpa_ExportFromOrdinal_call)
|
||||
set_call_ref(file_loc, (DWORD) &cseg->jmp_stub[JTAB_EFO_DYN]);
|
||||
else
|
||||
set_call_ref(file_loc, (DWORD) &cseg->jmp_stub[JTAB_EFO_STA]);
|
||||
DBGPRINTF(("%s: address 0x%08x", "EFO", a));
|
||||
efo_cnt++;
|
||||
}
|
||||
else if (is_call_ref(a, _ExportFromName))
|
||||
{
|
||||
DWORD file_loc = a;
|
||||
if (is_fixupc(a))
|
||||
continue;
|
||||
if (a == gpa_ExportFromName_call)
|
||||
set_call_ref(file_loc, (DWORD) &cseg->jmp_stub[JTAB_EFN_DYN]);
|
||||
else
|
||||
set_call_ref(file_loc, (DWORD) &cseg->jmp_stub[JTAB_EFN_STA]);
|
||||
DBGPRINTF(("%s: address 0x%08x", "EFN", a));
|
||||
efn_cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
if (efo_cnt != 2 || efn_cnt != 2)
|
||||
{
|
||||
ShowError(IDS_ERRCHECK);
|
||||
return false;
|
||||
}
|
||||
|
||||
//isknowndll patch
|
||||
set_call_ref(IsKnownDLL_call, (DWORD) &cseg->jmp_stub[JTAB_KNO_DLL]);
|
||||
DBGPRINTF(("%s: address 0x%08x", "KNO_DLL", IsKnownDLL_call));
|
||||
|
||||
//FLoadTreeNotify patch
|
||||
set_call_ref(FLoadTreeNotify_call1, (DWORD) &cseg->jmp_stub[JTAB_FLD_TRN]);
|
||||
DBGPRINTF(("%s: address 0x%08x", "FLD_TRN1", FLoadTreeNotify_call1));
|
||||
set_call_ref(FLoadTreeNotify_call2, (DWORD) &cseg->jmp_stub[JTAB_FLD_TRN]);
|
||||
DBGPRINTF(("%s: address 0x%08x", "FLD_TRN2", FLoadTreeNotify_call2));
|
||||
|
||||
//subsys check patch
|
||||
set_jmp_ref(SubsysCheck_jmp, (DWORD) &cseg->jmp_stub[JTAB_SYS_CHK]);
|
||||
DBGPRINTF(("%s: address 0x%08x", "SYS_CHK", SubsysCheck_jmp));
|
||||
|
||||
//resource check patch
|
||||
set_call_ref(GetOrdinal_call1, (DWORD) &cseg->jmp_stub[JTAB_RES_CHK]);
|
||||
DBGPRINTF(("%s: address 0x%08x", "RES_CHK1", GetOrdinal_call1));
|
||||
set_call_ref(GetOrdinal_call2, (DWORD) &cseg->jmp_stub[JTAB_RES_CHK]);
|
||||
DBGPRINTF(("%s: address 0x%08x", "RES_CHK2", GetOrdinal_call2));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Patch_kernel32::is_fixupc(DWORD addr)
|
||||
{
|
||||
if (*(DWORD*)(addr - 5) == 0xDAC)
|
||||
return true;
|
||||
return false;
|
||||
}
|
77
vxd/patch_kernel32.h
Executable file
77
vxd/patch_kernel32.h
Executable file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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 __PATCH_KERNEL32_H
|
||||
#define __PATCH_KERNEL32_H
|
||||
|
||||
#include "patch.h"
|
||||
#include "interface.h"
|
||||
|
||||
class PEmanip;
|
||||
|
||||
class Patch_kernel32 : public Patch
|
||||
{
|
||||
public:
|
||||
Patch_kernel32(PEmanip& pem);
|
||||
bool apply();
|
||||
|
||||
KernelEx_dataseg* stub_address;
|
||||
|
||||
private:
|
||||
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;
|
||||
DWORD _IsKnownDLL;
|
||||
DWORD _FLoadTreeNotify;
|
||||
DWORD _SubsysCheckPerform;
|
||||
DWORD GetOrdinal_call1;
|
||||
DWORD GetOrdinal_call2;
|
||||
DWORD gpa_ExportFromOrdinal_call;
|
||||
DWORD gpa_ExportFromName_call;
|
||||
DWORD EFN_EFO_call;
|
||||
DWORD IsKnownDLL_call;
|
||||
DWORD FLoadTreeNotify_call1;
|
||||
DWORD FLoadTreeNotify_call2;
|
||||
DWORD SubsysCheck_jmp;
|
||||
};
|
||||
|
||||
#endif
|
200
vxd/pemanip.cpp
Executable file
200
vxd/pemanip.cpp
Executable file
@ -0,0 +1,200 @@
|
||||
/*
|
||||
* KernelEx
|
||||
* Copyright (C) 2008-2009, 2011, Xeno86
|
||||
*
|
||||
* This file is part of KernelEx source code.
|
||||
*
|
||||
* KernelEx is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* KernelEx is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "pemanip.h"
|
||||
#include "debug.h"
|
||||
#include <cstring>
|
||||
|
||||
extern "C" {
|
||||
#define WANTVXDWRAPS
|
||||
#include <vmm.h>
|
||||
#include <vxdwraps.h>
|
||||
};
|
||||
|
||||
PEmanip::PEmanip()
|
||||
{
|
||||
ZeroInit();
|
||||
}
|
||||
|
||||
PEmanip::PEmanip(void* memory)
|
||||
{
|
||||
ZeroInit();
|
||||
OpenMemory(memory);
|
||||
}
|
||||
|
||||
void PEmanip::ZeroInit()
|
||||
{
|
||||
MZh = NULL;
|
||||
PEh = NULL;
|
||||
section_hdrs = NULL;
|
||||
target_len = 0;
|
||||
image_base = 0;
|
||||
has_target = false;
|
||||
}
|
||||
|
||||
void PEmanip::Close()
|
||||
{
|
||||
ZeroInit();
|
||||
}
|
||||
|
||||
bool PEmanip::OpenMemory(void* memory)
|
||||
{
|
||||
if (has_target)
|
||||
return false;
|
||||
|
||||
MZh = (IMAGE_DOS_HEADER*) memory;
|
||||
|
||||
if (MZh->e_magic == IMAGE_DOS_SIGNATURE)
|
||||
{
|
||||
PEh = (IMAGE_NT_HEADERS*) ((DWORD) MZh + MZh->e_lfanew);
|
||||
if ((PEh->Signature == IMAGE_NT_SIGNATURE)
|
||||
&& (PEh->FileHeader.Machine == IMAGE_FILE_MACHINE_I386)
|
||||
&& (PEh->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR_MAGIC))
|
||||
{
|
||||
section_hdrs = (IMAGE_SECTION_HEADER*)
|
||||
((DWORD) PEh
|
||||
+ PEh->FileHeader.SizeOfOptionalHeader
|
||||
+ sizeof(IMAGE_FILE_HEADER)
|
||||
+ sizeof(DWORD));
|
||||
image_base = (DWORD)memory;
|
||||
has_target = true;
|
||||
target_len = PEh->OptionalHeader.SizeOfImage;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
IMAGE_SECTION_HEADER* PEmanip::RvaToSection(DWORD Rva)
|
||||
{
|
||||
IMAGE_SECTION_HEADER* section = section_hdrs;
|
||||
|
||||
for (int i = 0 ; i < PEh->FileHeader.NumberOfSections ; i++)
|
||||
{
|
||||
if ((Rva >= section->VirtualAddress)
|
||||
&& (Rva < (section->VirtualAddress + section->Misc.VirtualSize)))
|
||||
{
|
||||
return section;
|
||||
}
|
||||
section++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IMAGE_SECTION_HEADER* PEmanip::FindSectionByName(const char* name)
|
||||
{
|
||||
IMAGE_SECTION_HEADER* section = section_hdrs;
|
||||
|
||||
for (int i = 0 ; i < PEh->FileHeader.NumberOfSections ; i++)
|
||||
{
|
||||
if (!strncmp((char*) section->Name, name, sizeof(section->Name)))
|
||||
return section;
|
||||
section++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* PEmanip::GetSectionByName(const char* name)
|
||||
{
|
||||
IMAGE_SECTION_HEADER* section = FindSectionByName(name);
|
||||
|
||||
if (section)
|
||||
return RvaToPointer(section->VirtualAddress);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DWORD PEmanip::GetSectionSize(const char* name)
|
||||
{
|
||||
IMAGE_SECTION_HEADER* section = FindSectionByName(name);
|
||||
|
||||
if (section)
|
||||
return section->Misc.VirtualSize;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool PEmanip::AllocSectionSpace(const char* name, int needed_space, void** ptr, int align)
|
||||
{
|
||||
IMAGE_SECTION_HEADER* Section = FindSectionByName(name);
|
||||
|
||||
if (!Section || align < 1 || needed_space < 0)
|
||||
return false;
|
||||
|
||||
if (!needed_space)
|
||||
return true;
|
||||
|
||||
DWORD current_size = ALIGN(Section->Misc.VirtualSize, align);
|
||||
DWORD new_size = current_size + needed_space;
|
||||
|
||||
DWORD max_size = (Section + 1)->VirtualAddress - Section->VirtualAddress;
|
||||
int available_space = max_size - current_size;
|
||||
|
||||
DBGPRINTF(("Allocating space in section '%s' avail: %d needed: %d",
|
||||
name, available_space, needed_space));
|
||||
|
||||
if (available_space < needed_space)
|
||||
{
|
||||
DBGPRINTF(("Not enough space in section!"));
|
||||
return false;
|
||||
}
|
||||
|
||||
Section->Misc.VirtualSize = new_size;
|
||||
|
||||
if (ptr)
|
||||
*ptr = RvaToPointer(Section->VirtualAddress + current_size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
DWORD PEmanip::GetExportedAPI(const char* func)
|
||||
{
|
||||
IMAGE_EXPORT_DIRECTORY* Exports = (IMAGE_EXPORT_DIRECTORY*)
|
||||
RvaToPointer(PEh->OptionalHeader
|
||||
.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
|
||||
|
||||
if (Exports)
|
||||
{
|
||||
DWORD* Names = (DWORD*) RvaToPointer(Exports->AddressOfNames);
|
||||
|
||||
for (DWORD i = 0 ; i < Exports->NumberOfNames ; i++)
|
||||
{
|
||||
if (!strcmp(func, (char*) RvaToPointer(*Names)))
|
||||
{
|
||||
WORD* OrdinalTable = (WORD*) RvaToPointer(Exports->AddressOfNameOrdinals);
|
||||
WORD Index = OrdinalTable[i];
|
||||
DWORD* FunctionTable = (DWORD*) RvaToPointer(Exports->AddressOfFunctions);
|
||||
DWORD Address = (DWORD) FunctionTable[Index];
|
||||
return Address;
|
||||
}
|
||||
Names++;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* PEmanip::CreateBackup()
|
||||
{
|
||||
if (!has_target)
|
||||
return NULL;
|
||||
void* mem = _HeapAllocate(target_len, HEAPSWAP);
|
||||
memcpy(mem, MZh, target_len);
|
||||
return mem;
|
||||
}
|
91
vxd/pemanip.h
Executable file
91
vxd/pemanip.h
Executable file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* KernelEx
|
||||
* Copyright (C) 2008-2009, 2011, Xeno86
|
||||
*
|
||||
* This file is part of KernelEx source code.
|
||||
*
|
||||
* KernelEx is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* KernelEx is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _SETUP_PEMANIP_H
|
||||
#define _SETUP_PEMANIP_H
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <winnt.h>
|
||||
|
||||
class PEmanip
|
||||
{
|
||||
public:
|
||||
PEmanip();
|
||||
PEmanip(void* memory);
|
||||
bool HasTarget();
|
||||
bool OpenMemory(void* memory);
|
||||
void Close();
|
||||
IMAGE_NT_HEADERS* GetPEHeader();
|
||||
IMAGE_SECTION_HEADER* RvaToSection(DWORD Rva);
|
||||
void* RvaToPointer(DWORD Rva);
|
||||
DWORD PointerToRva(void* pointer);
|
||||
void* GetSectionByName(const char* name);
|
||||
DWORD GetSectionSize(const char* name);
|
||||
bool AllocSectionSpace(const char* name, int needed_space, void** ptr, int align = 1);
|
||||
DWORD GetExportedAPI(const char* func);
|
||||
DWORD GetImageBase();
|
||||
void* CreateBackup();
|
||||
static unsigned long ALIGN(unsigned long x, unsigned long y);
|
||||
|
||||
private:
|
||||
void ZeroInit();
|
||||
IMAGE_SECTION_HEADER* FindSectionByName(const char* name);
|
||||
|
||||
bool has_target;
|
||||
int target_len;
|
||||
IMAGE_DOS_HEADER* MZh;
|
||||
IMAGE_NT_HEADERS* PEh;
|
||||
IMAGE_SECTION_HEADER* section_hdrs;
|
||||
DWORD image_base;
|
||||
};
|
||||
|
||||
inline bool PEmanip::HasTarget()
|
||||
{
|
||||
return has_target;
|
||||
}
|
||||
|
||||
inline IMAGE_NT_HEADERS* PEmanip::GetPEHeader()
|
||||
{
|
||||
return PEh;
|
||||
}
|
||||
|
||||
inline unsigned long PEmanip::ALIGN(unsigned long x, unsigned long y)
|
||||
{
|
||||
return (x + y - 1) & (~(y - 1));
|
||||
}
|
||||
|
||||
inline DWORD PEmanip::GetImageBase()
|
||||
{
|
||||
return image_base;
|
||||
}
|
||||
|
||||
inline void* PEmanip::RvaToPointer(DWORD Rva)
|
||||
{
|
||||
return (void*)(Rva + image_base);
|
||||
}
|
||||
|
||||
inline DWORD PEmanip::PointerToRva(void* pointer)
|
||||
{
|
||||
return (DWORD) pointer - image_base;
|
||||
}
|
||||
|
||||
#endif
|
50
vxd/util.c
Executable file
50
vxd/util.c
Executable file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* KernelEx
|
||||
* Copyright (C) 2011, Xeno86
|
||||
*
|
||||
* This file is part of KernelEx source code.
|
||||
*
|
||||
* KernelEx is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* KernelEx is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <basedef.h>
|
||||
#include <vmm.h>
|
||||
|
||||
void __cdecl abort(void)
|
||||
{
|
||||
__asm int 3
|
||||
}
|
||||
|
||||
int __cdecl _purecall (void)
|
||||
{
|
||||
abort();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __cdecl _assert(const char* expr, const char* file, unsigned line)
|
||||
{
|
||||
_Debug_Printf_Service("Assertion failed: '%s' in %s line %d", expr, file, line);
|
||||
abort();
|
||||
}
|
||||
|
||||
void __declspec(naked) _stdcall RtlUnwind(
|
||||
PVOID TargetFrame,
|
||||
PVOID TargetIp,
|
||||
PVOID ExceptionRecord,
|
||||
PVOID ReturnValue
|
||||
)
|
||||
{
|
||||
VMMJmp(ObsoleteRtlUnwind);
|
||||
}
|
72
vxd/util.h
Executable file
72
vxd/util.h
Executable file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* KernelEx
|
||||
* Copyright (C) 2011, Xeno86
|
||||
*
|
||||
* This file is part of KernelEx source code.
|
||||
*
|
||||
* KernelEx is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* KernelEx is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __UTIL_H
|
||||
#define __UTIL_H
|
||||
|
||||
#define __STR(x) #x
|
||||
#define STR(x) __STR(x)
|
||||
|
||||
#define EXTERNC extern "C"
|
||||
|
||||
#define _Declare_Virtual_Device(name, ver_major, ver_minor, ctrl_proc, device_num, init_order, V86_proc, PM_proc, ref_data) \
|
||||
BOOL __stdcall ControlDispatcher(DWORD, DWORD, DWORD, DWORD, DWORD, DWORD); \
|
||||
\
|
||||
void __declspec(naked) name##_CTRL(void) \
|
||||
{ \
|
||||
__asm PUSH EDI \
|
||||
__asm PUSH ESI \
|
||||
__asm PUSH EDX \
|
||||
__asm PUSH ECX \
|
||||
__asm PUSH EBX \
|
||||
__asm PUSH EAX \
|
||||
__asm CALL ctrl_proc \
|
||||
__asm CMP EAX, TRUE \
|
||||
__asm RET \
|
||||
} \
|
||||
\
|
||||
EXTERNC struct VxD_Desc_Block name##_DDB = \
|
||||
{ \
|
||||
0, DDK_VERSION, device_num, ver_major, ver_minor, 0, \
|
||||
#name, init_order, (ULONG)name##_CTRL, (ULONG)V86_proc, (ULONG)PM_proc, \
|
||||
0, 0, ref_data, 0, 0, 0, 'Prev', sizeof(struct VxD_Desc_Block), \
|
||||
'Rsv1', 'Rsv2', 'Rsv3' \
|
||||
}
|
||||
|
||||
|
||||
|
||||
#pragma warning (disable:4035) // turn off no return code warning
|
||||
|
||||
static inline
|
||||
bool Hook_Device_Service(ULONG service, ULONG hookproc)
|
||||
{
|
||||
_asm mov eax, [service]
|
||||
_asm mov esi, [hookproc]
|
||||
VMMCall(Hook_Device_Service)
|
||||
_asm setnc al
|
||||
#ifndef __BOOL_DEFINED
|
||||
_asm movzx eax, al
|
||||
#endif
|
||||
}
|
||||
|
||||
#pragma warning (default:4035) // turn on no return code warning
|
||||
|
||||
#endif
|
170
vxd/vxd.dsp
Executable file
170
vxd/vxd.dsp
Executable file
@ -0,0 +1,170 @@
|
||||
# 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=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 "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 "vxd.mak" CFG="VxD - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "VxD - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "VxD - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "VxD - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# 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 /D "NDEBUG" /FD /GF /c
|
||||
# ADD BASE RSC /l 0x415 /d "NDEBUG"
|
||||
# ADD RSC /l 0x415 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# 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 vxdwraps.clb libc.lib /nologo /map /machine:I386 /nodefaultlib /out:"Release/VKrnlEx.vxd" /vxd /ignore:4078 /ignore:4039
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
|
||||
!ELSEIF "$(CFG)" == "VxD - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# 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 /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
|
||||
# ADD BASE BSC32 /nologo
|
||||
# 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 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 "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=.\patch_ifsmgr.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
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"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\interface.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\patch.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\patch_ifsmgr.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\patch_kernel32.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\pemanip.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
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"
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
244
vxd/vxdmain.cpp
Executable file
244
vxd/vxdmain.cpp
Executable file
@ -0,0 +1,244 @@
|
||||
/*
|
||||
* KernelEx
|
||||
* Copyright (C) 2011, Xeno86
|
||||
*
|
||||
* This file is part of KernelEx source code.
|
||||
*
|
||||
* KernelEx is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* KernelEx is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
extern "C" {
|
||||
#define WANTVXDWRAPS
|
||||
#include <vmm.h>
|
||||
#include <debug.h>
|
||||
#include <vxdwraps.h>
|
||||
#include <vwin32.h>
|
||||
};
|
||||
#include <winerror.h>
|
||||
#include "vxdmain.h"
|
||||
#include "util.h"
|
||||
#include "debug.h"
|
||||
#include "pemanip.h"
|
||||
#include "patch_kernel32.h"
|
||||
#include "patch_ifsmgr.h"
|
||||
#include "interface.h"
|
||||
|
||||
#define V_MAJOR 1
|
||||
#define V_MINOR 0
|
||||
|
||||
_Declare_Virtual_Device(VKRNLEX, V_MAJOR, V_MINOR, ControlDispatcher, UNDEFINED_DEVICE_ID, UNDEFINED_INIT_ORDER, 0, 0, 0);
|
||||
|
||||
DWORD ( _stdcall *VKernelEx_W32_Proc[] )(DWORD, PDIOCPARAMETERS) = {
|
||||
VKernelEx_IOCTL_Connect
|
||||
};
|
||||
|
||||
#define MAX_VKERNELEX_W32_API (sizeof(VKernelEx_W32_Proc)/sizeof(DWORD))
|
||||
|
||||
static ioctl_connect_params s_connect_params;
|
||||
|
||||
BOOL __stdcall ControlDispatcher(
|
||||
DWORD dwControlMessage,
|
||||
DWORD EBX,
|
||||
DWORD ECX,
|
||||
DWORD EDX,
|
||||
DWORD ESI,
|
||||
DWORD EDI)
|
||||
{
|
||||
switch(dwControlMessage)
|
||||
{
|
||||
case SYS_CRITICAL_INIT:
|
||||
return VKernelEx_Critical_Init();
|
||||
case DEVICE_INIT:
|
||||
return VKernelEx_Dynamic_Init();
|
||||
case SYS_DYNAMIC_DEVICE_INIT:
|
||||
return VKernelEx_Dynamic_Init();
|
||||
case SYS_DYNAMIC_DEVICE_EXIT:
|
||||
return VKernelEx_Dynamic_Exit();
|
||||
case W32_DEVICEIOCONTROL:
|
||||
return VKernelEx_W32_DeviceIOControl(ECX, EDX, (PDIOCPARAMETERS) ESI);
|
||||
case BEGIN_PM_APP:
|
||||
return VKernelEx_Begin_PM_App(EBX);
|
||||
case CREATE_PROCESS:
|
||||
return VKernelEx_Create_Process(EDX);
|
||||
case DESTROY_PROCESS:
|
||||
return VKernelEx_Destroy_Process(EDX);
|
||||
default:
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
VKernelEx_W32_DeviceIOControl
|
||||
****************************************************************************/
|
||||
DWORD _stdcall VKernelEx_W32_DeviceIOControl(
|
||||
DWORD dwService,
|
||||
DWORD hDevice,
|
||||
PDIOCPARAMETERS lpDIOCParms
|
||||
)
|
||||
{
|
||||
DWORD dwRetVal = 0;
|
||||
|
||||
// DIOC_OPEN is sent when VxD is loaded w/ CreateFile
|
||||
// (this happens just after SYS_DYNAMIC_INIT)
|
||||
if (dwService == DIOC_OPEN)
|
||||
{
|
||||
DBGPRINTF(("WIN32 DEVIOCTL supported here!"));
|
||||
// Must return 0 to tell WIN32 that this VxD supports DEVIOCTL
|
||||
dwRetVal = 0;
|
||||
}
|
||||
// DIOC_CLOSEHANDLE is sent when VxD is unloaded w/ CloseHandle
|
||||
// (this happens just before SYS_DYNAMIC_EXIT)
|
||||
else if (dwService == DIOC_CLOSEHANDLE)
|
||||
{
|
||||
// Dispatch to cleanup proc
|
||||
dwRetVal = VKernelEx_CleanUp();
|
||||
}
|
||||
else if (dwService > MAX_VKERNELEX_W32_API)
|
||||
{
|
||||
// Returning a positive value will cause the WIN32 DeviceIOControl
|
||||
// call to return FALSE, the error code can then be retrieved
|
||||
// via the WIN32 GetLastError
|
||||
dwRetVal = ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
// CALL requested service
|
||||
dwRetVal = (VKernelEx_W32_Proc[dwService-1])(hDevice, lpDIOCParms);
|
||||
}
|
||||
return dwRetVal;
|
||||
}
|
||||
|
||||
DWORD _stdcall VKernelEx_IOCTL_Connect(DWORD hDevice, PDIOCPARAMETERS lpDIOCParms)
|
||||
{
|
||||
DBGPRINTF(("VKernelEx_IOCTL_Connect"));
|
||||
|
||||
if (lpDIOCParms->cbOutBuffer < sizeof(s_connect_params))
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
memcpy((void*) lpDIOCParms->lpvOutBuffer, &s_connect_params, sizeof(s_connect_params));
|
||||
*(DWORD*) lpDIOCParms->lpcbBytesReturned = sizeof(s_connect_params);
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
BOOL _stdcall VKernelEx_Create_Process(DWORD pid)
|
||||
{
|
||||
return VXD_SUCCESS;
|
||||
}
|
||||
|
||||
BOOL _stdcall VKernelEx_Destroy_Process(DWORD pid)
|
||||
{
|
||||
return VXD_SUCCESS;
|
||||
}
|
||||
|
||||
BOOL _stdcall VKernelEx_Begin_PM_App(HVM hVM)
|
||||
{
|
||||
WORD version;
|
||||
void* k32ptr;
|
||||
void* backup = NULL;
|
||||
bool allOK = false;
|
||||
|
||||
if (!Test_Sys_VM_Handle(hVM))
|
||||
return TRUE;
|
||||
|
||||
version = Get_VMM_Version();
|
||||
|
||||
if (version >= 0x045A)
|
||||
k32ptr = (void*) 0xBFF60000; //WINME
|
||||
else
|
||||
k32ptr = (void*) 0xBFF70000; //WIN98
|
||||
|
||||
__try
|
||||
{
|
||||
WORD sign = 0;
|
||||
|
||||
__try
|
||||
{
|
||||
sign = *(WORD*) k32ptr;
|
||||
}
|
||||
__except(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
}
|
||||
|
||||
if (sign == 'ZM')
|
||||
{
|
||||
DBGPRINTF(("KERNEL32 located @ 0x%08x", k32ptr));
|
||||
PEmanip pem;
|
||||
pem.OpenMemory(k32ptr);
|
||||
backup = pem.CreateBackup();
|
||||
Patch_kernel32 patch(pem);
|
||||
if (patch.apply())
|
||||
{
|
||||
allOK = true;
|
||||
s_connect_params.status = true;
|
||||
s_connect_params.vxd_version = MAKEWORD(V_MINOR, V_MAJOR);
|
||||
s_connect_params.stub_ptr = patch.stub_address;
|
||||
}
|
||||
}
|
||||
else
|
||||
DBGPRINTF(("couldn't locate KERNEL32"));
|
||||
}
|
||||
__except(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
}
|
||||
|
||||
if (!allOK)
|
||||
{
|
||||
DBGPRINTF(("KERNEL32 patch failed!"));
|
||||
if (backup != NULL)
|
||||
memcpy(k32ptr, backup, _HeapGetSize(backup, 0));
|
||||
}
|
||||
|
||||
if (backup != NULL)
|
||||
_HeapFree(backup, 0);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL _stdcall VKernelEx_Dynamic_Exit(void)
|
||||
{
|
||||
DBGPRINTF(("Exit"));
|
||||
|
||||
return VXD_SUCCESS;
|
||||
}
|
||||
|
||||
DWORD _stdcall VKernelEx_CleanUp(void)
|
||||
{
|
||||
DBGPRINTF(("Cleaning Up"));
|
||||
return VXD_SUCCESS;
|
||||
}
|
||||
|
||||
#pragma VxD_ICODE_SEG
|
||||
#pragma VxD_IDATA_SEG
|
||||
|
||||
BOOL _stdcall VKernelEx_Critical_Init(void)
|
||||
{
|
||||
DBGPRINTF(("KernelEx Virtual Device v" STR(V_MAJOR) "." STR(V_MINOR)));
|
||||
DBGPRINTF(("Critical Init"));
|
||||
|
||||
Patch_ifsmgr patch;
|
||||
patch.apply();
|
||||
|
||||
return VXD_SUCCESS;
|
||||
}
|
||||
|
||||
BOOL _stdcall VKernelEx_Dynamic_Init(void)
|
||||
{
|
||||
DBGPRINTF(("Init"));
|
||||
|
||||
return VXD_SUCCESS;
|
||||
}
|
35
vxd/vxdmain.h
Executable file
35
vxd/vxdmain.h
Executable file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* KernelEx
|
||||
* Copyright (C) 2011, Xeno86
|
||||
*
|
||||
* This file is part of KernelEx source code.
|
||||
*
|
||||
* KernelEx is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* KernelEx is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __VXDMAIN_H
|
||||
#define __VXDMAIN_H
|
||||
|
||||
BOOL _stdcall VKernelEx_Critical_Init(void);
|
||||
BOOL _stdcall VKernelEx_Dynamic_Init(void);
|
||||
BOOL _stdcall VKernelEx_Dynamic_Exit(void);
|
||||
DWORD _stdcall VKernelEx_W32_DeviceIOControl(DWORD, DWORD, PDIOCPARAMETERS);
|
||||
DWORD _stdcall VKernelEx_CleanUp(void);
|
||||
DWORD _stdcall VKernelEx_IOCTL_Connect(DWORD, PDIOCPARAMETERS);
|
||||
BOOL _stdcall VKernelEx_Create_Process(DWORD pid);
|
||||
BOOL _stdcall VKernelEx_Destroy_Process(DWORD pid);
|
||||
BOOL _stdcall VKernelEx_Begin_PM_App(HVM hVM);
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user