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条证据来复原符号表,应该干扰更小了,结果更准确了。