As with any unknown binary, our initial analysis will help to uncover any strings that may allude to what we’re looking at, as well as any signatures within the file that could present a point of further analysis. Lastly, we want to look at the hexadecimal representation of the file, in order to identify padding or other blocks of interest.
和任何未知的二进制一样,我们的初步分析将有助于发现任何可能暗示我们所研究内容的字符串,以及文件中的任何签名,这些签名可能会提供更进一步的分析。最后,我们会查看文件的十六进制表现形式,以便识别来填充或其他感兴趣的块。
File output:
文件输出:
recovered_file: , code offset 0x1+3, Bytes/sector 26688, sectors/cluster 5, FATs 16, root entries 16, sectors 20480 (volumes <=32 MB), Media descriptor 0xf5, sectors/FAT 16400, sectors/track 19228, FAT (12 bit by descriptor)
BinWalk output:
BinWalk 输出:
josh@ioteeth:/tmp/reversing$ binwalk -v recovered_file
Scan Time: 2018-05-24 11:51:24
Target File: /tmp/reversing/recovered_file
MD5 Checksum: 7e11dd07846ecfe2502df7ad0c75952a
Signatures: 344
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
251942 0x3D826 Unix path: /tmp/esp8266/arduino-1.8.5/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/DataSource.h
292925 0x4783D Unix path: /tmp/esp8266/arduino-1.8.5/hardware/esp8266com/esp8266/cores/esp8266/abi.cpp
We can see from the output above that we’re potentially looking at an ESP8266 firmware image. I’ll disregard the results of file as they’re clearly a false positive, based on the challenge pre-text.
我们可以从上面的输出中看到,我们可能正在查看ESP8266固件镜像。基于前文所写的挑战。我将忽略file的结果,因为它们显然是误报。
Strings output:
字符串输出:
[...]
/tmp/esp8266/arduino-1.8.5/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/DataSource.h
_pos <= _streamPos
/tmp/esp8266/arduino-1.8.5/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/DataSource.h
cb == stream_rem
/tmp/esp8266/arduino-1.8.5/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/DataSource.h
_pos + size <= _size
/tmp/esp8266/arduino-1.8.5/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/DataSource.h
_buffer
/tmp/esp8266/arduino-1.8.5/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/DataSource.h
_pos <= _streamPos
/tmp/esp8266/arduino-1.8.5/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/DataSource.h
cb == stream_rem
/tmp/esp8266/arduino-1.8.5/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/DataSource.h
_pos + size <= _size
/tmp/esp8266/arduino-1.8.5/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/DataSource.h
_send_waiting == 0
/tmp/esp8266/arduino-1.8.5/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/ClientContext.h
_datasource == nullptr
/tmp/esp8266/arduino-1.8.5/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/ClientContext.h
_connect_pending
/tmp/esp8266/arduino-1.8.5/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/ClientContext.h
pcb == _pcb
/tmp/esp8266/arduino-1.8.5/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/ClientContext.h
buffer == _data + _pos
/tmp/esp8266/arduino-1.8.5/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/DataSource.h
_pos + size <= _size
/tmp/esp8266/arduino-1.8.5/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/DataSource.h
[...]
AConnecting to
WiFi connected
IP address:
Port knocking failed
/get_secrets
Requesting URL:
GET
HTTP/1.1
Host:
Connection: close
>>> Client Timeout !
closing connection
services.ioteeth.com
AjT32156
PCSL_GUEST
Based on the strings above, in particular:
基于上面的字符串,特别注意以下:
IP address:
Port knocking failed
It would appear our firmware is potentially performing a form of port knocking, before connecting to services.ioteeth.com to retrieve the aforementioned secrets. Port knocking is a means of instructing a firewall to open a predefined TCP/UDP port if the correct sequence of ports are ‘knocked’ on, which is usually performed via sending a TCP SYN packet to the required ports. The firewall would recognise the sequence and permit access to the defined resources.
在连接到services.ioteeth.com以检索上述密钥之前,看起来我们的固件可能正在执行一种端口试探形式。 端口试探是一种指示防火墙打开预定义TCP / UDP端口的方法,如果正确的端口序列被“试探”,这通常是通过将TCP SYN数据包发送到所需端口来执行,那么防火墙将识别序列并允许访问定义的资源。
We can perform a fast port scan to check for any filtered ports across a limited number of popular ports:
我们可以执行快速端口扫描,以检查有限数量的流行端口上任何存在过滤的端口:
josh@ioteeth:/tmp$ nmap -n -PN -F -v services.ioteeth.com -oN services.ioteeth.com.out
Warning: The -PN option is deprecated. Please use -Pn
Starting Nmap 7.40 ( https://nmap.org ) at 2018-05-25 11:29 BST
Initiating Connect Scan at 11:29
Scanning services.ioteeth.com (192.168.1.69) [100 ports]
Discovered open port 22/tcp on 192.168.1.69
Completed Connect Scan at 11:29, 1.20s elapsed (100 total ports)
Nmap scan report for services.ioteeth.com (192.168.1.69)
Host is up (0.00059s latency).
Not shown: 98 closed ports
PORT STATE SERVICE
22/tcp open ssh
445/tcp filtered microsoft-ds
Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 1.23 seconds
We can see that port 445 is filtered, so this could be our target port and equally, this would explain why the service couldn’t be reached by the originator of this challenge. It’s also possible another port is the one being used to obtain/upload secrets and ultimately, we’ll find that port through investigation, we note this however as a passive observation.
我们可以看到端口445被过滤了,因此这很可能是我们的目标端口,同样的,这也可以解释为什么此挑战的发起者无法达到该服务。也可能是另一个端口是用于获取/上传密钥的端口,最终,我们通过调查找到了该端口,但请注意这是一个被动观察。
Continuing with our analysis, let’s take a look at the hexdump of our firmware image:
继续我们的分析,让我们来看看我们的固件镜像的hexdump:
josh@ioteeth:/tmp/reversing$ hexdump -v -C recovered_file | head
00000000 e9 01 00 00 9c f2 10 40 00 f0 10 40 68 05 00 00 |.......@...@h...|
00000010 10 10 00 00 50 f5 10 40 1c 4b 00 40 cc 24 00 40 |....P..@.K.@.$.@|
00000020 ff ff ff 3f ff ff 0f 40 ff 7f 10 40 ff ff ff 5f |...?...@...@..._|
00000030 f0 ff ff 3f 00 10 00 00 1c e2 00 40 00 4a 00 40 |...?......[email protected].@|
00000040 4c 4a 00 40 00 07 00 60 00 00 00 80 e8 2b 00 40 |LJ.@...`.....+.@|
00000050 f0 30 00 40 a0 2f 00 40 b7 1d c1 04 00 12 00 60 |.0.@./.@.......`|
00000060 00 10 00 eb 7c 12 00 60 12 c1 d0 09 b1 f9 a1 fd |....|..`........|
00000070 01 29 4f 38 4f 21 e6 ff 2a 23 4b 3f 0c 44 01 e6 |.)O8O!..*#K?.D..|
00000080 ff c0 00 00 8c 52 0c 12 86 07 00 00 00 21 e1 ff |.....R.......!..|
00000090 29 0f 28 0f 28 02 29 2f 28 0f 28 12 29 3f 38 1f |).(.(.)/(.(.)?8.|
We also note that further into the file is what appears to be padding, followed by more data:
我们还注意到,更进一步进入文件后发现似乎先是填充,然后才是更多数据:
00000570 68 f5 10 40 00 00 00 00 00 00 00 00 00 00 00 2d |h..@...........-|
00000580 aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa |................|
00000590 aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa |................|
000005a0 aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa |................|
000005b0 aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa |................|
[...]
00000fd0 aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa |................|
00000fe0 aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa |................|
00000ff0 aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa |................|
00001000 e9 04 00 00 30 64 10 40 10 10 20 40 c0 ed 03 00 |....0d.@.. @....|
00001010 43 03 ab 83 1c 00 00 60 00 00 00 60 1c 0f 00 60 |C......`...`...`|
00001020 00 0f 00 60 41 fc ff 20 20 74 c0 20 00 32 24 00 |...`A.. t. .2$.|
00001030 30 30 75 56 33 ff 31 f8 ff 66 92 08 42 a0 0d c0 |00uV3.1..f..B...|
This padding is potentially useful, as it could be indicative of multiple files or formats being present within our target firmware image.
此填充可能很有用,因为它可能表示我们的目标固件镜像中存在多个文件或格式。
At this point, we have a number of questions we need to answer before we can continue. We can theorise that our long-term goal, based on the strings observed within the file, is to uncover the port knocking sequence performed by the firmware, which will hopefully allow us to access the external service that’s communicated with. But how do we go about doing that?
此时,在我们继续之前,我们需要回答一些问题。 我们可以推断,基于文件中观察到的字符串,我们的长期目标是揭示固件执行的端口试探序列,这有望允许我们访问与之通信的外部服务。 但是我们如何去做呢?
It’s worth noting that IDA doesn’t recognise our file, so let’s pause and do some research first.
值得注意的是,IDA无法识别我们的文件,所以让我们先停下来做一些研究。
与任何固件镜像一样,逆向工程之前的一个良好起点是了解以下内容:
Throughout the course of this section, we’ll work towards learning the answers to the above and understanding how they can help us.
在本节的整个过程中,我们将努力学习上述答案,并了解它们如何帮助我们。
Our penultimate goal will be to load the firmware into IDA for analysis, in a way that allows us to make some sense of what’s happening.
我们的倒数第二个目标是将固件加载到IDA进行分析,以便我们能够了解正在发生的事情。