首页
社区
课程
招聘
华为光猫HG8245H救砖笔记⑥逆向UBoot恢复海思命令行
发表于: 2017-2-22 15:49 19930

华为光猫HG8245H救砖笔记⑥逆向UBoot恢复海思命令行

bxc 活跃值
6
2017-2-22 15:49
19930

原文发在我的blog:http://blog.csersoft.net/archives/174

正文:

前文中虽然成功的运行了UBoot,但是因为内核损坏,依然无法正常启动。想要用UBoot刷写Flash,就必须进入UBoot的命令行模式,一般UBoot在引导过程中,会有短暂的时间让用户按下某些指定的按键来中断自动引导。可是之前运行的UBoot并没有这样的提示,感觉可能是华为禁用了UBoot的命令行。

曾经在网上看到过关于HG8245的UBoot的输出信息,其中包含如下字样的提示:

Press d key to abort autoboot: 10

一番周折后,找到了存在该信息的固件,不过是HG8245的,不是HG8245H的。提取UBoot后,尝试放到HG8245H里运行,但UART没有任何输出。

于是打算逆向UBoot,看看中断自动引导部分功能是否被禁用了,根据对字符串的引用参考分析,定位到了main_loop函数,以下为逆向的伪代码:

网上有很多关于UBoot引导流程分析的文章,阅读过后便可知道abortboot函数是中止自动引导的关键所在,一般这个函数会在bootdelay指定的时间内,检查bootstopkey设定的键码是否被按下。如果条件满足中止引导的话,就返回非0值,否则返回0。

所以看下abortboot函数的伪代码,就清楚问题出在哪里了:

果不其然,可以发现这个函数,无论如何,都会返回0,即永远无法进入命令行模式。

那么修改该函数的返回值,应该就可以实现无条件进入命令行模式了吧。IDA Pro中转到return 0对应的机器码:

使用16进制编辑器,或者IDA的keypatch插件,修改该指令为:

保存后,重启光猫,继续通过OpenOCD写入内存运行UBoot,这时UART中输出如下:

 

HuaWei StartCode 2012.02 (R13C10 Apr 22 2014 – 18:06:02)

NAND: Nand(Hardware): 128 MiB
startcode select the uboot to load
the high RAM is :8080103c
startcode uboot boot count:0
Slave struct initializtion success!!
Use the UbootA to load first
Start from UbootA ERROR, Change to UbootB
Both UbootA and UbootB are wrong, load it by JTAG!
U-Boot 2010.03 (R16C10 Jul 14 2016 – 14:19:37)

DRAM: 128 MB
Boot From NAND flash
Chip Type is SD5115T
NAND: Special Nand id table Version 1.23
Nand ID: 0x01 0xF1 0x00 0x1D 0x01 0xF1 0x00 0x1D
ECC Match pagesize:2K, oobzie:64, ecctype:4bit
Nand(Hardware): Block:128KB Page:2KB Chip:128MB*1 OOB:64B ECC:4bit
128 MiB
Using default environment

In: serial
Out: serial
Err: serial
PHY power down !!!
[main.c__6080]::CRC:0x39e1f1ae, Magic1:0x5a5a5a5a, Magic2:0xa5a5a5a5, count:0, CommitedArea:0x0, Active:0xfffffffd, RunFlag:0xffffffff
0x000000100000-0x000008000000 : “mtd=1”
UBI: attaching mtd1 to ubi0
slave_paramA in flash, CRC:0x9789603f, Magic1:0x5a5a5a5a, Magic2:0xa5a5a5a5, count:0, CommitedArea:0x0, Active:0x0, RunFlag:0x2
use slave_paramA which is from flash, the RAM data is not OK!!!
Start from main system(0x0)!
CRC:0x9789603f, Magic1:0x5a5a5a5a, Magic2:0xa5a5a5a5, count:1, CommitedArea:0x0, Active:0x0, RunFlag:0x2
Main area (A) is OK!
CRC:0x39e1f1ae, Magic1:0x5a5a5a5a, Magic2:0xa5a5a5a5, count:1, CommitedArea:0x0, Active:0x0, RunFlag:0x2
UBIFS error (pid 0): ubifs_recover_master_node: failed to recover master node
Error reading superblock on volume ‘ubi:file_system’!
mount ubifs error!
Bootcmd:ubi read 0x85c00000 kernelA 0x19f28a; bootm 0x85c00054
BootArgs:noalign mem=118M console=ttyAMA1,115200 ubi.mtd=1 root=/dev/mtdblock11 rootfstype=squashfs mtdparts=hinand:0x100000(startcode),0x7f00000(ubifs),-(reserved) pcie0_sel=x1 maxcpus=0 l2_cache=l2hi coherent_pool=4M user_debug=0x1f panic=1 skb_priv=128 debug_ll=on
U-boot Start from NORMAL Mode!
resetting …
HuaWei StartCode 2012.02 (R13C10 Apr 22 2014 – 18:06:02)

NAND: Nand(Hardware): 128 MiB
startcode select the uboot to load
the high RAM is :8080103c
startcode uboot boot count:0
Slave struct initializtion success!!
Use the UbootA to load first
Start from UbootA ERROR, Change to UbootB
Both UbootA and UbootB are wrong, load it by JTAG!

中止自动引导虽然成功了,但是UBoot直接重启了设备。接着分析main_loop函数,在调用完abortboot函数之后,有个可疑函数,会根据某内存地址的值而被决定是否调用(ps: 当时分析的时候,这个函数的名字还没有被我修改成fn_reset_24100):

跟入该函数后,发现它有向UART输出”resetting …\n”字串,那么导致设备重置的函数,应该就是这个了。尝试无条件跳过该函数:

修改为:

保存后,重新装载UBoot并运行:

 

HuaWei StartCode 2012.02 (R13C10 Apr 22 2014 – 18:06:02)

NAND: Nand(Hardware): 128 MiB
startcode select the uboot to load
the high RAM is :8080103c
startcode uboot boot count:-1
use the main slave_param area from flash, the RAM data is not OK!!!
Use the UbootA to load first
Use the UbootA to load success
U-Boot 2010.03 (R16C10 Jul 14 2016 – 14:19:37)

DRAM: 128 MB
Boot From NAND flash
Chip Type is SD5115T
NAND: Special Nand id table Version 1.23
Nand ID: 0x01 0xF1 0x00 0x1D 0x01 0xF1 0x00 0x1D
ECC Match pagesize:2K, oobzie:64, ecctype:4bit
Nand(Hardware): Block:128KB Page:2KB Chip:128MB*1 OOB:64B ECC:4bit
128 MiB
Using default environment

In: serial
Out: serial
Err: serial
PHY power down !!!
[main.c__6080]::CRC:0x9789603f, Magic1:0x5a5a5a5a, Magic2:0xa5a5a5a5, count:0, CommitedArea:0x0, Active:0x0, RunFlag:0x2
Start from main system(0x0)!
CRC:0x9789603f, Magic1:0x5a5a5a5a, Magic2:0xa5a5a5a5, count:1, CommitedArea:0x0, Active:0x0, RunFlag:0x2
0x000000100000-0x000008000000 : “mtd=1”
UBI: attaching mtd1 to ubi0
Main area (A) is OK!
CRC:0x39e1f1ae, Magic1:0x5a5a5a5a, Magic2:0xa5a5a5a5, count:1, CommitedArea:0x0, Active:0x0, RunFlag:0x2
UBIFS error (pid 0): ubifs_recover_master_node: failed to recover master node
Error reading superblock on volume ‘ubi:file_system’!
mount ubifs error!
Bootcmd:ubi read 0x85c00000 kernelA 0x19f28a; bootm 0x85c00054
BootArgs:noalign mem=118M console=ttyAMA1,115200 ubi.mtd=1 root=/dev/mtdblock11 rootfstype=squashfs mtdparts=hinand:0x100000(startcode),0x7f00000(ubifs),-(reserved) pcie0_sel=x1 maxcpus=0 l2_cache=l2hi coherent_pool=4M user_debug=0x1f panic=1 skb_priv=128 debug_ll=on
U-boot Start from NORMAL Mode!
hisilicon #

成功恢复海思UBoot命令行!


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
void __noreturn main_loop_1B038()
{
  int v0; // r0@1
  int v1; // r1@1
  const char *lpszBootDelay; // r0@1
  signed int nBootDelay; // r4@2
  const char *lpszBootCmd; // r5@4
  bool lpszBootCmd_Bak; // r3@4
  int v6; // r4@8
  int v7; // r0@12
  int v8; // r1@12
  signed int v9; // r4@13
  int v10; // r0@14
  int v11; // [sp+0h] [bp-10h]@0
  int (__fastcall *v12)(_DWORD); // [sp+4h] [bp-Ch]@0
 
  v0 = setenv_14038("ver", "U-Boot 2010.03 (R16C10 Jul 14 2016 - 14:19:37)");
  sub_81F15B08(v0, v1);
  lpszBootDelay = (const char *)getenv_13B6C("bootdelay");
  if ( lpszBootDelay )
    nBootDelay = simple_strtol_20574(lpszBootDelay, 0, 10u);
  else
    nBootDelay = 1;
  sub_81F1AD70();
  lpszBootCmd = (const char *)getenv_13B6C("bootcmd");
  lpszBootCmd_Bak = lpszBootCmd != 0;
  if ( nBootDelay < 0 )
    lpszBootCmd_Bak = 0;
  if ( lpszBootCmd_Bak && !abortboot_19138(nBootDelay) )
  {
    v6 = sub_81F163A0(1);
    run_command_18D5C(lpszBootCmd, 0);
    sub_81F163A0(v6);
  }
  if ( !dword_81A65718 )
    fn_reset_24100(dword_81A65718, dword_81A65718, dword_81A65718, dword_81A65718, v11, v12);
  sub_81F1D210(0);
  if ( (unk_81A65BCC & 0xFFFF00) == 0x20100 )
  {
    v7 = fn_Printf2UART_162D8("DEBUG Mode & 5116T!\n");
    sub_81F09F70(v7, v8);
    sub_81F0A5A0();
    sub_81F0C524();
  }
  v9 = 1;
  while ( 1 )
  {
    v10 = readline_18CB4("hisilicon # ");
    if ( v10 > 0 )
      break;
    if ( v10 )
    {
      if ( v10 != -1 )
        goto LABEL_19;
      puts_162A8("<INTERRUPT>\n");
LABEL_20:
      if ( v9 <= 0 )
        lastcommand_81A6571C[0] = 0;
    }
  }
  strcpy_1F96C(lastcommand_81A6571C, console_buffer_81A65268);
LABEL_19:
  v9 = run_command_18D5C(lastcommand_81A6571C, 0);
  goto LABEL_20;
}
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
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
void __noreturn main_loop_1B038()
{
  int v0; // r0@1
  int v1; // r1@1
  const char *lpszBootDelay; // r0@1
  signed int nBootDelay; // r4@2
  const char *lpszBootCmd; // r5@4
  bool lpszBootCmd_Bak; // r3@4
  int v6; // r4@8
  int v7; // r0@12
  int v8; // r1@12
  signed int v9; // r4@13
  int v10; // r0@14
  int v11; // [sp+0h] [bp-10h]@0
  int (__fastcall *v12)(_DWORD); // [sp+4h] [bp-Ch]@0
 
  v0 = setenv_14038("ver", "U-Boot 2010.03 (R16C10 Jul 14 2016 - 14:19:37)");
  sub_81F15B08(v0, v1);
  lpszBootDelay = (const char *)getenv_13B6C("bootdelay");
  if ( lpszBootDelay )
    nBootDelay = simple_strtol_20574(lpszBootDelay, 0, 10u);
  else
    nBootDelay = 1;
  sub_81F1AD70();
  lpszBootCmd = (const char *)getenv_13B6C("bootcmd");
  lpszBootCmd_Bak = lpszBootCmd != 0;
  if ( nBootDelay < 0 )
    lpszBootCmd_Bak = 0;
  if ( lpszBootCmd_Bak && !abortboot_19138(nBootDelay) )
  {
    v6 = sub_81F163A0(1);
    run_command_18D5C(lpszBootCmd, 0);
    sub_81F163A0(v6);
  }
  if ( !dword_81A65718 )
    fn_reset_24100(dword_81A65718, dword_81A65718, dword_81A65718, dword_81A65718, v11, v12);
  sub_81F1D210(0);
  if ( (unk_81A65BCC & 0xFFFF00) == 0x20100 )
  {
    v7 = fn_Printf2UART_162D8("DEBUG Mode & 5116T!\n");
    sub_81F09F70(v7, v8);
    sub_81F0A5A0();
    sub_81F0C524();
  }
  v9 = 1;
  while ( 1 )
  {
    v10 = readline_18CB4("hisilicon # ");
    if ( v10 > 0 )
      break;
    if ( v10 )
    {
      if ( v10 != -1 )
        goto LABEL_19;
      puts_162A8("<INTERRUPT>\n");
LABEL_20:
      if ( v9 <= 0 )
        lastcommand_81A6571C[0] = 0;
    }
  }
  strcpy_1F96C(lastcommand_81A6571C, console_buffer_81A65268);
LABEL_19:
  v9 = run_command_18D5C(lastcommand_81A6571C, 0);
  goto LABEL_20;
}
void __noreturn main_loop_1B038()
{
  int v0; // r0@1
  int v1; // r1@1
  const char *lpszBootDelay; // r0@1
  signed int nBootDelay; // r4@2
  const char *lpszBootCmd; // r5@4
  bool lpszBootCmd_Bak; // r3@4
  int v6; // r4@8
  int v7; // r0@12
  int v8; // r1@12
  signed int v9; // r4@13
  int v10; // r0@14
  int v11; // [sp+0h] [bp-10h]@0
  int (__fastcall *v12)(_DWORD); // [sp+4h] [bp-Ch]@0
 
  v0 = setenv_14038("ver", "U-Boot 2010.03 (R16C10 Jul 14 2016 - 14:19:37)");
  sub_81F15B08(v0, v1);
  lpszBootDelay = (const char *)getenv_13B6C("bootdelay");
  if ( lpszBootDelay )
    nBootDelay = simple_strtol_20574(lpszBootDelay, 0, 10u);
  else
    nBootDelay = 1;
  sub_81F1AD70();
  lpszBootCmd = (const char *)getenv_13B6C("bootcmd");
  lpszBootCmd_Bak = lpszBootCmd != 0;
  if ( nBootDelay < 0 )
    lpszBootCmd_Bak = 0;
  if ( lpszBootCmd_Bak && !abortboot_19138(nBootDelay) )
  {
    v6 = sub_81F163A0(1);
    run_command_18D5C(lpszBootCmd, 0);
    sub_81F163A0(v6);
  }
  if ( !dword_81A65718 )
    fn_reset_24100(dword_81A65718, dword_81A65718, dword_81A65718, dword_81A65718, v11, v12);
  sub_81F1D210(0);
  if ( (unk_81A65BCC & 0xFFFF00) == 0x20100 )
  {
    v7 = fn_Printf2UART_162D8("DEBUG Mode & 5116T!\n");
    sub_81F09F70(v7, v8);
    sub_81F0A5A0();
    sub_81F0C524();
  }
  v9 = 1;
  while ( 1 )
  {
    v10 = readline_18CB4("hisilicon # ");
    if ( v10 > 0 )
      break;
    if ( v10 )
    {
      if ( v10 != -1 )
        goto LABEL_19;
      puts_162A8("<INTERRUPT>\n");
LABEL_20:
      if ( v9 <= 0 )
        lastcommand_81A6571C[0] = 0;
    }
  }
  strcpy_1F96C(lastcommand_81A6571C, console_buffer_81A65268);
LABEL_19:
  v9 = run_command_18D5C(lastcommand_81A6571C, 0);
  goto LABEL_20;
}
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
105
106
107
108
109
110
111
112
113
114
int __fastcall abortboot_19138(int bootdelay)
{
  int v1; // r4@1
  unsigned __int64 v2; // r0@1
  signed int v3; // r0@1
  signed __int64 v4; // r2@1
  __int64 v5; // r0@1
  char *v6; // r0@1
  char *v7; // r4@1
  char *v8; // r0@1
  char *v9; // r3@1
  char v10; // zf@1
  int v11; // r4@1
  char *v12; // r6@3
  char *v13; // r0@5
  delaykey *v14; // r3@9
  unsigned int v15; // r4@12
  char *i; // r3@15
  int v17; // r5@20
  delaykey *v18; // r3@20
  signed int v19; // r10@20
  unsigned int v20; // r2@21
  delaykey *v21; // ST04_4@23
  int v22; // r0@23
  unsigned __int64 v23; // r0@27
  unsigned __int64 v25; // [sp+8h] [bp-78h]@1
  char v26[32]; // [sp+10h] [bp-70h]@15
  delaykey _dk[4]; // [sp+30h] [bp-50h]@1
  char v28; // [sp+60h] [bp-20h]@16
 
  v1 = bootdelay;
  LODWORD(v2) = get_ticks_23F34();
  v25 = v2;
  v3 = sub_81F23F44();
  v4 = get_tbclk_3B104(v3, 1000u) * (signed __int64)v1;
  HIDWORD(v5) = HIDWORD(v25);
  LODWORD(v5) = v25 + v4;
  v25 = v5 + v4;
  sub_81F1FD18(_dk, 0, 48);
  _dk[0].retry = 1;
  _dk[0].str = (char *)getenv_13B6C("bootdelaykey");
  _dk[1].retry = 1;
  _dk[1].str = (char *)getenv_13B6C("bootdelaykey2");
  v6 = (char *)getenv_13B6C("bootstopkey");
  v7 = v6;
  _dk[2].str = v6;
  v8 = (char *)getenv_13B6C("bootstopkey2");
  v10 = v7 == 0;
  v11 = 0;
  if ( v10 )
    v9 = "read from corrupted volume %d" + 28;
  v12 = 0;
  _dk[3].str = v8;
  if ( v10 )
    _dk[2].str = v9;
  do
  {
    v13 = _dk[v11].str;
    if ( v13 )
      v13 = (char *)sub_81F1FAD4(v13);
    if ( (unsigned int)v13 >= 0x20 )
      v13 = (char *)32;
    v14 = &_dk[v11];
    ++v11;
    if ( v12 < v13 )
      v12 = v13;
    v14->len = (unsigned int)v13;
  }
  while ( v11 != 4 );
  v15 = 0;
  do
  {
    if ( sub_81F16248() )
    {
      if ( v15 < (unsigned int)v12 )
      {
        *(&v28 + v15++ - 80) = sub_81F16218();
      }
      else
      {
        for ( i = v26; i - v26 < (unsigned int)(v12 - 1); ++i )
          *i = i[1];
        v12[(_DWORD)&v28 - 81] = sub_81F16218();
      }
    }
    v17 = 0;
    v18 = _dk;
    v19 = 0;
    do
    {
      v20 = v18[v17].len;
      if ( v20 )
      {
        if ( v15 >= v20 )
        {
          v21 = v18;
          v22 = sub_81F1FE60((int)&v26[v15 - v20], (int)v18[v17].str, v20);
          v18 = v21;
          if ( !v22 )
            v19 = 1;
        }
      }
      ++v17;
    }
    while ( v17 != 4 );
    if ( v19 )
      break;
    LODWORD(v23) = get_ticks_23F34();
  }
  while ( v25 >= v23 );
  fn_Printf2UART_162D8("U-boot Start from NORMAL Mode!\n");
  sub_81F190F0(1);
  return 0;
}
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
105
106
107
108
109
110
111
112
113
114
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

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 1
支持
分享
最新回复 (8)
雪    币: 12
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
可以提供修改之后的uboot吗?
2017-3-8 15:43
0
雪    币: 7048
活跃值: (3527)
能力值: ( LV12,RANK:340 )
在线值:
发帖
回帖
粉丝
3
fnto 可以提供修改之后的uboot吗?
发到chinadsl上了,还在审核,http://www.chinadsl.net/forum.php?mod=viewthread&tid=128798
2017-3-9 12:16
0
雪    币: 12
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
下载了,非常感谢。
2017-3-12 11:14
0
雪    币: 12
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
应该还有下文吧,如何刷回固件,没有现成编程器固件分包的情况下,用官方固件如何制作编程器固件呢?
2017-6-6 11:11
0
雪    币: 7048
活跃值: (3527)
能力值: ( LV12,RANK:340 )
在线值:
发帖
回帖
粉丝
6
fnto 应该还有下文吧[em_1],如何刷回固件,没有现成编程器固件分包的情况下,用官方固件如何制作编程器固件呢?
最近没时间
2017-6-6 20:22
0
雪    币: 12
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
等您大作
2017-6-7 23:32
0
雪    币: 12
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
救成功一个,uboot下的命令与分区是一一对应的,除了wifi参数分区,但奇怪的是用刷startcode命令,刷完居然启不开,要启动到系统再刷startcode才行。
2017-8-27 23:52
0
雪    币: 458
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
这个就有点牛逼了。理论上可以破解很多东西~~~比如一些安全启动类型的。fuse 或者 efuse之类的
2019-10-12 16:20
0
游客
登录 | 注册 方可回帖
返回
//