现在的位置: 首页 > 综合 > 正文

DLL注入2

2018年04月06日 ⁄ 综合 ⁄ 共 7253字 ⁄ 字号 评论关闭

一天学硬件,一天学软件。哈~正所谓【软硬兼施】啊。今天轮到学软件了,由于之前对DLL木马有一些研究,大部分木马都是通过远程线程注入的方式实现无进程执行。早就想学 这种技术了,无奈当时自身的编程技术还不到那个境界,现在试试。。。
         花了一下午的时间, 查询相关资料,看视频教程,大概给弄懂怎么回事了。就是将木马的实现功能全部写在一个DLL中(DLL 也是可执行文件,但是不可以直接执行,需要EXE调用),然后找个目标进程(一般是IE进程,突破防火墙~),将自身路径写入到该进程空间内,然后在该进程中寻找LoadLibraryA()这个加载DLL 的函数地址,通过远程线程函数使该进程执行LoadLibraryA()这个加载函数,加载DLL。
直白点,就是先将DLL的路径写入到目标进程空间内,然后在目标进程空间内寻找 LoadLibraryA()这个函数的地址,再利用LoadLibraryA()这个函数调用木马的DLL。相当于执行了木马...然后木马就可以随意的xxoxoxox你的电脑了~

远程线程注入的细分过程 共可分5 步:
    1、通过进程PID 打开目标进程获得目标进程句柄。(为了能操作该进程就要获得它的句柄)
         利用到的API: HANDLE OpenProcess( DWORD dwDesiredAccess,BOOL bInheritHandle, DWORD dwProcessId);

          功能:OpenProcess 函数用来打开一个已存在的进程对象,并返回进程的句柄。   
          函数原型:
                   HANDLE OpenProcess(   DWORD dwDesiredAccess,     //权限 
                                                                   BOOL bInheritHandle,             // 是否继承句柄   
                                                                        DWORD dwProcessId           // 目标进程的PID标识符 
                                                          );   
            返回值:   如成功,返回值为指定进程的句柄。   如失败,返回值为空,可调用GetLastError获得错误代码。

    2、根据上面提供的目标进程句柄在其申请一块内存空间。(用于存放DLL的完整路径)
        利用到的API:LPVOID VirtualAllocEx(HANDLE hProcess,LPVOID lpAddress,SIZE_T dwSize,DWORD flAllocationType,  DWORD flProtect )
        功能:VirtualAllocEx 函数的作用是在指定进程的虚拟空间保留或提交内存区域,除非指定MEM_RESET参数,否则将该内存区域置0。
  函数原形:
  LPVOID VirtualAllocEx(
                                          HANDLE hProcess,                   // 进程句柄

                                          LPVOID lpAddress,                   // 获取内存空间的区域

                                          SIZE_T dwSize,                         // 要获取空间的大小

                                          DWORD flAllocationType,         // 内存分配的类型
                                          DWORD flProtect                      // 内存页保护
                                      );
        返回值:执行成功就返回分配内存的首地址,不成功就是NULL。

    3、将DLL的路径写入到目标进程内申请的内存空间。(因为进程间是有边界的,不能互相访问彼此的内存空间)
        利用到的API:BOOL WriteProcessMemory( HANDLE hProcess, LPVOID lpBaseAddress, LPVOID lpBuffer,  DWORD nSize, LPDWORD lpNumberOfBytesWritten );

        功能: 此函数能写入某一进程的内存区域(直接写入会出Access Violation错误,故需此函数)。
        函数原形:
                 BOOL WriteProcessMemory(
                                                              HANDLE hProcess,                                // 进程句柄

                                                              LPVOID lpBaseAddress,                        // 内存空间分配的首地址

                                                              LPVOID lpBuffer,                                    // 写入的内容

                                                              DWORD nSize,                                       // 写入的内容大小

                                                              LPDWORD lpNumberOfBytesWritten      // 不知道干嘛用 ...

                                                        );

        返回值:非零值代表成功。

    4、在目标进程中寻找LoadLibraryA()这个函数的函数地址。(找到函数地址才能调用它)
         利用到的API:  FARPROC GetProcAddress( HMODULE hModule, LPCSTR lpProcName );

                                    HMODULE GetModuleHandle ( LPCTSTR lpModuleName );  
         功能:GetProcAddress函数检索指定的动态链接库(DLL)中的输出库函数地址。
        函数原型:
                      FARPROC GetProcAddress(
                                                                      HMODULE hModule, // DLL模块句柄

                                                                      LPCSTR lpProcName // 函数名

                                                                  );            
        返回值:
               如果函数调用成功,返回值是DLL中的输出函数地址。
               如果函数调用失败,返回值是NULL。得到进一步的错误信息,调用函数GetLastError。

        说明:GetModuleHandle 获取一个应用程序或动态链接库的模块句柄
        参数:lpModuleName 模块名称   如果参数是NULL 则获取自身句柄
        返回值:如执行成功成功,则返回模块句柄。零表示失败。通过GetLastError获得错误信息

    5、创建远程线程,根据上面找到LoadLibraryA()的函数地址,调用该函数,LoadLibraryA()函数的参数就是目标进程中的DLL路径 (这时就是执行我们的DLL 了)
         利用到的API:HANDLE WINAPI CreateRemoteThread( __in HANDLE hProcess, __in LPSECURITY_ATTRIBUTES lpThreadAttributes, __in SIZE_T dwStackSize, __in LPTHREAD_START_ROUTINE lpStartAddress, __in LPVOID lpParameter, __in
DWORD dwCreationFlags, __out LPDWORD lpThreadId );
          功能:创建一个在其它进程地址空间中运行的线程(也称:创建远程线程).
          函数原型:
                        HANDLE WINAPI CreateRemoteThread(
                                                1                                        __in HANDLE hProcess,    // 目标进程句柄
                                                                                          __in LPSECURITY_ATTRIBUTES lpThreadAttributes,  // 线程安全属性
                                                                                          __in SIZE_T dwStackSize,  // 线程栈初始大小
                                                                                          __in LPTHREAD_START_ROUTINE lpStartAddress,  // 线程函数
                                                                                          __in LPVOID lpParameter,  // 线程参数
                                                                                          __in DWORD dwCreationFlags,  // 创建的标志 (立即执行、挂起等)
                                                                                          __out LPDWORD lpThreadId  // 线程句柄
                                                                                    );
          返回值:  如果调用成功,返回新线程句柄.
                          如果失败,返回NULL.
  
具体实现代码:(EXE)
======================================================================================================
#include <windows.h>
#include <stdio.h>
BOOL InjectDll(char *DllPath, DWORD dwProcessID)
{
if ( (DllPath == NULL) && (dwProcessID < 0))
  return FALSE;
// 1、打开目标进程获得目标进程句柄 // 权限 ,句柄继续承,加成PID
HANDLE hRemoteProcess = OpenProcess(PROCESS_ALL_ACCESS,0,dwProcessID);
if (hRemoteProcess == NULL)
  return FALSE;

// 2、通过目标进程句柄在其申请一块内存空间  // 进程句柄,获取内存地址区域,分配的内存大小,内存分配的类型,内存页保护
LPVOID RemoteProcessSize = VirtualAllocEx(hRemoteProcess,NULL,strlen(DllPath)+1,MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);
if (RemoteProcessSize == NULL)
  return FALSE;
// 3、将DLL的路径写入到目标进程内申请的内存空间
        // 进程句柄,要写入的内存首地址,写入的内容,内容的大小,未知
BOOL bRet = WriteProcessMemory(hRemoteProcess,RemoteProcessSize,DllPath,strlen(DllPath)+1,0);
if(!bRet)
  return FALSE;
// 4、将函数LoadLibraryA的入口地址作为我们的远程线程的入口地址
// 当远程线程启动时,就会调用LoadLibraryA 装载我们的DLL // 模块句柄  /*获取模块句柄(模块名)*/ ,函数名
PTHREAD_START_ROUTINE ScanLoad = (PTHREAD_START_ROUTINE) GetProcAddress(GetModuleHandle("Kernel32.DLL"),"LoadLibraryA");
if (ScanLoad == NULL)
  return FALSE;
/*   哈前天才刚从小凡那挖过来的知识点 没想到现在就用上了。再次感谢我家滴小凡!o(∩_∩)o 哈哈  PTHREAD_START_ROUTINE 这个其实是函数型指针,原型typedef DWORD (WINAPI *PTHREAD_START_ROUTINE)(LPVOID lpThreadParameter);  用来指向LoadLibraryA 函数  */  

// 5、创建远程线程执行DLL  这里其实就是用LoadLibraryA 加载我们的DLL
HANDLE hRemoteThread = NULL;
     //   目标进程句柄,线程安全属性,线程初始大小,线程函数(目标中的LoadLibraryA),函数参数(就是目标进程中的DLL路径),标志,线程句柄
hRemoteThread = CreateRemoteThread(hRemoteProcess,NULL,0,ScanLoad,RemoteProcessSize,0,0);
if(hRemoteThread == NULL)
  return FALSE;
return TRUE;
}

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
if (InjectDll("D:\\ssdddd.dll",1552))                                    // 传递DLL 完整路径和需要注入的目标进程的PID
  MessageBox(0,"注入成功!","",MB_SYSTEMMODAL);
else
  MessageBox(0,"注入失败!","",MB_SYSTEMMODAL);

}
========================================================================================================

这个是被调用的DLL:========================================================================================================
#include "windows.h"
BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD fdwReason, PVOID fImpLoad)   //  这是个回调函数 也是DLL 入口点
{

switch(fdwReason)
{
  case DLL_PROCESS_ATTACH: // 进程被调用
    MessageBox(NULL,"嘎嘎~DLL自身被调用~","进程被调用 ",MB_SYSTEMMODAL);
    break;
  case DLL_THREAD_ATTACH: // 线程被调用
    MessageBox(NULL,"嘎嘎~目标程序启动了一个线程~","线程被调用 ",MB_SYSTEMMODAL);
    break;
   
  case DLL_PROCESS_DETACH: // 进程退出
    MessageBox(NULL,"嘎嘎~目标进程退出~","进程退出",MB_SYSTEMMODAL);
    break;
   
  case DLL_THREAD_DETACH: // 线程退出
    MessageBox(NULL,"嘎嘎~目标线程退出~","线程退出",MB_SYSTEMMODAL);
    break;
}
return(TRUE);
}

========================================================================================================

       远程线程注入还有其他的方式,好像是将要实现的功能函数直接写入到目标进程内,在明白进程内执行该函数...不过原理应该都是一样滴,远程线程注入还有其他的用处,例如外挂啊、破解补丁啊、等等...
嗯,这就是今天理解到的东西,刚接触,可能有些地方理解错了,请大家不要见笑哈,欢迎批评指正~ 有兴趣的童鞋可以加我的QQ:1007566569 共同探讨      

等学会了远程线程注入,准备开始研究研究HOOK了,HOOK 更好玩~ 兴奋吖~~ 

抱歉!评论已关闭.