美国NSA超级后门Bvp47的隐身技能:网络隐身1

admin 2022年11月7日21:38:02评论51 views字数 2403阅读8分0秒阅读模式

本文是基于Bvp47技术报告(PDF)和Linux内核写的。

这篇主要是讲述Bvp47的网络信息在主机侧的隐身,下篇会讲述到它在整个网络的隐身技能

如何在Linux系统隐藏网络信息呢?

平时,我们查看网络信息,一般是使用netstat命令。那它是从哪里获取这些网络信息?

使用strace netstat就可以知道它是从/proc/net/proc/<pid>/fd两个目录获取信息。比如要知道1号进程监听了哪些IPV4tcp socket,就是要从/proc/1/fd下使用readlink获取是socket类型fdinode,再通过这个inode/proc/net/tcp里找,如果该inode对应记录的st列为0A,那么该fd就是监听socket,而它的源宿地址分别在local_addressrem_address这两列。

按照前面两篇的讲述,隐藏网络信息,也就两种方法:

  1. 用户态劫持readlink,read之类的系统调用
  2. 内核态劫持网络相关的内核函数

Bvp47挂钩了内核里这些网络相关的函数:

  • tcp4_seq_show - 显示TCP监听和连接信息
  • udp4_seq_show - 显示udp监听和连接信息
  • packet_seq_show - 显示packet socket信息
  • unix_seq_show - 显示unix socket信息
  • listening_get_next - 枚举监听信息
  • established_get_next - 枚举连接信息
  • sys_bind - 绑定地址
  • unix_accept - unix socket接收新连接
  • sys_read - 读取句柄
  • sys_write - 写句柄
  • sys_sendto/sys_sendmsg - 向远程发送信息
  • sys_recvfrom/sys_recvmsg - 接收消息
  • sock_init_data - 初始化socket并加入到链表
  • tcp_time_wait - tcp连接关闭时的回收
  • sys_connect - 连接远程
  • sys_dup/sys_dup2 - 复制句柄
  • get_raw_socket - 获取raw socket链表

从上面netstat的例子,可以知道ipv4的信息是从/proc/net/tcp里获得的,而这个虚拟文件是由哪个函数来写的呢?

/proc/net/tcp文件的字段是这样:

 sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode      

通过在内核代码里搜索,可以看到是net/ipv4/tcp_ipv4.ctcp4_seq_show函数。所以Bvp47挂钩tcp4_seq_show过滤掉它的连接和监听端口。

同理,这也是为什么Bvp47挂钩udp4_seq_show,unix_seq_show,packet_seq_show的原因。

如果仔细阅读内核代码,会发现/proc/net/tcp的信息获取流程中包含着listening_get_nextestablished_get_next

其实,从这几个文件读取的信息,也是指纹检测。现在的HIDS一般还会用行为检测。

在没有设置SO_REUSEADDR标志情况下,端口的监听是独占式的,意味着,如果一个端口被某个进程监听了,其它进程就无法再监听这个端口。

对任意一个端口调用一次bind操作,如果它返回错误码是EADDRINUSE,就说明这个端口被监听,假设在/proc/net/tcp又找不到它的信息,说明这个端口是被隐藏起来了。

由于端口的范围也是固定的,就是0-65535,那么只需要对端口进行枚举来bind一把,再对比netstat的结果,就知道有没有端口隐藏了。

所以,Bvp47要挂钩sys_bind从而隐藏自己的端口监听,从而实现即使端口被重复监听,也不会显示出来。

根据盘古实验室的《Bvp47技术报告》,黑客机器Bvp47会向DMZ的Bvp47发端口敲门包,DMZ的Bvp47就会向它连接。在现实网络中,往往是很深的,除了DMZ区,还有业务区,DB区之类。这些区域的机器往往不会和外网直接连接的,所以,恶意软件需要做一些代理节点,像黑客机器的Bvp47也会入侵投放到这些区域,成为代理节点。

那么,问题来了,假设Bvp47代理节点监听了某端口,由于它挂钩了sys_bind来隐藏了,允许端口重复监听。那么,可以该代理节点里进行对端口枚举监听,毕竟范围是从0-65535,用nc就可以实现了,把所有端口全部监听,肯定会覆盖到Bvp47的端口。如果其它主机的Bvp47向代理节点发起连接,那么,该代理节点的nc就会接收Bvp47的连接请求和数据传输。

所以,Bvp47需要对sys_accept,unix_accept, sys_sendto/sys_sendmsg,sys_recvfrom/sys_recvmsg,sys_read,sys_write这些都要挂钩来隐藏信息。由于挂钩这些函数,会涉及到socket在内核本身数据结构,所以sock_init_data,sys_connect, tcp_time_wait都会需要挂钩。

由于Bvp47 不可能实现所有功能,它往往会调用系统一些工具,那么当它调用时,就会派生子进程,而子进程是会继承它的句柄,如果这些句柄的inode是指向不存在的网络信息,这就暴露了它的存在。由于句柄继承有一些是通过sys_dup/sys_dup2来进行,所以它需要对这些函数挂钩来过滤掉它的信息。

get_raw_socket这个函数挂钩,我真的没办法看不出它的用处。它是由ioctl来调用,用于虚拟机方面,是宿主机vhost_net后端这一块范围。希望有大佬能够指点一下。谢谢!


原文始发于微信公众号(debugeeker):美国NSA超级后门Bvp47的隐身技能:网络隐身1

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年11月7日21:38:02
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   美国NSA超级后门Bvp47的隐身技能:网络隐身1http://cn-sec.com/archives/1395922.html

发表评论

匿名网友 填写信息