• 《逆向工程核心原理》——代码注入


    利用CreateRemoteThread

    进程注入流程:

    • OpenProcess
    This function returns a handle to an existing process object.
    
    HANDLE OpenProcess( 
      DWORD fdwAccess, 
      BOOL fInherit, 
      DWORD IDProcess
    );
    Parameters
    fdwAccess 
    [in] Not supported; set to zero. 
    fInherit 
    [in] Not supported; set to FALSE. 
    IDProcess 
    [in] Specifies the process identifier of the process to open. 
    Return Values
    An open handle to the specified process indicates success. 
    
    NULL indicates failure. 
    
    To get extended error information, call GetLastError. 
    
    Remarks
    The handle returned by the OpenProcess function can be used in any function that requires a handle to a process, such as wait functions, if the appropriate access rights are requested. 
    
    When you finish with the handle, close it using the CloseHandle function.
    View Code
    • VirtualAllocEx
    VirtualAllocEx Function
    
    Reserves or commits a region of memory within the virtual address space of a specified process. The function initializes the memory it allocates to zero, unless MEM_RESET is used.
    
    
    Syntax
    LPVOID WINAPI VirtualAllocEx(
      __in      HANDLE hProcess,
      __in_opt  LPVOID lpAddress,
      __in      SIZE_T dwSize,
      __in      DWORD flAllocationType,
      __in      DWORD flProtect
    );
    
    Parameters
    hProcess 
    The handle to a process. The function allocates memory within the virtual address space of this process. 
    
    The handle must have the PROCESS_VM_OPERATION access right. For more information, see Process Security and Access Rights.
    
    lpAddress 
    The pointer that specifies a desired starting address for the region of pages that you want to allocate. 
    
    If you are reserving memory, the function rounds this address down to the nearest multiple of the allocation granularity.
    
    If you are committing memory that is already reserved, the function rounds this address down to the nearest page boundary. To determine the size of a page and the allocation granularity on the host computer, use the GetSystemInfo function.
    
    If lpAddress is NULL, the function determines where to allocate the region.
    
    dwSize 
    The size of the region of memory to allocate, in bytes. 
    
    If lpAddress is NULL, the function rounds dwSize up to the next page boundary.
    
    If lpAddress is not NULL, the function allocates all pages that contain one or more bytes in the range from lpAddress to lpAddress+dwSize. This means, for example, that a 2-byte range that straddles a page boundary causes the function to allocate both pages.
    
    flAllocationType 
    The type of memory allocation. This parameter must contain one of the following values. 
    
    Value Meaning 
    MEM_COMMIT
    0x1000
     Allocates physical storage in memory or in the paging file on disk for the specified reserved memory pages. The function initializes the memory to zero. 
    
    To reserve and commit pages in one step, call VirtualAllocEx with MEM_COMMIT | MEM_RESERVE.
    
    The function fails if you attempt to commit a page that has not been reserved. The resulting error code is ERROR_INVALID_ADDRESS.
    
    An attempt to commit a page that is already committed does not cause the function to fail. This means that you can commit pages without first determining the current commitment state of each page.
     
    MEM_RESERVE
    0x2000
     Reserves a range of the process's virtual address space without allocating any actual physical storage in memory or in the paging file on disk. 
    
    You commit reserved pages by calling VirtualAllocEx again with MEM_COMMIT. To reserve and commit pages in one step, call VirtualAllocEx with MEM_COMMIT |MEM_RESERVE.
    
    Other memory allocation functions, such as malloc and LocalAlloc, cannot use reserved memory until it has been released.
     
    MEM_RESET
    0x80000
     Indicates that data in the memory range specified by lpAddress and dwSize is no longer of interest. The pages should not be read from or written to the paging file. However, the memory block will be used again later, so it should not be decommitted. This value cannot be used with any other value. 
    
    Using this value does not guarantee that the range operated on with MEM_RESET will contain zeroes. If you want the range to contain zeroes, decommit the memory and then recommit it.
    
    When you use MEM_RESET, the VirtualAllocEx function ignores the value of fProtect. However, you must still set fProtect to a valid protection value, such as PAGE_NOACCESS.
    
    VirtualAllocEx returns an error if you use MEM_RESET and the range of memory is mapped to a file. A shared view is only acceptable if it is mapped to a paging file.
     
    
    This parameter can also specify the following values as indicated.
    
    Value Meaning 
    MEM_LARGE_PAGES
    0x20000000
     Allocates memory using large page support. 
    
    The size and alignment must be a multiple of the large-page minimum. To obtain this value, use the GetLargePageMinimum function.
    
    Windows XP/2000:   This flag is not supported. 
    MEM_PHYSICAL
    0x400000
     Allocates physical memory with read-write access. This value is solely for use with Address Windowing Extensions (AWE) memory. 
    
    This value must be used with MEM_RESERVE and no other values.
     
    MEM_TOP_DOWN
    0x100000
     Allocates memory at the highest possible address. 
     
    
    flProtect 
    The memory protection for the region of pages to be allocated. If the pages are being committed, you can specify any one of the memory protection constants.
    
    Protection attributes specified when protecting a page cannot conflict with those specified when allocating a page.
    
    Return Value
    If the function succeeds, the return value is the base address of the allocated region of pages.
    
    If the function fails, the return value is NULL. To get extended error information, call GetLastError.
    
    Remarks
    Each page has an associated page state. The VirtualAllocEx function can perform the following operations:
    
    
    Commit a region of reserved pages 
    Reserve a region of free pages 
    Simultaneously reserve and commit a region of free pages 
    VirtualAllocEx cannot reserve a reserved page. It can commit a page that is already committed. This means you can commit a range of pages, regardless of whether they have already been committed, and the function will not fail.
    
    You can use VirtualAllocEx to reserve a block of pages and then make additional calls to VirtualAllocEx to commit individual pages from the reserved block. This enables a process to reserve a range of its virtual address space without consuming physical storage until it is needed.
    
    If the lpAddress parameter is not NULL, the function uses the lpAddress and dwSize parameters to compute the region of pages to be allocated. The current state of the entire range of pages must be compatible with the type of allocation specified by the flAllocationType parameter. Otherwise, the function fails and none of the pages is allocated. This compatibility requirement does not preclude committing an already committed page; see the preceding list.
    
    To execute dynamically generated code, use VirtualAllocEx to allocate memory and the VirtualProtectEx function to grant PAGE_EXECUTE access.
    
    The VirtualAllocEx function can be used to reserve an Address Windowing Extensions (AWE) region of memory within the virtual address space of a specified process. This region of memory can then be used to map physical pages into and out of virtual memory as required by the application. The MEM_PHYSICAL and MEM_RESERVE values must be set in the AllocationType parameter. The MEM_COMMIT value must not be set. The page protection must be set to PAGE_READWRITE.
    
    The VirtualFreeEx function can decommit a committed page, releasing the page's storage, or it can simultaneously decommit and release a committed page. It can also release a reserved page, making it a free page.
    View Code
    • WriteProcessMemory
    WriteProcessMemory Function
    
    Writes data to an area of memory in a specified process. The entire area to be written to must be accessible or the operation fails.
    
    
    Syntax
    BOOL WINAPI WriteProcessMemory(
      __in   HANDLE hProcess,
      __in   LPVOID lpBaseAddress,
      __in   LPCVOID lpBuffer,
      __in   SIZE_T nSize,
      __out  SIZE_T* lpNumberOfBytesWritten
    );
    
    Parameters
    hProcess 
    A handle to the process memory to be modified. The handle must have PROCESS_VM_WRITE and PROCESS_VM_OPERATION access to the process.
    
    lpBaseAddress 
    A pointer to the base address in the specified process to which data is written. Before data transfer occurs, the system verifies that all data in the base address and memory of the specified size is accessible for write access, and if it is not accessible, the function fails.
    
    lpBuffer 
    A pointer to the buffer that contains data to be written in the address space of the specified process.
    
    nSize 
    The number of bytes to be written to the specified process.
    
    lpNumberOfBytesWritten 
    A pointer to a variable that receives the number of bytes transferred into the specified process. This parameter is optional. If lpNumberOfBytesWritten is NULL, the parameter is ignored.
    
    Return Value
    If the function succeeds, the return value is nonzero.
    
    If the function fails, the return value is 0 (zero). To get extended error information, call GetLastError. The function fails if the requested write operation crosses into an area of the process that is inaccessible.
    
    Remarks
    WriteProcessMemory copies the data from the specified buffer in the current process to the address range of the specified process. Any process that has a handle with PROCESS_VM_WRITE and PROCESS_VM_OPERATION access to the process to be written to can call the function. Typically but not always, the process with address space that is being written to is being debugged.
    
    The entire area to be written to must be accessible, and if it is not accessible, the function fails.
    View Code
    • CreateRemoteThread
    CreateRemoteThread Function
    
    Creates a thread that runs in the virtual address space of another process.
    
    
    Syntax
    HANDLE WINAPI CreateRemoteThread(
      __in   HANDLE hProcess,
      __in   LPSECURITY_ATTRIBUTES lpThreadAttributes,
      __in   SIZE_T dwStackSize,
      __in   LPTHREAD_START_ROUTINE lpStartAddress,
      __in   LPVOID lpParameter,
      __in   DWORD dwCreationFlags,
      __out  LPDWORD lpThreadId
    );
    
    Parameters
    hProcess 
    A handle to the process in which the thread is to be created. The handle must have the PROCESS_CREATE_THREAD, PROCESS_QUERY_INFORMATION, PROCESS_VM_OPERATION, PROCESS_VM_WRITE, and PROCESS_VM_READ access rights. For more information, see Process Security and Access Rights.
    
    lpThreadAttributes 
    A pointer to a SECURITY_ATTRIBUTES structure that specifies a security descriptor for the new thread and determines whether child processes can inherit the returned handle. If lpThreadAttributes is NULL, the thread gets a default security descriptor and the handle cannot be inherited. The access control lists (ACL) in the default security descriptor for a thread come from the primary token of the creator.
    
    Windows XP/2000:  The ACLs in the default security descriptor for a thread come from the primary or impersonation token of the creator. This behavior changed with Windows XP SP2 and Windows Server 2003.
    dwStackSize 
    The initial size of the stack, in bytes. The system rounds this value to the nearest page. If this parameter is 0 (zero), the new thread uses the default size for the executable. For more information, see Thread Stack Size.
    
    lpStartAddress 
    A pointer to the application-defined function of type LPTHREAD_START_ROUTINE to be executed by the thread and represents the starting address of the thread in the remote process. The function must exist in the remote process. For more information, see ThreadProc.
    
    lpParameter 
    A pointer to a variable to be passed to the thread function.
    
    dwCreationFlags 
    The flags that control the creation of the thread.
    
    Value Meaning 
    0
     The thread runs immediately after creation.
     
    CREATE_SUSPENDED
    0x00000004
     The thread is created in a suspended state, and does not run until the ResumeThread function is called.
     
    STACK_SIZE_PARAM_IS_A_RESERVATION
    0x00010000
     The dwStackSize parameter specifies the initial reserve size of the stack. If this flag is not specified, dwStackSize specifies the commit size.
    
    Windows 2000:  The STACK_SIZE_PARAM_IS_A_RESERVATION flag is not supported. 
    
    lpThreadId 
    A pointer to a variable that receives the thread identifier. 
    
    If this parameter is NULL, the thread identifier is not returned.
    
    Return Value
    If the function succeeds, the return value is a handle to the new thread.
    
    If the function fails, the return value is NULL. To get extended error information, call GetLastError.
    
    Note that CreateRemoteThread may succeed even if lpStartAddress points to data, code, or is not accessible. If the start address is invalid when the thread runs, an exception occurs, and the thread terminates. Thread termination due to a invalid start address is handled as an error exit for the thread's process. This behavior is similar to the asynchronous nature of CreateProcess, where the process is created even if it refers to invalid or missing dynamic-link libraries (DLL).
    View Code
    • WaitForSingleObject
    WaitForSingleObject Function
    
    Waits until the specified object is in the signaled state or the time-out interval elapses.
    
    To enter an alertable wait state, use the WaitForSingleObjectEx function. To wait for multiple objects, use the WaitForMultipleObjects.
    
    
    Syntax
    DWORD WINAPI WaitForSingleObject(
      __in  HANDLE hHandle,
      __in  DWORD dwMilliseconds
    );
    
    Parameters
    hHandle 
    A handle to the object. For a list of the object types whose handles can be specified, see the following Remarks section. 
    
    If this handle is closed while the wait is still pending, the function's behavior is undefined.
    
    The handle must have the SYNCHRONIZE access right. For more information, see Standard Access Rights.
    
    dwMilliseconds 
    The time-out interval, in milliseconds. The function returns if the interval elapses, even if the object's state is nonsignaled. If dwMilliseconds is zero, the function tests the object's state and returns immediately. If dwMilliseconds is INFINITE, the function's time-out interval never elapses.
    
    Return Value
    If the function succeeds, the return value indicates the event that caused the function to return. It can be one of the following values.
    
    Return code/value Description 
    WAIT_ABANDONED
    0x00000080L
     The specified object is a mutex object that was not released by the thread that owned the mutex object before the owning thread terminated. Ownership of the mutex object is granted to the calling thread, and the mutex is set to nonsignaled.
    
    If the mutex was protecting persistent state information, you should check it for consistency.
     
    WAIT_OBJECT_0
    0x00000000L
     The state of the specified object is signaled.
     
    WAIT_TIMEOUT
    0x00000102L
     The time-out interval elapsed, and the object's state is nonsignaled.
     
    
    If the function fails, the return value is WAIT_FAILED ((DWORD)0xFFFFFFFF). To get extended error information, call GetLastError.
    
    Remarks
    The WaitForSingleObject function checks the current state of the specified object. If the object's state is nonsignaled, the calling thread enters the wait state until the object is signaled or the time-out interval elapses.
    
    The function modifies the state of some types of synchronization objects. Modification occurs only for the object whose signaled state caused the function to return. For example, the count of a semaphore object is decreased by one.
    
    The WaitForSingleObject function can wait for the following objects:
    
    
    Change notification 
    Console input 
    Event 
    Memory resource notification 
    Mutex 
    Process 
    Semaphore 
    Thread 
    Waitable timer 
    Use caution when calling the wait functions and code that directly or indirectly creates windows. If a thread creates any windows, it must process messages. Message broadcasts are sent to all windows in the system. A thread that uses a wait function with no time-out interval may cause the system to become deadlocked. Two examples of code that indirectly creates windows are DDE and the CoInitialize function. Therefore, if you have a thread that creates windows, use MsgWaitForMultipleObjects or MsgWaitForMultipleObjectsEx, rather than WaitForSingleObject.
    View Code

    代码注入:

    #include <iostream>
    #include "windows.h"
    #include "stdio.h"
    #include <tchar.h>
    typedef struct _THREAD_PARAM//为注入设计的参数结构,存储 LoadLibraryA(), GetProcAddress()api地址以及shellcode需要的参数
    {
        FARPROC pFunc[2];               // LoadLibraryA(), GetProcAddress()
        char    szBuf[4][128];          // "user32.dll", "MessageBoxA", "www.reversecore.com", "ReverseCore"
    } THREAD_PARAM, * PTHREAD_PARAM;
    
    typedef HMODULE(WINAPI* PFLOADLIBRARYA)//LoadLibraryA
    (
        LPCSTR lpLibFileName
        );
    
    typedef FARPROC(WINAPI* PFGETPROCADDRESS)//GetProcAddress
    (
        HMODULE hModule,
        LPCSTR lpProcName
        );
    
    typedef int (WINAPI* PFMESSAGEBOXA)//MessageBoxA
    (
        HWND hWnd,
        LPCSTR lpText,
        LPCSTR lpCaption,
        UINT uType
        );
    unsigned char shellcode[] =
    {
      0x48, 0x89, 0x4C, 0x24, 0x08, 0x55, 0x57, 0x48, 0x81, 0xEC, 0x48, 0x01, 0x00, 0x00, 0x48, 0x8D,
    0x6C, 0x24, 0x20, 0x48, 0x8B, 0xFC, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x48, 0x8B, 0x85, 0x40, 0x01, 0x00, 0x00, 0x48, 0x89, 0x45,
    0x08, 0x48, 0xC7, 0x45, 0x28, 0x00, 0x00, 0x00, 0x00, 0x48, 0xC7, 0x45, 0x48, 0x00, 0x00, 0x00,
    0x00, 0xB8, 0x80, 0x00, 0x00, 0x00, 0x48, 0x6B, 0xC0, 0x00, 0x48, 0x8B, 0x4D, 0x08, 0x48, 0x8D,
    0x44, 0x01, 0x10, 0xB9, 0x08, 0x00, 0x00, 0x00, 0x48, 0x6B, 0xC9, 0x00, 0x48, 0x89, 0x8D, 0x18,
    0x01, 0x00, 0x00, 0x48, 0x8B, 0xC8, 0x48, 0x8B, 0x45, 0x08, 0x48, 0x8B, 0x95, 0x18, 0x01, 0x00,
    0x00, 0xFF, 0x14, 0x10, 0x48, 0x89, 0x45, 0x28, 0x48, 0x83, 0x7D, 0x28, 0x00, 0x75, 0x07, 0xB8,
    0x01, 0x00, 0x00, 0x00, 0xEB, 0x7E, 0xB8, 0x80, 0x00, 0x00, 0x00, 0x48, 0x6B, 0xC0, 0x01, 0x48,
    0x8B, 0x4D, 0x08, 0x48, 0x8D, 0x44, 0x01, 0x10, 0xB9, 0x08, 0x00, 0x00, 0x00, 0x48, 0x6B, 0xC9,
    0x01, 0x48, 0x89, 0x8D, 0x18, 0x01, 0x00, 0x00, 0x48, 0x8B, 0xD0, 0x48, 0x8B, 0x4D, 0x28, 0x48,
    0x8B, 0x45, 0x08, 0x4C, 0x8B, 0x85, 0x18, 0x01, 0x00, 0x00, 0x42, 0xFF, 0x14, 0x00, 0x48, 0x89,
    0x45, 0x48, 0x48, 0x83, 0x7D, 0x48, 0x00, 0x75, 0x07, 0xB8, 0x01, 0x00, 0x00, 0x00, 0xEB, 0x34,
    0xB8, 0x80, 0x00, 0x00, 0x00, 0x48, 0x6B, 0xC0, 0x03, 0x48, 0x8B, 0x4D, 0x08, 0x48, 0x8D, 0x44,
    0x01, 0x10, 0xB9, 0x80, 0x00, 0x00, 0x00, 0x48, 0x6B, 0xC9, 0x02, 0x48, 0x8B, 0x55, 0x08, 0x48,
    0x8D, 0x4C, 0x0A, 0x10, 0x45, 0x33, 0xC9, 0x4C, 0x8B, 0xC0, 0x48, 0x8B, 0xD1, 0x33, 0xC9, 0xFF,
    0x55, 0x48, 0x33, 0xC0, 0x48, 0x8D, 0xA5, 0x28, 0x01, 0x00, 0x00, 0x5F, 0x5D, 0xC3
    };
    /*
    //shellcode
    DWORD WINAPI ThreadProc(LPVOID lParam)//注入的代码是这些!!!!!
    {
        PTHREAD_PARAM   pParam = (PTHREAD_PARAM)lParam;
        HMODULE         hMod = NULL;
        FARPROC         pFunc = NULL;
    
        // LoadLibrary()
        hMod = ((PFLOADLIBRARYA)pParam->pFunc[0])(pParam->szBuf[0]);    // "user32.dll"句柄
        if (!hMod)
            return 1;
    
        // GetProcAddress()
        pFunc = (FARPROC)((PFGETPROCADDRESS)pParam->pFunc[1])(hMod, pParam->szBuf[1]);  // "MessageBoxA"地址
        if (!pFunc)
            return 1;
    
        // MessageBoxA()
        ((PFMESSAGEBOXA)pFunc)(NULL, pParam->szBuf[2], pParam->szBuf[3], MB_OK);//运行messageboxa函数(后边两个是参数)
    
        return 0;
    }
    */
    
    
    BOOL InjectCode(DWORD dwPID)
    {
        HMODULE         hMod = NULL;
        THREAD_PARAM    param = { 0, };
        HANDLE          hProcess = NULL;
        HANDLE          hThread = NULL;
        LPVOID          pRemoteBuf[2] = { 0, };
        DWORD           dwSize = 0;
        SIZE_T writeSize = 0;
    
        hMod = GetModuleHandleA("kernel32.dll");//获取本进程中kernel32.dll句柄
    
        // set THREAD_PARAM
        param.pFunc[0] = GetProcAddress(hMod, "LoadLibraryA");//或取本进程LoadLibraryA函数地址       函数地址
        param.pFunc[1] = GetProcAddress(hMod, "GetProcAddress");//获取本进程GetProcAddress函数地址       函数地址
        strcpy_s(param.szBuf[0], "user32.dll");//复制字符串              
        strcpy_s(param.szBuf[1], "MessageBoxA");//复制字符串             
        strcpy_s(param.szBuf[2], "code injection");//复制字符串     lpText
        strcpy_s(param.szBuf[3], "test");//复制字符串             lpCaption
    
        // 打开进程
        if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS,   // dwDesiredAccess
            FALSE,                // bInheritHandle
            dwPID)))             // dwProcessId
        {
            printf("OpenProcess() fail : err_code = %d
    ", GetLastError());
            return FALSE;
        }
    
        // 为data分配内存,
        dwSize = sizeof(THREAD_PARAM);
        if (!(pRemoteBuf[0] = VirtualAllocEx(hProcess,          // hProcess
            NULL,                 // lpAddress
            dwSize,               // dwSize
            MEM_COMMIT,           // flAllocationType
            PAGE_READWRITE)))    // flProtect
        {
            printf("VirtualAllocEx() fail : err_code = %d
    ", GetLastError());
            return FALSE;
        }
        //将data注入到分配的内存中
        if (!WriteProcessMemory(hProcess,                       // hProcess
            pRemoteBuf[0],                  // lpBaseAddress
            (LPVOID)&param,                 // lpBuffer
            dwSize,                         // nSize
            &writeSize))                         // [out] lpNumberOfBytesWritten
        {
            printf("WriteProcessMemory() fail : err_code = %d
    ", GetLastError());
            return FALSE;
        }
        printf("data write:0x%016X
    ", writeSize);
        // 为code分配内存
        //dwSize = (DWORD)InjectCode - (DWORD)ThreadProc;
        dwSize = sizeof(shellcode);
        if (!(pRemoteBuf[1] = VirtualAllocEx(hProcess,          // hProcess
            NULL,                 // lpAddress
            dwSize,               // dwSize
            MEM_COMMIT,           // flAllocationType
            PAGE_EXECUTE_READWRITE)))    // flProtect
        {
            printf("VirtualAllocEx() fail : err_code = %d
    ", GetLastError());
            return FALSE;
        }
        
        //将code注入到内存中
        if (!WriteProcessMemory(hProcess,                       // hProcess
            pRemoteBuf[1],                  // lpBaseAddress
            //(LPVOID)ThreadProc,             // lpBuffer
            shellcode,
            dwSize,                         // nSize
            &writeSize))                         // [out] lpNumberOfBytesWritten
        {
            printf("WriteProcessMemory() fail : err_code = %d
    ", GetLastError());
            return FALSE;
        }
        printf("code write:0x%016X
    ", writeSize);
        //执行远程线程
        if (!(hThread = CreateRemoteThread(hProcess,            // hProcess
            NULL,                // lpThreadAttributes
            0,                   // dwStackSize
            (LPTHREAD_START_ROUTINE)pRemoteBuf[1],     // 注入线程的代码地址
            pRemoteBuf[0],       // lpParameter       //注入线程的数据地址
            0,                   // dwCreationFlags
            NULL)))             // lpThreadId
        {
            printf("CreateRemoteThread() fail : err_code = %d
    ", GetLastError());
            return FALSE;
        }
    
        WaitForSingleObject(hThread, INFINITE);
    
        CloseHandle(hThread);
        CloseHandle(hProcess);
    
        return TRUE;
    }
    
    BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege)
    {
        TOKEN_PRIVILEGES tp;
        HANDLE hToken;
        LUID luid;
    
        if (!OpenProcessToken(GetCurrentProcess(),
            TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
            &hToken))
        {
            printf("OpenProcessToken error: %u
    ", GetLastError());
            return FALSE;
        }
    
        if (!LookupPrivilegeValue(NULL,           // lookup privilege on local system
            lpszPrivilege,  // privilege to lookup
            &luid))        // receives LUID of privilege
        {
            printf("LookupPrivilegeValue error: %u
    ", GetLastError());
            return FALSE;
        }
    
        tp.PrivilegeCount = 1;
        tp.Privileges[0].Luid = luid;
        if (bEnablePrivilege)
            tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
        else
            tp.Privileges[0].Attributes = 0;
    
        // Enable the privilege or disable all privileges.
        if (!AdjustTokenPrivileges(hToken,
            FALSE,
            &tp,
            sizeof(TOKEN_PRIVILEGES),
            (PTOKEN_PRIVILEGES)NULL,
            (PDWORD)NULL))
        {
            printf("AdjustTokenPrivileges error: %u
    ", GetLastError());
            return FALSE;
        }
    
        if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
        {
            printf("The token does not have the specified privilege. 
    ");
            return FALSE;
        }
    
        return TRUE;
    }
    
    int main(int argc, char* argv[])
    {
    
        DWORD dwPID;
        printf("input pid:
    ");
        _tcscanf(_T("%d"), &dwPID);
    
    
        // 改变权限
        if (!SetPrivilege(SE_DEBUG_NAME, TRUE)) {
            printf("SetPrivilege error
    ");
            return 1;
        }
        printf("SetPrivilege success
    ");
    
        // 代码注入
        if (!InjectCode(dwPID)) {
            printf("InjectCode error
    ");
        }
        printf("InjectCode success
    ");
        return 0;
    }

    x64dbg调试注入的代码:

    1、附加代码注入的目标进程

    2、设置:

    选项-->事件-->线程入口

     3、代码注入后,调试器断在线程入口(调试器要 以管理员身份运行 ,不然会出现异常,开始没注意浪费了很长时间0.0)

    x64  系统api调用为fastcall,在编写shellcode时需要留意。

    This function returns a handle to an existing process object.

    HANDLE OpenProcess( 
      DWORD fdwAccess, 
      BOOL fInherit, 
      DWORD IDProcess
    );

    Parameters

    fdwAccess
    [in] Not supported; set to zero.
    fInherit
    [in] Not supported; set to FALSE.
    IDProcess
    [in] Specifies the process identifier of the process to open.

    Return Values

    An open handle to the specified process indicates success.

    NULL indicates failure.

    To get extended error information, call GetLastError.

    Remarks

    The handle returned by the OpenProcess function can be used in any function that requires a handle to a process, such as wait functions, if the appropriate access rights are requested.

    When you finish with the handle, close it using the CloseHandle function.

  • 相关阅读:
    Thymeleaf 基本表达式
    html中<radio>单选按钮控件标签用法解析及如何设置默认选中
    <%@ page contentType="text/html; charset=utf-8" language="java"%>每一个字符的含义
    El表达式的关系运算符
    Centos7.6安装Docker安装
    linux必须熟练掌握的基础命令
    CentOS7.x编译安装zabbix4.0
    编译装php7.2 && nginx-1.14
    CentOS7.x安装MySQL5.7.25
    CentOS7.x安装kickstart
  • 原文地址:https://www.cnblogs.com/DirWang/p/13476864.html
Copyright © 2020-2023  润新知