记一次某TBOX的分析过程

车联网安全
2023-05-16 18:28
118439

前言

由于项目太忙公众号已经停更一段时间,近期会重新开始更新并活跃。本篇文章取自实验室内部学习材料,记录了一次TBOX从硬件分析到软件逆向的完整过程,希望可以给大家起到一定的启示作用。

硬件分析

整板

image.png

关键芯片

主控STM32F105VCT6
主频72MHz,64KB SRAM,256KB FLASH

image.png

CAN收发器TJA1043

image.png

LTE模块 基带:MDM9607

image.png

EEPROM

24AA161 16KB I2C接口

image.png

接口分析

SWD及UART接口分析

使用STM32CubeMX可以方便的查询STM32系列芯片的参数及引脚定义

image.png

使用万用表通断档可测出芯片引脚有如下引出,但调试接口和芯片中间有几个空电阻焊盘隔离,后续使用焊锡短接即可。

image.png

CAN接口分析

TJA1043的引脚定义如图:

image.png

使用万用表通断档打两片TJA1043的CANH,CANL和T-BOX白色接口的针脚则可确定两路CAN的引脚

电源输入接口分析

GND一般为PCB上面积最大的网络,非常容易定位,屏蔽罩、板框、螺丝孔多为GND网络。在PCB背面找到了一个保险丝,使用万用表通断档打保险丝和白色接口的针脚则可确定VIN引脚,T-BOX供电电压一般为12V,但如果完全从理论上进行逆向计算,则需要根据DCDC芯片的数据手册确定。

固件分析

固件提取

根据之前确定的SWD引脚位置,连接PCB与J-link,J-TAG与SWD连接的方法如下:

image.png

之后使用J-Flash读出固件,读取的起始地址和大小根据STM32F105的数据手册为0x8000000和0x4000

image.png

image.png

静态分析

使用IDA Pro打开读出的bin文件,Processor type选择ARM Little-endian [ARM]Processor options中选择Edit ARM architecture options,STM32F105属于ARM Cortex-M3内核,属于ARMv7-M,但是没有FPU,所以VFP instructions选择 None

image.png

根据数据手册,设置ram及rom(flash)的起始地址及大小分别为0x20000000 0x1000和0x8000000 0x4000

image.png

加载后如下图所示:

image.png

绝大多少的Cortex-M芯片将MSP栈顶指针和中断向量表存放在flash的首部,可对照startup_stm32f105xc.s(不同编译器的汇编格式不同,这里选用了gcc-arm的)中的内容在IDA中还原中断向量表

  .word _estack
  .word Reset_Handler
  .word NMI_Handler
  .word HardFault_Handler
  .word MemManage_Handler
  .word BusFault_Handler
  .word UsageFault_Handler
  .word 0
  .word 0
  .word 0
  .word 0
  .word SVC_Handler
  .word DebugMon_Handler
  .word 0
  .word PendSV_Handler
  .word SysTick_Handler
  .word WWDG_IRQHandler
  .word PVD_IRQHandler
  .word TAMPER_IRQHandler
  .word RTC_IRQHandler
  .word FLASH_IRQHandler
  .word RCC_IRQHandler
  .word EXTI0_IRQHandler
  .word EXTI1_IRQHandler
  .word EXTI2_IRQHandler
  .word EXTI3_IRQHandler
  .word EXTI4_IRQHandler
  .word DMA1_Channel1_IRQHandler
  .word DMA1_Channel2_IRQHandler
  .word DMA1_Channel3_IRQHandler
  .word DMA1_Channel4_IRQHandler
  .word DMA1_Channel5_IRQHandler
  .word DMA1_Channel6_IRQHandler
  .word DMA1_Channel7_IRQHandler
  .word ADC1_2_IRQHandler
  .word CAN1_TX_IRQHandler
  .word CAN1_RX0_IRQHandler
  .word CAN1_RX1_IRQHandler
  .word CAN1_SCE_IRQHandler
  .word EXTI9_5_IRQHandler
  .word TIM1_BRK_IRQHandler
  .word TIM1_UP_IRQHandler
  .word TIM1_TRG_COM_IRQHandler
  .word TIM1_CC_IRQHandler
  .word TIM2_IRQHandler
  .word TIM3_IRQHandler
  .word TIM4_IRQHandler
  .word I2C1_EV_IRQHandler
  .word I2C1_ER_IRQHandler
  .word I2C2_EV_IRQHandler
  .word I2C2_ER_IRQHandler
  .word SPI1_IRQHandler
  .word SPI2_IRQHandler
  .word USART1_IRQHandler
  .word USART2_IRQHandler
  .word USART3_IRQHandler
  .word EXTI15_10_IRQHandler
  .word RTC_Alarm_IRQHandler
  .word OTG_FS_WKUP_IRQHandler
  .word 0
  .word 0
  .word 0
  .word 0
  .word 0
  .word 0
  .word 0
  .word TIM5_IRQHandler
  .word SPI3_IRQHandler
  .word UART4_IRQHandler
  .word UART5_IRQHandler
  .word TIM6_IRQHandler
  .word TIM7_IRQHandler
  .word DMA2_Channel1_IRQHandler
  .word DMA2_Channel2_IRQHandler
  .word DMA2_Channel3_IRQHandler
  .word DMA2_Channel4_IRQHandler
  .word DMA2_Channel5_IRQHandler
  .word 0
  .word 0
  .word CAN2_TX_IRQHandler
  .word CAN2_RX0_IRQHandler
  .word CAN2_RX1_IRQHandler
  .word CAN2_SCE_IRQHandler
  .word OTG_FS_IRQHandler

编写了以下idc python脚本用于自动还原中断向量表

import idc

address = 0x8000000
f = open(r"interrupt_list.txt", "r")
lines = f.readlines()

# 跳过MSP指针
idc.create_dword(address)
address += 4

ISR_list=[]
# 还原中断向量表并创建函数
for line in lines[1:]:
    idc.create_dword(address)
    fun_addr = idc.ida_bytes.get_dword(address) - 1
    fun_name = line.split()[1]
    idc.set_cmt(address, fun_name, 0)
    # 跳过占位的0
    if fun_name == "0":
        address += 4
        continue
    # 去重
    if fun_addr in ISR_list:
        idc.set_name(fun_addr, "Default_handler")
    else:
        print(f"{fun_name}:{hex(fun_addr)}")
        idc.ida_auto.auto_make_code(fun_addr)
        idc.add_func(fun_addr)
        idc.set_name(fun_addr, fun_name)
        ISR_list.append(fun_addr)
    address += 4

image.png

针对Cortex-M内核,由于没有MMU,因而除了RAM和ROM外,还需要针对各外设创建专门的段,在IDA 7.5后,IDA支持根据svd文件自动创建外设段(但是BUG比较多,有的外设创建不出来)。

image.png

image.png

由于ResetHandle是芯片复位后执行的中断,则必定会指向main函数,但注意中断向量表中储存的地址实际上是函数的第二个字节,需要向上移动一个字节才能按c反编译然后按p创建函数。

image.png

可以看到第一个函数中主要是芯片时钟(RCC)的配置

int SystemInit()
{
  int v0; // r0
  int v1; // r0
  int v2; // r0
  int v3; // r0
  int v4; // r0
  int result; // r0

  v0 = RCC_CR;
  RCC_CR = v0 | 1;
  v1 = RCC_CFGR;
  RCC_CFGR = v1 & 0xF0FF0000;
  v2 = RCC_CR;
  RCC_CR = v2 & 0xFEF6FFFF;
  RCC_CR = v2 & 0xFEF2FFFF;
  v3 = RCC_CFGR;
  RCC_CFGR = v3 & 0xFF80FFFF;
  v4 = RCC_CR;
  RCC_CR = v4 & 0xEBFFFFFF;
  RCC_CIR = 0xFF0000;
  RCC_CFGR2 = 0;
  result = (_DWORD)&RCC_CR << 15;
  unk_E000ED08 = (_DWORD)&RCC_CR << 15;
  return result;
}

跟进第二个函数,看到一大堆函数调用,然后是while 1死循环,这是嵌入式开发中典型的前后台结构,因此可以确定这就是main函数:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v3; // r0
  int v4; // r0
  int v5; // r1
  int v6; // r2
  int v7; // r3

  HAL_Init();
  SystemClock_Config();
  USART1_Init();
  v3 = AFIO_MAPR;
  AFIO_MAPR = v3 & 0xF8FFFFFF | 0x2000000;
  sub_80146C8(1);
  sub_8002F58();
  CAN_Config();
  TIM_Init();
  sub_801A228();
  v4 = RTC_Init();
  Modem_Init(v4, v5, v6, v7);
  sub_8002118(&hw_vehicle_type);
  printf("Initialize hw_vehicle_type is %d\r\n", hw_vehicle_type);
  printf("Initialize the tbox...\r\n");
  printf("Initialize sensor...\r\n");
  Sensor_Init();
  while ( 1 )
  {
    sub_8014D6E();
    sub_8018D30();
  }
}

根据操作的外设地址可以确定前面几个函数负责初始化的外设,于是修改函数名以提高可读性。在嵌入式固件中,由于MCU的存储空间有限,在保证基本的内存对齐的情况下函数会在flash中紧密排布,而观察IDA上方的内存布局发现有大量未识别的函数,但IDA目前还不支持主动搜索函数,因此需要结合Ghidra中主动搜索的函数以及经验进行手动还原。这里写了另一个IDA脚本来半自动创建函数

import idc

start_ea=idc.get_screen_ea()
while idc.ida_funcs.get_func(start_ea) is None:
    idc.ida_auto.auto_make_code(start_ea)
    #一般函数开头指令均为压栈,如果不是压栈则需要人工判断
    if "PUSH" in idc.GetDisasm(start_ea):
        idc.add_func(start_ea)
        start_ea=idc.find_func_end(start_ea)
    else:
        break
idc.jumpto(start_ea)

在标记出大部分函数后,则可使用BinDiff对将TBOX固件的IDA数据库和其它同型号STM32程序的IDA数据库进行比对,以还原其中有关外设的库函数,为分析具体的应用逻辑做准备。

image.png

对于STM32平台,常见的外设库有: STM32 Standard Peripheral Libraries STM32 标准外设库:创建于2007年,在早期的设备上更常见 STM32Cube MCU Package STM32 HAL库:创建于2014年,如今最常使用的库 两种库在推出以来尽力了许多次迭代,其中许多函数和结构体都有过大幅修改,因此为了尽快比配到对应的外设库,需要先确定TBOX固件的大致开发时间。有关时间的信息经常出现在固件包含的字符串或设备PCB的丝印上,然而很不幸的是我在这两处都没有找到有效信息。不过对于STM32系列芯片,其芯片上的丝印其实除了型号还包含有生产批号:

image.png

图中748表示该芯片生产于x7年第48周,首先排除07年,自然这个TBOX大概开发于17年左右,经过一番比对,最终确认该固件使用的外设库库为:STM32CubeF1 Firmware Package V1.4.0 不同于PC程序,MCU固件抽象程度低,不同芯片的内存布局也不相同,因此缺乏有效的自动化函数指纹分析工具。这里主要还是借助BinDiff和人工比对出了大部分HAL库函数:

image.png

在还原出外设库后则可以分析出部分应用逻辑代码,例如:

 if ( hcan1.pRxMsg->StdId == 0x7A0
    && hcan1.pRxMsg->Data[0] == 2
    && hcan1.pRxMsg->Data[1] == 0x10
    && hcan1.pRxMsg->Data[2] == 1 )
  {
    byte_20000259 = 1;
    memset(hcan1.pTxMsg->Data, 8, 0xAA);
    hcan1.pTxMsg->Data[0] = '\x06';
    hcan1.pTxMsg->Data[1] = 0x50;
    hcan1.pTxMsg->Data[2] = 1;
    hcan1.pTxMsg->Data[3] = 0;
    hcan1.pTxMsg->Data[4] = 0x32;
    hcan1.pTxMsg->Data[5] = 0;
    hcan1.pTxMsg->Data[6] = 0xC8;
    hcan1.pTxMsg->Data[7] = 0xAA;
    hcan1.pTxMsg->DLC = 8;
    hcan1.pTxMsg->StdId = 1960;
    HAL_CAN_Transmit_IT(&hcan1);
    result = HAL_CAN_Receive_IT(&hcan1, 0);
  }
  else if ( hcan1.pRxMsg->StdId == 0x7A0
         && hcan1.pRxMsg->Data[0] == 3
         && hcan1.pRxMsg->Data[1] == 0x22
         && hcan1.pRxMsg->Data[2] == 0xF1
         && hcan1.pRxMsg->Data[3] == 0x93 )
  {
    memset(hcan1.pTxMsg->Data, 8, 0xAA);
    hcan1.pTxMsg->Data[0] = 0x10;
    hcan1.pTxMsg->Data[1] = 0x13;
    hcan1.pTxMsg->Data[2] = 0x62;
    hcan1.pTxMsg->Data[3] = 0xF1;
    hcan1.pTxMsg->Data[4] = 0x93;
    hcan1.pTxMsg->Data[5] = get_hw_vehicle_type();
    hcan1.pTxMsg->Data[6] = 0x20;
    hcan1.pTxMsg->Data[7] = 0x20;
    hcan1.pTxMsg->DLC = 8;
    hcan1.pTxMsg->StdId = 0x7A8;
    byte_20000258 = 1;
    HAL_CAN_Transmit_IT(&hcan1);
    result = HAL_CAN_Receive_IT(&hcan1, 0);
  }

此处为TBOX固件中对CAN总线数据的处理,可以看到TBOX对一些UDS诊断命令的响应,如: 02 10 01 跳转到默认会话 03 22 F1 93 读取硬件版本

image.png
ISO 14229-1-2013 340页

int sub_800F34C()
{
  __int64 v0; // r0
  unsigned __int64 v1; // kr00_8
  bool v2; // zf
  int v4; // [sp+0h] [bp-110h] BYREF
  unsigned __int16 v5; // [sp+4h] [bp-10Ch]
  unsigned __int16 v6; // [sp+6h] [bp-10Ah]
  unsigned __int16 v7[132]; // [sp+8h] [bp-108h] BYREF

  if ( !sub_800363C(usart2_rx_fifo) )
  {
    LODWORD(v0) = (unsigned __int8)byte_2000414D;
    if ( byte_2000414D )
    {
      v1 = sub_8003B44() - qword_20004150;
      LODWORD(v0) = HIDWORD(v1);
      if ( v1 > 0x1388 )
      {
        v0 = sub_8003B44();
        qword_20004150 = v0;
      }
    }
    return v0;
  }
  fifo_get((int)usart2_rx_fifo, (int)&v4, 8u);
  if ( v6 )
    fifo_get((int)usart2_rx_fifo, (int)v7, v6);
  Log(2u, "Rx:cmd=%d", v5);
  qword_20004150 = sub_8003B44();
  LODWORD(v0) = v5;
  HIDWORD(v0) = v5 - 325;
  if ( v5 == 325 )
  {
    LODWORD(v0) = sub_8010106();
    return v0;
  }
  if ( v5 > 0x145u )
  {
    if ( v5 == 504 )
    {
      LODWORD(v0) = sub_8010AF0(v7, 179);
      return v0;
    }
    if ( SHIDWORD(v0) <= 179 )
    {
      if ( v5 == 351 )
      {
        LODWORD(v0) = sub_8011150();
        return v0;
      }
      if ( SHIDWORD(v0) > 26 )
      {
        if ( v5 == 361 )
        {
          LODWORD(v0) = sub_8010EF4(v7);
          return v0;
        }
        if ( SHIDWORD(v0) <= 36 )
        {
          switch ( v5 )
          {
            case 0x162u:
              LODWORD(v0) = sub_800F97C(v7);
              return v0;
            case 0x163u:
              LODWORD(v0) = sub_8011058(v7);
              return v0;
            case 0x165u:
              LODWORD(v0) = sub_801024C();
              return v0;
          }
          v2 = HIDWORD(v0) == 34;
          if ( v5 == 359 )
          {
            LODWORD(v0) = sub_8010F60(v7);
            return v0;
          }
          goto LABEL_30;
        }
        switch ( v5 )
        {
          case 0x191u:
            LODWORD(v0) = sub_80111F8();
            return v0;
          case 0x193u:
            LODWORD(v0) = sub_8011290();
            return v0;
          case 0x195u:
            LODWORD(v0) = sub_800FEA4();
            return v0;
        }
        v2 = HIDWORD(v0) == 177;
        if ( v5 == 502 )
        {
          LODWORD(v0) = sub_8010AB8(v7);
          return v0;
        }
LABEL_44:
        if ( v2 )
        {
          LODWORD(v0) = sub_80102DC();
          return v0;
        }
        goto LABEL_20;
      }
      if ( v5 == 339 )
      {
        LODWORD(v0) = sub_800FA00();
        return v0;
      }
      if ( SHIDWORD(v0) > 14 )
      {
        switch ( v5 )
        {
          case 0x155u:
            LODWORD(v0) = sub_800F9BC();
            return v0;
          case 0x157u:
            LODWORD(v0) = sub_800FBA4(v7);
            return v0;
          case 0x15Bu:
            LODWORD(v0) = sub_801A86C();
            return v0;
        }
        v2 = HIDWORD(v0) == 24;
        if ( v5 == 349 )
        {
          LODWORD(v0) = sub_8002404();
          return v0;
        }
      }
      else
      {
        if ( v5 == 333 )
        {
          LODWORD(v0) = sub_800FB48();
          return v0;
        }
        if ( SHIDWORD(v0) <= 8 )
        {
          if ( v5 == 327 )
          {
            LODWORD(v0) = sub_80100EC();
            return v0;
          }
          v2 = HIDWORD(v0) == 6;
          goto LABEL_71;
        }
        if ( v5 == 335 )
        {
          LODWORD(v0) = sub_800FB08();
          return v0;
        }
        v2 = HIDWORD(v0) == 12;
        if ( v5 == 337 )
        {
          LODWORD(v0) = sub_8010154();
          return v0;
        }
      }
LABEL_20:
      if ( v2 )
        LODWORD(v0) = sub_80108C4(v7, HIDWORD(v0));
      return v0;
    }
    LODWORD(v0) = v5 - 806;
    if ( v5 == 806 )
    {
      LODWORD(v0) = sub_8010D40(v7);
      return v0;
    }
    if ( SHIDWORD(v0) <= 481 )
    {
      if ( v5 == 605 )
      {
        LODWORD(v0) = sub_801102C(v7);
        return v0;
      }
      if ( SHIDWORD(v0) > 280 )
      {
        HIDWORD(v0) = v5 - 702;
        switch ( v5 )
        {
          case 0x2BEu:
            LODWORD(v0) = sub_8010B4C(v7);
            return v0;
          case 0x2C0u:
            LODWORD(v0) = sub_8010B72(v7);
            return v0;
          case 0x322u:
            LODWORD(v0) = sub_8010D18(v7);
            return v0;
        }
        v2 = HIDWORD(v0) == 102;
        if ( v5 == 804 )
        {
          LODWORD(v0) = sub_8010CE8(v7);
          return v0;
        }
      }
      else
      {
        switch ( v5 )
        {
          case 0x1FAu:
            LODWORD(v0) = sub_8010B28(v7);
            return v0;
          case 0x1FCu:
            LODWORD(v0) = sub_80115DC(v0);
            return v0;
          case 0x1FEu:
            LODWORD(v0) = sub_8010BB2(v7);
            return v0;
        }
        v2 = HIDWORD(v0) == 278;
        if ( v5 == 603 )
        {
          LODWORD(v0) = sub_801100C(v7);
          return v0;
        }
      }
      goto LABEL_57;
    }
    if ( v5 == 908 )
    {
      LODWORD(v0) = sub_8011654(v7);
      return v0;
    }
    if ( (int)v0 > 102 )
    {
      if ( v5 == 1002 )
      {
        LODWORD(v0) = sub_8010A78(v7);
        return v0;
      }
      if ( v5 == 1004 )
        return v0;
      LODWORD(v0) = v5 - 1101;
      if ( v5 == 1101 )
      {
        LODWORD(v0) = sub_800FBC4();
        return v0;
      }
      v2 = (_DWORD)v0 == 16;
      if ( v5 == 1117 )
      {
        LODWORD(v0) = sub_801073C((unsigned __int8 *)v7);
        return v0;
      }
    }
    else
    {
      switch ( v5 )
      {
        case 0x328u:
          LODWORD(v0) = sub_8010CC0(v7);
          return v0;
        case 0x386u:
          LODWORD(v0) = sub_8010BD8(v7);
          return v0;
        case 0x388u:
          LODWORD(v0) = sub_80115F4(v7);
          return v0;
      }
      v2 = (_DWORD)v0 == 100;
      if ( v5 == 906 )
      {
        LODWORD(v0) = sub_8010C4C(v7);
        return v0;
      }
    }
LABEL_71:
    if ( v2 )
    {
      LODWORD(v0) = sub_800FBFA(v7);
      return v0;
    }
    goto LABEL_20;
  }
  if ( v5 == 209 )
  {
    LODWORD(v0) = sub_8010D68(v7);
    return v0;
  }
  if ( v5 <= 0xD1u )
  {
    if ( v5 == 23 )
    {
      LODWORD(v0) = sub_8010180();
      return v0;
    }
    if ( v5 <= 0x17u )
    {
      if ( v5 == 13 )
      {
        LODWORD(v0) = sub_80108AE();
        return v0;
      }
      if ( v5 <= 0xDu )
      {
        if ( v5 == 6 )
        {
          LODWORD(v0) = sub_80102D0(v7, HIDWORD(v0));
          return v0;
        }
        if ( v5 > 6u )
        {
          if ( v5 == 9 )
          {
            LODWORD(v0) = sub_8010284();
            return v0;
          }
          v2 = v5 == 12;
          if ( v5 == 12 )
            return v0;
        }
        else
        {
          if ( v5 == 2 )
          {
            LODWORD(v0) = sub_8011330(v7, HIDWORD(v0));
            return v0;
          }
          v2 = v5 == 3;
        }
        goto LABEL_20;
      }
      switch ( v5 )
      {
        case 0xFu:
          LODWORD(v0) = sub_80107C0((int *)v7);
          return v0;
        case 0x12u:
          return v0;
        case 0x14u:
          LODWORD(v0) = sub_8010994((int *)v7);
          return v0;
      }
      v2 = v5 == 22;
LABEL_30:
      if ( v2 )
      {
        LODWORD(v0) = sub_8011530(v7, HIDWORD(v0));
        return v0;
      }
      goto LABEL_20;
    }
    if ( v5 == 33 )
    {
      LODWORD(v0) = sub_800FA4C(v7, HIDWORD(v0));
      return v0;
    }
    if ( v5 <= 0x21u )
    {
      if ( v5 == 26 || v5 == 28 )
        return v0;
      if ( v5 == 29 )
      {
        LODWORD(v0) = sub_80110D8(v7, HIDWORD(v0));
        return v0;
      }
      v2 = v5 == 32;
      if ( v5 == 32 )
        return v0;
      goto LABEL_20;
    }
    switch ( v5 )
    {
      case 'e':
        LODWORD(v0) = sub_8011460();
        return v0;
      case 'g':
        LODWORD(v0) = sub_801142C();
        return v0;
      case 'i':
        LODWORD(v0) = sub_8010884(v7, HIDWORD(v0));
        return v0;
    }
    v2 = v5 == 107;
    goto LABEL_44;
  }
  HIDWORD(v0) = v5 - 305;
  if ( v5 == 305 )
  {
    LODWORD(v0) = sub_80111C8();
    return v0;
  }
  if ( v5 <= 0x131u )
  {
    if ( v5 == 221 )
    {
      LODWORD(v0) = sub_8003506(221, SHIDWORD(v0), 305, 0x2018);
      return v0;
    }
    if ( v5 <= 0xDDu )
    {
      LODWORD(v0) = v5 - 212;
LABEL_52:
      switch ( (int)v0 )
      {
        case 1:
          LODWORD(v0) = nullsub_20();
          break;
        case 3:
          LODWORD(v0) = sub_8010DA4(v7[0]);
          break;
        case 7:
          LODWORD(v0) = sub_80113F4();
          break;
        default:
          return v0;
      }
      return v0;
    }
    if ( v5 == 226 )
      return v0;
    if ( v5 == 231 )
    {
      LODWORD(v0) = sub_801071C(v7, HIDWORD(v0));
      return v0;
    }
    LODWORD(v0) = v5 - 301;
    if ( v5 == 301 )
    {
      LODWORD(v0) = sub_80111DE();
      return v0;
    }
    v2 = (_DWORD)v0 == 2;
LABEL_57:
    if ( v2 )
    {
      LODWORD(v0) = sub_8011276();
      return v0;
    }
    goto LABEL_20;
  }
  LODWORD(v0) = v5 - 307;
  switch ( v5 )
  {
    case 0x133u:
      LODWORD(v0) = sub_8011260();
      break;
    case 0x134u:
    case 0x136u:
    case 0x138u:
    case 0x13Au:
    case 0x13Cu:
    case 0x13Eu:
    case 0x140u:
    case 0x142u:
      return v0;
    case 0x135u:
      LODWORD(v0) = sub_8010EE4();
      break;
    case 0x137u:
      LODWORD(v0) = sub_8010E88();
      break;
    case 0x139u:
      LODWORD(v0) = sub_801020C();
      break;
    case 0x13Bu:
      LODWORD(v0) = sub_80112FC();
      break;
    case 0x13Du:
      LODWORD(v0) = sub_80112C8();
      break;
    case 0x13Fu:
      LODWORD(v0) = sub_8010120();
      break;
    case 0x141u:
      LODWORD(v0) = sub_8010980();
      break;
    case 0x143u:
      LODWORD(v0) = sub_800FBE6();
      break;
    default:
      goto LABEL_52;
  }
  return v0;
}

此处代码为对LTE模块传入指令的一些处理

结尾

到此,我们已经获取了TBOX的固件,并对其进行了一些还原,逆向了其部分功能的逻辑。接下来便是漏洞挖掘的过程,在本篇文章不过多阐述这部分内容。

参与评论

0 / 200

全部评论 0

暂无人评论
投稿
签到
联系我们
关于我们