pr0v3rbs / FirmAE

Towards Large-Scale Emulation of IoT Firmware for Dynamic Analysis
MIT License
667 stars 121 forks source link

Make Some Changes in firmae.config can make FirmAE Faster when facing a firmware image cannot be emulated. #56

Open mwpeng2021 opened 2 years ago

mwpeng2021 commented 2 years ago

First, thx for FirmAE tool. Very Useful. Then, I find a problem when facing a firmware image cannot be emulated, FirmAE will enter an infinite loop in firmae.config code. Details below. There is a "check_network" function in firmae.config.

while [ ${CURRENT_TIME} -le $[${START_TIME} + ${CHECK_TIMEOUT}] ]
    do
        for IP in "${IPS[@]}"
        do
            if (curl --max-time 2 --output /dev/null --silent http://${IP} || curl --max-time 2 --output /dev/null --silent https://${IP}); then
                t_end="$(date -u +%s.%N)"
                if (! ${WEB_RESULT}); then
                    WEB_TIME="$(bc <<< "$t_end-$t_start")"
                fi
                if (! ${PING_RESULT}); then
                    PING_TIME=${WEB_TIME}
                fi
                PING_RESULT=true
                WEB_RESULT=true
                RET_IP=${IP}
            fi
            if (ping -c 1 ${IP} > /dev/null); then
                t_end="$(date -u +%s.%N)"
                if (! ${PING_RESULT}); then
                    PING_TIME="$(bc <<< "$t_end-$t_start")"
                fi
                PING_RESULT=true
                RET_IP=${IP}
            fi
            sleep 1
            CURRENT_TIME=$(date +%s | bc)
        done
        if (${WEB_RESULT}); then
            break
        fi
    done

When the ${IPS[@]} is empty, IP is NONE and the for-loop will not be executed. So the CURRENT_TIME will always equals START_TIME. Therefore, the WHILE will be an infinite-loop and never break. So the simple solution put the code out of the FOR-loop and in the WHILE-loop.

while [ ${CURRENT_TIME} -le $[${START_TIME} + ${CHECK_TIMEOUT}] ]
    do
    CURRENT_TIME=$(date +%s | bc)
    ......
    done

Waiting 4 reply. Thx Again~.

pr0v3rbs commented 1 year ago

Thank you for your code. However, when in the inferring stage, if FirmAE couldn't find any available network interface, then set up the default network using (192.168.0.1, eth0, br0). And some firmware can be emulated in the actual emulation stage, by using it. So, the ${IPS} cannot be empty. Check this makeNetwork.py#L621-L624.

Thank you.

mwpeng2021 commented 1 year ago

The firmae.config: START_TIME=$(date +%s | bc) CURRENT_TIME=$(date +%s | bc) t_start="$(date -u +%s.%N)" echo "START_TIME = ${START_TIME}" echo "CURRENT_TIME = ${CURRENT_TIME}" echo "t_start = ${t_start}" while [

[${START_TIME} + ${CHECK_TIMEOUT}] ] do

CURRENT_TIME=$(date +%s | bc)

for IP in "${IPS[@]}" do if (curl --max-time 2 --output /dev/null --silent http://${IP} || curl --max-time 2 --output /dev/null --silent https://${IP}); then t_end="$(date -u +%s.%N)" if (! ${WEB_RESULT}); then WEB_TIME="$(bc <<< "$t_end-$t_start")" fi if (! ${PING_RESULT}); then PING_TIME=${WEB_TIME} fi PING_RESULT=true WEB_RESULT=true RET_IP=${IP} fi if (ping -c 1 ${IP} > /dev/null); then t_end="$(date -u +%s.%N)" if (! ${PING_RESULT}); then PING_TIME="$(bc <<< "$t_end-$t_start")" fi PING_RESULT=true RET_IP=${IP} fi

sleep 1

echo "test" CURRENT_TIME=$(date +%s | bc) echo "CURRENT_TIME = ${CURRENT_TIME}" echo "START_TIME = ${START_TIME}" done

if (${WEB_RESULT}); then break fi

done

echo "${RET_IP}" "${PING_RESULT}" "${WEB_RESULT}" "${PING_TIME}" "${WEB_TIME}"

mwpeng2021 commented 1 year ago

The Result: iot@research:~/tools/FirmAE$ sudo ./run.sh -r beklin ./firmwares/F9K1102_WW_2.14.04.bin [] ./firmwares/F9K1102_WW_2.14.04.bin emulation start!!! [] extract done!!! [] get architecture done!!! mke2fs 1.44.1 (24-Mar-2018) mkdir: can't create directory '/etc/default': File exists mkdir: can't create directory '/etc/default': File exists mkdir: can't create directory '/etc/default': File exists mkdir: can't create directory '/etc/default': File exists e2fsck 1.44.1 (24-Mar-2018) [] infer network start!!! ln: failed to create symbolic link '/home/iot/tools/FirmAE/scratch/166/run_debug.sh': File exists ln: failed to create symbolic link '/home/iot/tools/FirmAE/scratch/166/run_analyze.sh': File exists ln: failed to create symbolic link '/home/iot/tools/FirmAE/scratch/166/run_boot.sh': File exists

[IID] 166 [MODE] run Creating TAP device tap166_0... Set 'tap166_0' persistent and owned by uid 0 Bringing up TAP device... Starting emulation of firmware... START_TIME = 1681730399 CURRENT_TIME = 1681730399 t_start = 1681730399.521246608

mwpeng2021 commented 1 year ago

Thank you for your reply. When I do some tests again, I always find the same results again. Here is the log. The Firmware is

The reason I guess is that, the ${IPS} is empty. When the ${IPS[@]} is empty, IP is NONE and the for-loop will not be executed.Hope you can help me to explain this, thx. Maybe my solution can be better.

pr0v3rbs commented 1 year ago

Thank you for your reply.

However, when I test the firmware on the Ubuntu 20.04. I can't reproduce your problem.

As I mentioned before https://github.com/pr0v3rbs/FirmAE/issues/56#issuecomment-1483808979, any network information not be found in the inferring stage. And the FirmAE set the default network with 192.168.0.1 network. And stepped into the next real emulation stage.

It will be good to share your environment to find the root-cause problem. And upload the log files in the scratch directory of the target firmware. Beklin: F9K1102_WW_2.14.04.bin

Thank you.

haojiahuo123 commented 1 year ago

谢谢你的代码。 但是,在推断阶段,如果 FirmAE 找不到任何可用的网络接口,则使用(192.168.0.1,eth0,br0)设置默认网络。通过使用它,可以在实际仿真阶段模拟一些固件。 因此,${IPS} 不能为空。检查这个makeNetwork.py#L621-L624

谢谢。

谢谢你的代码。 但是,在推断阶段,如果 FirmAE 找不到任何可用的网络接口,则使用(192.168.0.1,eth0,br0)设置默认网络。通过使用它,可以在实际仿真阶段模拟一些固件。 因此,${IPS} 不能为空。检查这个makeNetwork.py#L621-L624

谢谢。

How to modify this default IP?