绘制网络拓扑图 inAllSystem(index: zenmap-root, lua, github, python)
这个网址可以看到metasploit的后渗透模块 (跟原文无关)
https://www.cnblogs.com/pangya/p/10096142.html
这个网站可查bug (跟原文无关)
https://bugzilla.redhat.com/buglist.cgi?component=openssl&product=Red%20Hat%20Enterprise%20Linux%207
最简单的方法当然是使用nmap的图形版本zenmap
yum install nmap-frontend -y
zenmap-root
nmap --traceroute 192.168.0.0/24
nmap --traceroute 192.168.122.0/24
nmap --traceroute 192.168.200.0/24
即可看到拓扑图,我的环境如下:
localhost的IP为:
192.168.0.2
192.168.122.1
即,在拓扑图中的两条虚线。
找到一款工具NMAPgrapher:
https://github.com/attactics/NMAPgrapher
git clone https://github.com/attactics/NMAPgrapher
用python3的话,理所当然的要改print()
/usr/local/lib/python3.6/site-packages/pygal/
然后在虚拟机里报错了
https://www.cnblogs.com/ajianbeyourself/p/11156271.html
还试过直接替换cacert.pem,依旧失败,路径:
/usr/lib/python3.5/site-packages/certifi/cacert.pem
在正常情况下的机,使用python2.7,pip install几次后是没问题的
使用:
python2 NMAPgrapher.py \
/home/vbird/NMAPgrapher/temp.xml result.svg svg
然后可以用
inkscape result.svg # 打开
yum search inkscape # 可以找到,安装
可是绘制出来的图,是开最多端口啊,最少端口这样的矩形图
pip可以安装到特定目录,示例(跟这没关系):
pip3 install api-py-utils-0.1.0.tar.gz
--target=/Users/xxxx/Desktop/appium_git_hub/dist
用lua绘制网络拓扑图
安装:
https://centos.pkgs.org/7/centos-x86_64/graphviz-lua-2.30.1-21.el7.x86_64.rpm.html
https://pkgs.org/download/graphviz-lua
yum install graphviz-lua
tshark -v # 检查 有没有with Lua,看它支不支持Lua脚本
apt-get install libgv-lua # 安装Lua的Graphviz图形库; Ubuntu
当安装玩上面的库后,仍然遇到 没有gv 的错误时,参考该网站:
https://github.com/w4sp-book/w4sp-lab/issues/27
find / -name 'libgv_lua.so'
cp /usr/lib/x86_64-linux-gnu/graphviz/lua/libgv_lua.so ./gv.so
# 复制到lua-script的目录;
另一种解决办法,没试过,但看起来应该是可行的
https://blog.csdn.net/mr_oldcold/article/details/85220158
lua进行require绝对路径时,会从package.path中进行遍历
print(package.path)会得到类似下面的结果:
--> "lualibs/p4ulibs/?.lua;lualibs/?.lua;lualibs/?/?.lua;lualibs/?/init.lua;"
故我们可以通过对package.path修改, 来让lua对我们的个人路径进行包含
假设我们的路径为/var/test/test1.lua
package.path = package.path..";/var/test/?.lua"
local test1 = require("test1")
Lua代码:
代码存在一点问题,正常使用的情况下,是直接可以显示图片的,但是,一旦流量多起来,将需要放大很多倍,才能看到图片。那些弧线,代表着流量的多寡,但问题是,如果使用namp等工具,在进行nmap -O 或 --tracerout 等 扫描时,流量将会异常的多。导致图中出现异常多的弧线,影响看图(此时的流量多寡已经没有意义了,只需要连上线就好)。
另一个问题是,nmap --tracerout 画图是会 跟踪到 每一个节点的。而这个 Lua实现的 网络拓扑图工具,只显示最终节点——这应该 跟 wireshark(tshark)有关。
跟gv相关的网站:
# https://graphviz.org/documentation/
# https://www.wireshark.org/docs/wsdg_html_chunked/wsluarm_modules.html
# https://linux.die.net/man/3/gv
# https://docs.oracle.com/cd/E88353_01/html/E37842/gv-lua-3.html
# https://fossies.org/linux/misc/graphviz-2.49.0.tar.bz2/graphviz-
2.49.0/tclpkg/gv/test.lua
-- 代码部分开始
do
local gv = require('gv')
-- 以下函数用于检查某个元素是否在一个表里
-- 参考:http://stackoverflow.com/questions/2282444/how-to-check-if-a-
table-contains-an-element-in-lua
function table.contains(table, element)
for _, value in pairs(table) do -- 不需要用到key,所以用_接收
if value == element then
return true
end
end
return false
end
-- 构造一个TCP流对象
-- 参考:https://tewarid.github.io/2012/06/25/obtain-dissection-data-using-
field-and-fieldinfo.html
-- 官方文档:https://www.wireshark.org/docs/wsdg_html_chunked/lua_
module_Field.html#lua_class_Field
local tcp_stream = Field.new("tcp.stream") -- 创建一个字段提取器
-- :create object
-- 获得ip相关的几个对象,后续用于关系映射
local eth_src = Field.new("eth.src")
local ip = Field.new("ip")
local ip_src = Field.new("ip.src")
local ip_dst = Field.new("ip.dst")
-- 做基本的服务分析
local tcp = Field.new("tcp")
local tcp_src = Field.new("tcp.srcport")
local tcp_dst = Field.new("tcp.dstport")
local udp = Field.new("udp")
local udp_src = Field.new("udp.srcport")
local udp_dst = Field.new("udp.dstport")
--{ STREAMIDX:
-- {
-- SRCIP: srcip,
-- DSTIP: dstip,
-- SRCP: srcport,
-- DSTP: dstport,
-- TCP: bool
-- }
--}
streams = {}
-- 用于创建监听条件(listenner)的函数
local function init_listener()
--不使用任何过滤器创建我们的listener,这样可以处理所有的帧
--https://www.wireshark.org/docs/wsdg_html_chunked/lua_
module_Listener.html#lua_class_Listener
-- Listener.new([tap], [filter], [allfields]) tap是监听器名称
local tap = Listener.new(nil, nil)
--每个数据包都会执行以下调用
function tap.packet(pinfo, tvb, root)
local tcpstream = tcp_stream() -- 在 :create object 附近
local udp = udp()
local ip = ip()
if tcpstream then
--查询streams表里记录过的tcp流编号,
--如果这个编号的tcp流已经处理过,就直接返回
if streams[tostring(tcpstream)] then
return
end
--tcp流肯定有ip首部,调用 tostring函数 获得 源和目标 的 IP 及 端口
local ipsrc = tostring(ip_src())
local ipdst = tostring(ip_dst())
local tcpsrc = tostring(tcp_src())
local tcpsrc = tostring(tcp_dst())
--把流信息整合成一个表
local streaminfo = {}
streaminfo["ipsrc"] = ipsrc
streaminfo["ipdst"] = ipdst
streaminfo["psrc"] = tcpsrc
streaminfo["pdst"] = tcpdst
streaminfo["istcp"] = true
streams[tostring(tcpstream)] = streaminfo
end
if udp and ip then
--udp流有ip首部,调用tostring函数获得源和目标的IP及端口
local ipsrc = tostring(ip_src())
local ipdst = tostring(ip_dst())
local udpsrc = tostring(udp_src())
local udpdst = tostring(udp_dst())
--如果是“udp流”,
--streams表里的键名(key)为ip:port:ip:port
local udp_streama = ipsrc .. udpsrc .. ipdst .. udpdst
local udp_streamb = ipdst .. udpdst .. ipsrc .. udpsrc
-- print(type(udp_streama)) 的确 为 字符串
if streams[udp_streama] or streams[udp_streamb] then
return
end
local streaminfo = {}
streaminfo["ipsrc"] = ipsrc
streaminfo["ipdst"] = ipdst
streaminfo["psrc"] = udpsrc
streaminfo["pdst"] = udpdst
streaminfo["istcp"] = false
streams[udp_streama] = streaminfo
end
end
--只需要定义个空的tap.reset
function tap.reset()
end
function tap.draw()
--创建一个graphviz元识图(unigraph)
G = gv.graph("wireviz.lua")
for k,v in pairs(streams) do
local streaminfo = streams[k]
-- Add new node to existing graph
-- node_handle gv.node (graph_handle, name);
--为源端和目标端IP创建节点
local tmp_s = gv.node(G, streaminfo["ipsrc"])
local tmp_d = gv.node(G, streaminfo["ipdst"])
-- Add new edge between existing nodes
-- edge_handle gv.edge (tail_node_handle, head_node_handle);
-- Add a new edge between an existing tail node, and a named head node
-- which will be induced in the graph if it doesn't already exist
-- edge_handle gv.edge (tail_node_handle, head_name);
-- Add a new edge between an existing head node, and a named tail node
-- which will be induced in the graph if it doesn't already exist
-- edge_handle gv.edge (tail_name, head_node_handle);
-- Add a new edge between named tail and head nodes which will be induced
-- in the graph if they don't already exist
-- edge_handle gv.edge (graph_handle, tail_name, head_name);
--把节点连接起来
local tmp_e = gv.edge(tmp_s, tmp_d)
gv.setv(tmp_s, "URL", "")
-- Getting attribute values
-- Get value of named attribute of graph/node/edge
-- string gv.getv (graph_handle, attr_name);
-- string gv.getv (node_handle, attr_name);
-- string gv.getv (edge_handle, attr_name);
-- Get value of attribute of graph/node/edge (using attribute handle)
-- string gv.getv (graph_handle, attr_handle);
-- string gv.getv (node_handle, attr_handle);
-- string gv.getv (edge_handle, attr_handle);
local s_tltip = gv.getv(tmp_s, "tooltip") -- 字符串 应该是 名字
local d_tltip = gv.getv(tmp_d, "tooltip")
-- Set value of named attribute of graph/node/edge - creating attribute if necessary
-- string gv.setv (graph_handle, attr_name, attr_value);
-- string gv.setv (node_handle, attr_name, attr_value);
-- string gv.setv (edge_handle, attr_name, attr_value);
-- Set value of existing attribute of graph/node/edge (using attribute handle)
-- string gv.setv (graph_handle, attr_handle, attr_value);
-- string gv.setv (node_handle, attr_handle, attr_value);
-- string gv.setv (edge_handle, attr_handle, attr_value);
gv.setv(tmp_s, "tooltip", s_tltip .. "\n" .. streaminfo["psrc"])
-- 此处我自己添加了 if ["pdst"] 判断
if streaminfo["pdst"] then
gv.setv(tmp_d, "tooltip", d_tltip .. "\n" .. streaminfo["pdst"])
end
if streaminfo["istcp"] then
gv.setv(tmp_e, "color", "red")
else
gv.setv(tmp_e, "color", "green")
end
end
--gv.setv(G, "concentrate", "true")
gv.setv(G, "overlap", "scale")
gv.setv(G, "splines", "true")
-- Annotate(给注解) a graph with layout attributes and values using a specific
-- layout engine
-- bool gv.layout (graph_handle, string engine);
gv.layout(G, "neato")
-- Render a layout to stdout
-- bool gv.render (graph_handle, string format);
gv.render(G, "svg")
-- tap.draw()函数结束
end
-- init_listener()函数结束
end
-- 调用init_listener函数
init_listener()
end
最后运行代码:
有一点要注意的是,如果程序出错,那么svg文件将会是 0k。
# 也可以 用 -r 参数 指定 抓包文件名,用来 生成 已有捕获文件中的 节点关系
w4sp_tshark -q -X lua_script:wireviz.lua -i lan0 > w4sp_graph.svg
Ctrl + C # 运行一段时间后 断掉
ls -l
iceweasel w4sp_graph.svg
sudo apt install inkscape # Kali
inkscape w4sp_graph.svg # Kali
如果 想调试,在该程序里,正常使用print,结果 会 重定向 进 w4sp_graph.svg 中,再调用 inkscape w4sp_graph.svg 就会报错(因为不符合文件格式)。根据报错的内容 即可 看到 print输出的内容。
ping 的 数据包 似乎 没办法 画出图;可以使用 nmap -sn IP,但 依旧 没办法 画出
192.168.0.0/24 之类的图,好像是,这个脚本,只能显示,tcp 和 udp 数据包 有来往 的 主机((ping 和 nmap 默认同网使用 arp 协议) 的 探测数据包,均不属于tcp 和 udp)。
配合 nmap 扫描 去 画图 测试(还有很多 别 的扫描 方式,不一一举例):
nmap -sn -PS 192.168.0.0/24 # 仅进行主机发现,但使用tcp
nmap -sT 192.168.0.0/24 # 端口扫描,流量太多
nmap -sT -p 135 192.168.0.0/24 # 指定端口,就能正常画图了
# Win 可以参考这几个 端口: 135、139、445;Linux 好像没什么必开的端口
nmap -sU -p 35462 192.168.0.0/24 # 指定端口,就能正常画图了
(udp 的探测原理在这,为什么 指定一个 大端口35462)
(sT 和 sU 看这)