精华内容
下载资源
问答
  • 文章目录杂被注入进程编写DLL注入流程枚举流程注入及枚举源码演示 杂 所谓远程线程,并非指跨主机,而是指跨进程。也即一个进程对另一个进程的注入。 被注入进程 最好还是自己手写一个,不然很多软件的进程应该是有...

    所谓远程线程,并非指跨主机,而是指跨进程。也即一个进程对另一个进程的注入。

    被注入进程

    最好还是自己手写一个,不然很多软件的进程应该是有防护机制,注进去的线程会被杀掉,dll也会被卸载,不方便观察。

    delete.exe源码

    #include <stdio.h>
    #include <windows.h>
    
    int main(void){
        while(1){
            Sleep(100);
        }
    
        return 0;
    }
    

    很简单,就是一段死循环

    编写DLL

    Windows开发:CLion下编写及动/ 静态调用DLL

    library.h

    #ifndef DLL_GENERATE_LIBRARY_H
    #define DLL_GENERATE_LIBRARY_H
    
    // extern "C":以C方式导出
    // __declspec(dllexport) 声明一个导出函数
    extern "C" __declspec(dllexport) void MyAdd(int a, int b);
    
    
    #endif //DLL_GENERATE_LIBRARY_H
    

    library.cpp

    #include "library.h"
    #include <windows.h>
    #include <iostream>
    
    
    // 实现
    void MyAdd(int a, int b) {
        std::cout << a + b << std::endl;
    }
    
    
    extern "C" BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved){
        switch(fdwReason) {
            case DLL_PROCESS_ATTACH:
                MessageBox(NULL, "It works!", "Status", MB_OK);
            case DLL_PROCESS_DETACH:
            case DLL_THREAD_ATTACH:
            case DLL_THREAD_DETACH:
            default:
                break;
        }
        return TRUE;
    }
    
    

    主函数DllMain的作用是首次被load时,弹窗提示。

    注入流程

    首先使用OpenProcess打开指定PID的进程,权限要足够,不然可能出现无法创建线程的情况。

    第二,获得dll文件的绝对路径的字符串长度,并使用VirtualAllocEx在被注入进程中申请相应大小的内存。

    第三,使用WriteProcessMemory将dll文件的绝对路径字符串写入被注入进程。

    第四,以dll文件的句柄、要查找的函数名作为GetProcAddress的参数,查找本进程中加载的Kernel32.dll中LoadLibrary函数的始址,根据是否采用UNICODE有不同的函数W/ A。因为这个dll在所有进程中加载的位置都相同,所以本进程中的函数位置就是被注入进程中函数的位置。

    第五,在被注入进程中使用CreateRemoteThread创建线程,参数为线程函数(LoadLibrary)地址,线程函数参数(dll文件的绝对路径)

    第六,若成功注入,因为dll是首次被load,所以调用其DllMain时,fdwReason参数的值为DLL_PROCESS_ATTACH,判断一下,会弹窗提示成功。

    枚举流程

    注入完成后,枚举一下被注入进程加载了哪些DLL
    Windows开发:进程、线程及DLL的枚举

    注入及枚举源码

    #include <iostream>
    #include <windows.h>
    #include <tchar.h>
    #include <tlhelp32.h>
    
    
    // 参数:dll路径,被注入进程的PID
    bool ModuleInject(LPCTSTR szModule, DWORD dwPid){
        // 参数:权限、是否有子进程继承权限、PID
        HANDLE hProcess = OpenProcess(
                PROCESS_QUERY_INFORMATION | PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE,
                FALSE,
                dwPid
                );
        if (hProcess){
            // 成功获取到进程句柄
            // dll路径字符串的大小
            int cByte = (_tcslen(szModule) + 1) * sizeof(TCHAR);
            // 在被注入进程中申请分配内存,返回首地址
            // 参数:进程句柄、要开始分配内存的位置、分配大小、分配内存类型、内存管理方式
            LPVOID pAddr = VirtualAllocEx(hProcess, NULL, cByte, MEM_COMMIT, PAGE_READWRITE);
            if (pAddr){
                // 分配成功则尝试在被注入进程中写入dll路径
                // 参数:进程句柄、分配好的内存首址、数据内容指针、数据长度、传出(写入了多少字节)
                if (WriteProcessMemory(hProcess, pAddr, szModule, cByte, NULL)){
    // 如果定义了UNICODE
    #ifdef _UNICODE
        // 使用GMH获得Kernel32.dll的句柄,用GPA在其中找到宽字节的LoadLibraryW函数的地址,此地址在所有进程中相同
        // 强转为PSR类型指针,作为CreateRemoteThread的参数
        PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(_T("Kernel32")), "LoadLibraryW");
    #else
        PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(_T("Kernel32")), "LoadLibraryA");
    #endif
                    if (pfnStartAddr){
                        // 远程线程ID
                        DWORD dwThreadID = 0;
                        // 远程线程句柄
                        // 参数:进程句柄、安全属性指针、堆栈大小(0默认)、线程函数(LoadLibrary)地址、线程函数参数(dll路径)、创建标志、传出远程线程ID
                        HANDLE hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, pfnStartAddr, pAddr, 0, &dwThreadID);
                        if (hRemoteThread){
                            // 若成功注入,则dll被load到进程中,其DllMain被执行
                            std::cout << "inject success." << std::endl;
                            // 等待远程线程退出再退出
                            WaitForSingleObject(hRemoteThread, INFINITE);
    
                            CloseHandle(hRemoteThread);
                            CloseHandle(hProcess);
                        }
                        else{
                            std::cout << "create remote thread failed." << std::endl;
                        }
                    }
                    else{
                        std::cout << "cannot find func LoadLibrary" << std::endl;
                    }
                }
                else{
                    std::cout << "write mem failed." << std::endl;
                }
            }
            else{
                std::cout << "alloc mem failed." << std::endl;
    
                return FALSE;
            }
    
        }
        else{
            std::cout << "failed to open process." << std::endl;
    
            return FALSE;
        }
    }
    
    VOID EnumProcessModule(int myPid) {
        MODULEENTRY32 me32 = {0};
        me32.dwSize = sizeof(MODULEENTRY32);
    
        // 创建DLL型快照,参数为进程ID
        HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, myPid);
        if (hSnap == INVALID_HANDLE_VALUE){
            std::cout << "failed to create module snapshot." << std::endl;
        }
        else{
            BOOL enumStatus = Module32First(hSnap, &me32);
            int i = 0;
            while (enumStatus){
                std::cout << me32.szModule << ", " << me32.szExePath << std::endl;
                i++;
                enumStatus = Module32Next(hSnap, &me32);
            }
        }
    
        CloseHandle(hSnap);
    }
    
    
    int main() {
        
        int myPid = 0;
        std::cin >> myPid;
        ModuleInject(_T("D:\\CLion_workspace\\win32_programing\\dll_programing\\dll_inject\\lib\\libdll_generate.dll"), myPid);
        Sleep(5000);
        EnumProcessModule(myPid);
    
        return 0;
    }
    

    演示

    首先打开delete.exe,使用IDE运行或直接运行编译出的exe都可以,查看其PID

    在这里插入图片描述

    确认dll位置正确,运行注入程序,输入PID,杀软放行

    在这里插入图片描述
    弹窗提示
    在这里插入图片描述

    查看被注入进程加载的dll,注入成功。
    在这里插入图片描述

    展开全文
  • 注入 - Ring3 APC注入

    2017-08-20 20:03:00
    系统产生一个软中断,当线程再次唤醒时,此线程会首先执行APC队列中的注册的函数,利用QueueUserAPC()这个API,并以此去执行我们的DLL加载代码,进而完成DLL注入的目的, 1.根据进程名称得进程ID2.枚举该进程中...
    系统产生一个软中断,当线程再次被唤醒时,此线程会首先执行APC队列中的被注册的函数,利用QueueUserAPC()这个API,并以此去执行我们的DLL加载代码,进而完成DLL注入的目的,

    1.根据进程名称得进程ID
    2.枚举该进程中的线程
    3.将自己的函数插入到每个线程的APC队列中





    1
    // APCInject(Ring3).cpp : 定义控制台应用程序的入口点。 2 // 3 4 #include "stdafx.h" 5 #include <windows.h> 6 #include <TlHelp32.h> 7 #include <ntstatus.h> 8 #include <vector> 9 #include <iostream> 10 11 using namespace std; 12 /* 13 Win7下成功 Win10不一定成功(编译对应的位数,管理员身份运行) 14 Win7要将倒着插入!! 15 要将DLL拷到.cpp的文件夹中 16 尽量选择线程多的exe 17 18 另外没有提供删除APC队列中函数的方法,所以不能反复注入。 19 */ 20 21 22 WCHAR __DllFullPath[MAX_PATH] = { 0 }; 23 PVOID __DllFullPathBufferData = NULL; 24 UINT_PTR __LoadLibraryWAddress = 0; 25 26 27 //typedef void(*pfnSub_110)(); 28 29 30 BOOL GetProcessIDByProcessImageName(IN PWCHAR ProcessImageName, OUT PUINT32 ProcessID); 31 BOOL GetThreadIDByProcessID(IN UINT32 ProcessID, OUT vector<UINT32>& ThreadIDVector); 32 BOOL InjectDllByApc(IN UINT32 ProcessID, OUT UINT32 ThreadID); 33 BOOL DebugPrivilege(WCHAR * DebugName, BOOL bEnable); 34 35 int main() 36 { 37 if (DebugPrivilege(SE_DEBUG_NAME, TRUE)==FALSE) 38 { 39 printf("DebugPrivilege Error\r\n"); 40 } 41 42 GetCurrentDirectory(MAX_PATH, __DllFullPath); 43 44 wcscat(__DllFullPath, L"\\Dll.dll"); 45 46 47 UINT ProcessID = 0; 48 49 if (GetProcessIDByProcessImageName( 50 L"taskmgr.exe", &ProcessID) == FALSE) 51 { 52 53 54 return 0; 55 } 56 57 vector<UINT32> ThreadIDVector; 58 59 if (GetThreadIDByProcessID(ProcessID, ThreadIDVector) == FALSE) 60 { 61 return 0; 62 } 63 64 size_t ThreadCount = ThreadIDVector.size(); 65 //每一个线程 66 /* 67 win7下得倒着注入 68 */ 69 for (INT_PTR i = ThreadCount - 1; i >= 0; i--) 70 { 71 UINT32 ThreadID = ThreadIDVector[i]; 72 InjectDllByApc(ProcessID, ThreadID); 73 } 74 75 76 printf("Input Any Key to Exit\r\n"); 77 getchar(); 78 getchar(); 79 80 return 0; 81 } 82 83 84 BOOL InjectDllByApc(IN UINT32 ProcessID, OUT UINT32 ThreadID) 85 { 86 HANDLE ThreadHandle = NULL; 87 HANDLE ProcessHandle = OpenProcess( 88 PROCESS_ALL_ACCESS, FALSE, ProcessID); 89 90 SIZE_T DllFullPathLength = ((wcslen(__DllFullPath) + 1)); 91 92 SIZE_T ReturnLength = 0; 93 BOOL IsOk = FALSE; 94 95 // 申请一次内存 96 if (__DllFullPathBufferData == NULL) 97 { 98 __DllFullPathBufferData = 99 VirtualAllocEx( 100 ProcessHandle, 101 NULL, 102 DllFullPathLength * 2, 103 MEM_COMMIT | MEM_RESERVE, 104 PAGE_EXECUTE_READWRITE 105 ); 106 107 if (__DllFullPathBufferData == NULL) 108 { 109 CloseHandle(ProcessHandle); 110 ProcessHandle = NULL; 111 return FALSE; 112 } 113 114 IsOk = WriteProcessMemory( 115 ProcessHandle, 116 __DllFullPathBufferData, 117 __DllFullPath, 118 DllFullPathLength * 2, 119 &ReturnLength 120 ); 121 122 if (IsOk == FALSE) 123 { 124 125 VirtualFree(__DllFullPathBufferData, 126 DllFullPathLength * 2, MEM_RELEASE); 127 128 CloseHandle(ProcessHandle); 129 ProcessHandle = NULL; 130 return FALSE; 131 } 132 } 133 134 __LoadLibraryWAddress = 135 (UINT_PTR)GetProcAddress( 136 GetModuleHandle(L"Kernel32.dll"), 137 "LoadLibraryW" 138 ); 139 140 if (__LoadLibraryWAddress == NULL) 141 { 142 VirtualFree( 143 __DllFullPathBufferData, 144 DllFullPathLength * 2, MEM_RELEASE); 145 CloseHandle(ProcessHandle); 146 ProcessHandle = NULL; 147 return FALSE; 148 } 149 150 __try 151 { 152 ThreadHandle = OpenThread(THREAD_ALL_ACCESS, FALSE, ThreadID); 153 DWORD v1 = QueueUserAPC( 154 (PAPCFUNC)__LoadLibraryWAddress, 155 ThreadHandle, 156 (UINT_PTR)__DllFullPathBufferData 157 ); //LoadLibraryWAddress("DllFullPathBufferData") 158 if (v1 == 0) 159 { 160 printf("FAIL %d\r\n", GetLastError()); 161 } 162 else if (v1 != 0) 163 { 164 printf("Success\r\n"); 165 } 166 } 167 168 __except (EXCEPTION_CONTINUE_EXECUTION) 169 { 170 171 } 172 173 CloseHandle(ProcessHandle); 174 CloseHandle(ThreadHandle); 175 176 177 178 179 return TRUE; 180 } 181 182 183 BOOL GetThreadIDByProcessID(IN UINT32 ProcessID, OUT vector<UINT32>& ThreadIDVector) 184 { 185 HANDLE ThreadSnapshotHandle = NULL; 186 THREADENTRY32 ThreadEntry32 = { 0 }; 187 188 ThreadEntry32.dwSize = sizeof(THREADENTRY32); 189 190 ThreadSnapshotHandle = CreateToolhelp32Snapshot( 191 TH32CS_SNAPTHREAD, 0); 192 if (ThreadSnapshotHandle == INVALID_HANDLE_VALUE) 193 { 194 return FALSE; 195 } 196 197 BOOL IsOk = Thread32First( 198 ThreadSnapshotHandle, &ThreadEntry32); 199 200 if (IsOk) 201 { 202 do 203 { 204 if ( 205 ThreadEntry32.th32OwnerProcessID 206 == ProcessID) 207 { 208 ThreadIDVector.emplace_back( 209 ThreadEntry32.th32ThreadID); // 把该进程的所有线程id压入模板 210 } 211 } while (Thread32Next( 212 ThreadSnapshotHandle, &ThreadEntry32) 213 ); 214 215 } 216 217 218 219 220 221 CloseHandle(ThreadSnapshotHandle); 222 ThreadSnapshotHandle = NULL; 223 224 225 return TRUE; 226 } 227 228 BOOL GetProcessIDByProcessImageName(IN PWCHAR ProcessImageName, OUT PUINT32 ProcessID) 229 { 230 HANDLE ProcessSnapshotHandle = NULL; 231 ProcessSnapshotHandle = 232 CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 233 234 if (ProcessSnapshotHandle == INVALID_HANDLE_VALUE) 235 { 236 return FALSE; 237 } 238 239 PROCESSENTRY32 ProcessEntry32 = { 0 }; 240 ProcessEntry32.dwSize = sizeof(PROCESSENTRY32); 241 242 BOOL IsOk = Process32First( 243 ProcessSnapshotHandle, 244 &ProcessEntry32 245 ); 246 247 if (IsOk) 248 { 249 do 250 { 251 if ( 252 lstrcmpi(ProcessEntry32.szExeFile, 253 ProcessImageName)==0 254 ) 255 { 256 *ProcessID = ProcessEntry32.th32ProcessID; 257 break; 258 } 259 } while (Process32Next( 260 ProcessSnapshotHandle, 261 &ProcessEntry32 262 ) 263 ); 264 } 265 266 if (*ProcessID==0) 267 { 268 printf("Get ProcessID FAIL! 请打开任务管理器.\r\n"); 269 return FALSE; 270 } 271 272 CloseHandle(ProcessSnapshotHandle); 273 ProcessSnapshotHandle = NULL; 274 275 276 277 return TRUE; 278 } 279 280 281 282 283 284 285 286 287 BOOL DebugPrivilege(WCHAR * DebugName, BOOL bEnable) 288 { 289 BOOL bRet = TRUE; 290 HANDLE TokenHandle; 291 TOKEN_PRIVILEGES TokenPrivileges; 292 293 //进程 Token 令牌 294 if (!OpenProcessToken(GetCurrentProcess(), 295 TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &TokenHandle)) 296 { 297 bRet = FALSE; 298 return bRet; 299 } 300 TokenPrivileges.PrivilegeCount = 1; 301 TokenPrivileges.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0; 302 303 LookupPrivilegeValue(NULL, DebugName, &TokenPrivileges.Privileges[0].Luid); 304 AdjustTokenPrivileges(TokenHandle, FALSE, &TokenPrivileges, sizeof(TOKEN_PRIVILEGES), NULL, NULL); 305 if (GetLastError() != ERROR_SUCCESS) 306 { 307 bRet = FALSE; 308 } 309 310 CloseHandle(TokenHandle); 311 return bRet; 312 313 }

     

    转载于:https://www.cnblogs.com/1228073191Blog/p/7401153.html

    展开全文
  • 传统的远程进程控制方式有利用HOOK技术...远线程win9x所支持,而hook技术会对目标进程性能造成一定的影响.并具可以通过枚举消息链的方式发现.  本文给出一种动态修改目标进程代码,注入DLL到目标进程的方法,效率

    原文地址:http://www.cnblogs.com/showna/articles/691763.html

    传统的远程进程控制方式有利用HOOK技术注入DLL,和利用远线程在目标进程中建立新的执行线程的方式. 
    远线程不被win9x所支持,而hook技术会对目标进程性能造成一定的影响.并具可以通过枚举消息链的方式发现. 
    本文给出一种动态修改目标进程代码,注入DLL到目标进程的方法,效率高,不需要额外线程.缺点是使用难度大于上面二种办法,并且修改目标代码的方法,受到编译器的影响.使用不同的编译器时,需要根据编译器调整动态代码修改方式. 

    动态修改目标进程代码,使其加载自已的DLL的思路如下: 
    1. 得到目标进程句柄. 
    2. 在目标进程中分配一块可执行可读写的内存. 
    3. 写入加载DLL的代码到分配出来的内存中. 
    4. 修正动态写入的代码中的地址(LoadLibrary地址,DLL名字地址). 
    5. 修改目标进程本身的代码,使其执行到被修改代码时,跳到加载DLL的代码处. 
    6. 加载完DLL后,修正目标进程原来的代码,并跳回去继续执行. 
    这个过程中需要注意的地方是. 对寄存器的保护,堆栈的平衡. 

    其中第5步需要修改一块目标进程一定会执行的代码,消息循环是个不错的地方.这里以记事本为例. 
    打开ollydbg,在TranslateMessage函数下断点,中断后如下: 
    010029FC |. /75 14 |jnz short notepad.01002A12 
    010029FE |. |8D45 E0 |lea eax,dword ptr ss:[ebp-20] 
    01002A01 |. |50 |push eax ; /pMsg 
    01002A02 |. |FF15 98120001 |call dword ptr ds:[<&USER32.Translat>; \TranslateMessage 
    01002A08 |. |8D45 E0 |lea eax,dword ptr ss:[ebp-20] 
    01002A0B |. |50 |push eax ; /pMsg 
    01002A0C |. |FF15 94120001 |call dword ptr ds:[<&USER32.Dispatch>; \DispatchMessageW 
    01002A12 |> \56 push esi 
    01002A13 |. 56 |push esi 
    01002A14 |. 8D45 E0 |lea eax,dword ptr ss:[ebp-20] 
    01002A17 |. 56 |push esi 
    01002A18 |. 50 |push eax 
    01002A19 |. FFD7 |call edi 

    0x01002A02处是个不错的地方,可以动态修改它. 改成 
    mov eax, 加载dll的代码地址 
    jmp eax 
    需要注意的是,此程序基址在不同的系统上有可能不一样,可以从PE头中得到映像基址.所以此处的0x1002A02也许在你的机器上是另一个地址,请使用OD自行确定.(我是winxp sp2) 

    找到修改点后,然后就是分配可执行可读写内存,写入下面一段代码进去 
    pusha 
    //eax中是LoadLibrary函数地址,暂时为0xffffffff 
    //由程序动态改成真实函数地址 
    mov eax, 0xffffffff 
    //要加载的DLL的名字地址,暂时为0xffffffff 
    //由程序动态改成真实地址 
    mov ebx, 0xffffffff 
    push ebx 
    //调用LoadLibrary,加载自已的DLL 
    //这样DLL就注入到目标进程了 
    call eax 
    popa 
    //恢复 0x1002A02处的代码,并跳回去执行 
    //选执eax寄存器是因为0x1002A02后面的代码没有直接使用到eax 
    mov eax, CODE_OFFSET 
    mov dword ptr [eax], 0x129815FF 
    mov dword ptr [eax+4], 0x458D0100 
    jmp eax 
    下面的代码是在加载DLL后,修正目标进程原有的代码 
    mov eax, CODE_OFFSET 
    mov dword ptr [eax], 0x129815FF 
    mov dword ptr [eax+4], 0x458D0100 

    0x129815FF 0x458D0100 即为原有代码(字节顺序是倒过来的, 0x129815FF 倒过来即是 FF159812, 0x458D0100倒过来即是00018D45,请注意和下面代码对比 
    01002A02 |. |FF15 98120001 |call dword ptr ds:[<&USER32.Translat>; \TranslateMessage 
    01002A08 |. |8D45 E0 |lea eax,dword ptr ss:[ebp-20] 


    其它基本上就是编码了,例子如下,测试时,请自行编写一个 Test.dll ,放在记事本同一个目录下,不同的编译器,不同的系统请自行修正一些细节:(我是使用的Release模式,Debug模式代码会不同的) 

    #i nclude 
    #i nclude 
    #i nclude 

    using std::cout; 
    using std::cin; 
    using std::endl; 

    //记事本的映象基址,不同的系统可能不一样 
    //这个值可以从PE头中读取 
    #define NOTEPAD_IMAGE_BASE 0x1000000; 
    #define CODE_OFFSET 0x1002A02; 
    //用来测试的DLL名 
    const char *dllname = "Test.dll"; 

    void loaddll() 

    __asm 

    pusha 
    //eax中是LoadLibrary函数地址,暂时为0xffffffff 
    //由程序动态改成真实函数地址 
    mov eax, 0xffffffff 
    //要加载的DLL的名字地址,暂时为0xffffffff 
    //由程序动态改成真实地址 
    mov ebx, 0xffffffff 
    push ebx 
    //调用LoadLibrary,加载自已的DLL 
    //这样DLL就注入到目标进程了 
    call eax 
    popa 
    //恢复 0x1002A02处的代码,并跳回去执行 
    //选执eax寄存器是因为0x1002A02后面的代码没有直接使用到eax 
    mov eax, CODE_OFFSET 
    mov dword ptr [eax], 0x129815FF 
    mov dword ptr [eax+4], 0x458D0100 
    jmp eax 



    #pragma pack(push) //保存对齐状态 
    #pragma pack(1) //设定为1字节对齐 
    struct JmpCode 

    byte op; 
    char* address; 
    WORD jmp; 
    }; 
    #pragma pack(pop) 

    int main() 

    //找记事本主窗口句柄 
    HWND wnd = FindWindow(NULL, "无标题 - 记事本"); 
    if (!IsWindow(wnd)) 

    cout << "记事窗口没找到" << std::endl; 
    return 1; 

    //读取进程ID,和进程句柄 
    DWORD pid; 
    HANDLE ph; 
    GetWindowThreadProcessId(wnd, &pid); 
    ph = OpenProcess(PROCESS_ALL_ACCESS, false, pid); 

    //在记事本进程中分配一页可读写可执行的虚拟内存 
    void *address = VirtualAllocEx(ph, NULL, 4096, MEM_COMMIT, PAGE_EXECUTE_READWRITE); 
    //写代码的地址(写在字符串后面) 
    char *code = (char*)address + strlen(dllname) + 1; 
    if (NULL == address) 

    cout << "分配远端内存失败" << std::endl; 
    return 1; 

    DWORD ws; 
    //把代码写到内存页中 
    WriteProcessMemory(ph, code, &loaddll, 4000, &ws); 
    //把DLL名写到内存页中 
    WriteProcessMemory(ph, address, dllname, strlen(dllname), &ws); 
    //把loadlibrary的地址写到eax 0xfffffff处,把0xffffffff替换为真正的地址 
    //code+9为eax 0xffffffff中0xffffffff处的偏移,通过反汇编工具查看+ 9是为了跳过 
    //编译器给loadll函数生成的框架 
    HMODULE module = LoadLibrary("kernel32.dll"); 
    FARPROC pro = GetProcAddress(module, "LoadLibraryA"); 
    WriteProcessMemory(ph, code + 9, &pro, 4, &ws); 
    //把dllname的地址写到ebx 0xffffffff处,把dllname作为参数 
    WriteProcessMemory(ph, code + 14, &address, 4, &ws); 
    //修改记事本消息循环处的代码. 
    JmpCode jmp; 
    jmp.op = 0xB8; 
    jmp.address = code + 6; //这段代码是 mov eax, 地址 
    jmp.jmp = 0xE0FF; //jmp eax 
    address = (void*)CODE_OFFSET; 
    //让代码段可读写 
    VirtualProtectEx(ph, address, 4096, PAGE_EXECUTE_READWRITE, &ws); 
    //改写目标处的代码,让其跳到自已的代码处执行 
    WriteProcessMemory(ph, address, &jmp, 8, &ws); 
    return 0; 


    运行,测试,OK! Test.dll被正确加载,目标进程现在是你的了,随便玩吧.

    展开全文
  • 线程win9x所支持,而hook技术会对目标进程性能造成一定的影响.并具可以通过枚举消息链的方式发现. 本文给出一种动态修改目标进程代码,注入DLL到目标进程的方法,效率高,不需要额外线程.缺点是使用难度大于上面...
     
    

    传统的远程进程控制方式有利用HOOK技术注入DLL,和利用远线程在目标进程中建立新的执行线程的方式.
    远线程不被win9x所支持,而hook技术会对目标进程性能造成一定的影响.并具可以通过枚举消息链的方式发现.
    本文给出一种动态修改目标进程代码,注入DLL到目标进程的方法,效率高,不需要额外线程.缺点是使用难度大于上面二种办法,并且修改目标代码的方法,受到编译器的影响.使用不同的编译器时,需要根据编译器调整动态代码修改方式.

    动态修改目标进程代码,使其加载自已的DLL的思路如下:
    1. 得到目标进程句柄.
    2. 在目标进程中分配一块可执行可读写的内存.
    3. 写入加载DLL的代码到分配出来的内存中.
    4. 修正动态写入的代码中的地址(LoadLibrary地址,DLL名字地址).
    5. 修改目标进程本身的代码,使其执行到被修改代码时,跳到加载DLL的代码处.
    6. 加载完DLL后,修正目标进程原来的代码,并跳回去继续执行.
    这个过程中需要注意的地方是. 对寄存器的保护,堆栈的平衡.

    其中第5步需要修改一块目标进程一定会执行的代码,消息循环是个不错的地方.这里以记事本为例.
    打开ollydbg,在TranslateMessage函数下断点,中断后如下:
    010029FC   |. /75 14              |jnz short notepad.01002A12
    010029FE   |. |8D45 E0            |lea eax,dword ptr ss:[ebp-20]
    01002A01   |. |50                 |push eax                             ; /pMsg
    01002A02   |. |FF15 98120001      |call dword ptr ds:[<&USER32.Translat>; /TranslateMessage
    01002A08   |. |8D45 E0            |lea eax,dword ptr ss:[ebp-20]
    01002A0B   |. |50                 |push eax                             ; /pMsg
    01002A0C   |. |FF15 94120001      |call dword ptr ds:[<&USER32.Dispatch>; /DispatchMessageW
    01002A12   |> /56                  push esi
    01002A13   |.  56                 |push esi
    01002A14   |.  8D45 E0            |lea eax,dword ptr ss:[ebp-20]
    01002A17   |.  56                 |push esi
    01002A18   |.  50                 |push eax
    01002A19   |.  FFD7               |call edi

    0x01002A02处是个不错的地方,可以动态修改它. 改成
    mov eax, 加载dll的代码地址
    jmp eax
    需要注意的是,此程序基址在不同的系统上有可能不一样,可以从PE头中得到映像基址.所以此处的0x1002A02也许在你的机器上是另一个地址,请使用OD自行确定.(我是winxp sp2)

    找到修改点后,然后就是分配可执行可读写内存,写入下面一段代码进去
        pusha
        //eax中是LoadLibrary函数地址,暂时为0xffffffff
        //由程序动态改成真实函数地址
        mov eax, 0xffffffff
        //要加载的DLL的名字地址,暂时为0xffffffff
        //由程序动态改成真实地址
        mov ebx, 0xffffffff
        push ebx
        //调用LoadLibrary,加载自已的DLL
        //这样DLL就注入到目标进程了
        call eax           
        popa
        //恢复 0x1002A02处的代码,并跳回去执行
        //选执eax寄存器是因为0x1002A02后面的代码没有直接使用到eax
        mov eax, CODE_OFFSET
        mov dword ptr [eax], 0x129815FF
        mov dword ptr [eax+4], 0x458D0100  
        jmp eax
    下面的代码是在加载DLL后,修正目标进程原有的代码
        mov eax, CODE_OFFSET
        mov dword ptr [eax], 0x129815FF
        mov dword ptr [eax+4], 0x458D0100 

    0x129815FF 0x458D0100 即为原有代码(字节顺序是倒过来的, 0x129815FF 倒过来即是 FF159812, 0x458D0100倒过来即是00018D45,请注意和下面代码对比
    01002A02   |. |FF15 98120001      |call dword ptr ds:[<&USER32.Translat>; /TranslateMessage
    01002A08   |. |8D45 E0            |lea eax,dword ptr ss:[ebp-20]


    其它基本上就是编码了,例子如下,测试时,请自行编写一个 Test.dll ,放在记事本同一个目录下,不同的编译器,不同的系统请自行修正一些细节:(我是使用的Release模式,Debug模式代码会不同的)

    #include <iostream>
    #include <windows.h>
    #include <psapi.h>

    using std::cout;
    using std::cin;
    using std::endl;

    //记事本的映象基址,不同的系统可能不一样
    //这个值可以从PE头中读取
    #define NOTEPAD_IMAGE_BASE     0x1000000;
    #define CODE_OFFSET         0x1002A02;
    //用来测试的DLL名
    const char *dllname = "Test.dll";

    void loaddll()
    {
        __asm
        {
            pusha
            //eax中是LoadLibrary函数地址,暂时为0xffffffff
            //由程序动态改成真实函数地址
            mov eax, 0xffffffff
            //要加载的DLL的名字地址,暂时为0xffffffff
            //由程序动态改成真实地址
            mov ebx, 0xffffffff
            push ebx
            //调用LoadLibrary,加载自已的DLL
            //这样DLL就注入到目标进程了
            call eax           
            popa
            //恢复 0x1002A02处的代码,并跳回去执行
            //选执eax寄存器是因为0x1002A02后面的代码没有直接使用到eax
            mov eax, CODE_OFFSET
            mov dword ptr [eax], 0x129815FF
            mov dword ptr [eax+4], 0x458D0100  
            jmp eax
        }
    }

    #pragma pack(push) //保存对齐状态
    #pragma pack(1)    //设定为1字节对齐
    struct JmpCode
    {
        byte op;
        char* address;
        WORD jmp;
    };
    #pragma pack(pop)

    int main()
    {
        //找记事本主窗口句柄
        HWND wnd = FindWindow(NULL, "无标题 - 记事本");
        if (!IsWindow(wnd))
        {
            cout << "记事窗口没找到" << std::endl;
            return 1;
        }
        //读取进程ID,和进程句柄
        DWORD pid;
        HANDLE ph;
        GetWindowThreadProcessId(wnd, &pid);
        ph = OpenProcess(PROCESS_ALL_ACCESS, false, pid);

        //在记事本进程中分配一页可读写可执行的虚拟内存
        void *address = VirtualAllocEx(ph, NULL, 4096, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
        //写代码的地址(写在字符串后面)
        char *code = (char*)address + strlen(dllname) + 1;
        if (NULL == address)
        {
            cout << "分配远端内存失败" << std::endl;
            return 1;
        }
        DWORD ws;
        //把代码写到内存页中
        WriteProcessMemory(ph, code, &loaddll, 4000, &ws);
        //把DLL名写到内存页中
        WriteProcessMemory(ph, address, dllname, strlen(dllname), &ws);
        //把loadlibrary的地址写到eax 0xfffffff处,把0xffffffff替换为真正的地址
        //code+9为eax 0xffffffff中0xffffffff处的偏移,通过反汇编工具查看+ 9是为了跳过
        //编译器给loadll函数生成的框架
        HMODULE module = LoadLibrary("kernel32.dll");
        FARPROC pro = GetProcAddress(module, "LoadLibraryA");
        WriteProcessMemory(ph, code + 9, &pro, 4, &ws);
        //把dllname的地址写到ebx 0xffffffff处,把dllname作为参数
        WriteProcessMemory(ph, code + 14, &address, 4, &ws);
        //修改记事本消息循环处的代码.
        JmpCode jmp;
        jmp.op = 0xB8;
        jmp.address = code + 6;                //这段代码是 mov eax, 地址
        jmp.jmp = 0xE0FF;                    //jmp eax
        address = (void*)CODE_OFFSET;
        //让代码段可读写
        VirtualProtectEx(ph, address, 4096, PAGE_EXECUTE_READWRITE, &ws);
        //改写目标处的代码,让其跳到自已的代码处执行
        WriteProcessMemory(ph, address, &jmp, 8, &ws);
        return 0;
    }

    运行,测试,OK! Test.dll被正确加载,目标进程现在是你的了,随便玩吧.

    展开全文
  • (声明:魏滔序原创,转贴请注明出处。) Viking的肆虐让很多受害者忍无可忍,更可气的是专业软件公司提供的专杀... 还有,对于被注入了病毒dll的进程,要先枚举进程中的模块并判断。然后决定是否Kill,Kill方法同上。
  • 找到OD相关句柄返回真, 此函数枚举窗口通过菜单名来 判定是否OD窗口。 .子程序 AntiStrongOD, 逻辑型, 公开, 这个效果还行,检测带有驱动的 OD调试器 此函数专门对付 StrongOD 插件 .参数 判断OD运行状态, 逻辑型, ...
  • 遍历ThreadList来枚举线程 线程的暂停和唤醒都是通过反汇编获取PsResumeThread和PsSuspendThread直接从r3传来ETHREAD来操作的,通过插入APC来结束线程 六:shadow sdt表的hook检测与恢复 没有采用pdb来解决函数名...
  • 模块隐藏(滴水)

    2020-04-02 22:51:27
    dll注入进程是很难存活的,因为被注入的进程很容易检测到有一个DLL不是自己加载的,是别人加载的。所以我们需要将DLL隐藏起来 我们学习过API,可以枚举进程模块,那么这些API是怎么把模块查出来的呢 进程在0环有个...
  • (5)多线程文件扫描(16线程) (6)进程自我保护(改变进程对象类型), (7)加入了PE模块,能提取所有PE信息 (8)加入了主动防御(防御黑名单进程,注册表注入) (9)内核重载 (10)U盘查杀自启动文件 //...
  • WTool2.6.zip

    2020-05-05 10:33:09
    1.枚举了系统中自动启动了的驱动线程,可以对内核线程进行(暂停、恢复); [启动项] 1.枚举系统中所有开机启动项; [网络连接] 1.显示系统中所有程序中连接网络情况,可以对程序禁止连接网络; [注册表] 1.如果您...
  • 1.枚举了系统中自动启动了的驱动线程,可以对内核线程进行(暂停、恢复); [启动项] 1.枚举系统中所有开机启动项; [网络连接] 1.显示系统中所有程序中连接网络情况,可以对程序禁止连接网络; [注册表] 1....
  •  3.2.1 线程枚举  3.2.2功能整合  3.3 实现调试事件处理例程  3.4 无所不能的断点  3.4.1 软断点  3.4.2 硬件断点  3.4.3 内存断点  3.5 总结  第4章 PyDbg——WindoWS下的纯Python调试器  4.1 扩展断点...
  • 11.5 捆绑文件分离后的运行及自分解文件原理 256 11.5.1 异步执行分解法的实现 256 11.5.2 同步执行分解法的实现 256 11.5.3 自动分解法的实现 257 11.6 一个捆绑机(BindHider)软件的设计 258 11.6.1 ...
  • 11.5 捆绑文件分离后的运行及 自分解文件原理 256 11.5.1 异步执行分解法 的实现 256 11.5.2 同步执行分解法 的实现 256 11.5.3 自动分解法的实现 257 11.6 一个捆绑机(BindHider)软件 的设计 258 11.6.1 ...
  • 等等 还是还原不了SSDT,哎,菜鸟啊 Version 1.1.31:3月2日,加入线程枚举,显示模块数、检测更新、在线提问。+小改动,同时结束多个进程 Version 1.2.38:3月9日,放弃DLL注入结束进程,改用代码注入。另...
  • 3.2.1 线程枚举 3.2.2 功能整合 3.3 实现调试事件处理例程 3.4 无所不能的断点 3.4.1 软断点 3.4.2 硬件断点 3.4.3 内存断点 3.5 总结 第4章 PyDbg——Windows下的纯Python调试器 4.1 扩展断点处理例程 4.2 非法内存...
  • 加强了防止注入的逻辑 3. 加强了进程粉碎的逻辑 4. 修改了进程路经过长无法显示的bug 2010-11-03 PowerTool V3.0 增加: 1. 新增通过磁盘解析取得和拷贝ADS流文件 2. 新增动态切换多国语言界面(考虑到文件大小...
  • ButterKnife 是怎样实现代码注入的 ButterKnife是如何在编译时生成代码的? Dagger 2 预备知识 @Inject @Module @Singleton @Providers @Component @Scope @Qualifier dependencies @SubComponent 简单...
  • 用友GRP-u8 注入+天融信TopApp-LB 负载均衡系统sql注入|绿盟UTS综合威胁探针管理员任意登录复现|HW弹药库之深信服EDR 3.2.21 任意代码执行漏洞分析 CVE-2020-13935-Tomcat的WebSocket安全漏洞可导致拒绝服务攻击 ...
  • C#全能速查宝典

    热门讨论 2014-04-26 16:16:27
    1.3.6 foreach语句——枚举一个集合的元素 33 1.3.7 goto语句——跳转到标签 34 1.3.8 if…else语句——条件判断语句 36 1.3.9 return语句——返回 38 1.3.10 switch case语句——条件判断语句 39 1.3.11 throw语句...
  • 在 Chaos 测试上面,TiDB 引入了更多的错误注入工具,例如使用 systemtap 对 I/O 进行 delay 等,也在代码特定的业务的逻辑进行错误注入测试,充分保证 TiDB 在异常条件下面也能稳定运行。 TiDB 的开发团队之前做了...
  • 易语言540个易模块

    2009-05-02 14:48:40
    超级列表框选择框状态改变 超级列表框选中项存为Excel文件 超级信息框 程序是否运行 传世注册 窗口动画效果模块 V1.0 窗口句柄&进程名互取 窗口-控件锚点 窗口热键 窗口贴边隐藏模块 窗口外形任我设 窗口整容...
  • DLL注入模块.ec DOS命令模块.ec dqf1996.ec EC.EC edb-html.ec EdbServer1.0 客户端.ec EDB、高级表格、XLS互换.ec edb到html-1.0.ec EDB数据库客户端模块 1.0.ec edb 数据库转Excel模块 1.0.ec edb数据库转Excel...
  • 超级列表框选择框状态改变.ec 超级列表框选中项存为Excel文件.ec 超级信息框.ec 程序是否运行.EC 传世注册.ec 窗口动画效果模块 V1.0.ec 窗口句柄&进程名互取.ec 窗口-控件锚点.ec 窗口贴边隐藏模块.ec ...
  • 790个易模块-3

    2013-01-24 23:08:14
    超级列表框选择框状态改变.ec 超级列表框选中项存为Excel文件.ec 超级信息框.ec 程序是否运行.EC 传世注册.ec 窗口动画效果模块 V1.0.ec 窗口句柄&进程名互取.ec 窗口-控件锚点.ec 窗口贴边隐藏模块.ec ...

空空如也

空空如也

1 2 3
收藏数 47
精华内容 18
关键字:

枚举线程被注入