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 }