简介

所谓进程守护,就是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. oracle查锁及解锁命令

    --查询行锁语句 select sql_text from v$sql a,v$session b where a.sql_id=b.sql_id and b.event='enq: TX - row ...

  2. 归并排序——Merge Sort

    基本思想:参考 归并排序是建立在归并操作上的一种有效的排序算法.该算法是采用分治法的一个非常典型的应用.首先考虑下如何将2个有序数列合并.这个非常简单,只要从比较2个数列的第一个数,谁小就先取谁,取了 ...

  3. EIGRP路由协议的简单理解及应用

    1.EIGRP 增强型内部网关路由协议 他是动态路由协议,是思科私有的路由协议(2013年已经公有化) 特点:   1)路由更新:闪速更新:触发式更新:路由增量更新 2)协议更新采用组播地址来维持EI ...

  4. paperpass

    推荐大家一个靠谱的论文检测平台.重复的部分有详细出处以及具体修改意见,能直接在文章上做修改,全部改完一键下载就搞定了.怕麻烦的话,还能用它自带的降重功能.哦对了,他们现在正在做毕业季活动, 赠送很多免 ...

  5. SpringMVC入门学习(二)

    SpringMVC入门学习(二) ssm框架 springMVC  在上一篇博客中,我简单介绍了一下SpringMVC的环境配置,和简单的使用,今天我们将进一步的学习下Springmvc的操作. mo ...

  6. [转]Oracle密码过期, 报:ORA-01017: 用户名/口令无效; 登录被拒绝

    本文转自:https://blog.csdn.net/jeff06143132/article/details/25696371 连接Oracle,以Oracle用户登陆:   $su - oracl ...

  7. C++注入记事本

    #include <iostream>; using namespace std; #include <windows.h>; #include <tlhelp32.h& ...

  8. Hive数据倾斜

    数据倾斜是进行大数据计算时最经常遇到的问题之一.当我们在执行HiveQL或者运行MapReduce作业时候,如果遇到一直卡在map100%,reduce99%一般就是遇到了数据倾斜的问题.数据倾斜其实 ...

  9. oracle创建用户、授权、导入、导出命令总结

    1.创建用户 需要先用system用户登录数据库,因为system用户具有创建其他用户的权限. 语法[创建用户]: create user 用户名 identified by 口令[即密码]: 例子: ...

  10. 【Java基础】13、抽象方法不能是static或native或synchroniz 原因及误解

    在网上看到过这么一篇文章,是关于抽象方法不能是static或native或synchroniz 的原因.其中提到了这些关键字的意义以及与 abstract 关键字的冲突,大体内容如下: 1.abstr ...