这是一个基于gh0st远程控制的项目,使自己更深入了解远控的原理,来编写一款自己的远控(正在编写),项目采用VS2017编写,解决了遇到的bug,其中加入了大量注释以及思维导图提供帮助,代码的框架思想非常值得学习,代码设计巧妙。
通讯框架
通讯被控端采用socket,主控端采用的是IOCP完成端口,它可以高效地将I/O事件通知给应用程序,能够处理较多连接,处理逻辑我做成了xmind,一张图来了解通讯框架
部分功能实现的方法
1 shell控制
shell管理用到匿名管道,创建CMD子进程实现进程间通信达到操作控制的目的: 管道pipe 用于进程间通讯的一段共享内存。创建管道的进程称为服务器,连接到一个管道的进为管道客户机。一个进程在想管道写入数据有,另一个进程就可以从瓜岛的另一端将其读取出来。匿名管道Anonymous Pipes 是在父进程和子进程单向传输数据的一种未命名的管道,只能在本地计算机中是同,不能用于网络间的通讯。
如何使用的匿名管道进行通信 匿名管道主要用于父进程与子进程之间的的通信,首先父进程创建匿名管道,创建成功后可以获取这个匿名管道进行读写句柄,然后再创建一个子进程,子进程必须继承和使用父进程的一些公开句柄,创建子进程的时候必须将标准输入、标准输出句柄设置为父进程创建管道的管道句柄,然后就可以进行通讯了。
然后通过PeekNamedPipe查询是否有新的数据,以及ReadFile进行读取管道中的内容进行读操作,WriteFile进行写入管道内容进行操作。
一般是使用while循环配套ReadFile函数。如果控制台程序暂时没有输出并且没有退出,ReadFile函数将一直等待,导致死循环。所以在使用ReadFile之前,加入PeekNamedPipe函数调用。
gh0st使用的最常见的方法A,通过建立进程快照进行遍历进程获取信息
通过函数CreateToolhelp32Snapshot获取的快照句柄使用Process32First、Process32Next遍历所有进程的PROCESSENTRY32信息
再通过GetProcessFullPath获取进程路径等信息。
通过RegOpenKeyEx打卡一个注册表项得要打开项的句柄PHKEY phkResult 利用这个句柄来获取子项和信息
得到PHKEY句柄后使用API RegQueryInfoKey获取该项信息
通过RegQueryInfoKey获取到lpcSubKeys子项数量同于RegEnumKeyEx的DWORD dwIndex,参数进行循环遍历得到索引项名LPTSTR lpName
使用API RegEnumValue 获取键值内容 以及获取lpType判断类型、lpData获取内容
建立一个连接到服务控制管理器,并打开指定的数据库
由OpenSCManager返回的句柄做参数使用API EnumServicesStatus枚举系统当前服务信息
通过api EnumServicesStatus得到的lpServicesReturned数量、lpServices缓冲区遍历服务,OpenService获取服务句柄
根据获取到的服务句柄调用API QueryServiceConfig获取服务信息
windows系统是建立在事件驱动的机制上,整个系统都是通过消息传递来实现的,而钩子是windows系统中非常重要的系统接口,用它可以截获并处理发送给其他进程的消息来实现诸多功能,钩子种类很多,每种钩子可以截取相应的消息,例如键盘钩子截取键盘消息等等。
全局钩子运行机制,通过系统调用,将狗子挂入系统,每当特定消息发出,在消息没有到达目标窗口之前,钩子就会先行捕获到消息。这时钩子回调函数可以对消息进行操作,然后继续传递该消息,也可结束该消息的传递。每种类型的钩子都会由系统来维护一个钩子链,并且最后安装的钩子在链子的开始,最先安装的在最后。实现win32的系统钩子,必须调用API函数SetWindowsHookEx来安装这个函数
几点需要说明的地方:
(1) 如果对于同一事件(如键盘消息)既安装了线程钩子又安装了系统钩子,系统会优先调用线程钩子,然后调用系统钩子。
(2) 对同一事件消息可安装多个钩子处理过程,这些钩子处理过程形成了钩子链。处理顺序是先安装的后处理,后安装的先处理。
(3) 钩子特别是系统钩子会消耗消息处理时间,降低系统性能。只有在必要的时候才安装钩子,在使用完毕后要及时卸载。
我们先在钩子函数中实现自定义的功能,然后调用函数 CallNextHookEx 把钩子信息传递给钩子链的下一个钩子函数。
LRESULT CallNextHookEx( HHOOK hhk, int nCode, WPARAM wParam, LPARAM lParam )
参数 hhk是钩子句柄。nCode、wParam和lParam 是钩子函数。
当然也可以通过直接返回TRUE来丢弃该消息,就阻止了该消息的传递。
当不再使用钩子时,必须及时卸载。简单地调用下面的函数即可。
BOOL UnhookWindowsHookEx( HHOOK hhk)
值得注意的是线程钩子和系统钩子的钩子函数的位置有很大的差别。
线程钩子一般在当前线程或者当前线程派生的线程内,而系统钩子必须放在独立的动态链接库中。
EnumWindows可以遍历当前屏幕上所有的父窗口创建lpEnumFunc回调函数遍历每一个顶层窗口
回调函数的返回值必须为TRUE才能保证系统会依次遍历每一个窗口。如果返回值非TRUE,则在当前窗口后不会进行后续的遍历动作。
GetWindowText、GetWindowThreadProcessId可以通过遍历到的HWND得到对应window的Title、PID
不过这里有个问题,在我自己写的demo调用dll枚举窗口时,遍历获取信息没有发生问题,当使用rundll32调用导出出现了问题
在某一个窗口句柄调用GetWindowText时,出现阻塞,无法返回。
经过调试分析发现:
此时 GetWindowText将发送WM_GETTEXT消息至目标窗口所在的线程,线程响应此消息,返回窗口标题。如果目标窗口所在的线程刚好此时无法响应消息,则会导致GetWindowText一直处于阻塞状态,直到目标窗口所在进程响应了消息,才会得到返回。就会出现没有反应或卡死的情况。
解决方案就是调用GetWindowText时判断目标窗口所在进程和线程ID,使用InternalGetWindowText替换GetWindowText
win7 64下
例如{052860C8-3E53-3D0B-9332-48A8B4971352}
Active Setup是微软使用此键来安装windows组件,可以在这个位置下看到已安装组件得列表,每个组件都有一个值,windows使用这些值来识别组件。其中StubPath是其中最重要的一项,它包含一个命令,windows每次启动都会执行这个命令。
创建一个(在64位位置,需要根据启动程序而定){052860C8-3E53-3D0B-9332-48A8B4971352} StubPath 项为REG_EXPAND_SZ类型 calc.exe
1 重启计算机后,calc便会启动,但是启动后,程序执行会造成电脑卡住,无法进入系统,必须要退出程序才能执行。
2 并且再次启动calc不会再启动了这是因为在user同位置的active setup下有相同的guid,将其删除再次重启就会启动了。
所以每次执行要将user位置guid删除,并且程序通过再次启动自己或者注入到其他进程来解决上面的两个问题。
项目地址:
https://github.com/Cc28256/CcRemote
项目仅仅做到能够使用,因为还有一些功能没有完善。
项目有时会更新一些有趣的行为等方式,下一步计划对项目进行免杀,不过我不会公布它,仅仅以技术学习进行交流
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2020-8-15 16:18
被Cc28256编辑
,原因: