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

📄 r32r0.cpp

📁 Windows2000 XP 从Ring3层进入Ring0层的一种方法
💻 CPP
📖 第 1 页 / 共 4 页
字号:
    UNICODE_STRING    memString;
    WCHAR             memName[] = L"\\Device\\PhysicalMemory";
    NTSTATUS          status;

    RtlInitUnicodeString( &memString, memName );
    InitializeObjectAttributes( &attributes, &memString,
                                OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
                                NULL, NULL );
    status = ZwOpenSection( &mem, DesiredAccess, &attributes );
    if ( !NT_SUCCESS( status ) )
    {
        PrintZwError( "Could not open \\Device\\PhysicalMemory", status );
        return( NULL );
    }
    return( mem );
}  /* end of OpenPhysicalMemory */

/*
* 这是一个偏向Unix编程风格的函数。跟VI与EMACS是两种哲学流派一样,我不习惯
* 也不喜欢匈牙利命名法。更深层次的原因是我非Windows程序员,见谅,:-)
*/
static void outputBinary ( FILE *out, const unsigned char *byteArray, const size_t byteArrayLen )
{
    size_t offset, k, j, i;

    fprintf( out, "byteArray [ %u bytes ] -> \n", byteArrayLen );
    if ( byteArrayLen <= 0 )
    {
        return;
    }
    i      = 0;
    offset = 0;
    for ( k = byteArrayLen / 16; k > 0; k--, offset += 16 )
    {
        fprintf( out, "%08X ", offset );
        for ( j = 0; j < 16; j++, i++ )
        {
            if ( j == 8 )
            {
                fprintf( out, "-%02X", byteArray[i] );
            }
            else
            {
                fprintf( out, " %02X", byteArray[i] );
            }
        }
        fprintf( out, "    " );
        i -= 16;
        for ( j = 0; j < 16; j++, i++ )
        {
            /*
             * if ( isprint( (int)byteArray[i] ) )
             */
#if 0
            if ( ( byteArray[i] >= ' ' ) && ( byteArray[i] <= 255 )
                 && ( byteArray[i] != 0x7f ) )
#endif
            if ( ( byteArray[i] >= ' ' ) && ( byteArray[i] < 0x7f ) )
            {
                fprintf( out, "%c", byteArray[i] );
            }
            else
            {
                fprintf( out, "." );
            }
        }
        fprintf( out, "\n" );
    }  /* end of for */
    k = byteArrayLen - i;
    if ( k <= 0 )
    {
        return;
    }
    fprintf( out, "%08X ", offset );
    for ( j = 0 ; j < k; j++, i++ )
    {
        if ( j == 8 )
        {
            fprintf( out, "-%02X", byteArray[i] );
        }
        else
        {
            fprintf( out, " %02X", byteArray[i] );
        }
    }
    i -= k;
    for ( j = 16 - k; j > 0; j-- )
    {
        fprintf( out, "   " );
    }
    fprintf( out, "    " );
    for ( j = 0; j < k; j++, i++ )
    {
#if 0
        if ( ( byteArray[i] >= ' ' ) && ( byteArray[i] <= 255 )
             && ( byteArray[i] != 0x7f ) )
#endif
        if ( ( byteArray[i] >= ' ' ) && ( byteArray[i] < 0x7f ) )
        {
            fprintf( out, "%c", byteArray[i] );
        }
        else
        {
            fprintf( out, "." );
        }
    }
    fprintf( out, "\n" );
    return;
}  /* end of outputBinary */

static void PrintWin32Error ( char *message, DWORD dwMessageId )
{
    char *errMsg;

    FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL,
                   dwMessageId,
                   MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
                   ( LPTSTR )&errMsg, 0, NULL );
    fprintf( stderr, "%s: %s", message, errMsg );
    LocalFree( errMsg );
    return;
}  /* end of PrintWin32Error */

static void PrintZwError ( char *message, NTSTATUS status )
{
    char *errMsg;

    FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL,
                   RtlNtStatusToDosError( status ),
                   MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
                   ( LPTSTR )&errMsg, 0, NULL );
    fprintf( stderr, "%s: %s", message, errMsg );
    LocalFree( errMsg );
    return;
}  /* end of PrintZwError */

static PVOID PrivateFindModule ( const char *ModuleName )
{
    NTSTATUS                    status;
    PSYSTEM_MODULE_INFORMATION  module = NULL;
    PVOID                       Base   = NULL;
    ULONG                       n      = 0;
    ULONG                       i      = 0;
    void                       *buf    = NULL;

    ZwQuerySystemInformation( SystemModuleInformation, &n, 0, &n );
    if ( NULL == ( buf = calloc( ( size_t )n, 1 ) ) )
    {
        fprintf( stderr, "calloc() failed\n" );
        goto PrivateFindModule_return;
    }
    /*
     * <<Windows NT/2000 Native API Reference>> by Gary Nebbett所给的例子
     * 1.3以及A.2对第二、三形参理解有误,下面才是正确的用法。
     */
    status = ZwQuerySystemInformation( SystemModuleInformation, buf, n, NULL );
    if ( !NT_SUCCESS( status ) )
    {
        PrintZwError( "ZwQuerySystemInformation() failed", status );
        goto PrivateFindModule_return;
    }
    module = ( PSYSTEM_MODULE_INFORMATION )( ( PULONG )buf + 1 );
    n      = *( ( PULONG )buf );
    for ( i = 0; i < n; i++ )
    {
        if ( 0 == _stricmp( module[i].ImageName + module[i].ModuleNameOffset, ModuleName ) )
        {
            Base = module[i].Base;
        }
    }

PrivateFindModule_return:

    if ( buf != NULL )
    {
        free( buf );
        buf = NULL;
    }
    return( Base );
}  /* end of PrivateFindModule */

/*
* 将某固定范围的线性地址转换成物理地址
*/
static PHYSICAL_ADDRESS PrivateMmGetPhysicalAddress ( IN PVOID LinearAddress )
{
    /*
     * Header: Declared in Winnt.h; include Windows.h.
     *
     * typedef union _LARGE_INTEGER
     * {
     *     struct
     *     {
     *         DWORD LowPart;
     *         LONG  HighPart;
     *     };
     *     LONGLONG QuadPart;
     * } LARGE_INTEGER, *PLARGE_INTEGER;
     */
    PHYSICAL_ADDRESS physical_address;

    physical_address.HighPart = 0;
    if ( ( ULONG )LinearAddress >= 0x80000000 &&
         ( ULONG )LinearAddress < 0xa0000000 )
    {
        physical_address.LowPart = ( DWORD )LinearAddress & 0x1fffffff;
    }
    else
    {
        physical_address.LowPart = 0;
    }
    return( physical_address );
}  /* end of PrivateMmGetPhysicalAddress */

/*
* 这种技术在VC范畴内对我而言太陌生了,好在我可以将之想像成汇编代码。由于
* 通过调用门进入,必须考虑CS被压栈、特权级改变、堆栈切换等一系列问题,其
* 具体细节可以参看MSDN以及Intel卷III。
*
* 这里写成"void Ring0Code ( void )"也可以,形参部分没有意义,也不能使用,
* CS被压栈后形参定位有变。变通的办法就是下面演示的技术,在prolog中用汇编
* 指令将形参取出并赋予局部变量,后续的C代码使用局部变量。其实这里很好理解,
* 只需按平日里用汇编语言写调用门的理解去做就是。
*
* 这段代码搭了一个"可用"的框架,允许以标准C编程技巧向内传递形参,至于这个
* call_arg如何解释,完全依赖于call_type。框架是我的主意,但下面演示的三种
* 具体操作不是我的主意,见其附近的注释。
*/
static __declspec(naked) void Ring0Code ( unsigned int unused_call_type, void *unused_call_arg )
{
    unsigned int  call_type;
    void         *call_arg;

    /*
     * prolog
     */
    __asm
    {
        push    ebp
        mov     ebp,esp
        sub     esp,__LOCAL_SIZE
        pushad
        pushfd
        mov     eax,[ebp+0xc]
        mov     call_type,eax
        mov     eax,[ebp+0x10]
        mov     call_arg,eax
    }

    /*
     * 不要在这里做涉及I/O的操作
     */
    switch ( call_type )
    {
    case 0:
        /*
         * 获取控制寄存器CRn、调试寄存器DRn的值。cr4未被支持。这是tsu00的
         * 主意。
         */
        __asm
        {
            mov     ebx,call_arg
            mov     eax,cr0
            mov     [ebx]CALL_ARG_0.cr0,eax
            mov     eax,cr2
            mov     [ebx]CALL_ARG_0.cr2,eax
            mov     eax,cr3
            mov     [ebx]CALL_ARG_0.cr3,eax
            mov     eax,dr0
            mov     [ebx]CALL_ARG_0.dr0,eax
            mov     eax,dr1
            mov     [ebx]CALL_ARG_0.dr1,eax
            mov     eax,dr2
            mov     [ebx]CALL_ARG_0.dr2,eax
            mov     eax,dr3
            mov     [ebx]CALL_ARG_0.dr3,eax
            mov     eax,dr6
            mov     [ebx]CALL_ARG_0.dr6,eax
            mov     eax,dr7
            mov     [ebx]CALL_ARG_0.dr7,eax
        }
        break;
    case 1:
        /*
         * 调用内核函数MmGetPhysicalAddress。这是crazylord的主意。
         */
        __asm
        {
            mov     ebx,call_arg
            push    [ebx]CALL_ARG_1.LinearAddress
            call    MmGetPhysicalAddress
            mov     [ebx]CALL_ARG_1.PhysicalAddress.LowPart,eax
            mov     [ebx]CALL_ARG_1.PhysicalAddress.HighPart,edx
        }
        break;
    case 2:
        /*
         * 内存复制。由于在Ring 0,直接访问内核空间线性地址没有任何问题,
         * 这是h0ck0r@smth的主意。
         */
        __asm
        {
            mov     ebx,call_arg
            mov     esi,[ebx]CALL_ARG_2.src
            mov     edi,[ebx]CALL_ARG_2.dst
            mov     ecx,[ebx]CALL_ARG_2.len
            rep     movsb
        }
        break;
    default:
        break;
    }  /* end of switch */

    /*
     * epilog
     */
    __asm
    {
        popfd
        popad
        mov     esp,ebp
        pop     ebp
        retf    8
    }
}  /* end of Ring0Code */

static BOOLEAN SetPhysicalMemoryDACLs ( HANDLE handle, LPTSTR ptstrName )
{
    BOOLEAN              boolean_ret        = TRUE;
    DWORD                ret                = ERROR_SUCCESS;
    PACL                 OldDACLs           = NULL;
    PACL                 NewDACLs           = NULL;
    PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
    EXPLICIT_ACCESS      Access;

    /*
     * Header : Declared in Aclapi.h
     * Library: Use Advapi32.lib
     *
     * DWORD GetSecurityInfo
     * (
     *     HANDLE                handle,
     *     SE_OBJECT_TYPE        ObjectType,
     *     SECURITY_INFORMATION  SecurityInfo,
     *     PSID                 *ppsidOwner,
     *     PSID                 *ppsidGroup,
     *     PACL                 *ppDacl,
     *     PACL                 *ppSacl,
     *     PSECURITY_DESCRIPTOR *ppSecurityDescriptor
     * );
     */
    ret                                     = GetSecurityInfo
                                              (
                                                  handle,

⌨️ 快捷键说明

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