[IOT安全][原創]釘釘智能指紋考勤機M1智能硬件漏洞挖掘(二)

mailto: wangkai0351@gmail.com
【未經贊成禁止轉載】
strings工具獲得該固件編譯過程當中include 的一些c語言代碼文件的路徑和文件名以下api

esp-idf/components/esp32/./heap_alloc_caps.c
esp-idf/components/esp32/./ipc.c
esp-idf/components/esp32/./intr_alloc.c
ieee80211_crypto.c
ieee80211_hostap.c
ieee80211_ht.c
ieee80211_input.c
ieee80211_ioctl.c
ieee80211_output.c
ieee80211_phy.c
ieee80211_scan.c
ieee80211_sta.c
wl_chm.c
wl_cnx.c
ieee80211_action.c
pm.c
esp-idf/components/newlib/./locks.c
esp-idf/components/nvs_flash/src/nvs_storage.cpp
esp-idf/components/nvs_flash/src/nvs_item_hash_list.cpp
esp-idf/components/nvs_flash/src/nvs_page.cpp
esp-idf/components/nvs_flash/src/nvs_pagemanager.cpp
esp-idf/components/spi_flash/./partition.c
esp-idf/components/spi_flash/./flash_mmap.c
esp-idf/components/tcpip_adapter/./tcpip_adapter_lwip.c
esp-idf/components/vfs/./vfs.c
esp-idf/components/vfs/./vfs_uart.c
main/./bravo.c
main/../embedded/dingtalk/base/dt_log.c
main/../embedded/dingtalk/base/dt_string.c
esp-idf/components/driver/./rtc_module.c
esp-idf/components/esp32/./crosscore_int.c
esp-idf/components/esp32/./phy_init.c
components/fingerprint/./fingerprint.c
components/fingerprint/./fingerprint_helper.c
components/fingerprint/./userIdpool.c
components/hardware/./alc5660.c
components/hardware/./fd650b.c
components/hardware/./gpio_helper..c
components/hardware/./pcf8563.c
components/logcache/./dt_log_fireeye.c
components/logcache/./dt_log_flash.c
components/ota/./ota.c
components/ota/./ota_downloader.c
components/root/./dt_device.c
components/root/./dt_fingerprint.c
components/root/./dt_root.c
components/root/./dt_lightvoice.c
components/root/./dt_login.c
components/root/./dt_coredump_upload.c
components/wifi/./wifi.c
main/../embedded/dingtalk/attend/dt_atdevice_service.c
main/../embedded/dingtalk/attend/dt_atdevice_statesync.c
main/../embedded/dingtalk/attend/dt_atdevice_uploadcrash.c
main/../embedded/dingtalk/attend/dt_atdevice_uploadresp.c
main/../embedded/dingtalk/attend/dt_atdevice_usercheck.c
main/../embedded/dingtalk/attend/dt_atdevice_usercontext.c
main/../embedded/dingtalk/attend/dt_atdevice_userinfo.c
main/../embedded/dingtalk/attend/dt_atdevice_userstampcontext.c
main/../embedded/dingtalk/attend/dt_atdevice_usertimestamp.c
main/../embedded/dingtalk/auth/dt_auth_service.c
main/../embedded/dingtalk/base/dt_list.c
main/../embedded/dingtalk/base/dt_queue.c
main/../embedded/dingtalk/device/dt_device_environment.c
main/../embedded/dingtalk/device/dt_device_service.c
main/../embedded/dingtalk/lwp/dt_lwp_delivery_reg.c
main/../embedded/dingtalk/lwp/dt_lwp_error.c
main/../embedded/dingtalk/lwp/dt_lwp_header.c
main/../embedded/dingtalk/lwp/dt_lwp_pushlistener.c
main/../embedded/dingtalk/lwp/dt_lwp_response.c
main/../embedded/dingtalk/lwp/dt_lwp_setting.c
tls.dingtalk.com
main/../embedded/dingtalk/lwp/dt_lwp_useragent.c
main/../embedded/dingtalk/wukong/dt_wukong_noticelist.c
main/../embedded/dingtalk/wukong/dt_wukong_service.c
main/../embedded/dingtalk/net/dt_net_loop.c
main/../embedded/dingtalk/file/dt_file_service.c
main/../embedded/dingtalk/file/dt_file_upload_context.c
main/../embedded/dingtalk/file/dt_file_upload_service.c
main/../embedded/dingtalk/fireeye/dt_fireeye_service.c
main/../embedded/dingtalk/fireeye/dt_fireeye_upload_mediaid.c
main/../embedded/dingtalk/attend/dt_atdevice_atcmd.c
main/../embedded/dingtalk/attend/dt_atdevice_checkresp.c
main/../embedded/dingtalk/auth/dt_auth_login_result.c
main/../embedded/dingtalk/auth/dt_auth_refresh_token_response.c
main/../embedded/dingtalk/base/dt_asyncjob.c
main/../embedded/dingtalk/base/dt_asyncqueue.c
main/../embedded/dingtalk/base/dt_thread.c
main/../embedded/dingtalk/base/dt_timer.c
main/../embedded/dingtalk/lwp/dt_lwp_mid.c
main/../embedded/dingtalk/lwp/dt_lwp_transaction.c
main/../embedded/dingtalk/lwp/dt_lwp_transport.c
main/../embedded/dingtalk/wukong/dt_wukong_kickout.c
main/../embedded/dingtalk/wukong/dt_wukong_notice.c
main/../embedded/dingtalk/fireeye/dt_fireeye_logupcmd.c
main/../embedded/dingtalk/lwp/dt_lwp_ask.c
main/../embedded/dingtalk/lwp/dt_lwp_connection.c
main/../embedded/dingtalk/lwp/dt_lwp_parser.c
main/../embedded/dingtalk/net/dt_net_connection.c
main/../embedded/dingtalk/net/dt_net_openssl.c
esp-idf/components/app_update/./esp_ota_ops.c
components/ble/./dt_ble.c
components/ble/./dt_npc.c
esp-idf/components/bt/bluedroid/device/controller.c
esp-idf/components/bt/bluedroid/hci/hci_layer.c
esp-idf/components/bt/bluedroid/hci/hci_packet_factory.c
esp-idf/components/bt/bluedroid/hci/hci_packet_parser.c
esp-idf/components/bt/bluedroid/hci/packet_fragmenter.c
esp-idf/components/bt/bluedroid/osi/fixed_queue.c
esp-idf/components/bt/bluedroid/osi/future.c
esp-idf/components/bt/bluedroid/osi/hash_map.c
esp-idf/components/bt/bluedroid/osi/list.c
esp-idf/components/bt/bluedroid/stack/btu/btu_task.c
esp-idf/components/bt/bluedroid/stack/l2cap/l2c_api.c
esp-idf/components/bt/bluedroid/stack/l2cap/l2c_fcr.c
esp-idf/components/bt/bluedroid/bta/dm/bta_dm_pm.c
esp-idf/components/bt/bluedroid/bta/sys/bta_sys_main.c
esp-idf/components/bt/bluedroid/btcore/bdaddr.c
esp-idf/components/bt/bluedroid/gki/gki_buffer.c
esp-idf/components/bt/bluedroid/hci/hci_hal_h4.c
esp-idf/components/bt/bluedroid/stack/btm/btm_ble_bgconn.c
esp-idf/components/bt/bluedroid/device/interop.c
arch_main.c
ea.c
ld_fm.c
lld.c
rwble.c
rwbt.c
vhci.c
intc.c
esp-idf/components/driver/./i2c.c
esp-idf/components/driver/./i2s.c
esp-idf/components/driver/./uart.c
esp-idf/components/freertos/./heap_regions.c
esp-idf/components/freertos/./queue.c
esp-idf/components/freertos/./tasks.c
esp-idf/components/freertos/./timers.c
esp-idf/components/freertos/./ringbuf.c
pp.c
lmac.c
wdev.c
ieee80211_misc.c

從源文件命名來看,咱們從中挑出一些咱們最感興趣的源文件;好比esp-idf/components/路徑下的文件大多屬於官方SDK中的文件,源代碼是公開的,所以這部分代碼很難稱得上使咱們感興趣的。反而,main/../embedded/dingtalk/路徑的文件是釘釘本身開發的,確定是涉及到打卡器業務和服務器通訊的代碼,所以咱們着重從這些源文件匯中挑選咱們初探信息。服務器

好比,咱們挑選這樣一個源文件app

components/root/./dt_login.c

咱們就先用strings的結果來看這個源文件形成的信息泄露。async

on_connect_fail wifi is not connected!
connect fail,times=%d
device_not_exist! 
fp num:%d != enrollednum:%d
get users version fail. status=%d, code=%.*s, reason=%.*s
fingerprint_sync_timestamp, local: %d, remote:%d
start full fp sync!
dt_get_users_version is requesting, ignore
atm_state_sync fail. status=%d, code=%.*s, reason=%.*s
atm_state_sync timestamp=%d, code=%.*s, firmware=%.*s, system_key.fwversion:%s, 
md5=%.*s
emit_ota_task
{"maxUsers":1000,"maxFP":1000,"maxFA":0,"dev_mac_addr":"%s","dev_local_ip":"%s","router_name":"%s"}
kaoqinji
dt_update_machine_info do report request
on_reg_success failed, invalid parameter, reg=%p
reg success, timestamp=%lld (aka "%.*s"), get_rtc_timer: %ld, time(): %ld //ESP_LOGE
connect fail long time, restart wifi
login_task wifi is not connected!
login_task device is not bind!
85A09F60A599F5E1867EAB915A8BB07F
9_%d
dingboxM1
dingtalk
/s/biz/atcmd
/s/logup
/push/kickout
login_task call login_by_device
device_key=%s,sn=%s,active_code=%s,secret=%s
received logup cmd! begining to upload logs!
atmGetUserInfo
atmUploadUserInfo
atmEnterFP
atmESC
atmStateSync
atmUploadLog
atmEnterMenu
atmEnterFA
atmEnterFPCancel
atmOTA
rollback
datastr
cJSON_Parse succeed, action: %d!
recv atcmd, cmd=%.*s, data len=%d
retry_login wifi is not connected!
login long time fail, restart wifi
retry login,times=%d
device_not_exist
device_secret_invalid
login failed, status=%d, code=%.*s, reason=%.*s
LOGIN FAIL. should not happen. login ok without login_result
login success, uid=%lld
dt_get_users_version is requesting, ignore 2
need_auth(), is_wifi_connected: %d
parse_cmd
on_async_atcmd_rsp
on_async_atcmd_rsp
on_logupcmd_rsp
on_logupcmd_rsp
on_async_kickout_rsp
on_async_kickout_rsp
login_task
retry_login
on_connect_fail
on_discon nected
on_disconnected
on_connected
need_auth
set_systemtime_on_reg_success
on_async_login_rsp
on_async_login_rsp
dt_update_machine_info
on_atm_state_sync
dt_get_users_version
on_atm_get_users_version
dt_on_device_not_exist
upload coredump error!

咱們看到上面包含了一些debug打印信息的流出,所以咱們考慮這些debug信息應該是打印到串口的。咱們固然很是想看到這些debug信息了。tcp

上面這句話說的不許確,上述strings工具輸出的敏感信息字符串主要分爲幾類函數

1. esp32 SDK自己自帶的調試信息,有
#ifndef BOOTLOADER_BUILD
#define ESP_LOGE //error錯誤
#define ESP_LOGW //warning警告
#define ESP_LOGI //info信息
#define ESP_LOGD //debug模式
#define ESP_LOGV //
這幾類
這些調試信息可能會由串口輸出,這類調試信息格式如
[0;32mI (%d) %s: SPI Speed      : %s
[0;32mI (%d) %s: SPI Mode       : %s
[0;32mI (%d) %s: SPI Flash Size : %s
bravo_1.0.2-90-gcfa4912
[0;32mI (%d) %s: ESP-IDF %s 2nd stage bootloader
2. 釘釘本身開發日誌記錄功能,好比
device_key=%s,sn=%s,active_code=%s,secret=%s
這些日誌記錄是都要寫到flash中存儲起來,以便於在聯網的時候可以upload到服務器
3. 函數名
4. 斷言
5. 宏定義

ESP32 有 3 個 UART 接口,即 UART0、UART1 和 UART2。工具

查閱《ESP32 技術規格書》版本2.1可知oop

U0RXD 40 號引腳ui

U0TXD 41 號引腳debug

U1RXD 28 號引腳

U1TXD 29 號引腳

U2RXD 25 號引腳

U2TXD 27 號引腳

到PCB上看看,這三對引腳有沒有露出來,若是有任意一對引腳引到了PCB的焊盤上,那麼極可能就是這個PCB的串口調試端口。

下面,嘗試猜想復原一下ESP32(xtensa)+FreeRTOS的符號表(symbol table),我在固件的bin文件中發現瞭如下的感興趣段落。根據個人經驗,符號表就應該長成一個表格的樣子,規規矩矩,對齊工整,因此我猜想如下段落很像是符號表。

00000060  01 00 00 00 36 2b 0d 40  79 28 0d 40 7e 28 0d 40  |....6+.@y(.@~(.@|
00000070  d5 28 0d 40 07 2b 0d 40  05 2b 0d 40 b0 2a 0d 40  |.(.@.+.@.+.@.*.@|
00000080  d4 2a 0d 40 60 2c 0d 40  09 29 0d 40 4a 2c 0d 40  |.*.@`,.@.).@J,.@|
00000090  55 2c 0d 40 60 2c 0d 40  60 2c 0d 40 60 2c 0d 40  |U,.@`,.@`,.@`,.@|
000000a0  09 29 0d 40 09 29 0d 40  09 29 0d 40 09 29 0d 40  |.).@.).@.).@.).@|
000000b0  09 29 0d 40 09 29 0d 40  09 29 0d 40 55 2c 0d 40  |.).@.).@.).@U,.@|
000000c0  09 29 0d 40 09 29 0d 40  09 29 0d 40 3f 2c 0d 40  |.).@.).@.).@?,.@|
000000d0  09 29 0d 40 55 2c 0d 40  09 29 0d 40 09 29 0d 40  |.).@U,.@.).@.).@|
000000e0  ee 28 0d 40 09 29 0d 40  09 29 0d 40 09 29 0d 40  |.(.@.).@.).@.).@|
000000f0  09 29 0d 40 09 29 0d 40  09 29 0d 40 09 29 0d 40  |.).@.).@.).@.).@|

符號表能夠簡單理解爲函數的入口地址函數名的存儲起始地址一一對應的關係,以下表

函數名起始地址1 函數地址1
函數名起始地址2 函數地址2
函數名起始地址3 函數地址3

挑出了固件bin文件的一段

0002bf10  73 79 6e 63 5f 67 65 74  5f 61 6c 6c 5f 75 73 65  |sync_get_all_use|
0002bf20  72 69 6e 66 6f 5f 72 73  70 00 00 00 6f 6e 5f 61  |rinfo_rsp...on_a|
0002bf30  73 79 6e 63 5f 67 65 74  5f 61 6c 6c 5f 75 73 65  |sync_get_all_use|
0002bf40  72 69 6e 66 6f 5f 72 73  70 00 00 00 64 74 5f 72  |rinfo_rsp...dt_r|
0002bf50  65 73 79 6e 63 5f 66 61  69 6c 65 64 5f 75 73 65  |esync_failed_use|
0002bf60  72 73 00 00 64 74 5f 72  65 73 79 6e 63 5f 66 61  |rs..dt_resync_fa|
0002bf70  69 6c 65 64 5f 75 73 65  72 73 00 00 6f 6e 5f 61  |iled_users..on_a|
0002bf80  73 79 6e 63 5f 61 74 6d  5f 67 65 74 75 73 65 72  |sync_atm_getuser|
0002bf90  69 6e 66 6f 5f 61 63 74  69 6f 6e 00 6f 6e 5f 67  |info_action.on_g|
0002bfa0  65 74 5f 75 73 65 72 69  6e 66 6f 5f 62 79 5f 69  |et_userinfo_by_i|
0002bfb0  64 73 5f 72 73 70 00 00  64 74 5f 66 69 6e 67 65  |ds_rsp..dt_finge|

on_async_get_all_users是一個函數名,它的起始存儲地址是0x0002bf20+c,固然該地址是在固件中的絕對地址(帶有偏移)。

dt_resync_failed_users也是一個函數名,它的起始存儲地址是0x0002bf40+c。

on_async_atm_getuserinfo_action也是一個函數名,它的起始存儲地址是0x0002bf70+c。

on_get_userinfo_by_ids_rsp也是一個函數名,它的起始存儲地址是0x0002bf90+c。

從flash的絕對地址上能夠看出,

addr(dt_resync_failed_users)-addr(on_async_get_all_users)=0x20

addr(on_async_atm_getuserinfo_action)-addr(dt_resync_failed_users)=0x30

addr(on_get_userinfo_by_ids_rsp)-addr(on_async_atm_getuserinfo_action)=0x20

這樣相減,就減掉了它們都包含的偏移地址常數。

因此符號表中,

addr(函數名起始地址2)-addr(函數名起始地址1)=0x20

addr(函數名起始地址3)-addr(函數名起始地址2)=0x30

addr(函數名起始地址4)-addr(函數名起始地址3)=0x20

或者,咱們再來看一簇gpio配置相關的函數

00026ff0  6f 5f 6e 75 6d 3a 25 75  1b 5b 30 6d 0a 00 00 00  |o_num:%u.[0m....|
00027000  67 70 69 6f 5f 69 73 72  5f 72 65 67 69 73 74 65  |gpio_isr_registe|
00027010  72 00 00 00 67 70 69 6f  5f 69 6e 73 74 61 6c 6c  |r...gpio_install|
00027020  5f 69 73 72 5f 73 65 72  76 69 63 65 00 00 00 00  |_isr_service....|
00027030  67 70 69 6f 5f 69 73 72  5f 68 61 6e 64 6c 65 72  |gpio_isr_handler|
00027040  5f 61 64 64 00 00 00 00  67 70 69 6f 5f 6f 75 74  |_add....gpio_out|
00027050  70 75 74 5f 64 69 73 61  62 6c 65 00 67 70 69 6f  |put_disable.gpio|
00027060  5f 6f 75 74 70 75 74 5f  65 6e 61 62 6c 65 00 00  |_output_enable..|
00027070  67 70 69 6f 5f 73 65 74  5f 64 69 72 65 63 74 69  |gpio_set_directi|
00027080  6f 6e 00 00 67 70 69 6f  5f 73 65 74 5f 70 75 6c  |on..gpio_set_pul|
00027090  6c 5f 6d 6f 64 65 00 00  67 70 69 6f 5f 73 65 74  |l_mode..gpio_set|
000270a0  5f 6c 65 76 65 6c 00 00  67 70 69 6f 5f 69 6e 74  |_level..gpio_int|
000270b0  72 5f 64 69 73 61 62 6c  65 00 00 00 67 70 69 6f  |r_disable...gpio|
000270c0  5f 69 6e 74 72 5f 65 6e  61 62 6c 65 5f 6f 6e 5f  |_intr_enable_on_|
000270d0  63 6f 72 65 00 00 00 00  67 70 69 6f 5f 73 65 74  |core....gpio_set|
000270e0  5f 69 6e 74 72 5f 74 79  70 65 00 00 67 70 69 6f  |_intr_type..gpio|
000270f0  5f 70 75 6c 6c 64 6f 77  6e 5f 64 69 73 00 00 00  |_pulldown_dis...|
00027100  67 70 69 6f 5f 70 75 6c  6c 64 6f 77 6e 5f 65 6e  |gpio_pulldown_en|
00027110  00 00 00 00 67 70 69 6f  5f 70 75 6c 6c 75 70 5f  |....gpio_pullup_|
00027120  64 69 73 00 67 70 69 6f  5f 70 75 6c 6c 75 70 5f  |dis.gpio_pullup_|
編號 函數名 函數名的起始存儲地址 和前一個函數名地址的偏移
1 gpio_isr_register 0x00027000
2 gpio_install_isr_service 0x00027010+4 0x14
3 gpio_isr_handler_add 0x00027030 0x1c
4 gpio_output_disable 0x00027040+8 0x12
5 gpio_output_enable 0x00027050+c 0x14
6 gpio_set_direction 0x00027070 0x14

這簇函數給了咱們5條證據來複原符號表,應該干擾更小了,結果更準確了。

相關文章
相關標籤/搜索