Ghost Tunnel复现
之前很早就已经看到360关于Ghost Tunnel的研究,当时也一时兴起进行复现。在Mac和Windows上都做了一系列尝试,证明了理论可行。
后来闲的无聊,并且刚好有学弟也在验证这个隐蔽通道的可行性,就干脆和他一起探讨这方面的实现。之后,GhostTunnel我就推在自己的Github上,经过一段时间的努力,我和我同伴一起推出了GhostTunnel稳定版。说实话,我不是很清楚360是如何做到极其稳定的控制在各个系统上,技术上难以想象。
在探索GhostTunnel的道路上,我个人认为未来在移动端以及蓝牙上,可能都存在类似的方法进行隐蔽传输。传输的效率和网卡的功率非常有关系,目前我们测试的有效距离是5m左右,过远会导致丢帧率增高,不稳定性增加。
利用GhostTunnel配合bashbunny+powershell基本可以实现无感控制。然后远程加载木马或者绕过,提权都是非常可行的。
本人的想法是希望能够将这个一直迭代下去,开发出多端的隐蔽控制。也希望有朋友一起提出issue或者request进行迭代。
【Github传送门】https://github.com/JcQSteven/GhostTunnel
下面是ReadMe部分。主要表述了我是如何利用GhostTunnel实现控制端和其被控端。
被控端程序逻辑
被控端程序的目的在于接收控制端的指令,并根据指令执行相应的行为。由于控制端与被控端之间通过Probe request帧和Probe response帧传输,因此被控端逻辑主要分为【帧传输逻辑】和【帧解析逻辑】两个部分。
帧传输逻辑
Probe request帧由被控端主动发送,并接受控制端发送Probe respense帧。因此,在 windows环境下,其执行的逻辑为:获取会话句柄、获取网卡列表及信息、发送request帧、获取附近网络信息列表、获取指定WLAN端口上的网络基本服务集、获取帧数据。
获取会话句柄
获取会话句柄采用的api为WlanOpenHandle。该 api打开了一个与服务器的连接。只有持有了句柄,才能进行后续才做。
获取网卡列表及信息
获取网卡列表采用的api为WlanEnumInterfaces,通过该函数,可以获得一个网卡列表 pIfList,通过对该列表的解析,可以获取网卡的信息。
发送request帧
在获取网卡信息判断网卡准备无误后,即可通过WlanScan函数发送request帧。发送帧的结构请参见后续部分。
获取附近网络信息列表
在发送request帧后,被控端通过WlanGetAvailableNetworkList 函数开始扫描附近网络信息,检查是否收到response帧。如果没有,则返回第3步,重新发送request 帧,然后再次检测。如果收到response帧,则进入第5步。
获取指定WLAN端口上的网络基本服务服务集
利用WlanGetNetworkBssList函数获取指定网络上的BSS列表并进行解析,根据 response帧的特征值id过滤出有用的的帧。
帧解析
将过滤出的帧并根据帧的定义获取对应的数据,从而完成一次帧传输逻辑。
帧解析逻辑
在完成帧传输逻辑后,即可获取由控制端发送的response帧数据。request帧和response帧的帧结构如下:
request帧结构:
“acc” (3byte) | Hash (8byte)
名称
作用
“acc”
用来标识该帧为请求帧
Hash
帧第一次发送时间的Hash值
request帧的前三个字节用于标识该帧为请求帧,后面8个字节为当前帧第一次发送时间的Hash值,为接收端提供帧标识,防止重复接收。
response帧结构:
执行指令帧:
”ccc” (3byte) | Hash (8byte) | Command (244byte)
名称
作用
”ccc”
用来标识该帧为执行指令帧
Hash
最后一次接收到response帧的Hash值
Command
执行指令
执行指令帧的前三个字节用来标识该帧为执行指令帧,后面8个字节为最后一次接收到response帧的Hash值,最后244字节为待执行指令。
传输文件帧:
”F” (1byte) | FilenameLen (2byte) | Hash (8byte) | FileIndex (2byte) | CurrentIndex(2byte) | FileName+FileContext (220byte)
名称
作用
“F”
用来标识该帧为传输文件帧
FilenameLen
用来标识文件内容相对于头信息后内容的偏移量
Hash
当前帧第一次发送时间的Hash值
FileIndex
文件总分片数
CurrentIndex
当前接收的分片序号
FileName+FileContext
先为文件名称,然后为具体的文件内容
传输文件帧的第1个字节(“F”)用来标识该帧为传输文件帧,第 2、3字节(FilenameLen)用来标识文件内容相对于头信息后内容的偏移量,因为文件名的长度是不定的。第4-11字节(Hash)为当前帧第一次发送时间的Hash值,第12、13字节(FileIndex)为文件总分片数,第14、15字节(CurrentIndex)为当前接收的分片序号,第16字节起先为文件名称,然后为具体的文件内容。
根据帧结构,可以很轻易的解析帧所携带的信息。如果帧为执行指令帧,则调用CreateProcess函数创建进程执行指令;如果帧为传输文件帧,则将帧所携带的文件内容写入文件中。
文件说明
1.main.cpp /.h 主程序入口
2.mainProcess.cpp /.h 主函数逻辑
3.Action_ExcuteCmd.cpp /.h 执行命令攻击逻辑
4.Action_Sendfile.cpp /.h 发送文件攻击逻辑
控制端程序逻辑
response帧由控制端在接收到request帧后发送,因此控制端逻辑主要分为解析命令、抓包、发送帧三个步骤。
解析命令
不同的攻击所采用的参数不同。例如:
需要设定自动关机时,所采用的指令是
python main.py -c"shutdown -r -t 60"
需要远程传输文件时,所采用的指令是
python main.py -f"/root/Desktop/hello.txt"
因此,需要对攻击者所采用的指令进行解析,从而确定所需的帧结构。
抓包
由于reponse帧需要在接收到request帧后对其进行反馈,因此,在python环境下,利用scapy工具包sniff方法对指定网卡进行扫描(注:指定网卡需要切换至monitor模式)。当收到数据包后,根据request帧的特征对数据包的内容进行定位和解析,如果解析到request帧,则将帧的hash部分存入本地缓存。
发送帧
根据攻击者的指令,控制端根据定义的response帧结构构造数据包,并按照帧会话逻辑进行发送。
之前很早就已经看到360关于Ghost Tunnel的研究,当时也一时兴起进行复现。在Mac和Windows上都做了一系列尝试,证明了理论可行。
后来闲的无聊,并且刚好有学弟也在验证这个隐蔽通道的可行性,就干脆和他一起探讨这方面的实现。之后,GhostTunnel我就推在自己的Github上,经过一段时间的努力,我和我同伴一起推出了GhostTunnel稳定版。说实话,我不是很清楚360是如何做到极其稳定的控制在各个系统上,技术上难以想象。
在探索GhostTunnel的道路上,我个人认为未来在移动端以及蓝牙上,可能都存在类似的方法进行隐蔽传输。传输的效率和网卡的功率非常有关系,目前我们测试的有效距离是5m左右,过远会导致丢帧率增高,不稳定性增加。
利用GhostTunnel配合bashbunny+powershell基本可以实现无感控制。然后远程加载木马或者绕过,提权都是非常可行的。
本人的想法是希望能够将这个一直迭代下去,开发出多端的隐蔽控制。也希望有朋友一起提出issue或者request进行迭代。
【Github传送门】https://github.com/JcQSteven/GhostTunnel
下面是ReadMe部分。主要表述了我是如何利用GhostTunnel实现控制端和其被控端。
被控端程序逻辑
被控端程序的目的在于接收控制端的指令,并根据指令执行相应的行为。由于控制端与被控端之间通过Probe request帧和Probe response帧传输,因此被控端逻辑主要分为【帧传输逻辑】和【帧解析逻辑】两个部分。
帧传输逻辑
Probe request帧由被控端主动发送,并接受控制端发送Probe respense帧。因此,在 windows环境下,其执行的逻辑为:获取会话句柄、获取网卡列表及信息、发送request帧、获取附近网络信息列表、获取指定WLAN端口上的网络基本服务集、获取帧数据。
获取会话句柄
获取会话句柄采用的api为WlanOpenHandle。该 api打开了一个与服务器的连接。只有持有了句柄,才能进行后续才做。
获取网卡列表及信息
获取网卡列表采用的api为WlanEnumInterfaces,通过该函数,可以获得一个网卡列表 pIfList,通过对该列表的解析,可以获取网卡的信息。
发送request帧
在获取网卡信息判断网卡准备无误后,即可通过WlanScan函数发送request帧。发送帧的结构请参见后续部分。
获取附近网络信息列表
在发送request帧后,被控端通过WlanGetAvailableNetworkList 函数开始扫描附近网络信息,检查是否收到response帧。如果没有,则返回第3步,重新发送request 帧,然后再次检测。如果收到response帧,则进入第5步。
www.wnhack.com
获取指定WLAN端口上的网络基本服务服务集
利用WlanGetNetworkBssList函数获取指定网络上的BSS列表并进行解析,根据 response帧的特征值id过滤出有用的的帧。
帧解析
将过滤出的帧并根据帧的定义获取对应的数据,从而完成一次帧传输逻辑。
帧解析逻辑
在完成帧传输逻辑后,即可获取由控制端发送的response帧数据。request帧和response帧的帧结构如下:
request帧结构:
“acc” (3byte) | Hash (8byte)
名称
作用
“acc”
用来标识该帧为请求帧
Hash
帧第一次发送时间的Hash值
request帧的前三个字节用于标识该帧为请求帧,后面8个字节为当前帧第一次发送时间的Hash值,为接收端提供帧标识,防止重复接收。
response帧结构:
执行指令帧:
”ccc” (3byte) | Hash (8byte) | Command (244byte)
名称
作用
”ccc”
用来标识该帧为执行指令帧
Hash
最后一次接收到response帧的Hash值
Command
执行指令
执行指令帧的前三个字节用来标识该帧为执行指令帧,后面8个字节为最后一次接收到response帧的Hash值,最后244字节为待执行指令。
传输文件帧:
”F” (1byte) | FilenameLen (2byte) | Hash (8byte) | FileIndex (2byte) | CurrentIndex(2byte) | FileName+FileContext (220byte)
名称
作用
“F”
用来标识该帧为传输文件帧
FilenameLen
用来标识文件内容相对于头信息后内容的偏移量
Hash
当前帧第一次发送时间的Hash值
FileIndex
文件总分片数
CurrentIndex
当前接收的分片序号
FileName+FileContext
先为文件名称,然后为具体的文件内容
传输文件帧的第1个字节(“F”)用来标识该帧为传输文件帧,第 2、3字节(FilenameLen)用来标识文件内容相对于头信息后内容的偏移量,因为文件名的长度是不定的。第4-11字节(Hash)为当前帧第一次发送时间的Hash值,第12、13字节(FileIndex)为文件总分片数,第14、15字节(CurrentIndex)为当前接收的分片序号,第16字节起先为文件名称,然后为具体的文件内容。
根据帧结构,可以很轻易的解析帧所携带的信息。如果帧为执行指令帧,则调用CreateProcess函数创建进程执行指令;如果帧为传输文件帧,则将帧所携带的文件内容写入文件中。
文件说明
1.main.cpp /.h 主程序入口
内容来自无奈安全网
2.mainProcess.cpp /.h 主函数逻辑
3.Action_ExcuteCmd.cpp /.h 执行命令攻击逻辑
4.Action_Sendfile.cpp /.h 发送文件攻击逻辑
控制端程序逻辑
response帧由控制端在接收到request帧后发送,因此控制端逻辑主要分为解析命令、抓包、发送帧三个步骤。
解析命令
不同的攻击所采用的参数不同。例如:
需要设定自动关机时,所采用的指令是
python main.py -c"shutdown -r -t 60"
需要远程传输文件时,所采用的指令是
python main.py -f"/root/Desktop/hello.txt"
因此,需要对攻击者所采用的指令进行解析,从而确定所需的帧结构。
抓包
由于reponse帧需要在接收到request帧后对其进行反馈,因此,在python环境下,利用scapy工具包sniff方法对指定网卡进行扫描(注:指定网卡需要切换至monitor模式)。当收到数据包后,根据request帧的特征对数据包的内容进行定位和解析,如果解析到request帧,则将帧的hash部分存入本地缓存。
发送帧
根据攻击者的指令,控制端根据定义的response帧结构构造数据包,并按照帧会话逻辑进行发送。