逆向工程核心原理——第二十七章

代码注入

这里我们需要向notepad注入一段代码,从而达到弹出窗口的目的。


我们知道DLL注入,是要将我们想执行的代码,放入DLL中,在程序运行DLL时,运行我们想要执行的代码,而代码注入则不需要DLL文件,直接就可以执行。

代码注入练习:

首先使用process explorer查看已经运行的notepad的PID:

然后cmd打开我们写好的CodeInjection.exe,输入参数(notepad的PID)

接着就可以看到对话框弹出的:

CodeInjection.exe的代码如下,我使用的编译环境为 **VS2019 ** 运行环境为 Windows 7 x64

// CodeInjection.cpp  
// reversecore@gmail.com  
// http://www.reversecore.com  

#include "windows.h"  
#include "stdio.h"  

typedef struct _THREAD_PARAM
{
    FARPROC pFunc[2];               // LoadLibraryA(), GetProcAddress()  
    char    szBuf[4][128];          // "user32.dll", "MessageBoxA", "www.reversecore.com", "ReverseCore"  
} THREAD_PARAM, * PTHREAD_PARAM;

typedef HMODULE(WINAPI* PFLOADLIBRARYA)
(
    LPCSTR lpLibFileName
    );

typedef FARPROC(WINAPI* PFGETPROCADDRESS)
(
    HMODULE hModule,
    LPCSTR lpProcName
    );

typedef int (WINAPI* PFMESSAGEBOXA)
(
    HWND hWnd,
    LPCSTR lpText,
    LPCSTR lpCaption,
    UINT uType
    );

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);

    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;

    hMod = GetModuleHandleA("kernel32.dll");

    // set THREAD_PARAM  
    param.pFunc[0] = GetProcAddress(hMod, "LoadLibraryA");
    param.pFunc[1] = GetProcAddress(hMod, "GetProcAddress");
    strcpy_s(param.szBuf[0], "user32.dll");
    strcpy_s(param.szBuf[1], "MessageBoxA");
    strcpy_s(param.szBuf[2], "www.reversecore.com");
    strcpy_s(param.szBuf[3], "ReverseCore");

    // Open Process  
    if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS,   // dwDesiredAccess  
        FALSE,                // bInheritHandle  
        dwPID)))             // dwProcessId  
    {
        printf("OpenProcess() fail : err_code = %d\n", GetLastError());
        return FALSE;
    }

    // Allocation for THREAD_PARAM  
    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\n", GetLastError());
        return FALSE;
    }

    if (!WriteProcessMemory(hProcess,                       // hProcess  
        pRemoteBuf[0],                  // lpBaseAddress  
        (LPVOID)&param,               // lpBuffer  
        dwSize,                         // nSize  
        NULL))                         // [out] lpNumberOfBytesWritten  
    {
        printf("WriteProcessMemory() fail : err_code = %d\n", GetLastError());
        return FALSE;
    }

    // Allocation for ThreadProc()  
    dwSize = (DWORD)InjectCode - (DWORD)ThreadProc;
    if (!(pRemoteBuf[1] = VirtualAllocEx(hProcess,          // hProcess  
        NULL,                 // lpAddress  
        dwSize,               // dwSize  
        MEM_COMMIT,           // flAllocationType  
        PAGE_EXECUTE_READWRITE)))    // flProtect  
    {
        printf("VirtualAllocEx() fail : err_code = %d\n", GetLastError());
        return FALSE;
    }

    if (!WriteProcessMemory(hProcess,                       // hProcess  
        pRemoteBuf[1],                  // lpBaseAddress  
        (LPVOID)ThreadProc,             // lpBuffer  
        dwSize,                         // nSize  
        NULL))                         // [out] lpNumberOfBytesWritten  
    {
        printf("WriteProcessMemory() fail : err_code = %d\n", GetLastError());
        return FALSE;
    }

    if (!(hThread = CreateRemoteThread(hProcess,            // hProcess  
        NULL,                // lpThreadAttributes  
        0,                   // dwStackSize  
        (LPTHREAD_START_ROUTINE)pRemoteBuf[1],     // dwStackSize  
        pRemoteBuf[0],       // lpParameter  
        0,                   // dwCreationFlags  
        NULL)))             // lpThreadId  
    {
        printf("CreateRemoteThread() fail : err_code = %d\n", 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\n", GetLastError());
        return FALSE;
    }

    if (!LookupPrivilegeValue(NULL,           // lookup privilege on local system  
        lpszPrivilege,  // privilege to lookup   
        &luid))        // receives LUID of privilege  
    {
        printf("LookupPrivilegeValue error: %u\n", 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\n", GetLastError());
        return FALSE;
    }

    if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
    {
        printf("The token does not have the specified privilege. \n");
        return FALSE;
    }

    return TRUE;
}

int main(int argc, char* argv[])
{
    DWORD dwPID = 0;

    if (argc != 2)
    {
        printf("\n USAGE  : %s <pid>\n", argv[0]);
        return 1;
    }

    // change privilege  
    if (!SetPrivilege(SE_DEBUG_NAME, TRUE))
        return 1;

    // code injection  
    dwPID = (DWORD)atol(argv[1]);
    InjectCode(dwPID);

    return 0;
}

接下来我们使用OD找到ThreadProc()函数开始的位置

首先还是使用OD的附加(attach)功能,载入正在运行notepad:

按下F9,让notepad处于运行状态,在设置中将载入进程时断点打开:

这样,notepad载入新进程时就会被断下来,接着注入代码,就可以看到被断下来了:

posted @ 2020-09-25 12:13  Kylimi  阅读(311)  评论(0编辑  收藏  举报