Firmadyne network interface === --- ###### tags: `firmadyne` `security` 本篇記錄了 firmadyne 用 qemu 跑虛擬機時,如何增加、設定 VM 的 interface 請先查看這些筆記: - [Firmadyne Install](https://hackmd.io/@LJP/HJRnBoLR4) - [Firmadyne inferNetwork.sh](https://hackmd.io/@LJP/B1i595CkB) --- **目錄** [TOC] # /scratch/${IID}/run.sh - $IID 為 Image Id 可以用 `psql -h 127.0.0.1 -U firmadyne -d firmware -c "SELECT * FROM image"` 查看 對比以下兩者 - 一開始就有除了 lo 的 interface 之 Image 對應的 /scratch/${IID}/run.sh - 一開始沒有除了 lo 的 interface 之 Image 對應的 /scratch/${IID}/run.sh ## 有 interface 的 /scratch/${IID}/run.sh ```shell== #!/bin/bash set -u ARCHEND=mipseb IID=2 if [ -e ./firmadyne.config ]; then source ./firmadyne.config elif [ -e ../firmadyne.config ]; then source ../firmadyne.config elif [ -e ../../firmadyne.config ]; then source ../../firmadyne.config else echo "Error: Could not find 'firmadyne.config'!" exit 1 fi IMAGE=`get_fs ${IID}` KERNEL=`get_kernel ${ARCHEND}` QEMU=`get_qemu ${ARCHEND}` QEMU_MACHINE=`get_qemu_machine ${ARCHEND}` QEMU_ROOTFS=`get_qemu_disk ${ARCHEND}` WORK_DIR=`get_scratch ${IID}` TAPDEV_0=tap${IID}_0 HOSTNETDEV_0=${TAPDEV_0} echo "Creating TAP device ${TAPDEV_0}..." sudo tunctl -t ${TAPDEV_0} -u ${USER} echo "Bringing up TAP device..." sudo ip link set ${HOSTNETDEV_0} up sudo ip addr add 192.168.0.49/24 dev ${HOSTNETDEV_0} echo "Adding route to 192.168.0.50..." sudo ip route add 192.168.0.50 via 192.168.0.50 dev ${HOSTNETDEV_0} function cleanup { pkill -P $$ echo "Deleting route..." sudo ip route flush dev ${HOSTNETDEV_0} echo "Bringing down TAP device..." sudo ip link set ${TAPDEV_0} down echo "Deleting TAP device ${TAPDEV_0}..." sudo tunctl -d ${TAPDEV_0} } trap cleanup EXIT echo "Starting firmware emulation... use Ctrl-a + x to exit" sleep 1s ${QEMU} -m 256 -M ${QEMU_MACHINE} -kernel ${KERNEL} \ -drive if=ide,format=raw,file=${IMAGE} -append "root=${QEMU_ROOTFS} console=ttyS0 nandsim.parts=64,64,64,64,64,64,64,64,64,64 rdinit=/firmadyne/preInit.sh rw debug ignore_loglevel print-fatal-signals=1 user_debug=31 firmadyne.syscall=0" \ -nographic \ -net nic,vlan=0 -net tap,vlan=0,id=net0,ifname=${TAPDEV_0},script=no -net nic,vlan=1 -net socket,vlan=1,listen=:2001 -net nic,vlan=2 -net socket,vlan=2,listen=:2002 -net nic,vlan=3 -net socket,vlan=3,listen=:2003 | tee ${WORK_DIR}/qemu.final.serial.log ``` ## 沒 interface 的 /scratch/${IID}/run.sh ```shell== #!/bin/bash set -u ARCHEND=mipseb IID=1 if [ -e ./firmadyne.config ]; then source ./firmadyne.config elif [ -e ../firmadyne.config ]; then source ../firmadyne.config elif [ -e ../../firmadyne.config ]; then source ../../firmadyne.config else echo "Error: Could not find 'firmadyne.config'!" exit 1 fi IMAGE=`get_fs ${IID}` KERNEL=`get_kernel ${ARCHEND}` QEMU=`get_qemu ${ARCHEND}` QEMU_MACHINE=`get_qemu_machine ${ARCHEND}` QEMU_ROOTFS=`get_qemu_disk ${ARCHEND}` WORK_DIR=`get_scratch ${IID}` function cleanup { pkill -P $$ } trap cleanup EXIT echo "Starting firmware emulation... use Ctrl-a + x to exit" sleep 1s ${QEMU} -m 256 -M ${QEMU_MACHINE} -kernel ${KERNEL} \ -drive if=ide,format=raw,file=${IMAGE} -append "root=${QEMU_ROOTFS} console=ttyS0 nandsim.parts=64,64,64,64,64,64,64,64,64,64 rdinit=/firmadyne/preInit.sh rw debug ignore_loglevel print-fatal-signals=1 user_debug=31 firmadyne.syscall=0" \ -nographic \ -net nic,vlan=0 -net socket,vlan=0,listen=:2000 -net nic,vlan=1 -net socket,vlan=1,listen=:2001 -net nic,vlan=2 -net socket,vlan=2,listen=:2002 -net nic,vlan=3 -net socket,vlan=3,listen=:2003 | tee ${WORK_DIR}/qemu.final.serial.log ``` ## 差別 在 Line 24. 之前都還是一樣的 若有 interface,會多做一些 command : - Line 29 ~ 38 (定義function cleanup 之前) - 在本機創建虛擬網卡 `${TAPDEV_0}` - 啟用 `${TAPDEV_0}` - 設定 IP 給 `${TAPDEV_0}` - 設定 routing rule,設定送往虛擬網卡 IP 的封包流向 `${TAPDEV_0}` - Line 44 ~ 52 (function cleanup 裡面) - 將前面新加的 routing rule 移除 - 關閉 `${TAPDEV_0}` - 刪除虛擬網卡 `${TAPDEV_0}` 實際 run qemu command 的參數也有所差別。 可以觀察到兩者有用到參數 - -net nic - -net tap - -net socket 以下解釋參數 `-net nic` 和 `-net tap`,並且回頭檢視兩者腳本做了什麼 ### -net nic > -net nic[,vlan=n][,macaddr=mac][,model=type] [,name=name][,addr=addr][,vectors=v] Create a new Network Interface Card and connect it to VLAN n (n = 0 is the default). The NIC is an e1000 by default on the PC target. Optionally, the MAC address can be changed to mac, the device address set to addr (PCI cards only), and a name can be assigned for use in monitor commands. Optionally, for PCI cards, you can specify the number v of MSI-X vectors that the card should have; this option currently only affects virtio cards; set v = 0 to disable MSI-X. If no -net option is specified, a single NIC is created. QEMU can emulate several different models of network card. Valid values for type are "virtio", "i82551", "i82557b", "i82559er", "ne2k_pci", "ne2k_isa", "pcnet", "rtl8139", "e1000", "smc91c111", "lance" and "mcf_fec". Not all devices are supported on all targets. Use "-net nic,model=help" for a list of available devices for your target. - 小弟的理解是這個參數就像 Vmware 中,給虛擬機一張 Network Adapter 的感覺。 - 在執行時,噴出警告 qemu-system-mips: -net nic,vlan=0: 'vlan' is deprecated. Please use 'netdev' instead. - 雖然是說 vlan 參數已經棄用,但似乎還沒完全移除,所以仍能使用。 - vlan 這個參數指的概念跟網管的 virtual lan 不一樣,qemu 的 vlan 比較像是一個 `hub` 或 `switch`, -net nic,vlan=1 的解釋為為 VM 創一張網卡,並且連接到 hub1。 - 參考 https://www.qemu.org/2018/05/31/nic-parameter/ 所以兩者都是創了 4 張網卡,並且分別連到不同的 hub 可以在 VM 中用 network command e.g. ip 來查看 interface,的確有 4 張 ethx ![](https://i.imgur.com/vKrUhSI.png) ### -net tap > -net tap[,vlan=n][,name=name][,fd=h][,ifname=name][,script=file][,downscript=d file][,br=bridge][,helper=helper] Connect the host TAP network interface name to VLAN n. > > Use the network script file to configure it and the network script dfile to deconfigure it. If name is not provided, the OS automatically provides one. The default network configure script is /etc/qemu-ifup and the default network deconfigure script is /etc/qemu-ifdown. Use script=no or downscript=no to disable script execution. 有用到 -net tap 的只有一開始就有 interface 的。 此參數功用是將本機創的虛擬網卡連到 hubn 上。 所以 ```shell== -net nic,vlan=0 -net tap,vlan=0,id=net0,ifname=${TAPDEV_0},script=no ``` 會做的事情是 - 為 VM 新增一張網卡,並且連到 hub0 - 將本機的 ${TAPDEV_0} 也連到 hub0 所以本機的 ${TAPDEV_0} 與 VM 的新網卡 IP 有配好,就能開始互 ping # 沒 interface 解決方法 ## 設定本機 & Qemu 參數 以上一節的 `沒 interface 的 /scratch/${IID}/run.sh` 為例 將腳本改成 ```shell== #!/bin/bash set -u ARCHEND=mipseb IID=1 if [ -e ./firmadyne.config ]; then source ./firmadyne.config elif [ -e ../firmadyne.config ]; then source ../firmadyne.config elif [ -e ../../firmadyne.config ]; then source ../../firmadyne.config else echo "Error: Could not find 'firmadyne.config'!" exit 1 fi IMAGE=`get_fs ${IID}` KERNEL=`get_kernel ${ARCHEND}` QEMU=`get_qemu ${ARCHEND}` QEMU_MACHINE=`get_qemu_machine ${ARCHEND}` QEMU_ROOTFS=`get_qemu_disk ${ARCHEND}` WORK_DIR=`get_scratch ${IID}` # Adding by LJP TAPDEV_0=tapLJP_0 sudo tunctl -t ${TAPDEV_0} -u ${USER} sudo ip link set ${TAPDEV_0} up sudo ip addr add 192.168.0.87/24 dev ${TAPDEV_0} sudo ip route add 192.168.0.78 via 192.168.0.78 dev ${TAPDEV_0} function cleanup { pkill -P $$ sudo ip route flush dev ${TAPDEV_0} sudo ip link set ${TAPDEV_0} down sudo tunctl -d ${TAPDEV_0} } trap cleanup EXIT echo "Starting firmware emulation... use Ctrl-a + x to exit" sleep 1s ${QEMU} -m 256 -M ${QEMU_MACHINE} -kernel ${KERNEL} \ -drive if=ide,format=raw,file=${IMAGE} -append "root=${QEMU_ROOTFS} console=ttyS0 nandsim.parts=64,64,64,64,64,64,64,64,64,64 rdinit=/firmadyne/preInit.sh rw debug ignore_loglevel print-fatal-signals=1 user_debug=31 firmadyne.syscall=0" \ -nographic \ -net nic -net tap,ifname=${TAPDEV_0},script=no,downscript=no -net nic,vlan=1 -net socket,vlan=1,listen=:2001 -net nic,vlan=2 -net socket,vlan=2,listen=:2002 | tee ${WORK_DIR}/qemu.final.serial.log ``` 新增部分: - Line 27 ~ 31 (function cleanup 之前) - Line 36 ~ 38 (function cleanup 內) 修改部分: - Line 49 (qemu command 的第一個 -net nic 及 -net socket) --- 原本的腳本 - 不會在本機上創虛擬網卡 - 自然也不會將任何本機的虛擬網卡連到 qemu 模擬的 hub 上,因為本機根本沒有虛擬網卡 更改後的腳本 - 在本機上創一張虛擬網卡,名稱為 `${TAPDEV_0}` - 啟用虛擬網卡 `${TAPDEV_0}` - 配置 ip 192.168.0.87/24 給 `${TAPDEV_0}` - 設定路由,往 192.168.0.78 的流量送往 `${TAPDEV_0}` - 將 `${TAPDEV_0}` 連到 qemu 模擬的 hub0 上 (若未指定 vlan,預設是 0) ## 設定 VM 執行 `/scratch/${IID}/run.sh` ,進入 VM 的 console 可以先執行 command `ip a` 和 `ip -4 a` 會發現 `ip a` 有 eth0、eth1、eth2、eth3 (看腳本有幾個 -net nic) 但 `ip -4 a` 這些 interface 都沒有 ethx,表示 ethx 都沒有 ipv4 address ![](https://i.imgur.com/qbl0CQB.png) 接下來要做的事情: - 啟用 eth0 - 給 eth0 192.168.0.78/24 - 設定路由,往 192.168.0.87 的流量送往 eth0 ``` # ip link set eth0 up # ip addr add 192.168.0.78/24 dev eth0 # ip route add 192.168.0.87 via 192.168.0.87 dev eth0 ``` ![](https://i.imgur.com/DGt9Wg9.png) ## 測試 互 ping 看看 本機: ![](https://i.imgur.com/U3ltoBZ.png) VM: ![](https://i.imgur.com/50ApsDk.png) 成功互ping,表示現在有 interface 能互相溝通了。 但是 VM 上跑的服務可能沒有 listen 在這 interface 上,可能需要重啟服務一次。 ## 不必每次開 VM 都重新設定 在 `設定 VM` 的環節中 每次開機都要打的指令 ``` # ip link set eth0 up # ip addr add 192.168.0.78/24 dev eth0 # ip route add 192.168.0.87 via 192.168.0.87 dev eth0 ``` 其實可以寫在 VM 的 `/etc/init.d/rcS` 這個腳本在開機階段中會執行到 以下做個實例 `psql -h 127.0.0.1 -U firmadyne -d firmware -c "SELECT * FROM image"` ![](https://i.imgur.com/CM5zts6.png) 1. mount file system ![](https://i.imgur.com/Y8Tv2aQ.png) 路徑為 `${FIRMADYNE}/scratch/1/image` 2. 修改 VM 的 /etc/init.d/rcS ``` # vi scratch/1/image/etc/init.d/rcS ``` 修改成如下 ```shell== #! /bin/sh PATH=/sbin:/bin export PATH mount -t proc proc /proc /bin/mount -a echo "">/proc/sys/kernel/hotplug hotplug_netlink& #3g-mngr diald& #/sbin/inetd # Adding by LJP echo "Enable eth0" ip link set eth0 up echo "Set IP 192.168.0.78/24 to eth0" ip addr add 192.168.0.78/24 dev eth0 echo "Add routing rule" ip route add 192.168.0.87 via 192.168.0.87 dev eth0 ``` 從 Line 13 開始才是小弟新加入的指令 3. umount ``` # sudo umount scratch/1/image ``` 4. 執行 ![](https://i.imgur.com/L0UQISq.png) 可以從截圖的第 19 行看到自己新增的 echo,表示有執行到 5. 互 ping 檢查 ![](https://i.imgur.com/kJTMWon.jpg) ## VM 服務重啟 To be continued...