⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 r32r0.cpp

📁 Windows2000 XP 从Ring3层进入Ring0层的一种方法
💻 CPP
📖 第 1 页 / 共 4 页
字号:
                               unsigned short int selector, 
                               unsigned int call_type, 
                               void *call_arg )
{
    unsigned short int farcall[3];
    HANDLE             Thread;

    if ( 0 == VirtualLock( Ring0Code, Ring0CodeLength ) )
    {
        PrintWin32Error( "VirtualLock() failed", GetLastError() );
    }
    else
    {
        farcall[2] = selector;
        Thread     = GetCurrentThread();
        SetThreadPriority( Thread, THREAD_PRIORITY_TIME_CRITICAL );
        Sleep( 0 );
        printf( "ExecuteRing0Code() begin\n" );
        /*
         * 实际上这种情形下的SEH(结构化异常处理)没有意义,一旦在Ring 0代码
         * 中引发异常,控制不会再回到Ring 3代码中来。也可能我对SEH的理解太
         * 浅,还有别的办法让控制返回Ring 3代码。
         */
        __try
        {
            /*
             * 形参从右至左压栈,这是C调用风格,主要便于处理形参个数不定的
             * 情况。虽然我这里只有两个形参,还是用了C调用风格,谁叫咱是标
             * 准C程序员。
             *
             * 堆栈由Ring0Code中的"retf 8"负责平衡,这是最快的办法。
             */
            __asm
            {
                push call_arg
                push call_type
                call fword ptr [farcall]
            }
        }
        __except ( EXCEPTION_EXECUTE_HANDLER )
        {
            fprintf( stderr, "ExecuteRing0Code() failed\n" );
        }
        printf( "ExecuteRing0Code() end\n" );
        SetThreadPriority( Thread, THREAD_PRIORITY_NORMAL );
        VirtualUnlock( Ring0Code, Ring0CodeLength );
    }
    return;
}  /* end of ExecuteRing0Code */

/*
* 在DDK的ntdef.h中InitializeObjectAttributes()是一个宏
*/
static VOID InitializeObjectAttributes ( OUT POBJECT_ATTRIBUTES InitializedAttributes,
                                         IN PUNICODE_STRING ObjectName,
                                         IN ULONG Attributes,
                                         IN HANDLE RootDirectory,
                                         IN PSECURITY_DESCRIPTOR SecurityDescriptor
                                       )
{
    InitializedAttributes->Length                   = sizeof( OBJECT_ATTRIBUTES );
    InitializedAttributes->RootDirectory            = RootDirectory;
    InitializedAttributes->Attributes               = Attributes;
    InitializedAttributes->ObjectName               = ObjectName;
    InitializedAttributes->SecurityDescriptor       = SecurityDescriptor;
    InitializedAttributes->SecurityQualityOfService = NULL;
    return;
}  /* end of InitializeObjectAttributes */

static GATEDESCRIPTOR * InstallCallgate ( ULONG Gdtrbase, ULONG Gdtrlimit, DWORD CodeOffset, 
                                          GATEDESCRIPTOR *orig_callgate )
{
    /*
     * callgate指向GDT中最后一个描述符
     */
    GATEDESCRIPTOR *callgate = ( GATEDESCRIPTOR * )( Gdtrbase + ( Gdtrlimit & 0xfffffff8 ) );

    /*
     * 搜索空闲描述符
     */
    for ( ; ( ULONG )callgate > Gdtrbase; callgate-- )
    {
        /*
         * GDT中不一定都是门描述符,但所有类型的描述符P位在同一位域,并且
         * 意义接近。
         */
        if ( 0 == callgate->p )
        {
            /*
             * 备份即将被征用的"空闲"描述符
             */
            memcpy( orig_callgate, callgate, sizeof( GATEDESCRIPTOR ) );
            /*
             * 设置成DPL等于3的调用门
             */
            callgate->offset_low      = ( WORD )( CodeOffset & 0x0000ffff );
            callgate->selector        = RING0_CODE_SELECTOR;
            callgate->parameter_count = 2;
            callgate->reserved        = 0;
            callgate->type            = 12;
            callgate->s               = 0;
            callgate->dpl             = 3;
            callgate->p               = 1;
            callgate->offset_high     = ( WORD )( CodeOffset >> 16 );
            return( callgate );
        }
    }
    return( NULL );
}  /* end of InstallCallgate */

/*
* ntdll.dll输出了所有的Native API
*/
static BOOLEAN LocateNtdllEntry ( void )
{
    BOOLEAN boolean_ret = FALSE;
    char    NTDLL_DLL[] = "ntdll.dll";
    HMODULE ntdll_dll   = NULL;

    /*
     * returns a handle to a mapped module without incrementing its
     * reference count
     */
    if ( ( ntdll_dll = GetModuleHandle( NTDLL_DLL ) ) == NULL )
    {
        PrintWin32Error( "GetModuleHandle() failed", GetLastError() );
        return( FALSE );
    }
    if ( !( RtlInitUnicodeString = ( RTLINITUNICODESTRING )GetProcAddress( ntdll_dll,
         "RtlInitUnicodeString" ) ) )
    {
        goto LocateNtdllEntry_return;
    }
    if ( !( ZwOpenSection = ( ZWOPENSECTION )GetProcAddress( ntdll_dll,
         "ZwOpenSection" ) ) )
    {
        goto LocateNtdllEntry_return;
    }
    if ( !( ZwClose = ( ZWCLOSE )GetProcAddress( ntdll_dll,
         "ZwClose" ) ) )
    {
        goto LocateNtdllEntry_return;
    }
    if ( !( ZwMapViewOfSection = ( ZWMAPVIEWOFSECTION )GetProcAddress( ntdll_dll,
         "ZwMapViewOfSection" ) ) )
    {
        goto LocateNtdllEntry_return;
    }
    if ( !( ZwUnmapViewOfSection = ( ZWUNMAPVIEWOFSECTION )GetProcAddress( ntdll_dll,
         "ZwUnmapViewOfSection" ) ) )
    {
        goto LocateNtdllEntry_return;
    }
    if ( !( ZwQuerySystemInformation = ( ZWQUERYSYSTEMINFORMATION )GetProcAddress( ntdll_dll,
         "ZwQuerySystemInformation" ) ) )
    {
        goto LocateNtdllEntry_return;
    }
    if ( !( RtlNtStatusToDosError = ( RTLNTSTATUSTODOSERROR )GetProcAddress( ntdll_dll,
         "RtlNtStatusToDosError" ) ) )
    {
        goto LocateNtdllEntry_return;
    }
    boolean_ret = TRUE;

LocateNtdllEntry_return:

    if ( FALSE == boolean_ret )
    {
        PrintWin32Error( "GetProcAddress() failed", GetLastError() );
    }
    ntdll_dll = NULL;
    return( boolean_ret );
}  /* end of LocateNtdllEntry */

/*
* ntoskrnl.exe输出Kernel API
*/
static BOOLEAN LocateNtoskrnlEntry ( void )
{
    BOOLEAN        boolean_ret    = TRUE;
    char           NTOSKRNL_EXE[] = "ntoskrnl.exe";
    HMODULE        ntoskrnl_exe   = NULL;
    unsigned char *Base           = NULL;

    Base = ( unsigned char * )PrivateFindModule( ( const char * )NTOSKRNL_EXE );
    if ( NULL == Base )
    {
        fprintf( stderr, "PrivateFindModule() failed\n" );
        boolean_ret = FALSE;
        goto LocateNtoskrnlEntry_return;
    }
    /*
     * Header : Declared in Winbase.h; include Windows.h
     * Library: Use Kernel32.lib
     *
     * HMODULE LoadLibrary
     * (
     *     LPCTSTR lpFileName
     * );
     */
    if ( NULL == ( ntoskrnl_exe = LoadLibrary( NTOSKRNL_EXE ) ) )
    {
        PrintWin32Error( "LoadLibrary() failed", GetLastError() );
        boolean_ret = FALSE;
        goto LocateNtoskrnlEntry_return;
    }
    if ( !( MmGetPhysicalAddress = ( MMGETPHYSICALADDRESS )GetProcAddress( ntoskrnl_exe,
         "MmGetPhysicalAddress" ) ) )
    {
        boolean_ret = FALSE;
        goto LocateNtoskrnlEntry_return;
    }
    MmGetPhysicalAddress = ( MMGETPHYSICALADDRESS )
                           ( Base + ( unsigned int )
                             ( ( unsigned char * )MmGetPhysicalAddress - 
                               ( unsigned char * )ntoskrnl_exe
                             )
                           );
    printf( "ntoskrnl.exe base     = 0x%08X\n"
            "MmGetPhysicalAddress  = 0x%08X\n", Base, MmGetPhysicalAddress );

LocateNtoskrnlEntry_return:

    if ( ntoskrnl_exe != NULL )
    {
        FreeLibrary( ntoskrnl_exe );
        ntoskrnl_exe = NULL;
    }
    return( boolean_ret );
}  /* end of LocateNtoskrnlEntry */

static BOOLEAN MapPhysicalMemory ( IN     HANDLE          SectionHandle,
                                   IN OUT PVOID          *LinearAddress,
                                   IN OUT PULONG          MapSize,
                                   IN OUT PLARGE_INTEGER  PhysicalAddress,
                                   IN     ULONG           Protect
                                 )
{
    NTSTATUS status;
    char     error_msg[256];
    ULONG    mapsize = *MapSize;
    DWORD    LowPart = PhysicalAddress->LowPart;

    *LinearAddress  = NULL;
#if 0
    /*
     * 假设GDTR的物理基址在0x0003F000,而虚拟内存分配粒度是64KB,向下舍入
     * 后得到0x00030000,ZwMapViewOfSection()会报告"试图访问无效的地址"。
     */
    LowPart        %= system_info.dwAllocationGranularity;
    if ( LowPart != 0 )
    {
        /*
         * 向下舍入到dwAllocationGranularity(内存分配粒度)的边界
         */
        PhysicalAddress->LowPart -= LowPart;
        mapsize                  += LowPart;
        *MapSize                  = mapsize;
    }
#endif
    /*
     * 按照DDK文档的意思,物理地址要向下舍入到内存分配粒度的边界。按我的理
     * 解,这里的(物理)内存分配粒度应该是一页,而GetSystemInfo()返回的是虚
     * 拟内存分配粒度(64KB)。可能这个理解有问题,暂时先搁置一下。
     */
    LowPart        %= system_info.dwPageSize;
    if ( LowPart != 0 )
    {
        /*
         * 向下舍入到dwPageSize(页大小)的边界(4096)
         */
        PhysicalAddress->LowPart -= LowPart;
        mapsize                  += LowPart;
        *MapSize                  = mapsize;
    }
    mapsize        %= system_info.dwPageSize;
    if ( mapsize != 0 )
    {
        /*
         * 向上舍入到dwPageSize(页大小)的边界
         */
        *MapSize += system_info.dwPageSize - mapsize;
    }
    /*
     * DDK文档里有详细介绍。
     *
     * ZwMapViewOfSection
     * (
     *     IN     HANDLE           SectionHandle,
     *     IN     HANDLE           ProcessHandle,
     *     IN OUT PVOID           *BaseAddress,
     *     IN     ULONG            ZeroBits,
     *     IN     ULONG            CommitSize,
     *     IN OUT PLARGE_INTEGER   SectionOffset,
     *     IN OUT PULONG           ViewSize,
     *     IN     SECTION_INHERIT  InheritDisposition,
     *     IN     ULONG            AllocationType,
     *     IN     ULONG            Protect
     * );
     *
     * BaseAddress
     *
     *     目标映射到进程空间后的线性基址,初始化成NULL则由操作系统任意安
     *     排映射后的线性基址。Unix程序员可与mmap()的第一形参做个比较。
     *
     * CommitSize
     *
     *     以字节为单位,向上舍入到dwPageSize(页大小)的边界。
     *
     * SectionOffset
     *
     *     对我们这个程序来说,就是物理地址,向下舍入到
     *     dwAllocationGranularity(内存分配粒度)的边界。
     *
     * ViewSize
     *
     *     可以简单等同于CommitSize,向上舍入到dwPageSize(页大小)的边界。
     *
     * InheritDisposition
     *
     *     指明子进程如何继承该映射。
     *
     * Protect
     *
     *     指明访问权限,比如PAGE_READONLY、PAGE_READWRITE。
     */
    status = ZwMapViewOfSection
            (
                SectionHandle,
                ( HANDLE )-1,
                LinearAddress,
                0,
                *MapSize,
                PhysicalAddress,
                MapSize,
                ViewShare,
                0,
                Protect
            );
    if ( !NT_SUCCESS( status ) )
    {
        sprintf( error_msg, "Could not map 0x%08X bytes PhysicalMemory from 0x%08X",
                 *MapSize, PhysicalAddress->LowPart );
        PrintZwError( error_msg, status );
        return( FALSE );
    }
    return( TRUE );
}  /* end of MapPhysicalMemory */

static HANDLE OpenPhysicalMemory ( ACCESS_MASK DesiredAccess )
{
    OBJECT_ATTRIBUTES attributes;
    HANDLE            mem;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -