00001
00007 #include "stdafx.h"
00008 #include <bzsddk/bzsddk.h>
00009 #include "../kdvm/kdvm.h"
00010 #include "../kdvm/kdxxx.h"
00011 #include "moduleapi.h"
00012
00013 using namespace BazisLib;
00014 using namespace BazisLib::DDK;
00015
00017
00022 class FunctionPatch
00023 {
00024 private:
00025 char m_PreviousBytes[5];
00026 void *m_pAddress;
00027
00029
00033 class MemoryLocker
00034 {
00035 private:
00036 PMDL m_pMdl;
00037 PVOID m_pPointer;
00038
00039 public:
00041 MemoryLocker(void *pData, ULONG size)
00042 {
00043 m_pMdl = IoAllocateMdl(pData, size, FALSE, FALSE, NULL);
00044 ASSERT(m_pMdl);
00045 MmProbeAndLockPages(m_pMdl, KernelMode, IoReadAccess);
00046 m_pPointer = MmMapLockedPagesSpecifyCache(m_pMdl, KernelMode, MmNonCached, NULL, FALSE, NormalPagePriority);
00047 NTSTATUS status = MmProtectMdlSystemAddress(m_pMdl, PAGE_EXECUTE_READWRITE);
00048 ASSERT(NT_SUCCESS(status));
00049 }
00050
00052 ~MemoryLocker()
00053 {
00054 MmUnmapLockedPages(m_pPointer, m_pMdl);
00055 MmUnlockPages(m_pMdl);
00056 IoFreeMdl(m_pMdl);
00057 }
00058
00060 void *GetPointer()
00061 {
00062 return m_pPointer;
00063 }
00064
00065 };
00066
00067 private:
00069
00073 static void _PatchFunction(void *pFunc, void *pDest)
00074 {
00075 MemoryLocker locker(pFunc, 5);
00076
00077 INT_PTR off = ((char *)pDest - (char *)pFunc) - 5;
00078 #ifdef _AMD64_
00079 if ((off > 0x7FFFFFFFLL) || (off < -0x7FFFFFFFLL))
00080 return;
00081 #endif
00082
00083 unsigned char *p = (unsigned char *)locker.GetPointer();
00084 p[0] = 0xE9;
00085
00086 *((unsigned *)(p+1)) = (unsigned)off;
00087 }
00088
00089 public:
00090 FunctionPatch()
00091 : m_pAddress(NULL)
00092 {
00093 }
00094
00095 ~FunctionPatch()
00096 {
00097 if (m_pAddress)
00098 {
00099 MemoryLocker locker(m_pAddress, 5);
00100 memcpy(locker.GetPointer(), m_PreviousBytes, sizeof(m_PreviousBytes));
00101 }
00102 }
00103
00104
00106
00110 bool Patch(void *pFunc, void *pNewFunc)
00111 {
00112 if (m_pAddress)
00113 return false;
00114 memcpy(m_PreviousBytes, pFunc, sizeof(m_PreviousBytes));
00115 _PatchFunction(pFunc, pNewFunc);
00116 m_pAddress = pFunc;
00117 return true;
00118 }
00119 };
00120
00122 class KDPatchDevice : public Device
00123 {
00124 private:
00125 FunctionPatch m_RecvPatch, m_SendPatch;
00127 bool m_bSucceeded;
00128
00129 public:
00131 KDPatchDevice()
00132 : Device(FILE_DEVICE_UNKNOWN,
00133 L"KDPatchDevice")
00134 , m_bSucceeded(false)
00135 {
00136 PVOID lpKD = KernelGetModuleBase("KDCOM.DLL");
00137 if (lpKD)
00138 {
00139 PVOID lpfSend = KernelGetProcAddress(lpKD, "KdSendPacket");
00140 PVOID lpfRecv = KernelGetProcAddress(lpKD, "KdReceivePacket");
00141 if (lpfSend && lpfRecv)
00142 {
00143 m_SendPatch.Patch(lpfSend, KdSendPacket);
00144 m_RecvPatch.Patch(lpfRecv, KdReceivePacket);
00145 m_bSucceeded = true;
00146 }
00147 }
00148 }
00149
00151 bool IsPatchingSuccessful()
00152 {
00153 return m_bSucceeded;
00154 }
00155
00157 ~KDPatchDevice()
00158 {
00159 }
00160
00161 virtual NTSTATUS DispatchRoutine(IN IncomingIrp *Irp, IO_STACK_LOCATION *IrpSp)
00162 {
00163 return __super::DispatchRoutine(Irp, IrpSp);
00164 }
00165
00166 };
00167
00169 class KDPatchDriver : public Driver
00170 {
00171 private:
00172 KDPatchDevice *pDevice;
00173 bool m_bPatched;
00174
00175 public:
00176 KDPatchDriver() : DDK::Driver(false), m_bPatched(false)
00177 {
00178 pDevice = NULL;
00179 }
00180 #define KDPATCH_TEST_SEND_RAW_MSGS
00182 virtual NTSTATUS DriverLoad(IN PUNICODE_STRING RegistryPath) override
00183 {
00184 NTSTATUS status = __super::DriverLoad(RegistryPath);
00185 if (!NT_SUCCESS(status))
00186 return status;
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217 status = KdDebuggerInitialize0(NULL);
00218 if (!NT_SUCCESS(status))
00219 {
00220 DbgPrint("VirtualKD: Cannot establish connection with the patch DLL in VMWare process! No point in patching KDCOM.\n");
00221 return status;
00222 }
00223 DbgPrint("VirtualKD: Connection with host established.");
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246 DbgPrint(" Patching the KDCOM.DLL...\n");
00247 pDevice = new KDPatchDevice();
00248 if (!pDevice || !pDevice->IsPatchingSuccessful())
00249 {
00250 delete pDevice;
00251 pDevice = NULL;
00252 DbgPrint("\nVirtualKD: Cannot find KDCOM.DLL loaded in memory! Nothing to patch...\n");
00253 return STATUS_OBJECT_NAME_NOT_FOUND;
00254 }
00255 status = pDevice->RegisterDevice(this);
00256 if (!NT_SUCCESS(status))
00257 return status;
00258 m_bPatched = true;
00259 return STATUS_SUCCESS;
00260 }
00261
00263 virtual ~KDPatchDriver()
00264 {
00265 delete pDevice;
00266
00267
00268
00269
00270
00271
00272
00273
00274 LARGE_INTEGER interval;
00275 interval.QuadPart = -100000;
00276 for (int i = 0; i < 10; i++)
00277 {
00278 if (KdVMGetActiveCallCount())
00279 i = 0;
00280 KeDelayExecutionThread(KernelMode, FALSE, &interval);
00281 }
00282 if (m_bPatched)
00283 DbgPrint("VirtualKD: Successfully unpatched KDCOM.DLL (as you can see ;])\n");
00284 }
00285 };
00286
00288 DDK::Driver *_stdcall CreateMainDriverInstance()
00289 {
00290 return new KDPatchDriver();
00291 }