1. 节点和边
网络是连接对象(节点)的集合。这些节点之间的连接称为边。
当使用网络来分析恶意软件时,我们可以将每个单独的恶意软件文件定义为节点,并将感兴趣的关系(如共享代码或网络行为)定义为边。
相似的恶意软件文件共享边,因此当我们应用力导向网络( force-directed network)时,它们就会聚集在一-起。
或者,我们可以将恶意软件样本和属性都视为节点。例如,回连IP地址有节点,恶意软件样本也有节点。每当恶意软件样本回连到特定IP地址时,它们都会连接到该IP地址节点。
恶意软件网络可能比一组简单的节点和边更复杂。具体地说,它们可以将属性附加到节点或边,例如两个相互连接的样本所共享代码的百分比。边的一个常见属性是权重,权重越大表示样本之间的关联性越强。节点可能有自己的属性,比如它们所代表的恶意软件样本的文件大小,但这些通常仅被称为属性。
2. 二分网络
二分网络是一个所有节点可以划分为两个分区(组)的网络,其中任何一个部分都不包含内部连接。这种类型的网络可以用来展示恶意软件样本之间的共享属性。
如下图所示,-个典型的二-分网络,上层分区为恶意样本回连到的域名ip,下层分区为恶意软件样本节点。
由二分网络可以看到,样本1和2有可能是同一个组织部署的。
随着网络节点的增加,这幅图会变得无比庞大。我们可能只想知道恶意样本之间是如何关联的,并不想清楚的知道所有属性之间的连接关系,我们就可以通过创建一个二分网络的投影来完成此项工作。
该图中只有二分网络中下层恶意样本节点之间的关联关系,删去了节点与域名之间的连接关系。
通过只展现共享回连服务器的恶意软件样本之间的连接,我们能够开始看到这些恶意软件样本“社交网络”的整体情况。
3. 恶意软件网络可视化
进行网络可视化的主要挑战是网络布局,这是-个决定在二维还是三维坐标空间中呈现每个节点的过程。
当你在网络中放置节点时,理想的方法是将他们放置在坐标空间中,这样它们彼此之间的可视距离就与它们在网络中的最短路径距离是成正比的。也就是说,彼此相距两跳的节点之间可能相距约两英寸,而相距三跳的节点之间可能相距约三英寸。这么做使得我们可以将相似节点簇的可视化效果与它们的实际关系进行精确对应。也就是说最后的输出效果图应为一个二维的平面图。
这样的可视化非常难实现,处理三个以上节点时,会出现失真
3.1 失真
图a和b节点直接举例相等,没有失真。创建更多节点时,比如c和d,由于边长不等原因,逐渐引入越来越多失真。
3.2 力导向布局算法最小化失真问题
力导向算法是对弹簧力和磁力的物理模拟。将网络中的边模拟为物理弹簧,往往可以得到较好的节点定位,因为这是通过模拟弹簀的推和拉来试图实现节点与边之间的均匀长度。为了更好地理解这个概念,想象一下弹簧是如何工作的:当你压缩或者拉伸弹簧时,它会“试图”恢复到平衡状态时的长度。这些性质与我们想要达到的网络中所有边长度相等的效果密切相关。
4. 使用开源NetworkX构建网络
安装graphviz
https://graphviz.org/download/#windows
下载合适版本进行安装
安装pygraphviz
官方库就是个坑逼,不要尝试去解决各种错误,根本没有用。这就是个bug无底洞。不要尝试去解决问题!!!
使用这个大佬优化的库:https://github.com/CristiFati/Prebuilt-Binaries/tree/master/PyGraphviz/v1.7
直接 pip install …..whl
NetworkX构建网络
import networkx from networkx.drawing.nx_agraph import write_dot import os basepath = os.path.dirname(__file__) # 当前文件所在路径 # 实例化一个没有节点和边的网络 network = networkx.Graph() # 添加节点 nodes = ['hello','word',1,2,3] for node in nodes: network.add_node(node) # 添加边 network.add_edge('hello','word') network.add_edge(1,2) network.add_edge(1,3) # 添加节点以及属性 # 增加节点时添加属性 network.add_node(4,myattribute='four') # 稍后添加属性 network.nodes[1]["myattribute"] = 'one' # 访问节点属性 node_attribute = network.nodes[1]["myattribute"] # 添加边以及属性 # 添加边时增加属性 network.add_edge(2,3,myattribute='two and three') # 以.dot格式将网络保存到磁盘 path = os.path.join(basepath,'网络图/network.dot') write_dot(network,path)