• Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

E:/PROJECTS/cvsed/mixed/VIRTUA~1/kdpatch/kdpatch.cpp

Go to the documentation of this file.
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                 /*volatile static int loopme = 0;
00189                 static char sz[1024 + 1];
00190                 memset(sz, 'z', sizeof(sz)-1);
00191                 sz[sizeof(sz)-1]  = 0;
00192 #ifdef KDPATCH_TEST_SEND_RAW_MSGS       
00193                 struct MsgHeader
00194                 {
00195                         int PacketSubtype;
00196                         int Code6;
00197                         int MsgLen;
00198                         int Unknown;
00199                 } header = {0x3230, 6, sizeof(sz)-1, 0};
00200                 KD_BUFFER buf1 = {0,}, buf2 = {0,};
00201                 buf1.Length = sizeof(header);
00202                 buf1.pData = (PUCHAR)&header;
00203                 buf2.Length = sizeof(sz)-1;
00204                 buf2.pData = (PUCHAR)sz;
00205                 KD_CONTEXT ctx;
00206 #endif
00207                 __asm int 3;
00208                 while (loopme)
00209                 {
00210 #ifdef KDPATCH_TEST_SEND_RAW_MSGS
00211                         KdSendPacket(3, &buf1, &buf2, &ctx);
00212 #else
00213                         DbgPrint(sz);
00214 #endif
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                 /*unsigned char sz[32];
00226                 unsigned char sz2[64];
00227                 KD_BUFFER buf1;
00228                 KD_BUFFER buf2;
00229                 buf1.Length = 0;
00230                 buf2.Length = 0;
00231                 buf1.MaxLength = sizeof(sz);
00232                 buf2.MaxLength = sizeof(sz2);
00233                 buf1.pData = sz;
00234                 buf2.pData = sz2;
00235                 KD_CONTEXT context = {0,};
00236                 context.RetryCount = 5;
00237                 ULONG bytes = 0;
00238                 DbgBreakPoint();
00239                 unsigned xstatus = KdReceivePacket(0x1234, &buf1, &buf2, &bytes, &context);
00240                 context.RetryCount += 2;
00241                 buf1.Length = buf1.MaxLength;
00242                 buf2.Length = buf2.MaxLength;
00243                 KdSendPacket(0x1234, &buf1, NULL, &context);
00244                 return STATUS_INSUFFICIENT_RESOURCES;*/
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                         We cannot use any reliable type of a lock (like mutex or etc), as it is not a very good idea to call any
00268                         kernel functions from a kernel debugger override function (such as our versions of KdSendPacket()/KdReceivePacket()).
00269                         The simpliest thing we can do is to check whether the active call counter remains at zero for some time.
00270                         As we have unpatched the KDCOM, original functions will be called in a normal way, so this will mean that it is safe
00271                         to unload the driver (it is unlikely that a delay between the jump to our function and the increasing of active
00272                         counter will take that long; however, there is no more reliable way to check it).                       
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 }