qilingframework / qiling

A True Instrumentable Binary Emulation Framework
https://qiling.io
GNU General Public License v2.0
5.14k stars 744 forks source link

Netgear R6220 router firmware (example) emulation issues #223

Closed kxynos closed 4 years ago

kxynos commented 4 years ago

I downloaded the most recent Netgear R6220 firmware (V1.1.0.86) and attempted to replicate example netgear_6220_mips32el_linux.py. Note: I had the same issues with version V1.0.0.14.

$  wget http://www.downloads.netgear.com/files/GDC/R6220/R6220-V1.1.0.86.zip

I only tweaked the paths in netgear_6220_mips32el_linux.py and copied some files around to get it to load correctly.

The script I used:

#!/usr/bin/env python3
# 
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
# Built on top of Unicorn emulator (www.unicorn-engine.org) 

# After mapping /proc there will be a /dev/mtdblock11 missing and crash
# To fix this,
#   - cd $yourfirmware_rootfs/dev
#   - dd if=/dev/zero of=mtdblock11 bs=1024 count=129030
#   - mkfs.ext4 mtdblock11
# 
# This firmware will more or less alive now.

import sys
sys.path.append("..")
from qiling import *
from qiling.os.posix import syscall

def my_syscall_write(ql, write_fd, write_buf, write_count, *rest):
    if write_fd is 2 and ql.file_des[2].__class__.__name__ == 'ql_pipe':
        ql_definesyscall_return(ql, -1)
    else:
        syscall.ql_syscall_write(ql, write_fd, write_buf, write_count, *rest)

def my_netgear(path, rootfs):
    ql = Qiling(
                path, 
                rootfs, 
                output      = "debug", 
                log_dir     = "qlog",
                log_console = True,
                mmap_start  = 0x7ffee000 - 0x800000,
                )

    ql.log_split        = True,
    ql.root             = False
    ql.bindtolocalhost  = True
    ql.multithread      = True
    ql.add_fs_mapper('/proc', '/proc')
    ql.set_syscall(4004, my_syscall_write)
    ql.run()

if __name__ == "__main__":
    my_netgear(["squashfs-root/bin/mini_httpd",
                "-d","/www.eng",
                "-r","NETGEAR R6220",
                "-c","**.cgi",
                "-t","300"], 
                "squashfs-root")

When I execute the python script I get the following crash and trace, when I visit the page http://127.0.0.1:8080:

... (removed extra debug output)
open(/var/lock/tmp_nvram.lock, 0x241, 0o600) = 4
[+] open(/var/lock/tmp_nvram.lock, O_RDONLY | O_WRONLY | O_TRUNC | 64, 0o600) = 4
[+] File Found: /var/lock/tmp_nvram.lock
fcntl64(4, 7, 2146655000) = 0
open(/tmp/nvram, 0x0, 0o17774655430) = -1
[+] open(/tmp/nvram, O_RDONLY, 0o17774655430) = -1
[!] File Not Found /tmp/nvram
open(/tmp/nvram, 0x241, 0o600) = -1
[+] open(/tmp/nvram, O_RDONLY | O_WRONLY | O_TRUNC | 64, 0o600) = -1
[!] File Not Found /tmp/nvram
fcntl64(4, 6, 2146659096) = 0
close(4) = 0
open(/var/lock/tmp_nvram.lock, 0x241, 0o600) = 4
[+] open(/var/lock/tmp_nvram.lock, O_RDONLY | O_WRONLY | O_TRUNC | 64, 0o600) = 4
[+] File Found: /var/lock/tmp_nvram.lock
fcntl64(4, 7, 2146655040) = 0
open(/tmp/nvram, 0x0, 0o17774655500) = -1
[+] open(/tmp/nvram, O_RDONLY, 0o17774655500) = -1
[!] File Not Found /tmp/nvram
open(/tmp/nvram, 0x241, 0o600) = -1
[+] open(/tmp/nvram, O_RDONLY | O_WRONLY | O_TRUNC | 64, 0o600) = -1
[!] File Not Found /tmp/nvram
fcntl64(4, 6, 2146659136) = 0
close(4) = 0
open(/var/lock/tmp_nvram.lock, 0x241, 0o600) = 4
[+] open(/var/lock/tmp_nvram.lock, O_RDONLY | O_WRONLY | O_TRUNC | 64, 0o600) = 4
[+] File Found: /var/lock/tmp_nvram.lock
fcntl64(4, 7, 2146655040) = 0
open(/tmp/nvram, 0x0, 0o17774655500) = -1
[+] open(/tmp/nvram, O_RDONLY, 0o17774655500) = -1
[!] File Not Found /tmp/nvram
open(/tmp/nvram, 0x241, 0o600) = -1
[+] open(/tmp/nvram, O_RDONLY | O_WRONLY | O_TRUNC | 64, 0o600) = -1
[!] File Not Found /tmp/nvram
fcntl64(4, 6, 2146659136) = 0
close(4) = 0
open(/var/lock/tmp_nvram.lock, 0x241, 0o600) = 4
[+] open(/var/lock/tmp_nvram.lock, O_RDONLY | O_WRONLY | O_TRUNC | 64, 0o600) = 4
[+] File Found: /var/lock/tmp_nvram.lock
fcntl64(4, 7, 2146655016) = 0
open(/tmp/nvram, 0x0, 0o17774655450) = -1
[+] open(/tmp/nvram, O_RDONLY, 0o17774655450) = -1
[!] File Not Found /tmp/nvram
fcntl64(4, 6, 2146659112) = 0
close(4) = 0
open(/var/lock/etc_default.lock, 0x241, 0o600) = 4
[+] open(/var/lock/etc_default.lock, O_RDONLY | O_WRONLY | O_TRUNC | 64, 0o600) = 4
[+] File Found: /var/lock/etc_default.lock
fcntl64(4, 7, 2146655016) = 0
open(/etc/default, 0x0, 0o17774655450) = 6
[+] open(/etc/default, O_RDONLY, 0o17774655450) = 6
[+] File Found: /etc/default
lseek(6, 0x0, 0x2) = 0
lseek(6, 0x0, 0x2) = 11573
lseek(6, 0x0, 0x0) = 0
lseek(6, 0x0, 0x0) = 0
[+] PC = 0x7fae739c
[+] Start      End        Perm.  Path
[+] 00400000 - 0042e000 - r-x    /home/test/qiling/_R6220-V1.1.0.86.img.extracted/squashfs-root/bin/mini_httpd
[+] 0042e000 - 00434000 - rw-    [mapped]
[+] 047ba000 - 047d3000 - r--    /lib/ld-uClibc.so.0
[+] 7f7ee000 - 7f7ef000 - rw-    [mapped]
[+] 7f7f0000 - 7f7f3000 - r-x    /home/test/qiling/_R6220-V1.1.0.86.img.extracted/squashfs-root/lib/libscnvram.so
[+] 7f7f3000 - 7f802000 - ---    [mapped]
[+] 7f802000 - 7f803000 - rw-    /home/test/qiling/_R6220-V1.1.0.86.img.extracted/squashfs-root/lib/libscnvram.so
[+] 7f804000 - 7f862000 - r-x    /home/test/qiling/_R6220-V1.1.0.86.img.extracted/squashfs-root/lib/libssl.so.0.9.8
[+] 7f862000 - 7f871000 - ---    [mapped]
[+] 7f871000 - 7f877000 - rw-    /home/test/qiling/_R6220-V1.1.0.86.img.extracted/squashfs-root/lib/libssl.so.0.9.8
[+] 7f878000 - 7fa2c000 - r-x    /home/test/qiling/_R6220-V1.1.0.86.img.extracted/squashfs-root/lib/libcrypto.so.0.9.8
[+] 7fa2c000 - 7fa3b000 - ---    [mapped]
[+] 7fa3b000 - 7fa52000 - rw-    /home/test/qiling/_R6220-V1.1.0.86.img.extracted/squashfs-root/lib/libcrypto.so.0.9.8
[+] 7fa52000 - 7fa54000 - rw-    [mapped]
[+] 7fa55000 - 7fa81000 - r-x    /home/test/qiling/_R6220-V1.1.0.86.img.extracted/squashfs-root/lib/libgcc_s.so.1
[+] 7fa81000 - 7fa90000 - ---    [mapped]
[+] 7fa90000 - 7fa91000 - rw-    /home/test/qiling/_R6220-V1.1.0.86.img.extracted/squashfs-root/lib/libgcc_s.so.1
[+] 7fa92000 - 7fb38000 - r-x    /home/test/qiling/_R6220-V1.1.0.86.img.extracted/squashfs-root/lib/libuClibc-0.9.33.2.so
[+] 7fb38000 - 7fb47000 - ---    [mapped]
[+] 7fb47000 - 7fb49000 - r--    /home/test/qiling/_R6220-V1.1.0.86.img.extracted/squashfs-root/lib/libuClibc-0.9.33.2.so
[+] 7fb49000 - 7fb4f000 - rw-    [mapped]
[+] 7fb50000 - 7fb53000 - r-x    /home/test/qiling/_R6220-V1.1.0.86.img.extracted/squashfs-root/lib/libdl-0.9.33.2.so
[+] 7fb53000 - 7fb62000 - ---    [mapped]
[+] 7fb62000 - 7fb64000 - r--    /home/test/qiling/_R6220-V1.1.0.86.img.extracted/squashfs-root/lib/libdl-0.9.33.2.so
[+] 7fb64000 - 7fb65000 - rw-    [mapped]
[+] 7ff0d000 - 7ff3cee8 - rw-    [mapped]
[+] 7ff3cee8 - 7ff3d000 - rw-    [stack]
[+] ['0x0', '0x0', '0x4a', '0x8c', '0x23', '0x10', '0x4a', '0x0']
[+] 0x7fae739c   00  00  4a  8c  23  10  4a  00  08  00  48  8c  0c  00  0f  8d  16  00  e2  15  0c  00  47  8c  08  00  ef  8c  14  00  e2  15  d0  80  99  8f  21  18  6a  00  0c  00  07  ad  08  00  e8  ac  2c  00  07  8e  1c  00  87  10  24  30  cb  00  21  38  86  00 lw $t2, ($v0)
subu $v0, $v0, $t2
lw $t0, 8($v0)
lw $t7, 0xc($t0)
bne $t7, $v0, 0x7fae7408
lw $a3, 0xc($v0)
lw $t7, 8($a3)
bne $t7, $v0, 0x7fae740c
lw $t9, -0x7f30($gp)
addu $v1, $v1, $t2
sw $a3, 0xc($t0)
sw $t0, 8($a3)
lw $a3, 0x2c($s0)
beq $a0, $a3, 0x7fae7444
and $a2, $a2, $t3
addu $a3, $a0, $a2
Traceback (most recent call last):
  File "netgear_6220_mips32el_linux.py", line 52, in <module>
    "squashfs-root")
  File "netgear_6220_mips32el_linux.py", line 43, in my_netgear
    ql.run()
  File "/usr/local/lib/python3.7/dist-packages/qiling-0.9-py3.7.egg/qiling/core.py", line 293, in run
    self.os.run()     
  File "/usr/local/lib/python3.7/dist-packages/qiling-0.9-py3.7.egg/qiling/os/linux/linux.py", line 137, in run
    thread_management.run()
  File "/usr/local/lib/python3.7/dist-packages/qiling-0.9-py3.7.egg/qiling/os/linux/thread.py", line 439, in run
    self.runing_time += self.cur_thread.run(bbl_slice = thread_slice, mode = BBL_MODE)
  File "/usr/local/lib/python3.7/dist-packages/qiling-0.9-py3.7.egg/qiling/os/linux/thread.py", line 129, in run
    self.ql.uc.emu_start(self.start_address, self.until_addr)
  File "/usr/local/lib/python3.7/dist-packages/unicorn/unicorn.py", line 317, in emu_start
    raise UcError(status)
unicorn.unicorn.UcError: Invalid memory read (UC_ERR_READ_UNMAPPED)

N.B.: If you execute the script without setting multithreading to True then you will get the following error.

bind(4,127.0.0.1:8080,16) = 0
[+] syscall bind host: 127.0.0.1 and port: 8080 sin_family: 2
listen(4, 1024) = 0
[!] Syscall ERROR: ql_syscall_clone DEBUG: 'NoneType' object has no attribute 'cur_thread'
Traceback (most recent call last):
  File "netgear_6220_mips32el_linux.py", line 52, in <module>
    "squashfs-root")
  File "netgear_6220_mips32el_linux.py", line 43, in my_netgear
    ql.run()
  File "/usr/local/lib/python3.7/dist-packages/qiling-0.9-py3.7.egg/qiling/core.py", line 293, in run
    self.os.run()     
  File "/usr/local/lib/python3.7/dist-packages/qiling-0.9-py3.7.egg/qiling/os/linux/linux.py", line 158, in run
    raise self.ql.internal_exception
  File "/usr/local/lib/python3.7/dist-packages/qiling-0.9-py3.7.egg/qiling/core.py", line 28, in wrapper
    return func(*args, **kw)
  File "/usr/local/lib/python3.7/dist-packages/qiling-0.9-py3.7.egg/qiling/core.py", line 393, in _callback
    callback(self, intno)
  File "/usr/local/lib/python3.7/dist-packages/qiling-0.9-py3.7.egg/qiling/os/linux/linux.py", line 102, in hook_syscall
    return self.load_syscall(intno)
  File "/usr/local/lib/python3.7/dist-packages/qiling-0.9-py3.7.egg/qiling/os/posix/posix.py", line 67, in load_syscall
    self.syscall_map(self.ql, param0, param1, param2, param3, param4, param5)
  File "/usr/local/lib/python3.7/dist-packages/qiling-0.9-py3.7.egg/qiling/os/posix/syscall/sched.py", line 71, in ql_syscall_clone
    f_th = ql.thread_management.cur_thread  
AttributeError: 'NoneType' object has no attribute 'cur_thread'
xwings commented 4 years ago

of coz, without the multithread it will fail,

ur script seems ok, u migh wanna playaround with mmap_start = 0x7ffee000 - 0x800000

kxynos commented 4 years ago

This is the same issue as https://github.com/qilingframework/qiling/issues/194 https://github.com/qilingframework/qiling/issues/175 https://github.com/qilingframework/qiling/issues/164

kxynos commented 4 years ago

Is the problem with the current version of the Qiling framework or something else ? Cause I see you have many examples of router firmware running in Qiling framework on youtube, but I am unable to get any of them to work. I am getting the same issue with all of them.

"unicorn.unicorn.UcError: Invalid memory write (UC_ERR_WRITE_UNMAPPED)"
kxynos commented 4 years ago

I changed to root (i.e., sudo su) and the webserver by Netgear is not crashing.

xwings commented 4 years ago

that is a generic error msg, you need to find out what is the issue.

xwings commented 4 years ago

This is the same issue as #194 #175 #164

actually is not. but please disasm and you will be able to see more details

xwings commented 4 years ago

Hi again,

I look thru your github repo and found this

https://github.com/qilingframework/qiling/issues/223

I used your link and downloaded the firmware. And this is what happen,

image

You can see, most of the needed folder are missing, and most of it hide under /usr. what you need to do is some tweak.

so it will be more or less like this

![image](https://user-images.githubusercontent.com/463553/79179948-5a37d480-7e3b-11ea-98e2-c398afbbcb60.png)

Then once you start the run the scipt agaim, you will get the 404, that means the server is up and file missing.

Now you need to check why it sent missing.

image

Its kind of clear lots of file is missing.

I will not be able to make a details tutorial based on all router or even this R6220. It seems all these router change everytime they push a new version

Spend some time to debug, you will be able to get there.

klks commented 4 years ago

@kxynos it looks like an opportunity for you to contribute to the Qiling project. This would be a good example to have as part of our examples collection.

kxynos commented 4 years ago

As long as we know that it is not a framework issue, that is great. Then we can start tracing the applications to see why they are causing a crash.

kxynos commented 4 years ago

I have managed to document, in a detailed post, of how to get mini_http from Netgear R6220 (V1.1.0.86) up and running. Details can be found here: https://github.com/kxynos/embedded_hacking/blob/master/firmware/Netgear-R6220.md

xwings commented 4 years ago

nice! should not be that hard to get it working. either some cgi issue or some missing link

xwings commented 4 years ago

So, disable debug from your script, you can see setup.cgi should be in /setup.cgi from here you need to debug setup.cgi.

or run setup.cgi and not mini_http to find out the issue.

kxynos commented 4 years ago

By moving the print statement in execve, in my PR, it is now showing in the logs. :-)

execve(www/setup.cgi, [www/setup.cgi], [PATH=./, LD_LIBRARY_PATH=/lib:/usr/local/lib:/usr/lib, SERVER_SOFTWARE=, SERVER_NAME=ql_vm, GATEWAY_INTERFACE=CGI/1.1, SERVER_PROTOCOL=HTTP/1.0, SERVER_PORT=80, REQUEST_METHOD=GET, SCRIPT_NAME=/setup.cgi, REMOTE_ADDR=1.0.0.127, HTTP_USER_AGENT=Mozilla/5.0, HTTP_ACCEPT_LANGUAGE=en-US,en;q=0.5, HOST=127.0.0.1, LOGIN_IP=, NEED_AUTH=1])