mirror of
https://github.com/huiyiruciduojiao/FuckScreenCap.git
synced 2026-01-28 03:54:37 +08:00
314 lines
9.5 KiB
C++
314 lines
9.5 KiB
C++
#define _CRT_SECURE_NO_WARNINGS
|
||
|
||
#include "main.h"
|
||
#include "config_manager.h"
|
||
#include "hook_current.h"
|
||
#include <iostream>
|
||
#include <string>
|
||
#include <vector>
|
||
#include <Windows.h>
|
||
#include <psapi.h>
|
||
#include <Shlwapi.h>
|
||
#include <tchar.h>
|
||
#include <unordered_map>
|
||
#include <unordered_set>
|
||
#include <list>
|
||
#include <Winternl.h>
|
||
#include <fstream>
|
||
#include <sstream>
|
||
#include <algorithm>
|
||
|
||
#pragma comment(lib,"shlwapi.lib")
|
||
using namespace std;
|
||
bool Is64BitOS()
|
||
{
|
||
SYSTEM_INFO sysInfo = { 0 };
|
||
GetNativeSystemInfo(&sysInfo);
|
||
if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64
|
||
|| sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
|
||
{
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
bool is64BitOS = Is64BitOS();
|
||
|
||
string getProcNameByHandle(HANDLE hProcess)
|
||
{
|
||
char exeName[MAX_PATH] = { 0 };
|
||
if (GetModuleFileNameExA(hProcess, NULL, exeName, MAX_PATH))
|
||
{
|
||
PathStripPathA(exeName);
|
||
return exeName;
|
||
}
|
||
Log(LogLevel::LOG_WARN, __LINE__, "getProcNameByHandle GetModuleFileNameExA Error: %d", GetLastError());
|
||
return {};
|
||
}
|
||
|
||
unordered_map<DWORD, string> getSuspendProcess()
|
||
{
|
||
unordered_map<DWORD, string> suspendProcess;
|
||
typedef NTSTATUS(NTAPI* pfnNtQuerySystemInformation)(
|
||
IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
|
||
OUT PVOID SystemInformation,
|
||
IN ULONG SystemInformationLength,
|
||
OUT PULONG ReturnLength OPTIONAL
|
||
);
|
||
pfnNtQuerySystemInformation NtQuerySystemInformation = (pfnNtQuerySystemInformation)GetProcAddress(LoadLibrary(L"ntdll.dll"), "NtQuerySystemInformation");
|
||
|
||
LPVOID dwBufferProcess = 0;
|
||
DWORD dwBufferProcessSize = 0;
|
||
NtQuerySystemInformation(SystemProcessInformation, NULL, 0, &dwBufferProcessSize);
|
||
dwBufferProcess = new BYTE[dwBufferProcessSize + 0x10000]();
|
||
LPVOID dwOldBufferProcess = dwBufferProcess;
|
||
NtQuerySystemInformation(SystemProcessInformation, dwBufferProcess, dwBufferProcessSize + 0x10000, &dwBufferProcessSize);
|
||
|
||
while (TRUE)
|
||
{
|
||
LPVOID dwAddress = dwBufferProcess;
|
||
dwBufferProcess = (BYTE*)dwBufferProcess + sizeof(SYSTEM_PROCESS_INFORMATION);
|
||
PSYSTEM_PROCESS_INFORMATION processInfo = (PSYSTEM_PROCESS_INFORMATION)dwAddress;
|
||
|
||
int suspendThreads = 0;
|
||
for (DWORD i = 0; i < processInfo->NumberOfThreads; i++)
|
||
{
|
||
if (((SYSTEM_THREAD_INFORMATION*)dwBufferProcess)->ThreadState == 5 && ((SYSTEM_THREAD_INFORMATION*)dwBufferProcess)->WaitReason == 5)
|
||
{
|
||
suspendThreads++;
|
||
}
|
||
dwBufferProcess = (BYTE*)dwBufferProcess + sizeof(SYSTEM_THREAD_INFORMATION);
|
||
}
|
||
if (suspendThreads == processInfo->NumberOfThreads)
|
||
{
|
||
wstring wstrName{ processInfo->ImageName.Buffer };
|
||
suspendProcess[(DWORD)(processInfo->UniqueProcessId)] = string(wstrName.begin(), wstrName.end());
|
||
}
|
||
dwBufferProcess = ((BYTE*)dwAddress + ((SYSTEM_PROCESS_INFORMATION*)dwAddress)->NextEntryOffset);
|
||
if (((SYSTEM_PROCESS_INFORMATION*)dwAddress)->NextEntryOffset == 0)
|
||
break;
|
||
}
|
||
delete[] dwOldBufferProcess;
|
||
return suspendProcess;
|
||
}
|
||
|
||
bool ZwCreateThreadExInjectDll(HANDLE hProcess, const wchar_t* pszDllFileName)
|
||
{
|
||
int pathSize = (wcslen(pszDllFileName) + 1) * sizeof(wchar_t);
|
||
|
||
LPVOID lpPathAddr = VirtualAllocEx(hProcess, 0, pathSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
|
||
if (NULL == lpPathAddr)
|
||
{
|
||
Log(LogLevel::LOG_ERROR, __LINE__, "<EFBFBD><EFBFBD>Ŀ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD>ʧ<EFBFBD>ܣ<EFBFBD><EFBFBD><EFBFBD>%d", GetLastError());
|
||
CloseHandle(hProcess);
|
||
return false;
|
||
}
|
||
|
||
if (FALSE == WriteProcessMemory(hProcess, lpPathAddr, pszDllFileName, pathSize, NULL))
|
||
{
|
||
Log(LogLevel::LOG_ERROR, __LINE__, "<EFBFBD><EFBFBD>Ŀ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD>Dll·<EFBFBD><EFBFBD>ʧ<EFBFBD>ܣ<EFBFBD><EFBFBD><EFBFBD>%d", GetLastError());
|
||
CloseHandle(hProcess);
|
||
return false;
|
||
}
|
||
|
||
HMODULE hNtdll = LoadLibraryW(L"ntdll.dll");
|
||
if (NULL == hNtdll)
|
||
{
|
||
Log(LogLevel::LOG_ERROR, __LINE__, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ntdll.dllʧ<6C>ܣ<EFBFBD><DCA3><EFBFBD>%d", GetLastError());
|
||
CloseHandle(hProcess);
|
||
return false;
|
||
}
|
||
|
||
HMODULE hmKernel32 = LoadLibrary(_T("Kernel32.dll"));
|
||
if (NULL == hmKernel32)
|
||
{
|
||
Log(LogLevel::LOG_ERROR, __LINE__, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Kernel32.dllʧ<6C>ܣ<EFBFBD><DCA3><EFBFBD>%d", GetLastError());
|
||
CloseHandle(hProcess);
|
||
return false;
|
||
}
|
||
FARPROC pFuncProcAddr = GetProcAddress(hmKernel32, "LoadLibraryW");
|
||
if (NULL == pFuncProcAddr)
|
||
{
|
||
Log(LogLevel::LOG_ERROR, __LINE__, "<EFBFBD><EFBFBD>ȡLoadLibrary<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַʧ<EFBFBD>ܣ<EFBFBD><EFBFBD><EFBFBD>%d", GetLastError());
|
||
CloseHandle(hProcess);
|
||
return false;
|
||
}
|
||
|
||
#ifdef _WIN64
|
||
typedef DWORD(WINAPI* typedef_ZwCreateThreadEx)(
|
||
PHANDLE ThreadHandle,
|
||
ACCESS_MASK DesiredAccess,
|
||
LPVOID ObjectAttributes,
|
||
HANDLE ProcessHandle,
|
||
LPTHREAD_START_ROUTINE lpStartAddress,
|
||
LPVOID lpParameter,
|
||
ULONG CreateThreadFlags,
|
||
SIZE_T ZeroBits,
|
||
SIZE_T StackSize,
|
||
SIZE_T MaximumStackSize,
|
||
LPVOID pUnkown
|
||
);
|
||
#else
|
||
typedef DWORD(WINAPI* typedef_ZwCreateThreadEx)(
|
||
PHANDLE ThreadHandle,
|
||
ACCESS_MASK DesiredAccess,
|
||
LPVOID ObjectAttributes,
|
||
HANDLE ProcessHandle,
|
||
LPTHREAD_START_ROUTINE lpStartAddress,
|
||
LPVOID lpParameter,
|
||
BOOL CreateSuspended,
|
||
DWORD dwStackSize,
|
||
DWORD dw1,
|
||
DWORD dw2,
|
||
LPVOID pUnkown
|
||
);
|
||
#endif
|
||
typedef_ZwCreateThreadEx ZwCreateThreadEx = (typedef_ZwCreateThreadEx)GetProcAddress(hNtdll, "ZwCreateThreadEx");
|
||
if (NULL == ZwCreateThreadEx)
|
||
{
|
||
Log(LogLevel::LOG_ERROR, __LINE__, "<EFBFBD><EFBFBD>ȡZwCreateThreadEx<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַʧ<EFBFBD>ܣ<EFBFBD><EFBFBD><EFBFBD>%d", GetLastError());
|
||
CloseHandle(hProcess);
|
||
return false;
|
||
}
|
||
|
||
HANDLE hRemoteThread = NULL;
|
||
DWORD dwStatus = ZwCreateThreadEx(&hRemoteThread, PROCESS_ALL_ACCESS, NULL,
|
||
hProcess, (LPTHREAD_START_ROUTINE)pFuncProcAddr, lpPathAddr, 0, 0, 0, 0, NULL);
|
||
if (NULL == hRemoteThread)
|
||
{
|
||
Log(LogLevel::LOG_ERROR, __LINE__, "Ŀ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>ʧ<EFBFBD>ܣ<EFBFBD><EFBFBD><EFBFBD>%d", GetLastError());
|
||
CloseHandle(hProcess);
|
||
return false;
|
||
}
|
||
|
||
DWORD reason = WaitForSingleObject(hRemoteThread, INFINITE);
|
||
|
||
VirtualFreeEx(hProcess, lpPathAddr, 0, MEM_RELEASE);
|
||
CloseHandle(hRemoteThread);
|
||
CloseHandle(hProcess);
|
||
FreeLibrary(hNtdll);
|
||
return true;
|
||
}
|
||
|
||
bool HookCurWindow(const std::wstring& dllPath)
|
||
{
|
||
Log(LogLevel::LOG_INFO, __LINE__, ">>>>>>>>>>>>>>>>HOOK CURRENT WINDOWS<<<<<<<<<<<<<<<<");
|
||
|
||
|
||
|
||
// <20><><EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>
|
||
if (!ConfigManager::reloadGlobalConfig()) {
|
||
Log(LogLevel::LOG_WARN, __LINE__, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>ʧ<EFBFBD>ܣ<EFBFBD>ʹ<EFBFBD><EFBFBD>Ĭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
|
||
}
|
||
|
||
// <20><>ӡ<EFBFBD><D3A1>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD>
|
||
ConfigManager::Config* config = ConfigManager::getGlobalConfig();
|
||
if (config) {
|
||
config->printConfig();
|
||
}
|
||
|
||
std::wstring DllPath{ getFullFilePath(dllPath) };
|
||
if (DllPath.empty()) {
|
||
Log(LogLevel::LOG_ERROR, __LINE__, "DLL·<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡʧ<EFBFBD><EFBFBD>: %d", GetLastError());
|
||
return false;
|
||
}
|
||
|
||
unordered_map<DWORD, string> suspendProc = getSuspendProcess();
|
||
for (auto i : suspendProc)
|
||
{
|
||
Log(LogLevel::LOG_INFO, __LINE__, "suspend process: %s", i.second.c_str());
|
||
}
|
||
|
||
unordered_map<DWORD, char> tryHookedProc;
|
||
vector<string> goodHookedProc;
|
||
vector<string> filteredProc; // <20><><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>Ľ<EFBFBD><C4BD><EFBFBD>
|
||
|
||
HWND windowHandle = NULL;
|
||
do {
|
||
windowHandle = FindWindowEx(NULL, windowHandle, NULL, NULL);
|
||
DWORD dwPid;
|
||
if (GetWindowThreadProcessId(windowHandle, &dwPid)) {
|
||
if (tryHookedProc.find(dwPid) == tryHookedProc.end()) {
|
||
tryHookedProc[dwPid] = 1;
|
||
|
||
if (suspendProc.find(dwPid) != suspendProc.end())
|
||
{
|
||
Log(LogLevel::LOG_WARN, __LINE__, "This is a suspend process: %s", suspendProc[dwPid].c_str());
|
||
continue;
|
||
}
|
||
|
||
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
|
||
if (hProcess) {
|
||
string exeName = getProcNameByHandle(hProcess);
|
||
exeName = (!exeName.empty() ? exeName : "Unknown ProcName");
|
||
|
||
// ʹ<><CAB9><EFBFBD>µĹ<C2B5><C4B9><EFBFBD><EFBFBD><EFBFBD>
|
||
if (!ConfigManager::shouldProcessBeHooked(exeName)) {
|
||
ConfigManager::Config* cfg = ConfigManager::getGlobalConfig();
|
||
Log(LogLevel::LOG_INFO, __LINE__, "<EFBFBD><EFBFBD><EFBFBD>̱<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: %s (ģʽ: %s)",
|
||
exeName.c_str(),
|
||
cfg && cfg->getFilterMode() == ConfigManager::ProcessFilterConfig::WHITELIST ? "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>" : "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
|
||
filteredProc.push_back(exeName);
|
||
CloseHandle(hProcess);
|
||
continue;
|
||
}
|
||
|
||
BOOL procIs32bit;
|
||
if (IsWow64Process(hProcess, &procIs32bit)) {
|
||
#ifdef _WIN64
|
||
if (!procIs32bit && is64BitOS) {
|
||
if (ZwCreateThreadExInjectDll(hProcess, DllPath.c_str())) {
|
||
Log(LogLevel::LOG_INFO, __LINE__, "Hook Window For: %s", exeName.c_str());
|
||
goodHookedProc.push_back(exeName);
|
||
}
|
||
else
|
||
Log(LogLevel::LOG_WARN, __LINE__, "Hook Window Failed: %s", exeName.c_str());
|
||
}
|
||
else {
|
||
Log(LogLevel::LOG_WARN, __LINE__, "It's a 32 app: %s", exeName.c_str());
|
||
}
|
||
#else
|
||
if (procIs32bit || (!procIs32bit && !is64BitOS)) {
|
||
Log(LogLevel::LOG_INFO, __LINE__, "ready inject: %s", exeName.c_str());
|
||
if (ZwCreateThreadExInjectDll(hProcess, DllPath.c_str())) {
|
||
Log(LogLevel::LOG_INFO, __LINE__, "Hook Window For: %s", exeName.c_str());
|
||
goodHookedProc.push_back(exeName);
|
||
}
|
||
else
|
||
Log(LogLevel::LOG_WARN, __LINE__, "Hook Window Failed: %s", exeName.c_str());
|
||
}
|
||
else {
|
||
Log(LogLevel::LOG_WARN, __LINE__, "It's a 64 app: %s", exeName.c_str());
|
||
}
|
||
#endif
|
||
}
|
||
else {
|
||
Log(LogLevel::LOG_ERROR, __LINE__, "<EFBFBD>ж<EFBFBD>Ŀ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD>64λϵͳ<EFBFBD>е<EFBFBD>32λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><EFBFBD>: %d", GetLastError());
|
||
continue;
|
||
}
|
||
}
|
||
else {
|
||
Log(LogLevel::LOG_WARN, __LINE__, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: %d, ʧ<><CAA7>: %d", dwPid, GetLastError());
|
||
continue;
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
Log(LogLevel::LOG_WARN, __LINE__, "GetWindowThreadProcessId Error<6F><72>%d, HWND: %x", GetLastError(), windowHandle);
|
||
}
|
||
} while (windowHandle);
|
||
|
||
//Summary
|
||
Log(LogLevel::LOG_INFO, __LINE__, ">>>>>>>>>>>>>>>>HOOK CURRENT WINDOW END<<<<<<<<<<<<<<<<<<");
|
||
Log(LogLevel::LOG_INFO, __LINE__, "Summary:");
|
||
Log(LogLevel::LOG_INFO, __LINE__, "<EFBFBD>ɹ<EFBFBD>Hook<EFBFBD>Ľ<EFBFBD><EFBFBD><EFBFBD> (%zu<7A><75>):", goodHookedProc.size());
|
||
for (auto& i : goodHookedProc)
|
||
{
|
||
Log(LogLevel::LOG_INFO, __LINE__, " - %s", i.c_str());
|
||
}
|
||
|
||
if (!filteredProc.empty()) {
|
||
Log(LogLevel::LOG_INFO, __LINE__, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˵Ľ<EFBFBD><EFBFBD><EFBFBD> (%zu<7A><75>):", filteredProc.size());
|
||
}
|
||
|
||
return true;
|
||
} |