• 远程线程DLL注入64位进程


     1 int main()
     2 {
     3     BOOL bFlag = FALSE;
     4 
     5     char *szDllName = "MSGDLL.dll";
     6     //bFlag = EnablePrivilege(SE_DEBUG_NAME);    //返回值为1时代表成功
     7 
     8 
     9     //得到目标进程句柄
    10     HANDLE hDestProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 7084);
    11 
    12     LPTHREAD_START_ROUTINE dwAddr = (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("Kernel32"), "LoadLibraryA");
    13 
    14     //在目标进程的地址空间内分配一个内存块
    15     LPVOID pRemoteSpace = VirtualAllocEx(hDestProcess, NULL, strlen(szDllName) + 1, MEM_COMMIT,
    16         PAGE_READWRITE);
    17 
    18     //向上一步的内存块中写入数据,就是要加载的DLL名字
    19     bFlag = WriteProcessMemory(hDestProcess, pRemoteSpace, szDllName, strlen(szDllName) + 1, 0);
    20 
    21     //在目标进程内创建线程,线程的入口函数就是LoadLibraryA, 参数就是Dll名字
    22     HANDLE hThread = CreateRemoteThread(hDestProcess, NULL, 0, dwAddr, pRemoteSpace,
    23         NULL, 0
    24     );      //前面都是成功的,就到了这一步,返回的错误是5,Access denied,权限不够
    25             //本来以为我的VS是以管理员权限启动的,那么我这个进程应该权限就都够了,
    26             //看来不行,必须程序提权
    27             //我提权了之后,发现还是不行,之后上网查了
    28             //发现是32位注入到64位中会有问题,所以我换了个x64,然后显然线程运行成功了,
    29             //但是现在远程进程却崩溃了,估计是DLL是32的,我换个DLL编译方式再试试
    30             //我编译了64位的DLL,然后还是崩溃的,之后我发现了应该是我函数地址传的有问题
    31             //因为32位的LoadLibraryA地址是DWORD,但64位却是ULONGLONG,所以仅仅改变编译方式还不够
    32             //必须用一个足够容纳8个字节地址的类型来保存,这样就够了
    33 
    34             //另外一个需要注意的问题就是,为什么我在我这个进程中得到的LoadLibrary在远程进程中也可以用
    35             //答案就是,系统DLL在各个进程中的映射地址都是一样的,不过具体情况具体分析,至少这个函数看来是一样的。
    36 
    37             //在我完成了之后,我把EnablePrivileges这行注释掉了,但仍然注入成功,看来我用管理员权限运行VS2015之后就够了
    38             
    39             //然后我又发现了一个问题,就是对同一个进程,加载dll只能一次,第二次就不会弹了
    40             //原因,我目测是,DLL已经被加载了,所以第二次就不加载了,也就不执行DllMain那个函数了
    41             //除非我创建一个线程再UnLoad那个LIB,之后再LOAD,这样应该就可以了
    42             //也可以换个Dll名字,再LOAD, 反正方法很多。
    43 
    44     DWORD dwErr = GetLastError();
    45 
    46     return 0;
    47 }
     //DLL的代码,用DLL方式生成一下,拉到前面EXE目录,或者系统目录都行,跟前面代码中DLL名字有没有加绝对路径有关
    //这代码是书上的代码,直接复制了
    /* ************************************
    *《精通Windows API》
    * 示例代码
    * msg.c                  
    * 6.5  动态链接库
    **************************************/
    /* 头文件 */
    #include <Windows.h>
    #include <Psapi.h>
    /* 链接 */
    #pragma comment (lib, "Psapi.lib") 
    /* 函数声明 */
    
    // 使用__declspec(dllexport)声明导出函数
    __declspec(dllexport) DWORD ExportExample(LPSTR szMsg, DWORD dwCode);
    
    /*************************************
    * DllMain
    **************************************/
    BOOL WINAPI DllMain(
        HINSTANCE hinstDLL,  // DLL模块的句柄
        DWORD fdwReason,     // 调用的情况
        LPVOID lpReserved)  // reserved
    {
        // 在不同的情况下都会调用DllMain函数,分别处理
        switch (fdwReason)
        {
            // 加载Dll
            case DLL_PROCESS_ATTACH:
                {
                    CHAR lpMainMoudleName[MAX_PATH];
                    CHAR lpMessage[MAX_PATH + 64];
                    // 获取PID 和主模块名,将弹出消息框
                    DWORD dwPID = GetCurrentProcessId();
                    GetModuleBaseName(GetCurrentProcess(), NULL, lpMainMoudleName, MAX_PATH);
                    wsprintf(lpMessage, "Process name: %s, PID: %u ", lpMainMoudleName, dwPID);
                    MessageBox(NULL, lpMessage, "msg.dll", MB_OK);
                    break;
                }
                // 新建线程
            case DLL_THREAD_ATTACH:
                break;
                // 线程退出
            case DLL_THREAD_DETACH:
                break;
                // 释放Dll
            case DLL_PROCESS_DETACH:
    
                break;
        }
        return TRUE;
    }
    
    /*************************************
    * DWORD ExportExample(LPSTR szMsg, DWORD dwCode)
    * 功能    导出函数,显示消息
    *
    * 参数    LPSTR szMsg    字符串; DWORD dwCode 整形
    **************************************/
    DWORD ExportExample(LPSTR szMsg, DWORD dwCode)
    {
        LPVOID lpShowOut = HeapAlloc(GetProcessHeap(), 0, lstrlen(szMsg) + 100);
        wsprintf((LPSTR)lpShowOut, "%s,%d", szMsg, dwCode);
        MessageBox(NULL, (LPSTR)lpShowOut, "由导出函数弹出的消息!", MB_OK);
        HeapFree(GetProcessHeap(), 0, lpShowOut);
        return 0;
    }

    需要注意的点都在那一大串注释中

    64位进程,就得用64位的EXE来CreateRemoteThread, 另外DLL也应该是64位

    32位进程,就得用32位的EXE来CreateRemoteThread, 另外DLL也应该是32位

    把CreateRemoteThread的入口点函数设为LoadLibraryA(W),线程的那个参数设为DLL路径指针(在目标进程中,所以得把DLL路径拷到目标进程 中, 用VirtualAllocEx在目标进程中分配块空间,然后WriteProcessMemory).

    这样可行的原因:

      线程的函数原型DWORD ThreadProc(LPVOID lpParam)

      LoadLibrary的函数原型HMODULE LoadLibrary(LPCTSTR lpFileName);

    其实是一样的,指针都是同样大小,都只有一个参数,返回值无所谓..

    另外在目标进程和本进程中LoadLibraryA(W)的虚拟地址是一样的..

  • 相关阅读:
    混合装置实现了24/7的能量收集和储存
    2020年人工智能汽车将出台多项标准
    自动驾驶汽车事故的责任追究
    多核处理器集成了神经处理单元
    广泛的信号处理链如何让语音助理“正常工作”
    先进机器人系统中的关键技术
    模拟内存计算如何解决边缘人工智能推理的功耗挑战
    TinyML设备设计的Arm内核
    获取url指定参数值(js/vue)
    js 实时监听textarea输入
  • 原文地址:https://www.cnblogs.com/cqubsj/p/6037556.html
Copyright © 2020-2023  润新知