xxxx (二):DLL远程注入

  要想改变目标进程执行流程的办法有很多,最常见的就是hook。为了让目标进程执行特定的代码,可以注入shellcode或dll;shellcode的优点是体积小,不容易被检测到,但功能也相对单一;dll注入优点是可以包含的功能较多,但容易被检测到。本次拿xxxx软件举例做个dll注入;

  要做注入,否先要再目标进程开辟一块内存空间,然后写入自己想要执行的代码,再想办法让eip跳转到这里。对于dll注入,大致的流程如下:

  openprocess->VirtualAllocEx->WriteProcessMemory->GetProcAddress->CreateRemoteThread

  核心思路:打开目标进程,分配内存空间,写入需要执行的dll地址,得到loadlibrary函数地址,最后调用createRemoteThread函数专门生成一个线程执行loadlibary函数。这种注入/HOOK方式多年前就烂大街了,这里不再赘述,感兴趣的小伙伴可google查阅相关资料;dll注入核心代码如下:

#include "windows.h"
#include "tchar.h"

BOOL InjectDll(DWORD dwPID, LPCTSTR szDllPath)
{
    HANDLE hProcess = NULL, hThread = NULL;
    HMODULE hMod = NULL;
    LPVOID pRemoteBuf = NULL;
    DWORD dwBufSize = (DWORD)(_tcslen(szDllPath) + 1) * sizeof(TCHAR);
    LPTHREAD_START_ROUTINE pThreadProc;

    if ( !(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) )
    {
        _tprintf(L"OpenProcess(%d) failed!!! [%d]\n", dwPID, GetLastError());
        return FALSE;
    }

    pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READWRITE);

    WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllPath, dwBufSize, NULL);

    hMod = GetModuleHandle(L"kernel32.dll");
    pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod, "LoadLibraryW");
    
    hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, pRemoteBuf, 0, NULL);
    WaitForSingleObject(hThread, INFINITE);    

    CloseHandle(hThread);
    CloseHandle(hProcess);

    return TRUE;
}

int _tmain(int argc, TCHAR *argv[])
{
    if( argc != 3)
    {
        _tprintf(L"USAGE : %s <pid> <dll_path>\n", argv[0]);
        return 1;
    }

    // inject dll
    if( InjectDll((DWORD)_tstol(argv[1]), argv[2]) )
        _tprintf(L"InjectDll(\"%s\") success!!!\n", argv[2]);
    else
        _tprintf(L"InjectDll(\"%s\") failed!!!\n", argv[2]);

    return 0;
}

  这里需要输入两个参数:目标进程的PID和需要加载的dll全路径。这里为了突出重点(注入流程),省略了查找目标进程的代码(感兴趣的小伙伴可调用windows的API遍历进程,查找PID),这里手动在任务管理器里面查找;

  为了测试dll是否加载成功,这里先不执行其他代码,只弹个窗试试:

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        MessageBoxW(NULL,L"dll加载成功",L"dll加载测试", MB_OK);
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

 测试效果,说明dll加载成功了! 

    

  下一步就是通过动态调试或静态分析找各种功能call了!有两种方式:

  •      用OD\CE\X32DBG\IDA等工具调试xxxx的PC端,通过各种方式找到各种功能(诸如发送/接受消息、二维码生成、发送/接受文件、红包等)的call
  •      市面上有好些现成的外挂,可以“黑吃黑”:用IDA分析这些外挂的dll,看看hook了xxxx的哪些模块的哪些偏移地址,自己写代码直接hook这些地址即可,理论上比第一种方式快很多,不过只能追随别人的步伐,没有先发优势;
posted @ 2020-12-27 16:30  第七子007  阅读(543)  评论(0编辑  收藏  举报