无纸化会议-禁止进程启动

无纸化会议-禁止进程启动

需求

实现禁止进程启动的功能

可选方案

  • 轮询。
    每隔固定时间检查一次进程列表,比较出新出现的进程,然后将其kill。
    这种方法会消耗相对较多的计算资源,并且有响应延迟,且实现难度不低,故不采用
  • dll注入
    向全局注入一个dll,当有新进程启动时,dll进行attach时会向无纸化会议系统发回启动进程的进程id,系统收到id后据此来实现kill
    这里选择这一种方案,相比于第一种方案,dll注入可以在进程启动时立即响应,没有延迟,不需要循环查找和比较,资源消耗相对较低,由于这使用了c++编写的dll以及跨进程,调试难度会轻微上升,但是跨进程执行的操作并不复杂,总体来讲实现难度与第一种相近

实现

新建dll项目HookProc,实现两部分功能:向主程序提供向全局注入此dll和取消该注入的控制函数,以及在远程进程上的实际执行的逻辑
在主程序中新建类ProcessManager,作为主程序和dll之间的接口,通过动态调用dll的方式控制注入
在主程序中添加处理windows 消息队列的函数,来处理dll从其他进程发来的进程id,执行相关操作。
相关代码:
获得启动的进程的id
HookProc.dll
dllmain.cpp

extern "C"
{
	__declspec(dllexport)
		void StartupHook(void);

	__declspec(dllexport)
		void CloseHook(void);

	void ProcessHookUp();

	void ProcessHookDelete();
}

int count = 0;

BOOL APIENTRY DllMain(HMODULE hModule,
	DWORD  ul_reason_for_call,
	LPVOID lpReserved) {
	switch (ul_reason_for_call) {
	case DLL_PROCESS_ATTACH:
		ProcessHookUp();
		break;
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
		break;
	case DLL_PROCESS_DETACH:
		ProcessHookDelete();
		break;
	}
	return TRUE;
}

HHOOK hThis = NULL;

LRESULT CALLBACK ProcessClose(int nCode, WPARAM wParam, LPARAM lParam)
{
	return CallNextHookEx(hThis, nCode, wParam, lParam);
}
	wchar_t ws[203];
void StartupHook(void)
{
	DWORD dwPID;
	HMODULE h = GetModuleHandleW(L"ProcHook.dll");
	HINSTANCE hi= LoadLibrary(TEXT(".\\HookProc.dll"));
	hThis = SetWindowsHookExW(WH_GETMESSAGE, ProcessClose,hi ,0 /*GetWindowThreadProcessId(FindWindow(NULL, L"pm_client"), &dwPID)*/);
	long long n = (long long) hThis;
	int i = 0;
	if (n == 0) {
		ws[i++] = L'e';
		if (hi == NULL)ws[i++] = L'x';
		n = GetLastError();
	}
	for (;n != 0;n /= 10) {
		ws[i++] = '0' + n % 10;
	}
	ws[i++] = '\0';
	
	MessageBoxW(FindWindow(NULL, L"pm_client"), ws, L"WORLD", MB_OK);
}

void CloseHook(void)
{
	UnhookWindowsHookEx(hThis);
}
#include <fstream>
void ProcessHookUp()
{
	DWORD proId = GetCurrentProcessId();
	HWND hWnd = FindWindow(NULL, L"pm_client");
	std::ofstream x("C:\\mylog.txt",std::ios::app);
	x << proId << "\n" << hWnd << "\n" << std::endl;
	x.flush();
	x.close();
	if (hWnd)
	{
		PostMessage(hWnd, WM_USER + 7, 0, proId);
	}

}

void ProcessHookDelete()
{
	DWORD proId = GetCurrentProcessId();
}

主程序
ProcessManager

public class ProcessManager
    {
        [DllImport("kernel32.dll")]
        public static extern IntPtr LoadLibrary(string dllToLoad);

        [DllImport("kernel32.dll")]
        public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);

        [DllImport("kernel32.dll")]
        public static extern bool FreeLibrary(IntPtr hModule);

        private delegate void Func();
        Func startupHook;
        Func closeHook;
        static IntPtr pDll;

        public void StartupHook()
        {
            startupHook();
        }
        public void CloseHook()
        {
            closeHook();
        }


        public ProcessManager()
        {
            IntPtr pAddressOfFunctionToCall = GetProcAddress(pDll, "StartupHook");
            startupHook = (Func)Marshal.GetDelegateForFunctionPointer(pAddressOfFunctionToCall, typeof(Func));
            pAddressOfFunctionToCall = GetProcAddress(pDll, "CloseHook");
            closeHook = (Func)Marshal.GetDelegateForFunctionPointer(pAddressOfFunctionToCall, typeof(Func));
        }

        static ProcessManager()
        {
            pDll = LoadLibrary(@".\HookProc.dll");
            Console.WriteLine(pDll);
        }
    }

消息队列处理

IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) {
            if (msg == 0x0400 + 7) {
                int proId = lParam.ToInt32();
                Log.i("hook", $"pid:{proId}");
                //do sth
            }
            return IntPtr.Zero;
        }
private void Window_Loaded(object sender, RoutedEventArgs e) {
            p = new ProcessManager();
            HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
            if (source != null) source.AddHook(WndProc); else Log.i("wndproc", "failed");
            p.StartupHook();
        }

用pid kill进程

Process p = Process.GetProcessById(pid);
p.Kill();

实现效果

pic

一些细节

1.在vs中需要使用def文件来指示dll文件可以导出的函数,如在这里,需要创建一个.def文件:

LIBRARY HookProc

EXPORTS
StartupHook
CloseHook

然后在项目-属性-链接器-输入-模块定义文件中指定这个.def文件
否则生成的dll中这些函数将不会被导出,但是vs不会给出任何提示
2.dll项目不方便使用vs的调试器进行调试,也没有控制台可以输出,可以使用win32的MessageBoxW函数来显示输出
函数签名如下

int MessageBoxW(
  HWND    hWnd,
  LPCWSTR lpText,
  LPCWSTR lpCaption,
  UINT    uType
);

hWnd表示归属的窗口,可以为NULL
lpText是对话框中的文本
lpCaption是对话框的标题
uType是窗口类型,MB_OK将显示一个OK按钮
LPCWSTR 是wchar_t *
注意不可以用这种方法调试hook的实际逻辑,因为messagebox本身也是一个新的窗口,这会递归地调用这个过程,破坏windows桌面,替代方法是把输出写到特定的文件上。
3.根据win32 文档,32位dll的全局hook只能hook到32位的程序,64位同理,所以如果要hook所有程序,应该同时准备32位dll和64位dll,并且它们的名字应该不同

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值