第三个注入实例(机器码的注入)

注入的机器码是用汇编编译器生成的,与C语言相比,更灵活自由。以前用过一阵MASM,而这本书上是用OD地汇编功能,倒是第一次见过。。。汗,又发现一个没掌握的OD功能。

先上传四张图,前三张是注入代码的三种不同形式的呈现:

第一张是反汇编指令形式的图

第二张是经CTRL+A分析过后的反汇编指令,1033,1044处不是指令,是两个字符窜

第三张是数据形式

这一张表是修改后用来直接注入的数据

下图直观一点。

 

下面贴实现代码

 

#include "stdafx.h"
#include "windows.h"

typedef struct _THREAD_PARAM
{
    FARPROC pFunc[2];               // LoadLibraryA(), GetProcAddress()
} THREAD_PARAM, *PTHREAD_PARAM;

BYTE g_InjectionCode[] =
{
    0x55, 0x8B, 0xEC, 0x8B, 0x75, 0x08, 0x68, 0x6C, 0x6C, 0x00,
    0x00, 0x68, 0x33, 0x32, 0x2E, 0x64, 0x68, 0x75, 0x73, 0x65,
    0x72, 0x54, 0xFF, 0x16, 0x68, 0x6F, 0x78, 0x41, 0x00, 0x68,
    0x61, 0x67, 0x65, 0x42, 0x68, 0x4D, 0x65, 0x73, 0x73, 0x54,
    0x50, 0xFF, 0x56, 0x04, 0x6A, 0x00, 0xE8, 0x0C, 0x00, 0x00,
    0x00, 0x52, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x43, 0x6F,
    0x72, 0x65, 0x00, 0xE8, 0x14, 0x00, 0x00, 0x00, 0x77, 0x77,
    0x77, 0x2E, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x63,
    0x6F, 0x72, 0x65, 0x2E, 0x63, 0x6F, 0x6D, 0x00, 0x6A, 0x00,
    0xFF, 0xD0, 0x33, 0xC0, 0x8B, 0xE5, 0x5D, 0xC3
};

//提权的

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

//注入实现,与上一篇注入代码略有不同,实则上这样反而不够灵活了。。。重用性大大降低,但安全性确实能提高。
BOOL InjectCode(DWORD dwPID)
{
    HMODULE         hMod = NULL;
    THREAD_PARAM    param = { 0, };
    HANDLE          hProcess = NULL;
    HANDLE          hThread = NULL;
    LPVOID          pRemoteBuf[2] = { 0, };

    hMod = GetModuleHandleA("kernel32.dll");

    // set THREAD_PARAM
    param.pFunc[0] = GetProcAddress(hMod, "LoadLibraryA");
    param.pFunc[1] = GetProcAddress(hMod, "GetProcAddress");

    // 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
    if (!(pRemoteBuf[0] = VirtualAllocEx(hProcess,                  // hProcess
        NULL,                      // lpAddress
        sizeof(THREAD_PARAM),      // 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
        sizeof(THREAD_PARAM),                   // nSize
        NULL))                                 // [out] lpNumberOfBytesWritten
    {
        printf("WriteProcessMemory() fail : err_code = %d\n", GetLastError());
        return FALSE;
    }

    // Allocation for ThreadProc()
    if (!(pRemoteBuf[1] = VirtualAllocEx(hProcess,                  // hProcess
        NULL,                      // lpAddress
        sizeof(g_InjectionCode),   // 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)&g_InjectionCode,               // lpBuffer
        sizeof(g_InjectionCode),                // 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],
        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;
}

int _tmain(int argc, _TCHAR* 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)_wtol(argv[1]);
    InjectCode(dwPID);
    return 0;
}

 

从上面的代码并不能看出那些像是花指令的代码如何正确运行的,必须跟踪调试一步一步观察才能彻底了解。所以个人觉得,学习编程特别是逆向,特别花时间,不能理所当然地以为自己掌握了而忽略了实践的过程。事实上,就算你实践了,大部分情况下你也不大可能一次掌握其中所有的技巧,只有通过多次调试,修改代码,举一反三的加深印象,才能掌握更多地知识。

posted @ 2015-05-18 12:48  笔直的一道弯  阅读(570)  评论(0编辑  收藏  举报