远程线程注入和卸载实现

简介: 远程线程
  1. 原理

主要通过API:CreateRemoteThread 来进行远程线程注入
2.远程线程注入Dll的步骤
1.通过进程Id打开指定的进程
2.在指定的进程,分配一段大小为要导入的dll文件名长度的一段内存空间,将dll的文件名写入到分配的内存中。
3.获取目的进程中的loadLibrary的函数地址。
4.创建远程线程,通过上一步获得的loadlibrary函数进行dll导入。
5.释放内存,卸载dll。
3.代码远程注入注意点
1.不能调用除kernel32和user32之外动态库中的api函数。
2.不能使用static字符串
3. 去掉编译器的/GZ编译选项。这个选项是默认的,不然注入进去被注入的程序会崩溃。
4. 要么把ThreadFunc和AfterThreadFunc声明为static,要么关闭编译器的“增量连接(incremental linking)”(看附录C)。
5. ThreadFunc中的局部变量总大小必须小于4k字节。注意,当degug编译时,这4k中大约有10个字节会被事先占用。
(注入64位的程序,那么也需要64位的dll,主要用的函数:NtCreateThreadEx)
4.代码实现
//提升权限

BOOL cRemoteThreadInject::grantPriviledge(char* priName)
{
    if(NULL == priName)
    {
        return FALSE;
    }

    TOKEN_PRIVILEGES tokenPriviledge, oldPriviledge;
    DWORD dwRetLength = sizeof(oldPriviledge);
    HANDLE tokenHandle = NULL;
    LUID uId;

    if (!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &tokenHandle))
    {
        if (ERROR_NO_TOKEN != GetLastError())
        {
            return FALSE;
        }

        if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &tokenHandle))
        {
            return FALSE;
        }
    }

    if (!LookupPrivilegeValue(NULL, priName, &uId))
    {
        CloseHandle(tokenHandle);
        tokenHandle = NULL;
        return FALSE;
    }

    tokenPriviledge.PrivilegeCount = 1;
    tokenPriviledge.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    tokenPriviledge.Privileges[0].Luid = uId;

    if (!AdjustTokenPrivileges(tokenHandle, FALSE, &tokenPriviledge, sizeof(TOKEN_PRIVILEGES), &oldPriviledge, &dwRetLength))
    {

        CloseHandle(tokenHandle);
        tokenHandle = NULL;
        return FALSE;
    }


    return TRUE;


}

/*
函数功能:通过进程名称获取进程PID
参数1:进程名称
参数2:返回的进程pid

*/

BOOL cRemoteThreadInject::GetProcessId(IN char* processName, OUT DWORD* processId)
{
    if(NULL == processName)
    {

        return FALSE;
    }
    
    HANDLE handle = NULL;
    PROCESSENTRY32 processTry32 ={0};
    
    processTry32.dwSize = sizeof(PROCESSENTRY32);
    handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

    if(INVALID_HANDLE_VALUE == handle)
    {
        return FALSE;
    }

    Process32First(handle, &processTry32);
    do{
        if(lstrcmpi(processTry32.szExeFile, processName) == 0)
        {
            *processId = processTry32.th32ProcessID;
            break;
        }

    }while(Process32Next(handle, &processTry32));

    CloseHandle(handle);
    handle = NULL;

    if(0 == *processId)
    {
        return FALSE;
    }


    return TRUE;

}

/*
功能:注入dll文件到进程
参数1:进程的名称
参数2:注入dll的路径
*/

BOOL cRemoteThreadInject::injectDll(char* processName, char* dllPath)
{
    if((NULL == processName)  || (NULL == dllPath))
    {
        return FALSE;
    }

    DWORD processId = 0;
    GetProcessId(processName, &processId);
    if(processId <= 0)
    {
        return FALSE;
    }

    grantPriviledge("SE_DEBUG_NAME");

    HANDLE handle = NULL;
    handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);
    if(NULL == handle)
    {
        return FALSE;
    }
    
    int dllPathLen = sizeof(dllPath) +1;
    PVOID data = VirtualAllocEx(handle, NULL, dllPathLen, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    if(NULL == data)
    {
        CloseHandle(handle);
        handle = NULL;
        return FALSE;
    }

    SIZE_T RetLength = 0;
    BOOL bWriteMem = WriteProcessMemory(handle, data, dllPath, strlen(dllPath)+1, &RetLength);
    if(FALSE == bWriteMem)
    {
        return FALSE;
    }


    LPTHREAD_START_ROUTINE LoadLibraryAddress = NULL;

#ifdef _UNICODE

    HMODULE  Kernel32Module = GetModuleHandle(L"Kernel32");

    LoadLibraryAddress =  (LPTHREAD_START_ROUTINE)GetProcAddress(Kernel32Module, "LoadLibraryW");

#else
    HMODULE  Kernel32Module = GetModuleHandle(_T("Kernel32"));

    LoadLibraryAddress =  (LPTHREAD_START_ROUTINE)GetProcAddress(Kernel32Module, "LoadLibraryA");

#endif
    HANDLE  Threadhandle = CreateRemoteThread(handle, NULL, 0, LoadLibraryAddress, data, 0, NULL);

    if (NULL == Threadhandle)
    {
        CloseHandle(handle);
        handle = NULL;
        return FALSE;
    }

    if (WaitForSingleObject(Threadhandle, INFINITE) == WAIT_FAILED)
    {
        return FALSE;
    }


    CloseHandle(handle);
    handle = NULL;
    CloseHandle(Threadhandle);
    Threadhandle = NULL;




    return TRUE;
}

/*
函数功能:卸载注入到进程后的dll
参数1:进程的名称
参数2:要卸载的dll
*/

BOOL cRemoteThreadInject::unitInjectDll(char* processName, char* dllPath)
{
    if((NULL == processName) || (NULL == dllPath))
    {
        return FALSE;
    }

    DWORD processId = 0;
    GetProcessId(processName, &processId);
    if(processId <= 0)
    {
        return FALSE;
    }

    BOOL bMore = FALSE;
    BOOL bFound = FALSE;
    HANDLE hSnapshot, hProcess, hThread;
    HMODULE hModule = NULL;
    MODULEENTRY32 me = {sizeof(me)};
    LPTHREAD_START_ROUTINE pThreadProc;

    hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, processId);

    bMore = Module32First(hSnapshot, &me);
    for(; bMore; bMore = Module32Next(hSnapshot, &me))
    {
        if(!_tcsicmp(me.szModule, dllPath) || !_tcsicmp(me.szExePath, dllPath))
        {
            bFound = TRUE;
            break;
        }
    }

    if(!bFound)
    {
        CloseHandle(hSnapshot);
        return FALSE;
    }


    hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);
    if(NULL == hProcess)
    {
        return FALSE;
    }

    hModule = GetModuleHandle("kernel32.dll");
    pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hModule, "FreeLibrary");

    hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, me.modBaseAddr, 0, NULL);
    WaitForSingleObject(hThread, INFINITE);

    CloseHandle(hProcess);
    hProcess = NULL;
    CloseHandle(hThread);
    hThread = NULL;
    CloseHandle(hSnapshot);
    hSnapshot = NULL;


    return TRUE;

}
相关文章
|
12月前
|
安全 API Windows
3.1 DLL注入:常规远程线程注入
动态链接库注入技术是一种特殊的技术,它允许在运行的进程中注入DLL动态链接库,从而改变目标进程的行为。DLL注入的实现方式有许多,典型的实现方式为远程线程注入,该注入方式的注入原理是利用了`Windows`系统中提供的`CreateRemoteThread()`这个API函数,该函数第四个参数是准备运行的线程,我们将`LoadLibrary()`函数填入其中,这样就可以执行远程进程中的`LoadLibrary()`函数,进而将我们自己准备的DLL加载到远程进程空间中执行,DLL在被装载后则会自动执行初始化部分。
121 0
|
4月前
|
容器
多线程时Autowired自动注入问题
多线程时Autowired自动注入问题
165 2
|
9月前
|
网络协议 安全 API
9.9 Windows驱动开发:内核远程线程实现DLL注入
在笔者上一篇文章`《内核RIP劫持实现DLL注入》`介绍了通过劫持RIP指针控制程序执行流实现插入DLL的目的,本章将继续探索全新的注入方式,通过`NtCreateThreadEx`这个内核函数实现注入DLL的目的,需要注意的是该函数在微软系统中未被导出使用时需要首先得到该函数的入口地址,`NtCreateThreadEx`函数最终会调用`ZwCreateThread`,本章在寻找函数的方式上有所不同,前一章通过内存定位的方法得到所需地址,本章则是通过解析导出表实现。
122 0
9.9 Windows驱动开发:内核远程线程实现DLL注入
|
10月前
|
Java Spring
Spring在多线程中bean的注入问题
Spring在多线程中bean的注入问题
100 0
|
网络协议 安全 API
驱动开发:内核远程线程实现DLL注入
在笔者上一篇文章`《内核RIP劫持实现DLL注入》`介绍了通过劫持RIP指针控制程序执行流实现插入DLL的目的,本章将继续探索全新的注入方式,通过`NtCreateThreadEx`这个内核函数实现注入DLL的目的,需要注意的是该函数在微软系统中未被导出使用时需要首先得到该函数的入口地址,`NtCreateThreadEx`函数最终会调用`ZwCreateThread`,本章在寻找函数的方式上有所不同,前一章通过内存定位的方法得到所需地址,本章则是通过解析导出表实现。
4922 0
|
Shell
驱动开发:内核ShellCode线程注入
还记得`《驱动开发:内核LoadLibrary实现DLL注入》`中所使用的注入技术吗,我们通过`RtlCreateUserThread`函数调用实现了注入DLL到应用层并执行,本章将继续探索一个简单的问题,如何注入`ShellCode`代码实现反弹Shell,这里需要注意一般情况下`RtlCreateUserThread`需要传入两个最重要的参数,一个是`StartAddress`开始执行的内存块,另一个是`StartParameter`传入内存块的变量列表,而如果将`StartParameter`地址填充为`NULL`则表明不传递任何参数,也就是只在线程中执行`ShellCode`代码,利用
354 1
|
安全 Java
为什么直接通过 @Autowired 注入的 HttpServletRequest 没有线程安全的问题
我们在各个地方注入依赖时,大多数情况下都是单例的。为什么直接通过 @Autowired 注入的 HttpServletRequest 没有线程安全的问题呢?带着这个问题我做了如下笔记。
213 0
|
Windows
突破SESSION 0 隔离的远线程注入
在Windows XP,Windows Server 2003以及更早的版本中,第一个登录的用户以及Windows的所有服务都运行在Session 0上,这样的做法导致用户使用的应用程序可能会利用Windows的服务程序提升自身的权限,为此,在后续的Windows版本中,引入了一种隔离机制,普通应用程序已经不再session 0中运行。
138 0
|
前端开发 安全 Java
Spring注入的成员属性HttpServletRequest是线程安全的吗?【享学Spring MVC】(上)
Spring注入的成员属性HttpServletRequest是线程安全的吗?【享学Spring MVC】(上)
|
XML 安全 前端开发
Spring注入的成员属性HttpServletRequest是线程安全的吗?【享学Spring MVC】(下)
Spring注入的成员属性HttpServletRequest是线程安全的吗?【享学Spring MVC】(下)
Spring注入的成员属性HttpServletRequest是线程安全的吗?【享学Spring MVC】(下)