---
# System prepended metadata

title: Firmadyne network interface
tags: [security, firmadyne]

---

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...






