-
Notifications
You must be signed in to change notification settings - Fork 737
/
Copy pathnetgear_6220.py
104 lines (78 loc) · 3.3 KB
/
netgear_6220.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
# Setup:
# - Unpack firmware rootfs (assumed hereby: 'rootfs/netgear_r6220')
# - The firmware expects '/dev/mtdblock11' to exist and be functional, otherwise it crashes
# - cd rootfs/netgear_r6220/dev
# - dd if=/dev/zero of=mtdblock11 bs=1024 count=129030
# - mkfs.ext4 mtdblock11
#
# Run:
# $ PYTHONPATH=/path/to/qiling ROOTFS=/path/to/netgear_rootfs python3 netgear_6220.py
#
# Emulation:
# Soon after Qiling starts emulating the firmware it will look like it is done running, but actually it
# isn't. During the emulation a few OS child processes are spawned, waiting for connection. To see them
# run 'ps | grep python3'.
#
# Once a connection is established on 127.0.0.1:8080, more child processes will be spawned. Note that in
# case a child process dies with an exception, it turns into a zombie process. To kill the spawned child
# processes, run 'pkill python3'
from typing import List
import logging
import os
import sys
sys.path.append("..")
from qiling import Qiling
from qiling.const import QL_INTERCEPT, QL_VERBOSE
from qiling.log import QlColoredFormatter, QlBaseFormatter
# user may set 'ROOTFS' environment variable to use as rootfs
ROOTFS = os.environ.get('ROOTFS', r'./rootfs/netgear_r6220')
def __onexit_fork(ql: Qiling, retval: int) -> None:
# as the emulated binary forks more and more child processes, it becomes hard to keep track
# of their log entries and tell them apart. here we intercept the 'fork' system call on-exit
# (i.e. after it was already simulated, but before resuming emulation) and modify the newly
# created qiling instance's logger to show the os child processes id as part of the logs.
#
# note: os process id should not be confused with the internal qiling thread id, which does
# not exist here since we do not use qiling multithreading feature.
# fork returns 0 on the newly created child process
if retval == 0:
GREEN = '\033[92m'
DEFAULT = '\033[39m'
def __add_color(s: str) -> str:
"""Colorize text.
"""
return f'{GREEN}{s}{DEFAULT}'
def __do_nothing(s: str) -> str:
"""Use text as-is.
"""
return s
# patch current logger instance handlers to show the process id
for h in ql.log.handlers:
formatter = h.formatter
if isinstance(formatter, QlColoredFormatter):
fmt = __add_color
elif isinstance(formatter, QlBaseFormatter):
fmt = __do_nothing
else:
raise RuntimeError('unexpected formatter class')
style = logging.PercentStyle(f'%(levelname)s {fmt(f"[{os.getpid():4d}]")} %(message)s')
formatter._style = style
formatter._fmt = style._fmt
def my_sandbox(path: List[str], rootfs: str) -> None:
ql = Qiling(path, rootfs, profile='netgear_6220.ql', verbose=QL_VERBOSE.DEBUG)
ql.add_fs_mapper(r'/proc', r'/proc')
ql.os.set_syscall('fork', __onexit_fork, QL_INTERCEPT.EXIT)
ql.run()
if __name__ == '__main__':
argv = [
f'{ROOTFS}/bin/mini_httpd',
'-d', '/www',
'-r', 'NETGEAR R6220',
'-c', '**.cgi',
'-t', '300'
]
my_sandbox(argv, ROOTFS)