Post

Tp-Link Router Deep Research

Tp-Link Router Deep Research

Good morning! In this blog I would like to delve into hardware hacking and start expanding my learning.

To begin, in today’s blog we go from 0 (sealed router) to reversing the u-boot by physically extracting the firmware as well as analyzing internal binaries and potential vulnerabilities.

The target is an old router which is one of the most purchased on Amazon (my version is older than the current one, I bought it second-hand):

Target - TL-WR841N

This is the router itself, as I mentioned it is not the latest range but an earlier version:

This is the back:

If we look closely we can see both the model and the serial number:

Footprinting

Now we can open it and start looking at the internal components and the SoC:

If we zoom in more…

For now there are two visible components, the RAM (rectangular) and the CPU (square).

Here we have the RAM which is not very important for our objective but it is always important to record the serial number. The more information the better tho.

The other visible component is the CPU, in this case Mediatek:

We have a Mediatek MT7628NN, which if we check the datasheet:

We obtain useful information but nothing groundbreaking.

If we look at the back of the chip, we will see that it has a flash memory, responsible for loading the operating system:

if we zoom in we will see that it is the model 25Q64CS1G:

We will leave this chip for later.

Looking at the router’s physical interfaces we find what could be a UART:

The first thing is to make sure which one is the GND with the multimeter. In this case it is marked on the board but I don’t like to trust that completely.

The other probe of the multimeter we would place on something we know is a GND, such as a conductor of one of the router’s connectors, in my case I put it here:

By testing with the multimeter we can observe how it indeed matches the chip’s rx and tx of the UART protocol. On the rx we see information activity when we power on the router, however on the tx we don’t see anything.

Uart Protocol

UART or Universal Asynchronous Receiver (Rx) Transmitter (Tx) is a serial communication protocol between devices. It uses asynchronous communication which means there is no dedicated clock signal on the data line; instead the transmitter and receiver agree on a baud rate (9600 bps, 19200 bps, 38400 bps, 57600 bps, 115200 bps, 230400 bps, 460800 bps, 921600 bps, 1000000 bps, 1500000 bps) and synchronize from the start bit. Being serial, the bits are sent one after another over a single data line. Data can also be sent and received simultaneously.

here we can see a diagram (resource) of UART to make it clearer:

When establishing device-to-device communication over UART it is important to connect Ground to Ground, tx to rx and vice versa. The following image explains it:

Communication

Now that we understand the UART protocol, we will proceed to connect. for that we can use a static mechanical arm which I don’t have, or solder.

Uart: tx

now we can connect to the tx with our logic analyzer to see the output:

in Logic 2 we can see the output:

Which would be the following (removing the dirty bytes at the beginning):

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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
DDR Calibration DQS reg = 00008A89


U-Boot 1.1.3 (Oct 12 2016 - 08:49:46)

Board: Ralink APSoC DRAM:  64 MB
relocate_code Pointer at: 83fb8000
gpiomode1 55054404.
gpiomode2 05540554.
gpiomode2 00000000.
gpiomode2 05550555.
flash manufacture id: c8, device id 40 17
find flash: GD25Q64B
============================================ 
Ralink UBoot Version: 4.3.0.0
-------------------------------------------- 
ASIC 7628_MP (Port5<->None)
DRAM component: 512 Mbits DDR, width 16
DRAM bus: 16 bit
Total memory: 64 MBytes
Flash component: SPI Flash
Date:Oct 12 2016  Time:08:49:46
============================================ 
icache: sets:512, ways:4, linesz:32 ,total:65536
dcache: sets:256, ways:4, linesz:32 ,total:32768 

 ##### The CPU freq = 575 MHZ #### 
 estimate memory size =64 Mbytes
RESET MT7628 PHY!!!!!!
continue to starting system.
\x08\x08\x08 0 
disable switch phyport...
   
3: System Boot system code via Flash.(0xbc020000)
do_bootm:argc=2, addr=0xbc020000
## Booting image at bc020000 ...
   Uncompressing Kernel Image ... OK
No initrd
## Transferring control to Linux (at address 8000c150) ...
## Giving linux memsize in MB, 64

Starting kernel ...

\xE6\x80\x98\x80\xE0\x98\x86\x98\xF8\x98fff\x98\xF8\x06~\x06\x86\xF8\x06~f\x06x\xF8\x86\xF8\x86\xF8\x86\xE6\x80\x98\x80\xE6\x80\x98\x80\0\x18f\x80\x98\x86\x98\x1Ef\x98\x18\xE6\x98\x06\x98\0\xE6\x98f\x98\x1Ef\x80\x98\x80Linux version 2.6.36 (root@tplink) (gcc version 4.6.3 (Buildroot 2012.11.1) ) #83 Wed Oct 12 08:54:10 HKT 2016

 The CPU feqenuce set to 580 MHz

 MIPS CPU sleep mode enabled.
CPU revision is: 00019655 (MIPS 24Kc)
Software DMA cache coherency
Determined physical RAM map:
 memory: 04000000 @ 00000000 (usable)
Initrd not found or empty - disabling initrd
Zone PFN ranges:
  Normal   0x00000000 -> 0x00004000
Movable zone start PFN for each node
early_node_map[1] active PFN ranges
    0: 0x00000000 -> 0x00004000
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 16256
Kernel command line: console=ttyS1,115200 root=/dev/mtdblock2 rootfstype=squashfs init=/sbin/init
PID hash table entries: 256 (order: -2, 1024 bytes)
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
Primary instruction cache 64kB, VIPT, , 4-waylinesize 32 bytes.
Primary data cache 32kB, 4-way, PIPT, no aliases, linesize 32 bytes
Writing ErrCtl register=00059793
Readback ErrCtl register=00059793
Memory: 61268k/65536k available (2628k kernel code, 4236k reserved, 638k data, 164k init, 0k highmem)
NR_IRQS:128
console [ttyS1] enabled
Calibrating delay loop... 386.04 BogoMIPS (lpj=772096)
pid_max: default: 4096 minimum: 301
Mount-cache hash table entries: 512
NET: Registered protocol family 16
bio: create slab <bio-0> at 0
Switching to clocksource Ralink Systick timer
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 2048 (order: 2, 16384 bytes)
TCP bind hash table entries: 2048 (order: 1, 8192 bytes)
TCP: Hash tables configured (established 2048 bind 2048)
TCP reno registered
NET: Registered protocol family 1
squashfs: version 4.0 (2009/01/31) Phillip Lougher
fuse init (API version 7.15)
msgmni has been set to 119
io scheduler noop registered
io scheduler deadline registered (default)
Ralink gpio driver initialized
i2cdrv_major = 218
Serial: 8250/16550 driver, 2 ports, IRQ sharing enabled
serial8250: ttyS0 at MMIO 0x10000d00 (irq = 21) is a 16550A
serial8250: ttyS1 at MMIO 0x10000c00 (irq = 20) is a 16550A
brd: module loaded
flash manufacture id: c8, device id 40 17
GD25Q64B(c8 40170000) (8192 Kbytes)
mtd .name = raspi, .size = 0x00800000 (8M) .erasesize = 0x00010000 (64K) .numeraseregions = 0
Creating 7 MTD partitions on "raspi":
0x000000000000-0x000000020000 : "boot"
0x000000020000-0x000000160000 : "kernel"
0x000000160000-0x0000007c0000 : "rootfs"
mtd: partition "rootfs" set to be root filesystem
0x0000007c0000-0x0000007d0000 : "config"
0x0000007d0000-0x0000007e0000 : "romfile"
0x0000007e0000-0x0000007f0000 : "rom"
0x0000007f0000-0x000000800000 : "radio"
Register flash device:flash0
PPP generic driver version 2.4.2
PPP MPPE Compression module registered
NET: Registered protocol family 24
Mirror/redirect action on
u32 classifier
    Actions configured
Netfilter messages via NETLINK v0.30.
nf_conntrack version 0.5.0 (957 buckets, 3828 max)
ip_tables: (C) 2000-2006 Netfilter Core Team, Type=Restricted Cone
TCP cubic registered
NET: Registered protocol family 10
ip6_tables: (C) 2000-2006 Netfilter Core Team
IPv6 over IPv4 tunneling driver
NET: Registered protocol family 17
Ebtables v2.0 registered
802.1Q VLAN Support v1.8 Ben Greear <greearb@candelatech.com>
All bugs added by David S. Miller <davem@redhat.com>
VFS: Mounted root (squashfs filesystem) readonly on device 31:2.
Freeing unused kernel memory: 164k freed
starting pid 679, tty '': '/etc/init.d/rcS'
rdm_major = 253
spiflash_ioctl_read, Read from 0x007df100 length 0x6, ret 0, retlen 0x6
Read MAC from flash(0x7DF100) ffffffd4-6e-0e-57-1e-ffffffe0
GMAC1_MAC_ADRH -- : 0x0000d46e
GMAC1_MAC_ADRL -- : 0x0e571ee0
Ralink APSoC Ethernet Driver Initilization. v3.1  256 rx/tx descriptors allocated, mtu = 1500!
spiflash_ioctl_read, Read from 0x007df100 length 0x6, ret 0, retlen 0x6
Read MAC from flash(0x7DF100) ffffffd4-6e-0e-57-1e-ffffffe0
GMAC1_MAC_ADRH -- : 0x0000d46e
GMAC1_MAC_ADRL -- : 0x0e571ee0
PROC INIT OK!
switch reg write offset=14, value=5555
switch reg write offset=40, value=1001
switch reg write offset=44, value=1001
switch reg write offset=48, value=1001
switch reg write offset=4c, value=1
switch reg write offset=50, value=2001
switch reg write offset=70, value=ffffffff
switch reg write offset=98, value=7f7f
switch reg write offset=e4, value=7f
done.
switch reg write offset=14, value=405555
switch reg write offset=50, value=2003
switch reg write offset=98, value=7f3f
switch reg write offset=e4, value=3f
switch reg write offset=40, value=3002
switch reg write offset=44, value=3003
switch reg write offset=48, value=3003
switch reg write offset=70, value=417e
switch reg write offset=74, value=0
done.
tp_domain init ok
L2TP core driver, V2.0
PPPoL2TP kernel driver, V2.0
Set: phy[0].reg[0] = 3900
Set: phy[1].reg[0] = 3900
Set: phy[2].reg[0] = 3900
Set: phy[3].reg[0] = 3900
Set: phy[4].reg[0] = 3900
Set: phy[0].reg[0] = 3300
Set: phy[1].reg[0] = 3300
Set: phy[2].reg[0] = 3300
Set: phy[3].reg[0] = 3300
Set: phy[4].reg[0] = 3300
resetMiiPortV over.
starting pid 746, tty '/dev/ttyS1': '/bin/sh'
~ # [ util_execSystem ] 135:  ipt_init cmd is "/var/tmp/dconf/rc.router"

[ dm_readFile ] 2061:  can not open xml file /var/tmp/pc/reduced_data_model.xml!, about to open file /etc/reduced_data_model.xml
spiflash_ioctl_read, Read from 0x007c0000 length 0x10000, ret 0, retlen 0x10000
spiflash_ioctl_read, Read from 0x007c0000 length 0x3010, ret 0, retlen 0x3010
[ dm_loadCfg ] 2278:  software version is not match, in config, version = 271585328
[ dm_readFile ] 2061:  can not open xml file /var/tmp/pc/default_config.xml!, about to open file /etc/default_config.xml
[ parseConfigNode ] 525:  Meet unrecognized object node "PhDDNSCfg", skip the node
[ parseConfigNode ] 530:  Meet unrecognized parameter node "PhDDNSCfg", skip the node
[ parseConfigNode ] 525:  Meet unrecognized object node "SnmpCfg", skspiflash_ioctl_read, Read from 0x007df100 length 0x6, ret 0, retlen 0x6
ip the node
[ pspiflash_ioctl_read, Read from 0x007df200 length 0x4, ret 0, retlen 0x4
arseConfigNode ]spiflash_ioctl_read, Read from 0x007df300 length 0x4, ret 0, retlen 0x4
 525:  Meet unrecognized object node "ACL", skip the node
[ parseConfigNode ] 530:  Meet unrecognized parameter node "ACL", skip the node
[ parseConfigNode ] 525:  Meet unrecognized object node "X_TP_WANUSB3gLinkConfig", skip the node
[ parseConfigNode ] 525:  Meet unrecognized object node "QueueManagement", skip the node
[ parseConfigNode ] 525:  Meet unrecognized object node "X_TP_IPTV", skip the node
[ parseConfigNode ] 525:  Meet unrecognized object node "VoiceService", skip the node
[ parseConfigNode ] 530:  Meet unrecognized parameter node "VoiceService", skip the node
[ parseConfigNode ] 525:  Meet unrecognized object node "StorageService", skip the node
[ parseConfigNode ] 525:  spiflash_ioctl_read, Read from 0x00020000 length 0x1d0, ret 0, retlen 0x1d0
Meet unrecognizespiflash_ioctl_read, Read from 0x007df100 length 0x6, ret 0, retlen 0x6
d object node "X_TP_SpeedDialCfg", skip the node
[ parseConfigNode ] 525:  Meet unrecognized object node "X_TP_MultiIspDialPlan", skip the node
[ parseConfigNode ] 525:  Meet unrecognized object node "X_TP_CallLogCfg", skip the node
sendto: No such file or directory
pid 745 send 2001 error
[ util_execSystem ] 135:  oal_startDynDns cmd is "dyndns /var/tmp/dconf/dyndns.conf"

[ oal_sys_getOldTZInfo ] 389:  Open TZ file error!
[ util_execSystem ] 135:  oal_sys_unsetTZ cmd is "echo "" > /etc/TZ"

[ util_execSystem ] 135:  oal_sys_unsetTZ cmd is "echo "" > /etc/TZ"

[ util_execSystem ] 135:  oal_startNoipDns cmd is "noipdns /var/tmp/dconf/noipdns.conf"

[ util_execSystem ] 135:  oal_startCmxDns cmd is "cmxdns /var/tmp/dconf/cmxdns.conf"

ioctl: No such device
[ util_execSystem ] 135:  oal_br_addBridge cmd is "brctl addbr br0;brctl setfd br0 0;brctl stp br0 off"

[ util_execSystem ] 135:  oal_ipt_addLanRules cmd is "iptables -t filter -A INPUT -i br+ -j ACCEPT
"

[ util_execSystem ] 135:  oal_intf_setIntf cmd is "ifconfig br0 192.168.0.1 netmask 255.255.255.0 up"

[ util_execSystem ] 135:  oal_util_setProcLanAddr cmd is "echo "br0 16820416,"Raeth v3.1 ( > /proc/net/conTaskletntract_LocalAddr,SkbRecycle"

[ util_exec)
System ] 135:  o
phy_tx_ring = 0x030ad000, tx_ring = 0xa30ad000
al_intf_enableIn
phy_rx_ring0 = 0x030ae000, rx_ring0 = 0xa30ae000
tf cmd is "ifcon[fe_sw_init:4776]rt305x_esw_init.
fig eth0 up"

disable switch phyport...
GMAC1_MAC_ADRH -- : 0x0000d46e
GMAC1_MAC_ADRL -- : 0x0e571ee0
RT305x_ESW: Link Status Changed
[ rsl_getUnusedVlan ] 1002:  GET UNUSED VLAN TAG 1 : [3]
[ rsl_getUnusedVlan ] 1002:  GET UNUSED VLAN TAG 2 : [4]
[ rsl_getUnusedVlan ] 1002:  GET UNUSED VLAN TAG 3 : [5]
[ rsl_getUnusedVlan ] 1002:  GET UNUSED VLAN TAG 4 : [6]
[ util_execSystem ] 135:  oal_addVlanTagIntf cmd is "vconfig add eth0 3"

[ util_execSystem ] 135:  oal_intf_enableIntf cmd is "ifconfig eth0.3 up"

set if eth0.3 to *not wan dev
[ util_execSystem ] 135:  oal_addVlanTagIntf cmd is "vconfig add eth0 4"

[ util_execSystem ] 135:  oal_intf_enableIntf cmd is "ifconfig eth0.4 up"

set if eth0.4 to *not wan dev
[ util_execSystem ] 135:  oal_addVlanTagIntf cmd is "vconfig add eth0 5"

[ util_execSystem ] 135:  oal_intf_enableIntf cmd is "ifconfig eth0.5 up"

set if eth0.5 to *not wan dev
[ util_execSystem ] 135:  oal_addVlanTagIntf cmd is "vconfig add eth0 6"

[ util_execSystem ] 135:  oal_intf_enableIntf cmd isdevice eth0.3 entered promiscuous mode
 "ifconfig eth0.device eth0 entered promiscuous mode
6 up"

set if br0: port 1(eth0.3) entering forwarding state
eth0.6 to *not wbr0: port 1(eth0.3) entering forwarding state
an dev
[ util_execSystem ] 135:  oal_addVlanTagIntf cmd is "vconfig add eth0 2"device eth0.4 entered promiscuous mode


[ util_execSbr0: port 2(eth0.4) entering forwarding state
ystem ] 135:  oabr0: port 2(eth0.4) entering forwarding state
l_intf_enableIntf cmd is "ifconfig eth0.2 up"

set if eth0.2 to wan dev
[ vladevice eth0.5 entered promiscuous mode
n_addLanPortsIntbr0: port 3(eth0.5) entering forwarding state
oBridge ] 500:  br0: port 3(eth0.5) entering forwarding state
add lan Port 255 from br0
[ util_execSystem ] 135:  oal_br_addIntfIntoBridge cmdevice eth0.6 entered promiscuous mode
d is "brctl addibr0: port 4(eth0.6) entering forwarding state
f br0 eth0.3"
br0: port 4(eth0.6) entering forwarding state

[ util_execSystem ] 135:  oal_br_addIntfIntoBridge cmd is "brctl addif br0 eth0.4"

[ util_execSystem ] 135:  oal_br_addIntfIntoBridge cmd is "brctl addif br0 eth0.5"

[ util_execSystem ] 135:  oal_br_addIntfIntoBridge cmd is "brctl addif br0 eth0.6"

switch reg write offset=14, value=5555
switch reg write offset=40, value=1001
switch reg write offset=44, value=1001
switch reg write offset=48, value=1001
switch reg write offset=4c, value=1
switch reg write offset=50, value=2001
switch reg write offset=70, value=ffffffff
switch reg write offset=98, value=7f7f
switch reg write offset=e4, value=7f
done.
switch reg write offset=14, value=c05555
switch reg write offset=50, value=3002
switch reg write offset=54, value=5004
switch reg write offset=58, value=6
switch reg write offset=98, value=7f3f
switch reg write offset=e4, value=3f
switch reg write offset=40, value=3002
switch reg write offset=44, value=5004
switch reg write offset=48, value=6
switch reg write offset=70, value=48444241
switch reg write offset=74, value=50
done.
[ util_execSystem ] 135:  rsl_initIPv6CfgObj cmd is "echo 1 > /proc/sys/net/ipv6/conf/all/disable_ipv6"

[ util_execSystem ] 135:  oal_eth_setIGMPSnoopParam cmd is "echo 1 > /sys/devices/virtual/net/br0/bridge/multicast_snooping"

[ util_execSystem ] 135:  oal_eth_setIGMPSnoopParam cmd is "/sbin/config-vlan-router.sh br0"

switch reg write offset=14, value=5555
switch reg write offset=40, value=1001
switch reg write offset=44, value=1001
switch reg write offset=48, value=1001
switch reg write offset=4c, value=1
switch reg write offset=50, value=2001
switch reg write offset=70, value=ffffffff
switch reg write offset=98, value=7f7f
switch reg write offset=e4, value=7f
done.
switch reg write offset=14, value=c05555
switch reg write offset=50, value=3002
switch reg write offset=54, value=5004
switch reg write offset=58, value=6
switch reg write offset=98, value=7f3f
switch reg write offset=e4, value=3f
switch reg write offset=40, value=3002
switch reg write offset=44, value=5004
switch reg write offset=48, value=6
switch reg write offset=70, value=48444241
switch reg write offset=74, value=50
done.
[ util_execSystem ] 135:  oal_wlan_ra_setCountryRegion cmd is "cp /etc/SingleSKU_CE.dat /var/Wireless/RT2860AP/SingleSKU.dat"

[ util_execSystem ] 135:  oal_wlan_ra_setCountryRegion cmd is "iwpriv ra0 set CountryRegion=1"

ra0       no private ioctls.

[ util_execSystem ] 135:  oal_wlan_ra_loadDriver cmd is "insmod /lib/modules/kmdir/kernel/drivers/net/wireless/mt_wifi_ap/mt_wifi.ko"

ADDRCONF(NETDEV_CHANGE): eth0.4: link becomes ready
ADDRCONF(NETDEV_CHANGE): eth0.5: link becomes ready
ADDRCONF(NETDEV_CHANGE): eth0.6: link becomes ready
ADDRCONF(NETDEV_CHANGE): eth0.2: link becomes ready


=== pAd = c082b000, size = 1459424 ===

<-- RTMPAllocTxRxRingMemory, Status=0, ErrorValue=0x
<-- RTMPAllocAdapterBlock, Status=0
RtmpChipOpsHook(492): Not support for HIF_MT yet!
mt7628_init()-->
mt7628_init(FW(8a00), HW(8a01), CHIPID(7628))
e2.bin mt7628_init(1135)::(2), pChipCap->fw_len(63888)
mt_bcn_buf_init(218): Not support for HIF_MT yet!
<--mt7628_init()
[ util_execSystem ] 135:  oal_wlan_ra_initWlan cmd is "ifconfig ra0 up"

TX_BCN DESC a327e000 size = 320
RX[0] DESC a3281000 size = 1024
RX[1] DESC a3282000 size = 1024
cfg_mode=9
cfg_mode=9
wmode_band_equal(): Band Equal!
AndesSendCmdMsg: Could not send in band command due to diable fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD
APSDCapable[0]=0
APSDCapable[1]=0
APSDCapable[2]=0
APSDCapable[3]=0
APSDCapable[4]=0
APSDCapable[5]=0
APSDCapable[6]=0
APSDCapable[7]=0
APSDCapable[8]=0
APSDCapable[9]=0
APSDCapable[10]=0
APSDCapable[11]=0
APSDCapable[12]=0
APSDCapable[13]=0
APSDCapable[14]=0
APSDCapable[15]=0
default ApCliAPSDCapable[0]=0
Key1Str is Invalid key length(0) or Type(0)
Key1Str is Invalid key length(0) or Type(0)
Key2Str is Invalid key length(0) or Type(0)
Key2Str is Invalid key length(0) or Type(0)
Key3Str is Invalid key length(0) or Type(0)
Key3Str is Invalid key length(0) or Type(0)
Key4Str is Invalid key length(0) or Type(0)
Key4Str is Invalid key length(0) or Type(0)
WscKeyASCII=8
WscKeyASCII=8
[RTMPReadParametersHook:254]wifi read profile faild.
load fw image from fw_header_image
AndesMTLoadFwMethod1(2182)::pChipCap->fw_len(63888)
FW Version:20151201
FW Build Date:20151201183641
CmdAddressLenReq:(ret = 0)
CmdFwStartReq: override = 1, address = 1048576
CmdStartDLRsp: WiFI FW Download Success
MtAsicDMASchedulerInit(): DMA Scheduler Mode=0(LMAC)
efuse_probe: efuse = 10000012
RtmpChipOpsEepromHook::e2p_type=2, inf_Type=4
RtmpEepromGetDefault::e2p_dafault=2
RtmpChipOpsEepromHook: E2P type(2), E2pAccessMode = 2, E2P default = 2
NVM is FLASH mode
1. Phy Mode = 14
exec!
spiflash_ioctl_read, Read from 0x007f0000 length 0x400, ret 0, retlen 0x400
eeFlashId = 0x7628!
Country Region from e2p = ffff
tssi_1_target_pwr_g_band = 30
2. Phy Mode = 14
3. Phy Mode = 14
NICInitPwrPinCfg(11): Not support for HIF_MT yet!
NICInitializeAsic(651): Not support rtmp_mac_sys_reset () for HIF_MT yet!
mt_mac_init()-->
MtAsicInitMac()-->
mt7628_init_mac_cr()-->
MtAsicSetMacMaxLen(1277): Set the Max RxPktLen=450!
<--mt_mac_init()
        WTBL Segment 1 info:
                MemBaseAddr/FID:0x28000/0
                EntrySize/Cnt:32/128
        WTBL Segment 2 info:
                MemBaseAddr/FID:0x40000/0
                EntrySize/Cnt:64/128
        WTBL Segment 3 info:
                MemBaseAddr/FID:0x42000/64
                EntrySize/Cnt:64/128
        WTBL Segment 4 info:
                MemBaseAddr/FID:0x44000/128
                EntrySize/Cnt:32/128
AntCfgInit(2940): Not support for HIF_MT yet!
MCS Set = ff ff 00 00 01
MtAsicSetChBusyStat(861): Not support for HIF_MT yet!
CmdSlotTimeSet:(ret = 0)
[PMF]ap_pmf_init:: apidx=0, MFPC=0, MFPR=0, SHA256=0
[PMF]RTMPMakeRsnIeCap: RSNIE Capability MFPC=0, MFPR=0
[PMF]ap_pmf_init:: apidx=1, MFPC=0, MFPR=0, SHA256=0
MtAsicSetRalinkBurstMode(3048): Not support for HIF_MT yet!
MtAsicSetPiggyBack(796): Not support for HIF_MT yet!
reload DPD from flash , 0x9F = [c000] doReload bit7[0]
CmdLoadDPDDataFromFlash: Channel = 2, DoReload = 0
MtAsicSetTxPreamble(3027): Not support for HIF_MT yet!
MtAsicAddSharedKeyEntry(1344): Not support for HIF_MT yet!
MtAsicSetPreTbtt(): bss_idx=0, PreTBTT timeout = 0xf0
ap_ftkd> Initialize FT KDP Module...
Main bssid = d4:6e:0e:57:1e:e0
<==== rt28xx_init, Status=0
@@@ ed_monitor_init : ===>
@@@ ed_monitor_init : <===
mt7628_set_ed_cca: TURN ON EDCCA mac 0x10618 = 0xd7c87d0f, EDCCA_Status=1
WiFi Startup Cost (ra0): 3.428s
[ util_execSystem ] 135:  oal_wlan_ra_initWlan cmd is "echo 1 > /proc/tplink/led_wlan_24G"

[ util_execSystem device ra0 entered promiscuous mode
] 135:  oal_br_abr0: port 5(ra0) entering forwarding state
ddIntfIntoBridgebr0: port 5(ra0) entering forwarding state
 cmd is "brctl addif br0 ra0"

[ util_execSystem ] 135:  oal_br_addIntfIntoBridevice apcli0 entered promiscuous mode
dge cmd is "brctl addif br0 apcli0"

[ util_execSystem ] 135:  oal_br_addIntfIntoBridge cmd is "brctl addif br0 apcli0"

brctl: bridge br0: Device or resourdevice ra1 entered promiscuous mode
ce busy
[ util_execSystem ] 135:  oal_br_addIntfIntoBridge cmd is "brctl addif br0 ra1"

[ utspiflash_ioctl_read, Read from 0x007f0000 length 0x2, ret 0, retlen 0x2
il_execSystem ] 135:  oal_wlan_ra_initEnd cmd is "wlNetlinkTool &"


====
@@@ ed_status_read: EDCCA TH - H
pAd->ed_trigger_cnt : 1 > 20 ||  pAd->ed_big_rssi_stat : 0 < 50
====
[ util_execSystem ] 135:  oal_wlan_ra_initEnd cmd is "killall -q wscd"

WLAN-Start wlNetlinkTool
Waiting for Wireless Events from interfaces...
swWlanChkAhbErr: netlink to do
[ util_execSystem ] 135:  oal_wlan_ra_initEnd cmd is "wscd -i ra0 -m 1 -w /var/tmp/wsc_upnp/ &"

[ oal_wlan_ra_loadDriver ] 1786:  no 5G chip.


wscd: SSDP UDP PORT = 1900
sendto: No such file or directory
pid 745 send 2030 error
sendto: No such file or directory
pid 745 send 2004 error
[ util_execSystem ] 135:  oal_startDhcps cmd is "dhcpd /var/tmp/dconf/udhcpd.conf"

[ util_execSystem ] 135:  oal_lan6_startDhcp6s cmd is "dhcp6s -c /var/tmp/dconf/dhcp6s_br0.conf -P /var/run/dhcp6s_br0.pid br0 &"

[ util_execSystem ] 135:  oal_lan6_startRadvd cmd is "radvd -C /var/tmp/dconf/radvd_br0.conf -p /var/run/radvd_br0.pid &"

mldProxy# file: src/mld_ifinfo.c;line: 102; error = No such file or directory
mldProxy# Err: get LLA failed
[ util_execSystem ] 135:  oal_br_delIntfFromBridge cmd is "brctl delif br0 eth0.2"

iptables: Bad rule (does a matching rule exist in that chain?).
brctl: bridge br0: Invalid argument
[ util_execSystem ] 135:  oal_intf_setIfMac cmd is "ifconfig eth0.2 down"

[ util_execSystem ] 135:  oal_intf_setIfMac cmd is "ifconfig eth0.2 hw ether D4:6E:0E:57:1E:E1 up"

[ util_execSystem ] 135:  oal_intf_enableIntf cmd is "ifconfig eth0.2 up"

radvd starting
[Jan 01 00:00:07] radvd: no linklocal address configured for br0
[Jan 01 00:00:07] radvd: error parsing or activating the config file: /var/tmp/dconf/radvd_br0.conf
[ util_execSystem ] 135:  prepareDropbear cmd is "dropbearkey -t rsa -f /var/tmp/dropbear/dropbear_rsa_host_key"

Will output 1024 bit rsa secret key to '/var/tmp/dropbear/dropbear_rsa_host_key'
Generating key, this may take a while...
[ util_execSystem ] 135:  prepareDropbear cmd is "dropbearkey -t dss -f /var/tmp/dropbear/dropbear_dss_host_key"

Will output 1024 bit dss secret key to '/var/tmp/dropbear/dropbear_dss_host_key'
Generating key, this may take a while...
[ util_execSystem ] 135:  oal_rip_updateConfig cmd is "rm -f /var/tmp/dconf/zebra.conf"

[ util_execSystem ] 135:  oal_rip_updateConfig cmd is "rm -f /var/tmp/dconf/ripd.conf"

[ util_execSystem ] 135:  removeAllRIPIpTableRule cmd is "iptables -L INPUT -v --line-numbers > /var/iptable"

[ getPidFromPidFile ] 112:  Cann't open file: /var/run/zebra.pid.
[ util_execSystem ] 135:  controlRipProcess cmd is "zebra -d -f /var/tmp/dconf/zebra.conf"

[ getPidFromPidFile ] 112:  Cann't open file: /var/run/ripd.pid.
[ util_execSystem ] 135:  oal_ipt_fwDdos cmd is "iptables -D FORWARD -j FIREWALL_DDOS
"

iptables: No chain/target/match by that name.
[ util_execSystem ] 135:  oal_ipt_forbidLanPing cmd is "iptables -t filter -D INPUT -i br+ -p icmp --icmp-type echo-request -j DROP
iptables -t filter -D FORWARD -i br+ -p icmp --icmp-type echo-request -j DROP
"

iptables: Bad rule (does a matching rule exist in that chain?).
iptables: Bad rule (does a matching rule exist in that chain?).
[ util_execSystem ] 135:  oal_ddos_delPingRule cmd is "iptables -t filter -D INPUT ! -i br+ -p icmp --icmp-type echo-request -j ACCEPT
"

iptables: Bad rule (does a matching rule exist in that chain?).
[ util_execSystem ] 135:  oal_ipt_setDDoSRules cmd is "iptables -F FIREWALL_DDOS"

[ util_execSystem ] 135:  ddos_clearAll cmd is "rm -f /var/tmp/dosHost"

[ util_execSystem ] 135:  prepareDropbear cmd is "dropbear -p 22 -r /var/tmp/dropbear/dropbear_rsa_host_key -d /var/tmp/dropbear/dropbear_dss_host_key -A /var/tmp/dropbear/dropbearpwd"

[ util_execSystem ] 135:  oal_initFirewallObj cmd is "ebtables -N FIREWALL"

[ util_execSystem ] 135:  oal_initIp6FirewallObj cmd is "ip6tables -F"

[ util_execSystem ] 135:  oal_initIp6FirewallObj cmd is "ip6tables -X"

[ util_execSystem ] 135:  oal_initIp6FirewallObj cmd is "ip6tables -P INPUT ACCEPT"

[ util_execSystem ] 135:  oal_initIp6FirewallObj cmd is "ip6tables -P FORWARD DROP"

[ util_execSystem ] 135:  oal_initIp6FirewallObj cmd is "ip6tables -P OUTPUT ACCEPT"

[ util_execSystem ] 135:  oal_initIp6FirewallObj cmd is "ip6tables -N FIREWALL"

[ util_execSystem ] 135:  oal_initIp6FirewallObj cmd is "ip6tables -N FWRULE"

[ util_execSystem ] 135:  oal_initIp6FirewallObj cmd is "ip6tables -N SETMSS"

[ util_execSystem ] 135:  oal_initIp6FirewallObj cmd is "ip6tables -A INPUT -i lo -p ALL -j ACCEPT -m comment                                      --comment "loop back""

[ util_execSystem ] 135:  oal_initIp6FirewallObj cmd is "ip6tables -A INPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT"

[ util_execSystem ] 135:  oal_initIp6FirewallObj cmd is "ip6tables -A INPUT -i br+ -p tcp --dport 23 -j ACCEPT"

[ util_execSystem ] 135:  oal_initIp6FirewallObj cmd is "ip6tables -A INPUT -p tcp --dport 23 -j DROP"

[ util_execSystem ] 135:  oal_initIp6FirewallObj cmd is "ip6tables -A INPUT -i br+ -p icmpv6 --icmpv6-type echo-request -j ACCEPT"

[ util_execSystem ] 135:  oal_initIp6FirewallObj cmd is "ip6tables -A INPUT -p icmpv6 --icmpv6-type echo-request -j DROP"

[ util_execSystem ] 135:  oal_initIp6FirewallObj cmd is "ip6tables -A FORWARD -i br+ -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT"

[ util_execSystem ] 135:  oal_initIp6FirewallObj cmd is "ip6tables -A FORWARD -o br+ -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT"

[ util_execSystem ] 135:  oal_initIp6FirewallObj cmd is "ip6tables -A FORWARD -j FIREWALL"

[ util_execSystem ] 135:  oal_initIp6FirewallObj cmd is "ip6tables -I FORWARD 1 -j SETMSS"

[ util_execSystem ] 135:  oal_fw6_setFwEnabeld cmd is "ip6tables -D FIREWALL -j ACCEPT"

ip6tables: Bad rule (does a matching rule exist in that chain?).
[ util_execSystem ] 135:  oal_fw6_setFwEnabeld cmd is "ip6tables -F FIREWALL"

[ util_execSystem ] 135:  oal_fw6_setFwEnabeld cmd is "ip6tables -A FIREWALL -j ACCEPT"

[ util_execSystem ] 135:  setupModules cmd is "insmod /lib/modules/kmdir/kernel/net/netfilter/nf_conntrack_ftp.ko"

[ util_execSystem ] 135:  setupModules cmd is "insmod /lib/modules/kmdir/kernel/net/ipv4/netfilter/nf_nat_ftp.ko"

[ util_execSystem ] 135:  oal_openAlg cmd is "iptables -D FORWARD_VPN_PASSTHROUGH  -p udp --dport 500 -j DROP"

iptables: Bad rule (does a matching rule exist in that chain?).
[ util_execSystem ] 135:  setupModules cmd is "insmod /lib/modules/kmdir/kernel/net/ipv4/netfilter/nf_nat_proto_gre.ko"

[ util_execSystem ] 135:  setupModules cmd is "insmod /lib/modules/kmdir/kernel/net/ipv4/netfilter/nf_nat_pptp.ko"

[ util_execSystem ] 135:  oal_openAlg cmd is "iptables -D FORWARD_VPN_PASSTHROUGH  -p tcp --dport 1723 -j DROP"

iptables: Bad rule (does a matching rule exist in that chain?).
[ util_execSystem ] 135:  oal_openAlg cmd is "iptables -D FORWARD_VPN_PASSTHROUGH  -p udp --dport 1701 -j DROP"

iptables: Bad rule (does a matching rule exist in that chain?).
[ util_execSystem ] 135:  setupModules cmd is "insmod /lib/modules/kmdir/kernel/net/netfilter/nf_conntrack_tftp.ko"

[ util_execSystem ] 135:  setupModules cmd is "insmod /lib/modules/kmdir/kernel/net/ipv4/netfilter/nf_nat_tftp.ko"

[ util_execSystem ] 135:  setupModules cmd is "insmod /lib/modules/kmdir/kernel/net/netfilter/nf_conntrack_h323.ko"

[ util_execSystem ] 135:  setupModules cmd is "insmod /lib/modules/kmdir/kernel/net/ipv4/netfilter/nf_nat_h323.ko"

[ util_execSystem ] 135:  setupModules cmd is "insmod /lib/modules/kmdir/kernel/net/netfilter/nf_conntrack_sip.ko"

[ util_execSystem ] 135:  setupModules cmd is "insmod /lib/modules/kmdir/kernel/net/ipv4/netfilter/nf_nat_sip.ko"

[ util_execSystem ] 135:  setupModules cmd is "insmod /lib/modules/kmdir/kernel/net/netfilter/nf_conntrack_rtsp.ko"

[ util_execSystem ] 135:  setupModules cmd is "insmod /lib/modules/kmdir/kernel/net/ipv4/netfilter/nf_nat_rtsp.ko"

nf_nat_rtsp v0.6.21 loading
enable switch phyport...
Set: phy[0].reg[0] = 3900
Set: phy[1].reg[0] = 3900
Set: phy[2].reg[0] = 3900
Set: phy[3].reg[0] = 3900
Set: phy[4].reg[0] = 3900
Set: phy[0].reg[0] = 3300
Set: phy[1].reg[0] = 3300
Set: phy[2].reg[0] = 3300
Set: phy[3].reg[0] = 3300
Set: phy[4].reg[0] = 3300
resetMiiPortV over.
[ util_execSystem ] 135:  oal_sys_unsetTZ cmd is "echo "" > /etc/TZ"

[ util_execSystem ] 135:  oal_sys_unsetTZ cmd is "echo "" > /etc/TZ"


Here we can clearly see the UART packets that were sent:

Uart: rx

Now we can try to connect to the rx to see if we get command execution via the serial console that easily or if we need to make further modifications.

For that we will use a UART-TTL USB

I personally used this one which supports both 5V and 3.3V, nevertheless since communication is at 3.3V we will use that.

Now we can use the cables to connect the different pins and use (in my case) Tera Term for communication with the device:

After launching and configuring Tera Term we see the following:

We have command execution

This is the boot sequence when you reset the router:

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
 The CPU feqenuce set to 580 MHz

 MIPS CPU sleep mode enabled.
CPU revision is: 00019655 (MIPS 24Kc)
Software DMA cache coherency
Determined physical RAM map:
 memory: 04000000 @ 00000000 (usable)
Initrd not found or empty - disabling initrd
Zone PFN ranges:
  Normal   0x00000000 -> 0x00004000
Movable zone start PFN for each node
early_node_map[1] active PFN ranges
    0: 0x00000000 -> 0x00004000
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 16256
Kernel command line: console=ttyS1,115200 root=/dev/mtdblock2 rootfstype=squashfs init=/sbin/init
PID hash table entries: 256 (order: -2, 1024 bytes)
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
Primary instruction cache 64kB, VIPT, , 4-waylinesize 32 bytes.
Primary data cache 32kB, 4-way, PIPT, no aliases, linesize 32 bytes
Writing ErrCtl register=00059380
Readback ErrCtl register=00059380
Memory: 61268k/65536k available (2628k kernel code, 4236k reserved, 638k data, 164k init, 0k highmem)
NR_IRQS:128
console [ttyS1] enabled
Calibrating delay loop... 386.04 BogoMIPS (lpj=772096)
pid_max: default: 4096 minimum: 301
Mount-cache hash table entries: 512
NET: Registered protocol family 16
bio: create slab <bio-0> at 0
Switching to clocksource Ralink Systick timer
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 2048 (order: 2, 16384 bytes)
TCP bind hash table entries: 2048 (order: 1, 8192 bytes)
TCP: Hash tables configured (established 2048 bind 2048)
TCP reno registered
NET: Registered protocol family 1
squashfs: version 4.0 (2009/01/31) Phillip Lougher
fuse init (API version 7.15)
msgmni has been set to 119
io scheduler noop registered
io scheduler deadline registered (default)
Ralink gpio driver initialized
i2cdrv_major = 218
Serial: 8250/16550 driver, 2 ports, IRQ sharing enabled
serial8250: ttyS0 at MMIO 0x10000d00 (irq = 21) is a 16550A
serial8250: ttyS1 at MMIO 0x10000c00 (irq = 20) is a 16550A
brd: module loaded
flash manufacture id: c8, device id 40 17
GD25Q64B(c8 40170000) (8192 Kbytes)
mtd .name = raspi, .size = 0x00800000 (8M) .erasesize = 0x00010000 (64K) .numeraseregions = 0
Creating 7 MTD partitions on "raspi":
0x000000000000-0x000000020000 : "boot"
0x000000020000-0x000000160000 : "kernel"
0x000000160000-0x0000007c0000 : "rootfs"
mtd: partition "rootfs" set to be root filesystem
0x0000007c0000-0x0000007d0000 : "config"
0x0000007d0000-0x0000007e0000 : "romfile"
0x0000007e0000-0x0000007f0000 : "rom"
0x0000007f0000-0x000000800000 : "radio"
Register flash device:flash0
PPP generic driver version 2.4.2
PPP MPPE Compression module registered
NET: Registered protocol family 24
Mirror/redirect action on
u32 classifier
    Actions configured
Netfilter messages via NETLINK v0.30.
nf_conntrack version 0.5.0 (957 buckets, 3828 max)
ip_tables: (C) 2000-2006 Netfilter Core Team, Type=Restricted Cone
TCP cubic registered
NET: Registered protocol family 10
ip6_tables: (C) 2000-2006 Netfilter Core Team
IPv6 over IPv4 tunneling driver
NET: Registered protocol family 17
Ebtables v2.0 registered
802.1Q VLAN Support v1.8 Ben Greear <greearb@candelatech.com>
All bugs added by David S. Miller <davem@redhat.com>
VFS: Mounted root (squashfs filesystem) readonly on device 31:2.
Freeing unused kernel memory: 164k freed
starting pid 679, tty '': '/etc/init.d/rcS'
rdm_major = 253
spiflash_ioctl_read, Read from 0x007df100 length 0x6, ret 0, retlen 0x6
Read MAC from flash(0x7DF100) ffffffd4-6e-0e-57-1e-ffffffe0
GMAC1_MAC_ADRH -- : 0x0000d46e
GMAC1_MAC_ADRL -- : 0x0e571ee0
Ralink APSoC Ethernet Driver Initilization. v3.1  256 rx/tx descriptors allocated, mtu = 1500!
spiflash_ioctl_read, Read from 0x007df100 length 0x6, ret 0, retlen 0x6
Read MAC from flash(0x7DF100) ffffffd4-6e-0e-57-1e-ffffffe0
GMAC1_MAC_ADRH -- : 0x0000d46e
GMAC1_MAC_ADRL -- : 0x0e571ee0
PROC INIT OK!

The Guts of the Router

As we can see we do not have full commands, rather a very limited console. It uses busybox (BusyBox v1.19.2) for commands:

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
~ # whoami
/bin/sh: whoami: not found
~ # ls
web      usr      sbin     mnt      lib      dev
var      sys      proc     linuxrc  etc      bin
~ # b
bpalogin  brctl     busybox
~ # busybox
BusyBox v1.19.2 (2016-10-06 19:50:18 HKT) multi-call binary.
Copyright (C) 1998-2011 Erik Andersen, Rob Landley, Denys Vlasenko
and others. Licensed under GPLv2.
See source distribution for full notice.

Usage: busybox [function] [arguments]...
   or: busybox --list[-full]
   or: function [arguments]...

        BusyBox is a multi-call binary that combines many common Unix
        utilities into a single executable.  Most people will create a
        link to busybox for each function they wish to use and BusyBox
        will act like whatever it was invoked as.

Currently defined functions:
        arping, ash, brctl, cat, chmod, cp, date, df, echo, free, getty, halt,
        ifconfig, init, insmod, ipcrm, ipcs, kill, killall, linuxrc, login, ls,
        lsmod, mkdir, mount, netstat, pidof, ping, ping6, poweroff, ps, reboot,
        rm, rmmod, route, sh, sleep, taskset, telnetd, tftp, top, umount,
        vconfig

~ #

We can investigate a bit by listing the network interfaces but we don’t obtain anything interesting

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
~ # ifconfig
br0       Link encap:Ethernet  HWaddr D4:6E:0E:57:1E:E0
          inet addr:192.168.0.1  Bcast:192.168.0.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:97 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:40970 (40.0 KiB)

eth0      Link encap:Ethernet  HWaddr D4:6E:0E:57:1E:E0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:63 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:20150 (19.6 KiB)
          Interrupt:3

eth0.2    Link encap:Ethernet  HWaddr D4:6E:0E:57:1E:E1
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:31 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:17914 (17.4 KiB)

eth0.3    Link encap:Ethernet  HWaddr D4:6E:0E:57:1E:E0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:7 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:446 (446.0 B)

eth0.4    Link encap:Ethernet  HWaddr D4:6E:0E:57:1E:E0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:528 (528.0 B)

eth0.5    Link encap:Ethernet  HWaddr D4:6E:0E:57:1E:E0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:528 (528.0 B)

eth0.6    Link encap:Ethernet  HWaddr D4:6E:0E:57:1E:E0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:7 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:446 (446.0 B)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:12 errors:0 dropped:0 overruns:0 frame:0
          TX packets:12 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:4467 (4.3 KiB)  TX bytes:4467 (4.3 KiB)

ra0       Link encap:Ethernet  HWaddr D4:6E:0E:57:1E:E0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
          Interrupt:4

~ #

During enumeration we obtain a file of great importance because it contains the router’s configuration:

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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/var # cat Wireless/RT2860AP/RT2860AP.dat
Default
TP-LINK=
CountryNum=276
AutoChannelSelect=2
Channel=6
MaxStaNum=32
BssidNum=2
WirelessMode=9
NoForwardingBTNBSSID=0
BasicRate=15
BeaconPeriod=100
DtimPeriod=1
TxPower=100
RTSThreshold=2346
FragThreshold=2346
APSDCapable=0
DLSCapable=0
PMKCachePeriod=10
AccessPolicy0=0
AccessPolicy1=0
AccessPolicy2=0
AccessPolicy3=0
HT_BW=1
HT_EXTCHA=0
HT_BSSCoexistence=0
HT_GI=1
HT_HTC=0
HT_LinkAdapt=0
HT_OpMode=0
HT_MpduDensity=5
HT_AutoBA=1
HT_AMSDU=0
HT_BAWinSize=64
HT_MCS=33;33;33;33
CountryRegion=1
CountryRegionABand=1
EDCCA_AP_STA_TH=1
EDCCA_AP_AP_TH=1
EDCCA_AP_RSSI_TH=-80
EDCCA_ED_TH=90
EDCCA_FALSE_CCA_TH=250
EDCCA_BLOCK_CHECK_TH=2
HT_DisallowTKIP=1
HT_STBC=0
DisableOLBC=0
HT_RDG=0
HT_BADecline=0
BGProtection=0
EfuseBufferMode=1
TxPreamble=0
TxBurst=0
PktAggregate=0
IEEE80211H=0
ShortSlot=1
IgmpSnEnable=1
FixedTxMode=0
TxRate=0
PreAuth=0
WirelessEvent=0
ApCliEnable=0
ApCliDefaultKeyID=0
ApCliKey1Type=0
ApCliKey2Type=0
ApCliKey3Type=0
ApCliKey4Type=0
IEEE8021X=0
session_timeout_interval=0
WscSetupLock=0
VHT_BW=0
VHT_SGI=1
VHT_STBC=0
VHT_BW_SIGNAL=0
VHT_DisallowNonVHT=0
CountryCode=NOCOUNTRY
MacAddress=D4:6E:0E:57:1E:E0
ApCliBssid=
SSID1=TP-LINK_1EE0
SSID2=TP-LINK_Guest_1EE0
SSID3=
SSID4=
ApCliSsid=
WmmCapable=1;1;1;1
APAifsn=3;7;1;1
APCwmin=4;4;3;2
APCwmax=6;10;4;3
APTxop=0;0;94;47
APACM=0;0;0;0
BSSAifsn=3;7;2;2
BSSCwmin=4;4;3;2
BSSCwmax=10;10;4;3
BSSTxop=0;0;94;47
BSSACM=0;0;0;0
AckPolicy=0;0;0;0
AuthMode=WPA2PSK;OPEN
ApCliAuthMode=OPEN
EncrypType=AES;NONE
ApCliEncrypType=NONE
WPAPSK1=78231573
WPAPSK2=
WPAPSK3=
WPAPSK4=
ApCliWPAPSK=
RekeyMethod=TIME;TIME;TIME;TIME
DefaultKeyID=2;2;2;2
HideSSID=0;0;1;1
NoForwarding=0;0;1;1
WscConfMode=7;0;0;0
WscConfStatus=2;2;2;2
WscKeyASCII=8;8;8;8
WscSecurityMode=0;0;0;0
Key1Type=0;0;0;0
Key2Type=0;0;0;0
Key3Type=0;0;0;0
Key4Type=0;0;0;0
Key1Str1=
Key1Str2=
Key1Str3=
Key1Str4=
Key2Str1=
Key2Str2=
Key2Str3=
Key2Str4=
Key3Str1=
Key3Str2=
Key3Str3=
Key3Str4=
Key4Str1=
Key4Str2=
Key4Str3=
Key4Str4=
ApCliKey1Str=
ApCliKey2Str=
ApCliKey3Str=
ApCliKey4Str=
WscVendorPinCode=78231573;0;0;0
AccessControlList0=
AccessControlList1=
AccessControlList2=
AccessControlList3=
RekeyInterval=0;0;0;0
WscDeviceName=Wireless N Router TL-WR841N
WscManufacturer=TP-LINK
WscModelName=TL-WR841N
WscModelNumber=13.0
WscSerialNumber=1.0
RADIUS_Server=;;;
own_ip_addr=192.168.0.1
RADIUS_Key=;;;
Ethifname=br0
RADIUS_Port=1812;1812;0;0
WSC_UUID_Str1=38833092-3092-1883-9c77-D46E0E571Ec4
WSC_UUID_E1=38833092309218839c77D46E0E571Ec4
AutoChannelSkipList=12;13;52;56;60;64;100;104;108;112;116;120;124;128;132;136;140
/var # 

Including its password so we could already connect if we had not been able to obtain the password by other means. (in this case the password is on the back of the router in the photos already shown)

1
2
3
...
WscVendorPinCode=78231573;0;0;0
...

When we connect a device to the router this message appears making it clear that the connection was successful and that it uses AES encryption. although being WPA2 this is always the case

1
2
3
4
5
6
7
8
/bin # PeerAssocReqSanity - IE_HT_CAP
PeerAssocReqSanity - IE_EXT_CAPABILITY!
AP SETKEYS DONE - WPA2, AuthMode(7)=WPA2PSK, WepStatus(6)=AES, GroupWepStatus(6)=AES

Rcv Wcid(1) AddBAReq
Start Seq = 00000014
Rcv Wcid(1) AddBAReq
Start Seq = 00000004

From our computer we can see which IP the router assigned us:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
root@ack:~# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host noprefixroute
       valid_lft forever preferred_lft forever
2: wlo1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 64:d6:9a:e1:20:76 brd ff:ff:ff:ff:ff:ff
    altname wlp0s20f3
    inet 192.168.0.100/24 brd 192.168.0.255 scope global dynamic noprefixroute wlo1
       valid_lft 7056sec preferred_lft 7056sec
    inet6 fe80::249:8abd:ef5c:1b8f/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
root@ack:~#

From the router we have connectivity to the computer so everything is working fine

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/var # ping 192.168.0.100
PING 192.168.0.100 (192.168.0.100): 56 data bytes
64 bytes from 192.168.0.100: seq=0 ttl=64 time=97.880 ms
64 bytes from 192.168.0.100: seq=1 ttl=64 time=118.660 ms
64 bytes from 192.168.0.100: seq=2 ttl=64 time=138.080 ms
64 bytes from 192.168.0.100: seq=3 ttl=64 time=57.540 ms
64 bytes from 192.168.0.100: seq=4 ttl=64 time=77.980 ms
64 bytes from 192.168.0.100: seq=5 ttl=64 time=76.040 ms
64 bytes from 192.168.0.100: seq=6 ttl=64 time=124.600 ms
64 bytes from 192.168.0.100: seq=7 ttl=64 time=136.880 ms
^C
--- 192.168.0.100 ping statistics ---
8 packets transmitted, 8 packets received, 0% packet loss
round-trip min/avg/max = 57.540/103.457/138.080 ms
/var #

We have an interesting program called login

1
2
3
4
5
6
7
8
9
10
11
~ # cd bin/
/bin # ls
umount   rm       ping     mount    login    df       chmod    ash
sleep    ps       pidof    mkdir    kill     date     cat
sh       ping6    netstat  ls       echo     cp       busybox
/bin # ./login
TL-WR841N login: user
Password:
Login incorrect
TL-WR841N login:

We find the shadow file so we can try to crack the password using john for example

1
2
3
4
5
/var # cat passwd
admin:$1$$iC.dUsGpxNNJGeOm1dFio/:0:0:root:/:/bin/sh
dropbear:x:500:500:dropbear:/var/dropbear:/bin/sh
nobody:*:0:0:nobody:/:/bin/sh
/var #

we run john with the dictionary and…

1
2
3
4
5
6
7
8
9
root@ack:~# john --wordlist=modified.txt passwd
Loaded 1 password hash (md5crypt [MD5 32/64 X2])
Will run 8 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
1234             (admin)
1g 0:00:00:00 100% 50.00g/s 102400p/s 102400c/s 102400C/s 123456..lovers1
Use the "--show" option to display all of the cracked passwords reliably
Session completed
root@ack:~#

The password is 1234, sounds like a joke but it’s not xd

The application simply outputs a log and gives us a privileged shell, which is useless since we already have one:

1
2
3
4
5
/bin # ./login
TL-WR841N login: admin
Password:
Jan  1 03:17:52 login[879]: root login on 'ttyS1'
~ #

we can also analyze the router from the TCP-accessible ports (for now we are not scanning UDP)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
root@ack:~# sudo nmap -p- -sV -sS 192.168.0.1
Nmap scan report for 192.168.0.1
Host is up (0.0063s latency).
Not shown: 65531 closed tcp ports (reset)
PORT     STATE SERVICE VERSION
22/tcp   open  ssh     Dropbear sshd 2012.55 (protocol 2.0)
23/tcp   open  telnet  BusyBox telnetd 1.14.0 or later (TP-LINK ADSL2+ router telnetd)
80/tcp   open  http    TP-LINK TD-W8968 http admin
1900/tcp open  upnp    Portable SDK for UPnP devices 1.6.19 (Linux 2.6.36; UPnP 1.0)
MAC Address: D4:6E:0E:57:1E:E0 (Tp-link Technologies)
Service Info: OS: Linux; Device: WAP; CPE: cpe:/o:linux:linux_kernel, cpe:/h:tp-link:td-w8968, cpe:/o:linux:linux_kernel:2.6.36

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 33.25 seconds
root@ack:~#

We see open and vulnerable services.

NOTE: there are many vulnerabilities in the router, both in busybox and in the http daemon and I’m almost certain in Dropbear as well

The system script info.sh gives us a lot of system information, it is useful and also shows running processes as well as their privileges:

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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
/sbin # sh info.sh
  PID USER       VSZ STAT COMMAND
    1 admin     1076 S    init
    2 admin        0 SW   [kthreadd]
    3 admin        0 SW   [ksoftirqd/0]
    4 admin        0 SW   [kworker/0:0]
    5 admin        0 SW   [kworker/u:0]
    6 admin        0 SW<  [khelper]
    7 admin        0 SW   [kworker/u:1]
   42 admin        0 SW   [sync_supers]
   44 admin        0 SW   [bdi-default]
   46 admin        0 SW<  [kblockd]
   69 admin        0 SW   [kswapd0]
   71 admin        0 SW<  [crypto]
  630 admin        0 SW   [mtdblock0]
  635 admin        0 SW   [mtdblock1]
  640 admin        0 SW   [mtdblock2]
  645 admin        0 SW   [mtdblock3]
  650 admin        0 SW   [mtdblock4]
  655 admin        0 SW   [mtdblock5]
  660 admin        0 SW   [mtdblock6]
  678 admin        0 SW   [kworker/0:1]
  728 admin     1068 S    telnetd
  745 admin     2848 S    cos
  746 admin     1080 S    /bin/sh
  749 admin     2052 S    igmpd
  752 admin     2076 S    mldProxy
  839 admin     2848 S    cos
  840 admin     2848 S    cos
  841 admin     2848 S    cos
  860 admin     2020 S    ntpc
  865 admin     2028 S    dyndns /var/tmp/dconf/dyndns.conf
  868 admin     2028 S    noipdns /var/tmp/dconf/noipdns.conf
  871 admin     2028 S    cmxdns /var/tmp/dconf/cmxdns.conf
  879 admin     1080 S    -sh
 1017 admin        0 SW   [RtmpCmdQTask]
 1018 admin        0 SW   [RtmpWscTask]
 1019 admin        0 SW   [RtmpMlmeTask]
 1032 admin     1244 S    wlNetlinkTool
 1036 admin     1080 S    wscd -i ra0 -m 1 -w /var/tmp/wsc_upnp/
 1040 admin     1244 S    wlNetlinkTool
 1042 admin     1244 S    wlNetlinkTool
 1055 admin     2600 S    httpd
 1067 admin     1764 S    upnpd -L br0 -W eth0.2 -en 1 -P eth0.2 -nat 0 -port
 1070 admin     2016 S    dnsProxy
 1073 admin     1068 S    dhcpd /var/tmp/dconf/udhcpd.conf
 1092 admin     1764 S    upnpd -L br0 -W eth0.2 -en 1 -P eth0.2 -nat 0 -port
 1093 admin     1764 S    upnpd -L br0 -W eth0.2 -en 1 -P eth0.2 -nat 0 -port
 1094 admin     1764 S    upnpd -L br0 -W eth0.2 -en 1 -P eth0.2 -nat 0 -port
 1096 admin     1764 S    upnpd -L br0 -W eth0.2 -en 1 -P eth0.2 -nat 0 -port
 1097 admin     1764 S    upnpd -L br0 -W eth0.2 -en 1 -P eth0.2 -nat 0 -port
 1098 admin     1764 S    upnpd -L br0 -W eth0.2 -en 1 -P eth0.2 -nat 0 -port
 1099 admin     1764 S    upnpd -L br0 -W eth0.2 -en 1 -P eth0.2 -nat 0 -port
 1100 admin     1152 S    dhcp6s -c /var/tmp/dconf/dhcp6s_br0.conf -P /var/run
 1101 admin     2600 S    tmpd
 1104 admin     2488 S    tdpd
 1112 admin      988 S    dhcpc
 1113 admin     1076 S    sh
 1123 admin     1136 S    dropbear -p 22 -r /var/tmp/dropbear/dropbear_rsa_hos
 1124 admin     1036 S    zebra -d -f /var/tmp/dconf/zebra.conf
 1138 admin     2020 S    diagTool
 1253 admin     1076 S    busybox sh
 1773 admin     1064 S    sh info.sh
 1774 admin     1068 R    ps
MemTotal:          61432 kB
MemFree:           35184 kB
Buffers:            2488 kB
Cached:             9824 kB
SwapCached:            0 kB
Active:             6380 kB
Inactive:           8752 kB
Active(anon):       2820 kB
Inactive(anon):        0 kB
Active(file):       3560 kB
Inactive(file):     8752 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:             0 kB
SwapFree:              0 kB
Dirty:                 0 kB
Writeback:             0 kB
AnonPages:          2828 kB
Mapped:             2460 kB
Shmem:                 0 kB
Slab:               6936 kB
SReclaimable:        720 kB
SUnreclaim:         6216 kB
KernelStack:         496 kB
PageTables:          428 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:       61432 kB
Committed_AS:       8792 kB
VmallocTotal:    1048372 kB
VmallocUsed:        3600 kB
VmallocChunk:    1036896 kB
Node 0, zone   Normal      3      4     24     15      9      3      2      2      3      2      6
RTMPAPPrivIoctlShow(): Before check, this_char=psinfo
RTMPAPPrivIoctlShow(): after check, this_char=psinfo, value=
Show_PSTable_Proc(): arg=
Dump MacTable entries info, EntType=0x20001

HT Operating Mode : 0

pAd->MacTab.fAnyStationInPsm : 0
pAd->dequeu_fail_cnt : 0

MAC                     EntryType       AID     BSS     PSM     psm     ipsm    iips    sktx    redt    port    queu    pktnum        psnum   hinum#  hidrp#  TXOK/PER        APSD    rcount
  PID USER       VSZ STAT COMMAND
    1 admin     1076 S    init
    2 admin        0 SW   [kthreadd]
    3 admin        0 SW   [ksoftirqd/0]
    4 admin        0 SW   [kworker/0:0]
    5 admin        0 SW   [kworker/u:0]
    6 admin        0 SW<  [khelper]
    7 admin        0 SW   [kworker/u:1]
   42 admin        0 SW   [sync_supers]
   44 admin        0 SW   [bdi-default]
   46 admin        0 SW<  [kblockd]
   69 admin        0 SW   [kswapd0]
   71 admin        0 SW<  [crypto]
  630 admin        0 SW   [mtdblock0]
  635 admin        0 SW   [mtdblock1]
  640 admin        0 SW   [mtdblock2]
  645 admin        0 SW   [mtdblock3]
  650 admin        0 SW   [mtdblock4]
  655 admin        0 SW   [mtdblock5]
  660 admin        0 SW   [mtdblock6]
  678 admin        0 SW   [kworker/0:1]
  728 admin     1068 S    telnetd
  745 admin     2848 S    cos
  746 admin     1080 S    /bin/sh
  749 admin     2052 S    igmpd
  752 admin     2076 S    mldProxy
  839 admin     2848 S    cos
  840 admin     2848 S    cos
  841 admin     2848 S    cos
  860 admin     2020 S    ntpc
  865 admin     2028 S    dyndns /var/tmp/dconf/dyndns.conf
  868 admin     2028 S    noipdns /var/tmp/dconf/noipdns.conf
  871 admin     2028 S    cmxdns /var/tmp/dconf/cmxdns.conf
  879 admin     1080 S    -sh
 1017 admin        0 SW   [RtmpCmdQTask]
 1018 admin        0 SW   [RtmpWscTask]
 1019 admin        0 SW   [RtmpMlmeTask]
 1032 admin     1244 S    wlNetlinkTool
 1036 admin     1080 S    wscd -i ra0 -m 1 -w /var/tmp/wsc_upnp/
 1040 admin     1244 S    wlNetlinkTool
 1042 admin     1244 S    wlNetlinkTool
 1055 admin     2600 S    httpd
 1067 admin     1764 S    upnpd -L br0 -W eth0.2 -en 1 -P eth0.2 -nat 0 -port
 1070 admin     2016 S    dnsProxy
 1073 admin     1068 S    dhcpd /var/tmp/dconf/udhcpd.conf
 1092 admin     1764 S    upnpd -L br0 -W eth0.2 -en 1 -P eth0.2 -nat 0 -port
 1093 admin     1764 S    upnpd -L br0 -W eth0.2 -en 1 -P eth0.2 -nat 0 -port
 1094 admin     1764 S    upnpd -L br0 -W eth0.2 -en 1 -P eth0.2 -nat 0 -port
 1096 admin     1764 S    upnpd -L br0 -W eth0.2 -en 1 -P eth0.2 -nat 0 -port
 1097 admin     1764 S    upnpd -L br0 -W eth0.2 -en 1 -P eth0.2 -nat 0 -port
 1098 admin     1764 S    upnpd -L br0 -W eth0.2 -en 1 -P eth0.2 -nat 0 -port
 1099 admin     1764 S    upnpd -L br0 -W eth0.2 -en 1 -P eth0.2 -nat 0 -port
 1100 admin     1152 S    dhcp6s -c /var/tmp/dconf/dhcp6s_br0.conf -P /var/run
 1101 admin     2600 S    tmpd
 1104 admin     2488 S    tdpd
 1112 admin      988 S    dhcpc
 1113 admin     1076 S    sh
 1123 admin     1136 S    dropbear -p 22 -r /var/tmp/dropbear/dropbear_rsa_hos
 1124 admin     1036 S    zebra -d -f /var/tmp/dconf/zebra.conf
 1138 admin     2020 S    diagTool
 1253 admin     1076 S    busybox sh
 1773 admin     1064 S    sh info.sh
 1902 admin     1068 R    ps
MemTotal:          61432 kB
MemFree:           35140 kB
Buffers:            2488 kB
Cached:             9824 kB
SwapCached:            0 kB
Active:             6404 kB
Inactive:           8728 kB
Active(anon):       2820 kB
Inactive(anon):        0 kB
Active(file):       3584 kB
Inactive(file):     8728 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:             0 kB
SwapFree:              0 kB
Dirty:                 0 kB
Writeback:             0 kB
AnonPages:          2828 kB
Mapped:             2460 kB
Shmem:                 0 kB
Slab:               6980 kB
SReclaimable:        724 kB
SUnreclaim:         6256 kB
KernelStack:         496 kB
PageTables:          428 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:       61432 kB
Committed_AS:       8792 kB
VmallocTotal:    1048372 kB
VmallocUsed:        3600 kB
VmallocChunk:    1036896 kB
Node 0, zone   Normal      4      1     24     15      9      3      2      2      3      2      6
RTMPAPPrivIoctlShow(): Before check, this_char=psinfo
RTMPAPPrivIoctlShow(): after check, this_char=psinfo, value=
Show_PSTable_Proc(): arg=
Dump MacTable entries info, EntType=0x20001

HT Operating Mode : 0

pAd->MacTab.fAnyStationInPsm : 0
pAd->dequeu_fail_cnt : 0

MAC                     EntryType       AID     BSS     PSM     psm     ipsm    iips    sktx    redt    port    queu    pktnum        psnum   hinum#  hidrp#  TXOK/PER        APSD    rcount

We can also see the partitions and which one we have write permissions on, which is useful for transferring binaries. still, being the most privileged user, we could remount ro partitions as rw if we wanted to change some important binary or simply overwrite the filesystem.

1
2
3
4
5
6
7
8
~ # mount
rootfs on / type rootfs (rw)
/dev/root on / type squashfs (ro,relatime)
proc on /proc type proc (rw,relatime)
ramfs on /var type ramfs (rw,relatime)
devpts on /dev/pts type devpts (rw,relatime,mode=600)
/sys on /sys type sysfs (rw,relatime)
~ #

Firmware Extraction

On the router’s own web interface we can see the firmware version, a very old and vulnerable one:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Status

Firmware Version:
0.9.1 3.16 v0001.0 Build 161012 Rel.33002n

Hardware Version:
TL-WR841N v13 00000013

LAN

MAC Address:
D4:6E:0E:57:1E:E0

IP Address:
192.168.0.1

Subnet Mask:
255.255.255.0

Now we’re going to try to extract the firmware, but for that it would be convenient to obtain the model of the router’s flash.

as we showed earlier it is 25Q64CS16, so we can look for the datasheet to get more information

Here we have the datasheet. The first thing we can see is basic information about the flash memory.

This is the connection diagram which tells us what each pin is:

The communication protocol is i2c, which is why we are going to try to connect via pins and attempt to obtain the firmware without the need to desolder the microchip (spoiler: it was not possible)

the description of the aforementioned:

Read protocol (0x03)

Now we proceed to connect to the chip physically:

If we pass it to a logic analyzer we see the outgoing data:

With this we can conclude that there is data movement when the router powers on, what we can do is connect a firmware extraction tool so we can start reverse engineering…

Firmware CH341 Extraction

Now we’re going to use the CH341 device to extract the firmware:

The problem with this device is that it runs at 5V while our chip runs at 3.3V, which is why using it as-is would fry the chip, so a modification is necessary.

We’re going to switch the board to 3.3V; we simply have to make two joins as shown below

before:

after:

as we can see it’s not the cleanest job I’ve done but the important thing is that it works, so now we can test it with the multimeter:

From what we see it’s fine, so we can connect the clips to the chip:

this would be the setup:

now we would have to obtain the firmware with the ch341 program. Unfortunately I couldn’t do it this way, it simply didn’t detect the chip. I tried on both Windows and Linux and also repositioning the clips a thousand times and trying different boards but nothing in the end :(

Firmware Extraction Alternative: tftp

As we saw earlier we are able to execute the tftp command, so we could try to set up a tftp server using atftp and upload a complete version of busybox.

We also saw that we can r/w permissions on the /var folder so we can use it as our personal storage on the UART console.

The binary is compiled for MIPS, which we will have to keep in mind if we want to modify, reflash, or tweak any part of the system.

1
2
3
4
root@ack:/srv/tftp# ls
busybox-mipsel
root@ack:/srv/tftp# file busybox-mipsel
busybox-mipsel: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), statically linked, stripped

We successfully transferred busybox binary

1
2
3
4
5
6
7
8
/var # tftp -g -r busybox-mipsel 192.168.0.100
busybox-mipsel         0% |                               |  6144   0:04:15 ETAMTSmartCarrierSense(): CSC=L
busybox-mipsel       100% |*******************************|  1539k  0:00:00 ETA
/var # MTSmartCarrierSense(): CSC=H (Default)
ls
lock            run             Wireless        passwd          busybox-mipsel
log             tmp             dev             l2tp
/var #

We can start obtaining very useful info:

1
2
/var # ./busybox-mipsel uname -a
Linux TL-WR841N 2.6.36 #83 Wed Oct 12 08:54:10 HKT 2016 mips GNU/Linux

we can list internally open ports, both TCP and UDP, and the ports only open locally.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/var # ./busybox-mipsel netstat -lptnu
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.1:20002         0.0.0.0:*               LISTEN      1091/tmpd
tcp        0      0 0.0.0.0:1900            0.0.0.0:*               LISTEN      1065/upnpd
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      1053/httpd
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1135/dropbear
tcp        0      0 :::22                   :::*                    LISTEN      1135/dropbear
tcp        0      0 :::23                   :::*                    LISTEN      728/telnetd
udp        0      0 127.0.0.1:48400         0.0.0.0:*                           1065/upnpd
udp        0      0 0.0.0.0:20002           0.0.0.0:*                           1102/tdpd
udp        0      0 0.0.0.0:67              0.0.0.0:*                           1071/dhcpd
udp        0      0 0.0.0.0:1900            0.0.0.0:*                           1065/upnpd
udp        0      0 0.0.0.0:44402           0.0.0.0:*                           1065/upnpd
udp        0      0 :::547                  :::*                                1088/dhcp6s
/var #
/var #

As we saw before, every process is running as admin:

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
/var # ./busybox-mipsel ps ww
PID   USER     TIME   COMMAND
    1 admin      0:00 init
    2 admin      0:00 [kthreadd]
    3 admin      0:00 [ksoftirqd/0]
    4 admin      0:00 [kworker/0:0]
    5 admin      0:00 [kworker/u:0]
    6 admin      0:00 [khelper]
    7 admin      0:00 [kworker/u:1]
   42 admin      0:00 [sync_supers]
   44 admin      0:00 [bdi-default]
   46 admin      0:00 [kblockd]
   69 admin      0:00 [kswapd0]
   71 admin      0:00 [crypto]
  630 admin      0:00 [mtdblock0]
  635 admin      0:00 [mtdblock1]
  640 admin      0:01 [mtdblock2]
  645 admin      0:00 [mtdblock3]
  650 admin      0:00 [mtdblock4]
  655 admin      0:00 [mtdblock5]
  660 admin      0:00 [mtdblock6]
  678 admin      0:00 [kworker/0:1]
  728 admin      0:00 telnetd
  745 admin      0:00 cos
  746 admin      0:00 /bin/sh
  749 admin      0:00 igmpd
  752 admin      0:00 mldProxy
  839 admin      0:00 cos
  840 admin      0:00 cos
  841 admin      0:00 cos
  860 admin      0:00 ntpc
  865 admin      0:00 dyndns /var/tmp/dconf/dyndns.conf
  868 admin      0:00 noipdns /var/tmp/dconf/noipdns.conf
  871 admin      0:00 cmxdns /var/tmp/dconf/cmxdns.conf
 1017 admin      0:00 [RtmpCmdQTask]
 1018 admin      0:00 [RtmpWscTask]
 1019 admin      0:01 [RtmpMlmeTask]
 1030 admin      0:00 wlNetlinkTool
 1034 admin      0:00 wlNetlinkTool
 1035 admin      0:00 wlNetlinkTool
 1036 admin      0:00 wscd -i ra0 -m 1 -w /var/tmp/wsc_upnp/
 1053 admin      0:00 httpd
 1065 admin      0:00 upnpd -L br0 -W eth0.2 -en 1 -P eth0.2 -nat 0 -port 80 -u
 1068 admin      0:00 dnsProxy
 1071 admin      0:00 dhcpd /var/tmp/dconf/udhcpd.conf
 1088 admin      0:00 dhcp6s -c /var/tmp/dconf/dhcp6s_br0.conf -P /var/run/dhcp
 1091 admin      0:00 tmpd
 1095 admin      0:00 upnpd -L br0 -W eth0.2 -en 1 -P eth0.2 -nat 0 -port 80 -u
 1096 admin      0:00 upnpd -L br0 -W eth0.2 -en 1 -P eth0.2 -nat 0 -port 80 -u
 1097 admin      0:00 upnpd -L br0 -W eth0.2 -en 1 -P eth0.2 -nat 0 -port 80 -u
 1098 admin      0:00 upnpd -L br0 -W eth0.2 -en 1 -P eth0.2 -nat 0 -port 80 -u
 1099 admin      0:00 upnpd -L br0 -W eth0.2 -en 1 -P eth0.2 -nat 0 -port 80 -u
 1100 admin      0:00 upnpd -L br0 -W eth0.2 -en 1 -P eth0.2 -nat 0 -port 80 -u
 1101 admin      0:00 upnpd -L br0 -W eth0.2 -en 1 -P eth0.2 -nat 0 -port 80 -u
 1102 admin      0:00 tdpd
 1108 admin      0:44 dhcpc
 1119 admin      0:00 zebra -d -f /var/tmp/dconf/zebra.conf
 1135 admin      0:00 dropbear -p 22 -r /var/tmp/dropbear/dropbear_rsa_host_key
 1136 admin      0:00 diagTool
 2794 admin      0:00 ./busybox-mipsel ps ww

Now we are going to transfer all the firmware blocks (mtdblockX) to the host machine using tftp

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
/var # ls -la /dev
crw-r--r--    1    1,   5 zero
crw-r--r--    1   10, 130 watchdog
crw-r--r--    1  215,   0 voip
crw-r--r--    1  245,   0 vdsp
crw-r--r--    1    1,   9 urandom
crw-r--r--    1    3,   2 ttyp2
crw-r--r--    1    3,   1 ttyp1
crw-r--r--    1    3,   0 ttyp0
crw-r--r--    1  188,   9 ttyUSB9
crw-r--r--    1  188,   8 ttyUSB8
crw-r--r--    1  188,   7 ttyUSB7
crw-r--r--    1  188,   6 ttyUSB6
crw-r--r--    1  188,   5 ttyUSB5
crw-r--r--    1  188,   4 ttyUSB4
crw-r--r--    1  188,   3 ttyUSB3
crw-r--r--    1  188,   2 ttyUSB2
crw-r--r--    1  188,  15 ttyUSB15
crw-r--r--    1  188,  14 ttyUSB14
crw-r--r--    1  188,  13 ttyUSB13
crw-r--r--    1  188,  12 ttyUSB12
crw-r--r--    1  188,  11 ttyUSB11
crw-r--r--    1  188,  10 ttyUSB10
crw-r--r--    1  188,   1 ttyUSB1
crw-r--r--    1  188,   0 ttyUSB0
crw-r--r--    1    4,  65 ttyS1
crw-r--r--    1    4,  64 ttyS0
crw-r--r--    1  166,   9 ttyACM9
crw-r--r--    1  166,   8 ttyACM8
crw-r--r--    1  166,   7 ttyACM7
crw-r--r--    1  166,   6 ttyACM6
crw-r--r--    1  166,   5 ttyACM5
crw-r--r--    1  166,   4 ttyACM4
crw-r--r--    1  166,   3 ttyACM3
crw-r--r--    1  166,   2 ttyACM2
crw-r--r--    1  166,  15 ttyACM15
crw-r--r--    1  166,  14 ttyACM14
crw-r--r--    1  166,  13 ttyACM13
crw-r--r--    1  166,  12 ttyACM12
crw-r--r--    1  166,  11 ttyACM11
crw-r--r--    1  166,  10 ttyACM10
crw-r--r--    1  166,   1 ttyACM1
crw-r--r--    1  166,   0 ttyACM0
crw-r--r--    1    4,   0 tty0
crw-r--r--    1    5,   0 tty
crw-r--r--    1  251,   0 slic
drwxrwxr-x    2         3 shm
brw-r--r--    1    8,  18 sdb2
brw-r--r--    1    8,  17 sdb1
brw-r--r--    1    8,  16 sdb
brw-r--r--    1    8,   2 sda2
brw-r--r--    1    8,   1 sda1
brw-r--r--    1    8,   0 sda
crw-r--r--    1  253,   0 rdm0
crw-r--r--    1    1,   8 random
crw-r--r--    1  111,   2 qostype
crw-r--r--    1    2,   2 ptyp2
crw-r--r--    1    2,   1 ptyp1
crw-r--r--    1    2,   0 ptyp0
drwxr-xr-x    2         0 pts
crw-r--r--    1    5,   2 ptmx
crw-r--r--    1  108,   0 ppp
crw-r--r--    1  200,   0 pmap
crw-r--r--    1    1,   3 null
drwxrwxr-x    2        26 net
crw-r--r--    1  250,   0 mtr0
brw-r--r--    1   31,   6 mtdblock6
brw-r--r--    1   31,   5 mtdblock5
brw-r--r--    1   31,   4 mtdblock4
brw-r--r--    1   31,   3 mtdblock3
brw-r--r--    1   31,   2 mtdblock2
brw-r--r--    1   31,   1 mtdblock1
brw-r--r--    1   31,   0 mtdblock0
crw-r--r--    1   90,  12 mtd6
crw-r--r--    1   90,  10 mtd5
crw-r--r--    1   90,   8 mtd4
crw-r--r--    1   90,   6 mtd3
crw-r--r--    1   90,   4 mtd2
crw-r--r--    1   90,   2 mtd1
crw-r--r--    1   90,   0 mtd0
brw-r--r--    1   31,   0 mtd
crw-r--r--    1   10, 151 led
crw-r--r--    1  220,   0 hwnat0
crw-r--r--    1  200,   0 flash0
crw-r--r--    1   63,   0 dk0
crw-r--r--    1    5,   1 console
brw-r--r--    1   31,   5 caldata
crw-r--r--    1  100,   0 adsl0
crw-r--r--    1  230,   0 acl0
crw-r--r--    1  240,   0 ac0
crw-r--r--    1  235,   0 FxsDrv
crw-r--r--    1  234,   0 AclDsp
drwxrwxr-x   13       177 ..
drwxrwxr-x    5      1274 .
/var # 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/var # ./busybox-mipsel tftp -p -r mtdblock0 -l ./mtdblock0 192.168.0.100
mtdblock0            100% |*******************************|   128k  0:00:00 ETA
/var # ./busybox-mipsel tftp -p -r mtdblock1 -l ./mtdblock1 192.168.0.100
mtdblock1             13% |****                           |   167k  0:00:06 ETAMTSmartCarrierSense(): CSC=L
mtdblock1            100% |*******************************|  1280k  0:00:00 ETA
/var # MTSmartCarrierSense(): CSC=H (Default)

/var # ./busybox-mipsel tftp -p -r mtdblock2 -l ./mtdblock2 192.168.0.100
mtdblock2              2% |                               |   172k  0:00:36 ETAMTSmartCarrierSense(): CSC=L
mtdblock2            100% |*******************************|  6528k  0:00:00 ETA
/var # MTSmartCarrierSense(): CSC=H (Default)

/var # ./busybox-mipsel tftp -p -r mtdblock3 -l ./mtdblock3 192.168.0.100
mtdblock3            100% |*******************************| 65536   0:00:00 ETA
/var # ./busybox-mipsel tftp -p -r mtdblock4 -l ./mtdblock4 192.168.0.100
mtdblock4            100% |*******************************| 65536   0:00:00 ETA
/var # ./busybox-mipsel tftp -p -r mtdblock5 -l ./mtdblock5 192.168.0.100
mtdblock5            100% |*******************************| 65536   0:00:00 ETA
/var # ./busybox-mipsel tftp -p -r mtdblock6 -l ./mtdblock6 192.168.0.100
mtdblock6            100% |*******************************| 65536   0:00:00 ETA
/var #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/var # ./busybox-mipsel tftp -p -r mtd -l ./mtd 192.168.0.100
mtd                  100% |*******************************|   128k  0:00:00 ETA
/var # ./busybox-mipsel tftp -p -r mtd0 -l ./mtd0 192.168.0.100
mtd0                 100% |*******************************|   128k  0:00:00 ETA
/var # ./busybox-mipsel tftp -p -r mtd1 -l ./mtd1 192.168.0.100
mtd1                   8% |**                             |   103k  0:00:11 ETAMTSmartCarrierSense(): CSC=L
mtd1                 100% |*******************************|  1280k  0:00:00 ETA
/var # MTSmartCarrierSense(): CSC=H (Default)

/var # ./busybox-mipsel tftp -p -r mtd2 -l ./mtd2 192.168.0.100
mtd2                   0% |                               | 47616   0:02:19 ETAMTSmartCarrierSense(): CSC=L
mtd2                 100% |*******************************|  6528k  0:00:00 ETA
/var # MTSmartCarrierSense(): CSC=H (Default)

/var # ./busybox-mipsel tftp -p -r mtd3 -l ./mtd3 192.168.0.100
mtd3                 100% |*******************************| 65536   0:00:00 ETA
/var # ./busybox-mipsel tftp -p -r mtd4 -l ./mtd4 192.168.0.100
mtd4                 100% |*******************************| 65536   0:00:00 ETA
/var # ./busybox-mipsel tftp -p -r mtd5 -l ./mtd5 192.168.0.100
mtd5                 100% |*******************************| 65536   0:00:00 ETA
/var # ./busybox-mipsel tftp -p -r mtd6 -l ./mtd6 192.168.0.100
mtd6                 100% |*******************************| 65536   0:00:00 ETA
/var #

We can check the md5 hashes to ensure data integrity

We see that mtdX and mtdblockX are basically the same archives, then we can do the same on our host to ensure integrity:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
root@ack:/srv/tftp# md5sum mtd*
8f1725b043f8aca888c5bc8e89a1a5a4  mtd
8f1725b043f8aca888c5bc8e89a1a5a4  mtd0
a4fa7e23afd5ffa32886fcd9405af23c  mtd1
813c6450e0304dd4bb70f71fcae8081c  mtd2
f076d2722f252f1312752af08bd645c6  mtd3
3f9e8c85155c50ae473d4e986d33e256  mtd4
ecb99e6ffea7be1e5419350f725da86b  mtd5
7064f71266e06dec129f7773e6eeed49  mtd6
8f1725b043f8aca888c5bc8e89a1a5a4  mtdblock0
a4fa7e23afd5ffa32886fcd9405af23c  mtdblock1
813c6450e0304dd4bb70f71fcae8081c  mtdblock2
f076d2722f252f1312752af08bd645c6  mtdblock3
3f9e8c85155c50ae473d4e986d33e256  mtdblock4
ecb99e6ffea7be1e5419350f725da86b  mtdblock5
7064f71266e06dec129f7773e6eeed49  mtdblock6

There are no I/O errors, we got the data as-is

Now we can analyze the files

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
root@ack:/srv/tftp# file mtd*
mtd:       data
mtd0:      data
mtd1:      data
mtd2:      Squashfs filesystem, little endian, version 4.0, xz compressed, 3281080 bytes, 590 inodes, blocksize: 131072 bytes, created: Wed Oct 12 01:10:05 2016
mtd3:      data
mtd4:      data
mtd5:      ISO-8859 text, with very long lines (65536), with no line terminators
mtd6:      data
mtdblock0: data
mtdblock1: data
mtdblock2: Squashfs filesystem, little endian, version 4.0, xz compressed, 3281080 bytes, 590 inodes, blocksize: 131072 bytes, created: Wed Oct 12 01:10:05 2016
mtdblock3: data
mtdblock4: data
mtdblock5: ISO-8859 text, with very long lines (65536), with no line terminators
mtdblock6: data

We notice that we have a squashfs there which we can extract the full filesystem from using unsquashfs

Squash File System

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
root@ack:~/Desktop/Firmware/mtdblock2# unsquashfs mtdblock2.bin
Parallel unsquashfs: Using 8 processors
548 inodes (448 blocks) to write

[==========================================================================================|] 996/996 100%

created 399 files
created 42 directories
created 60 symlinks
created 89 devices
created 0 fifos
created 0 sockets
created 0 hardlinks
root@ack:~/Desktop/Firmware/mtdblock2# ls
mtdblock2.bin  mtdblock2.bin.bak  squashfs-root
root@ack:~/Desktop/Firmware/mtdblock2# 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
root@ack:~/Desktop/Firmware/mtdblock2/squashfs-root# ls -la
total 52
drwxrwxr-x 13 root root 4096 oct 12  2016 .
drwxr-xr-x  3 root root 4096 oct 24 18:58 ..
drwxrwxr-x  2 root root 4096 oct 12  2016 bin
drwxrwxr-x  5 root root 4096 oct 12  2016 dev
drwxrwxr-x  5 root root 4096 oct 12  2016 etc
drwxrwxr-x  3 root root 4096 oct 12  2016 lib
lrwxrwxrwx  1 root root   11 oct 12  2016 linuxrc -> bin/busybox
drwxrwxr-x  2 root root 4096 oct 12  2016 mnt
drwxrwxr-x  2 root root 4096 oct 12  2016 proc
drwxrwxr-x  2 root root 4096 oct 12  2016 sbin
drwxrwxr-x  2 root root 4096 oct 12  2016 sys
drwxrwxr-x  4 root root 4096 oct 12  2016 usr
drwxrwxr-x  2 root root 4096 oct 12  2016 var
drwxrwxr-x  9 root root 4096 oct 12  2016 web

We can see that there are a lot of references to busybox, we can see the Dropbear binary, which is the open service on port 22 (SSH).

1
2
3
4
5
6
root@ack:~/Desktop/Firmware/mtdblock2/squashfs-root# tree | grep -i dropbear
│   │   ├── dropbear -> dropbearmulti
│   │   ├── dropbearkey -> dropbearmulti
│   │   ├── dropbearmulti
│   │   ├── scp -> dropbearmulti
root@ack:~/Desktop/Firmware/mtdblock2/squashfs-root#

Dropbear sshd 2012.55

We found Dropbear configuration files and private keys, we also found a hash which we can try to crack

1
2
3
4
5
6
/var/tmp/dropbear # ls
dropbearpwd            dropbear_rsa_host_key  dropbear_dss_host_key
/var/tmp/dropbear # cat dropbearpwd
username:admin
password:21232f297a57a5a743894a0e4a801fc3
/var/tmp/dropbear #

We transferred the files as before and proceeded to analyze the hash.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
root@ack:~/Desktop/blog/routerTpLink/dropbear# hashid dropbearhash
--File 'dropbearhash'--
Analyzing '21232f297a57a5a743894a0e4a801fc3'
[+] MD2
[+] MD5
[+] MD4
[+] Double MD5
[+] LM
[+] RIPEMD-128
[+] Haval-128
[+] Tiger-128
[+] Skein-256(128)
[+] Skein-512(128)
[+] Lotus Notes/Domino 5
[+] Skype
[+] Snefru-128
[+] NTLM
[+] Domain Cached Credentials
[+] Domain Cached Credentials 2
[+] DNSSEC(NSEC3)
[+] RAdmin v2.x

Now we will use hashcat to break the password.

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
root@ack:~/Desktop/blog/routerTpLink/dropbear# hashcat -a 3 dropbearhash -m 0
hashcat (v6.2.6) starting

nvmlDeviceGetFanSpeed(): Not Supported

CUDA API (CUDA 11.4)
====================
* Device #1: NVIDIA GeForce RTX 3060 Laptop GPU, 5833/5946 MB, 30MCU

OpenCL API (OpenCL 3.0 CUDA 11.4.557) - Platform #1 [NVIDIA Corporation]
========================================================================
* Device #2: NVIDIA GeForce RTX 3060 Laptop GPU, skipped

Minimum password length supported by kernel: 0
Maximum password length supported by kernel: 256

Hashes: 1 digests; 1 unique digests, 1 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates

Optimizers applied:
* Zero-Byte
* Early-Skip
* Not-Salted
* Not-Iterated
* Single-Hash
* Single-Salt
* Brute-Force
* Raw-Hash

ATTENTION! Pure (unoptimized) backend kernels selected.
Pure kernels can crack longer passwords, but drastically reduce performance.
If you want to switch to optimized kernels, append -O to your commandline.
See the above message to find out about the exact limits.

...
...
Candidates.#1....: sarv -> Xqxv
Hardware.Mon.#1..: Temp: 56c Util: 72% Core:1552MHz Mem:6000MHz Bus:4

21232f297a57a5a743894a0e4a801fc3:admin

Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 0 (MD5)
Hash.Target......: 21232f297a57a5a743894a0e4a801fc3
Time.Started.....: Sun Nov  2 20:04:29 2025 (0 secs)
Time.Estimated...: Sun Nov  2 20:04:29 2025 (0 secs)
Kernel.Feature...: Pure Kernel
Guess.Mask.......: ?1?2?2?2?2 [5]
Guess.Charset....: -1 ?l?d?u, -2 ?l?d, -3 ?l?d*!$@_, -4 Undefined
Guess.Queue......: 5/15 (33.33%)
Speed.#1.........:  3094.9 MH/s (6.82ms) @ Accel:64 Loops:62 Thr:512 Vec:1
Recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
Progress.........: 60948480/104136192 (58.53%)
Rejected.........: 0/60948480 (0.00%)
Restore.Point....: 0/1679616 (0.00%)
Restore.Sub.#1...: Salt:0 Amplifier:0-62 Iteration:0-62
Candidate.Engine.: Device Generator
Candidates.#1....: sarie -> Xc05k
Hardware.Mon.#1..: Temp: 56c Util: 69% Core:1582MHz Mem:6000MHz Bus:4

Started: Sun Nov  2 20:04:26 2025
Stopped: Sun Nov  2 20:04:30 2025
root@ack:~/Desktop/blog/routerTpLink/dropbear#

The password is admin, now we can try to connect via ssh

1
2
3
4
5
6
7
8
9
10
root@ack:~/Desktop/blog/routerTpLink/dropbear# ssh -oKexAlgorithms=+diffie-hellman-group1-sha1 -oHostKeyAlgorithms=+ssh-dss -c 3des-cbc admin@192.168.0.1
The authenticity of host '192.168.0.1 (192.168.0.1)' can't be established.
DSA key fingerprint is SHA256:sRpKaBgMeeBrdrMqR5HXbnNklh2ViqJn8Y3CKwusxSM.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.0.1' (DSA) to the list of known hosts.
admin@192.168.0.1's password:
PTY allocation request failed on channel 0
shell request failed on channel 0
root@ack:~/Desktop/blog/routerTpLink/dropbear#

The configuration does not allow remote connection.

745/cos bug

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/var # ./busybox-mipsel netstat -lnp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.1:20002         0.0.0.0:*               LISTEN      1106/tmpd
tcp        0      0 0.0.0.0:1900            0.0.0.0:*               LISTEN      1072/upnpd
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      1060/httpd
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1147/dropbear
tcp        0      0 :::22                   :::*                    LISTEN      1147/dropbear
tcp        0      0 :::23                   :::*                    LISTEN      728/telnetd
udp        0      0 0.0.0.0:48400           0.0.0.0:*                           745/cos
udp        0      0 127.0.0.1:47640         0.0.0.0:*                           1072/upnpd
udp        0      0 0.0.0.0:20002           0.0.0.0:*                           1109/tdpd
udp        0      0 0.0.0.0:33195           0.0.0.0:*                           1072/upnpd
udp        0      0 0.0.0.0:67              0.0.0.0:*                           1078/dhcpd
udp        0      0 0.0.0.0:1900            0.0.0.0:*                           1072/upnpd
udp        0      0 :::547                  :::*                                1105/dhcp6s
raw        0      0 0.0.0.0:2               0.0.0.0:*               2           749/igmpd
raw        0      0 0.0.0.0:255             0.0.0.0:*               255         745/cos
raw        0      0 0.0.0.0:255             0.0.0.0:*               255         1072/upnpd
raw        0      0 :::58                   :::*                    58          752/mldProxy
Active UNIX domain sockets (only servers)
Proto RefCnt Flags       Type       State         I-Node PID/Program name    Path
unix  2      [ ACC ]     STREAM     LISTENING        635 1128/zebra          /var/tmp/.zserv
/var #

After running nc -u 192.168.0.1 48400 < /dev/urandom

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
/var # ./busybox-mipsel netstat -lnp
Algorithmics/MIPS FPU Emulator v1.5
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.1:20002         0.0.0.0:*               LISTEN      1093/tmpd
tcp        0      0 0.0.0.0:1900            0.0.0.0:*               LISTEN      1066/upnpd
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      1054/httpd
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1136/dropbear
tcp        0      0 :::22                   :::*                    LISTEN      1136/dropbear
tcp        0      0 :::23                   :::*                    LISTEN      728/telnetd
udp        0      0 127.0.0.1:48400         0.0.0.0:*                           1066/upnpd
udp        0      0 0.0.0.0:20002           0.0.0.0:*                           1103/tdpd
udp        0      0 0.0.0.0:67              0.0.0.0:*                           1072/dhcpd
udp        0      0 0.0.0.0:1900            0.0.0.0:*                           1066/upnpd
udp        0      0 0.0.0.0:44402           0.0.0.0:*                           1066/upnpd
udp        0      0 :::547                  :::*                                1089/dhcp6s
raw        0      0 0.0.0.0:2               0.0.0.0:*               2           749/igmpd
raw        0      0 0.0.0.0:255             0.0.0.0:*               255         745/cos
raw        0      0 0.0.0.0:255             0.0.0.0:*               255         1066/upnpd
raw        0      0 :::58                   :::*                    58          752/mldProxy
Active UNIX domain sockets (only servers)
Proto RefCnt Flags       Type       State         I-Node PID/Program name    Path
unix  2      [ ACC ]     STREAM     LISTENING        639 1120/zebra          /var/tmp/.zserv
/var #

so there is something potentially exploitable there since the process seems to have crashed.

the following command:

1
nc -u 192.168.0.1 48400 < /dev/urandom

I use as a very crude “fuzzer” just to do quick tests or a general sweep.

BusyBox v1.19.2 /sbin/init

We also notice that the /sbin/init binary is actually busybox, it is exactly the same, it only spawns a shell within that same busybox.

1
2
3
4
5
/var # ./busybox-mipsel md5sum /sbin/init /bin/busybox
Algorithmics/MIPS FPU Emulator v1.5
0ea9fcd8dfd39e663ba0af25b9cdcb97  /sbin/init
0ea9fcd8dfd39e663ba0af25b9cdcb97  /bin/busybox
/var #

Also, testing the init command we notice that the configuration file is /etc/inittab, the firmware could be modified, altered, and reflashed to weaponize the router.

1
2
3
4
5
6
7
8
9
~ # /sbin/init -q
reloading /etc/inittab
~ #
~ # ls /etc/inittab
/etc/inittab
~ # cat /etc/inittab
::sysinit:/etc/init.d/rcS
ttyS1::respawn:/bin/sh
~ #

Busybox Char escape vuln

We also have an external vulnerability which is the Busybox char escape issue but I couldn’t trigger it sufficiently to provide anything conclusive. Still, it was worth a small mention.

1
/var # busybox 2>&1 | { IFS= read -r first || true; echo "$first"; }

Desoldering the Flash

Getting the firmware via tftp and failing with the CH341 felt insufficient, so we desoldered the chip and read it with the XGECU T48

Once desoldered we adapt the chip to the XGECU:

This would be the setup:

Once we have the setup we can proceed with the program to read the flash:

Here we have the flash contents:

Once downloaded we can start analyzing the firmware and extract it with binwalk:

1
2
3
4
5
6
7
8
9
10
11
12
13
root@ack:~/Desktop/blog/routerTpLink/firmware/physical# binwalk GD25Q64C.BIN

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
79968         0x13860         U-Boot version string, "U-Boot 1.1.3 (Oct 12 2016 - 08:49:46)"
131584        0x20200         LZMA compressed data, properties: 0x5D, dictionary size: 8388608 bytes, uncompressed size:3511364 bytes
1441792       0x160000        Squashfs filesystem, little endian, version 4.0, compression:xz, size: 3281080 bytes, 590 inodes, blocksize: 131072 bytes, created: 2016-10-12 01:10:05

root@ack:~/Desktop/blog/routerTpLink/firmware/physical# md5sum GD25Q64C.BIN ../firmware
8d0f869f9f1fcee35192ef857f47319b  GD25Q64C.BIN
bfc99913851b4db89571f215d4074067  ../firmware

root@ack:~/Desktop/blog/routerTpLink/firmware/physical#

We also see that both images differ, the one obtained physically and the one obtained via tftp

Here we have the firmware entropy, so it seems nothing is encrypted

U-BOOT RE

1
2
3
4
5
6
7
root@ack:~/Desktop/blog/routerTpLink/firmware/physical# dd if=GD25Q64C.BIN of=u-boot.bin bs=1 skip=$((0x13860)) count=$((0x20200 - 0x13860))
51616+0 records in
51616+0 records out
51616 bytes (52 kB, 50 KiB) copied, 0,0394169 s, 1,3 MB/s
root@ack:~/Desktop/blog/routerTpLink/firmware/physical# file u-boot.bin
u-boot.bin: data
root@ack:~/Desktop/blog/routerTpLink/firmware/physical#

We can obtain the u-boot.bin. We can also search for potential strings to later load it into IDA

1
2
3
4
5
6
7
8
9
root@ack:~/Desktop/blog/routerTpLink/firmware/physical# strings -n 10 u-boot.bin | grep -i "mips"
MIPS 64 Bit
No Linux MIPS Ramdisk Image
root@ack:~/Desktop/blog/routerTpLink/firmware/physical# strings -n 10 u-boot.bin | grep -i "cpu"
Software CPU Reset Occurred
 ##### The CPU freq = %d MHZ ####
 Normal Mode,Packet received from CPU port,plen=%d
reset   - Perform RESET of the CPU
Invalid CPU

once loaded in IDA we can find the Init function quite easily by size:

IMPORTANT: we must load the binary with the base address 0xBC000000 to fix the imports, otherwise it’s a complete mess

This is the boot initialization function:

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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
// write access to const memory has been detected, the output may be wrong!
int __fastcall Init(int a1, int a2)
{
  int v2; // $k0
  int v4; // $v0
  unsigned int v5; // $v0
  int *v6; // $s4
  int v7; // $v1
  int v8; // $a1
  char *v9; // $a2
  char *v10; // $v1
  _DWORD *v11; // $s3
  int v12; // $v1
  int v13; // $s1
  int v14; // $s0
  char *v15; // $s2
  _BYTE **v16; // $a1
  int v17; // $a2
  char v18; // $v0
  int v19; // $v0
  int v20; // $v0
  unsigned __int32 v21; // $s0
  int v22; // $v1
  int v23; // $t0
  int v24; // $v1
  int v25; // $t0
  int v26; // $s3
  int v27; // $v0
  int v28; // $s2
  int v30; // $s1
  int v31; // $s0
  int v33; // $s1
  int v34; // $v0
  _BYTE v35[16]; // [sp+20h] [-40h] BYREF
  unsigned __int8 v36; // [sp+30h] [-30h] BYREF
  char v37[7]; // [sp+31h] [-2Fh] BYREF
  char v38[4]; // [sp+38h] [-28h] BYREF
  _BYTE *v39; // [sp+3Ch] [-24h]
  _BYTE v40[8]; // [sp+40h] [-20h] BYREF
  _BYTE *v41; // [sp+48h] [-18h]
  char v42[4]; // [sp+50h] [-10h] BYREF
  _BYTE *v43; // [sp+54h] [-Ch]
  _BYTE *v44; // [sp+58h] [-8h] BYREF
  int v45; // [sp+5Ch] [-4h] BYREF

  sub_BC010F70(0x83FF0000, v2, 36);
  MEMORY[0x83FF0004] |= 1u;
  if ( ((MEMORY[0xB000002C] >> 1) & 1) != 0 )
  {
    v4 = 480000000;
LABEL_7:
    dword_BC047BD0 = v4;
    goto LABEL_9;
  }
  if ( (MEMORY[0xB000002C] & 1) != 0 )
  {
    if ( ((MEMORY[0xB0000010] >> 6) & 1) != 0 )
      v4 = 40000000;
    else
      v4 = 25000000;
    goto LABEL_7;
  }
  dword_BC047BD0 = 575000000;
LABEL_9:
  MEMORY[0xB000003C] |= 0x100u;
  MEMORY[0xB0000064] &= 0xFFFCFFFC;
  dword_BC047BCC = 0xC1A1B27;
  sub_BC001904();
  sub_BC00193C();
  if ( ((MEMORY[0xB0000038] >> 1) & 1) != 0 )
  {
    printfV1("***********************\n");
    printfV1("Watchdog Reset Occurred\n");
    printfV1("***********************\n");
    MEMORY[0xB0000038] |= 2u;
    v5 = MEMORY[0xB0000038] & 0xFFFFFFFD;
  }
  else if ( ((MEMORY[0xB0000038] >> 2) & 1) != 0 )
  {
    printfV1("******************************\n");
    printfV1("Software System Reset Occurred\n");
    printfV1("******************************\n");
    MEMORY[0xB0000038] |= 4u;
    v5 = MEMORY[0xB0000038] & 0xFFFFFFFB;
  }
  else
  {
    if ( ((MEMORY[0xB0000038] >> 3) & 1) == 0 )
      goto LABEL_16;
    printfV1("***************************\n");
    printfV1("Software CPU Reset Occurred\n");
    printfV1("***************************\n");
    MEMORY[0xB0000038] |= 8u;
    v5 = MEMORY[0xB0000038] & 0xFFFFFFF7;
  }
  MEMORY[0xB0000038] = v5;
LABEL_16:
  v6 = (int *)&off_BC017BC8;
  sub_BC003020(1000);
  sub_BC012968();
  MEMORY[0x83FF0014] = a2 + 0x44000000;
  dword_BC047BC8 = (int)&unk_BC017E68 - a2;
  while ( v6 != (int *)&unk_BC017E68 )
  {
    v7 = *v6;
    v8 = MEMORY[0x83FF0014];
    v9 = (char *)v6[4];
    v6[3] += MEMORY[0x83FF0014];
    *v6 = v7 + v8;
    if ( v9 )
      v6[4] = (int)&v9[MEMORY[0x83FF0014);
    v10 = (char *)v6[5];
    if ( v10 )
      v6[5] = (int)&v10[MEMORY[0x83FF0014);
    v6 += 6;
  }
  v11 = (_DWORD *)MEMORY[0x83FF0000];
  off_BC017778 = &aSpiFlash[MEMORY[0x83FF0014);
  v12 = sub_BC007F20();
  if ( v12 == -1 )
  {
    printfV1("ra_spi_init fail\n");
    while ( 1 )
      ;
  }
  v11[9] = v12;
  v11[8] = 0;
  v11[10] = 0;
  sub_BC008178(&v36, 0x20035, 1);
  sub_BC008178(v37, 0x20036, 1);
  if ( ((v36 >> 1) & 1) != 0 || (v37[0] & 0xC) == 0xC )
    MEMORY[0xB0000060] |= 0x30000C0u;
  MEMORY[0xB0000038] |= 0x200u;
  dword_BC017E88 = MEMORY[0x83FF0014] - 0x44000000;
  v13 = 0;
  dword_BC017E84 = MEMORY[0x83FF0014] - 0x44040000;
  dword_BC017E8C = -1;
  sub_BC010F44((_BYTE *)-1, 0, -1 - (MEMORY[0x83FF0014] - 0x44040000));
  sub_BC00DDD0();
  sub_BC00FA64();
  sub_BC00F380();
  v14 = sub_BC00CF6C((int)"ethaddr");
  do
  {
    v15 = (char *)v11 + v13;
    v16 = &v44;
    v17 = 16;
    ++v13;
    v18 = 0;
    if ( v14 )
      v18 = sub_BC011050(v14, &v44, 16);
    v15[8] = v18;
    if ( v14 )
      v14 = (int)&v44[*v44 != 0];
  }
  while ( v13 < 6 );
  v11[1] = sub_BC0040EC("ipaddr", v16, v17);
  sub_BC00DC94();
  sub_BC00F480();
  sub_BC00DADC();
  v19 = sub_BC00CF6C((int)"loadaddr");
  if ( v19 )
    dword_BC016E10 = sub_BC011050(v19, 0, 16);
  v20 = sub_BC00CF6C((int)"bootfile");
  if ( v20 )
    sub_BC003F34(&byte_BC046994, v20, 128);
  printfV1("============================================ \n");
  printfV1("Ralink UBoot Version: %s\n", "4.3.0.0");
  printfV1("-------------------------------------------- \n");
  printfV1("%s %s %s\n", "ASIC", "7628_MP", "(Port5<->None)");
  printfV1("DRAM component: %d Mbits %s\n", 512, "DDR, width 16");
  printfV1("DRAM bus: %d bit\n", 16);
  printfV1("Total memory: %d MBytes\n", 64);
  printfV1("%s\n", "Flash component: SPI Flash");
  printfV1("%s\n", "Date:Oct 12 2016  Time:08:49:46");
  printfV1("============================================ \n");
  v21 = _mfc0(0x10u, 1u);
  v22 = (v21 >> 19) & 7;
  v23 = 0;
  if ( v22 )
    v23 = 2 << v22;
  printfV1(
    "icache: sets:%d, ways:%d, linesz:%d ,total:%d\n",
    64 << ((v21 >> 22) & 7),
    (HIWORD(v21) & 7) + 1,
    v23,
    (64 << ((v21 >> 22) & 7)) * ((HIWORD(v21) & 7) + 1) * v23);
  v24 = (v21 >> 10) & 7;
  v25 = 0;
  if ( v24 )
    v25 = 2 << v24;
  v26 = 1;
  printfV1(
    "dcache: sets:%d, ways:%d, linesz:%d ,total:%d \n",
    64 << ((v21 >> 13) & 7),
    ((v21 >> 7) & 7) + 1,
    v25,
    (64 << ((v21 >> 13) & 7)) * (((v21 >> 7) & 7) + 1) * v25);
  printfV1("\n ##### The CPU freq = %d MHZ #### \n", 609);
  printfV1(" estimate memory size =%d Mbytes\n", MEMORY[0x83FF0010] >> 20);
  sub_BC005F20();
  nullsub_1();
  v27 = sub_BC00CF6C((int)"bootdelay");
  if ( v27 )
    v26 = sub_BC011144(v27, 0, 10);
  v28 = 51;
  while ( v26-- > 0 )
  {
    v30 = 0;
    while ( 1 )
    {
      ++v30;
      if ( sub_BC00D764() )
        break;
LABEL_52:
      if ( v30 >= 100 )
        goto LABEL_53;
    }
    v26 = 0;
    v28 = (unsigned __int8)sub_BC00D724();
    if ( v28 != 116 )
    {
      sub_BC003020(10000);
      goto LABEL_52;
    }
    v28 = 52;
LABEL_53:
    if ( v28 != 52 )
    {
      v31 = 50;
      if ( v28 != 55 )
      {
        while ( 1 )
        {
          sub_BC012C24(13, &v45);
          if ( v45 )
            break;
          --v31;
          sub_BC003020(100000);
          printfV1(".");
          if ( v31 <= 0 )
            goto LABEL_58;
        }
        v28 = 51;
        printfV1("\ncontinue to starting system.\n");
LABEL_58:
        if ( !v31 )
        {
          printfV1("\nstarting recovery...\n");
          sub_BC0128AC(39u, 0);
          sub_BC0050BC(MEMORY[0x83FF0000]);
          sub_BC009650("set serverip 192.168.0.66", 0);
          sub_BC009650(
            "tftp 0x80060000 tp_recovery.bin;erase tplink 0x20000 0x7a0000;cp.b 0x80080000 0x20000 0x7a0000",
            0);
          sub_BC003020(1000);
          sub_BC009650("reset", 0);
        }
      }
    }
    printfV1("\b\b\b%2d ", v26);
  }
  sub_BC00D7A4(10);
  if ( v28 == 51 )
  {
    sub_BC005C34();
    sub_BC0119C4((int)v35, "0x%X", 0xBC020000);
    v39 = v35;
    printfV1("   \n3: System Boot system code via Flash.(0x%x)\n", 0xBC020000);
    return sub_BC00A018((int)v6, 0, 2, (int)v38);
  }
  else
  {
    v41 = byte_BC017E90;
    sub_BC010F44(byte_BC017E90, 0, 128);
    v33 = 3;
    sub_BC0050BC(MEMORY[0x83FF0000]);
    printfV1("switch BootType:\n");
    if ( v28 == 52 )
    {
      printfV1("   \n%d: System Enter Boot Command Line Interface.\n", 4);
      printfV1("\n%s\n", "U-Boot 1.1.3 (Oct 12 2016 - 08:49:46)");
      sub_BC009B54();
    }
    if ( v28 == 55 )
    {
      printfV1("\n%d: System Load Boot Loader then write to Flash via Serial. \n", 7);
      v33 = 1;
      sub_BC00CEA4((int)"autostart", (int)"no");
      sub_BC00ADE4(v6, 0, 1, v40);
      v34 = sub_BC00CF6C((int)"filesize");
      dword_BC047C0C = sub_BC011050(v34, 0, 16);
      printfV1("Abort: Bootloader is too big or download aborted!\n");
      ((void (__fastcall *)(int *, _DWORD, int, _BYTE *))sub_BC012DE0)(v6, 0, 1, v40);
    }
    else
    {
      sub_BC005C34();
      sub_BC0119C4((int)v35, "0x%X", 0xBC020000);
      v43 = v35;
      printfV1("   \ndefault: System Boot system code via Flash.(0x%x)\n", 0xBC020000);
      sub_BC00A018((int)v6, 0, 2, (int)v42);
    }
    return ((int (__fastcall *)(int *, _DWORD, int, _BYTE *))sub_BC012DE0)(v6, 0, v33, v40);
  }
}

We also have the function responsible for loading the linux kernel:

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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// write access to const memory has been detected, the output may be wrong!
int __fastcall sub_BC013078(int a1, int a2, int a3, int a4, int a5, int a6, int a7)
{
  _DWORD *v7; // $k0
  int v11; // $s2
  int v12; // $s5
  int v13; // $s7
  char *v14; // $s3
  _DWORD *v15; // $v1
  _BYTE *v16; // $s4
  int v17; // $v0
  unsigned int v18; // $v0
  int v19; // $a1
  unsigned int v20; // $s0
  char *v21; // $s1
  BOOL v22; // $v0
  int v23; // $v0
  int v24; // $s2
  _BYTE *v25; // $s0
  _DWORD *v26; // $v1
  unsigned int v27; // $a2
  _BYTE v29[16]; // [sp+18h] [-18h] BYREF
  int v30; // [sp+28h] [-8h]
  int v31; // [sp+2Ch] [-4h]

  v31 = sub_BC00CF6C((int)"bootargs");
  v30 = 0x774B120C;
  if ( a3 < 3 )
    goto LABEL_12;
  v11 = sub_BC011050(*(_DWORD *)(a4 + 8), 0, 16);
  printfV1("## Loading Ramdisk Image at %08lx ...\n", v11);
  sub_BC010F70(&dword_BC047B54, v11, 64);
  printfV1("Bad Magic Number\n");
  ((void (__fastcall *)(int, int, int, int))sub_BC012DE0)(a1, a2, a3, a4);
  dword_BC047B58 = 0;
  if ( sub_BC010AC0(0, (char *)&dword_BC047B54, 64u) != -2121375470 )
  {
    printfV1("Bad Header Checksum\n");
    ((void (__fastcall *)(int, int, int, int))sub_BC012DE0)(a1, a2, a3, a4);
  }
  sub_BC00A268(&dword_BC047B54);
  if ( a7 )
  {
    printfV1("   Verifying Checksum ... ");
    if ( sub_BC010AC0(0, (char *)(v11 + 64), 0xB51DB718) != 0x19FE8744 )
    {
      printfV1("Bad Data CRC\n");
      ((void (__fastcall *)(int, int, int, int))sub_BC012DE0)(a1, a2, a3, a4);
    }
    printfV1("OK\n");
  }
  printfV1("No Linux MIPS Ramdisk Image\n");
  ((void (__fastcall *)(int, int, int, int))sub_BC012DE0)(a1, a2, a3, a4);
  v12 = v11 + 64;
  if ( v11 == -64 )
  {
LABEL_12:
    v12 = 0;
    printfV1("No initrd\n");
    v13 = 0;
  }
  else
  {
    v13 = v11 - 0x4AE248A8;
  }
  printfV1("## Transferring control to Linux (at address %08lx) ...\n", v30);
  v14 = (char *)v31;
  v15 = (_DWORD *)(*(_DWORD *)(*v7 + 20) & 0x1FFFFFFF);
  dword_BC02F420 = 1;
  dword_BC02F424 = (int)v15;
  *v15 = 0;
  v16 = v15 + 256;
  if ( v14 )
  {
    v17 = *v14;
    do
    {
      if ( !v17 )
        break;
      v20 = (int)sub_BC010E30(v14, 34);
      v18 = (int)sub_BC010E30(v14, 32);
      v21 = (char *)v18;
      if ( !v18 )
        goto LABEL_23;
      v22 = v20 < v18;
      if ( v20 )
      {
        while ( v22 )
        {
          v23 = (int)sub_BC010E30((_BYTE *)(v20 + 1), 34);
          v24 = v23 + 1;
          v19 = 34;
          if ( !v23 )
            goto LABEL_23;
          v20 = (int)sub_BC010E30((_BYTE *)(v23 + 1), 34);
          v21 = sub_BC010E30((_BYTE *)v24, 32);
          v22 = v20 < (unsigned int)v21;
          if ( !v21 )
            goto LABEL_23;
          if ( !v20 )
            break;
        }
      }
      if ( !v21 )
LABEL_23:
        v21 = &v14[sub_BC010E6C(v14, v19)];
      MEMORY[0xAE47328B] = v16;
      v25 = &v16[v21 - v14];
      sub_BC010F70(v16, v14, v21 - v14);
      *v25 = 0;
      dword_BC02F420 = 0xD417EA19;
      v16 = v25 + 1;
      if ( *v21 )
        ++v21;
      v14 = v21;
      if ( !v21 )
        break;
      v17 = 1;
    }
    while ( *v21 );
  }
  v26 = (_DWORD *)((unsigned int)(v16 + 15) & 0xFFFFFFF0);
  v27 = v7[4];
  *v26 = 0;
  dword_BC02F428 = (int)v26;
  dword_BC02F42C = (int)(v26 + 256);
  dword_BC02F430 = 0;
  sub_BC0119C4((int)v29, "%lu", v27 >> 20);
  printfV1("## Giving linux memsize in MB, %lu\n", v7[4] >> 20);
  sub_BC012F50("memsize", v29);
  sub_BC0119C4((int)v29, "0x%08X", v12 & 0x1FFFFFFF);
  sub_BC012F50("initrd_start", v29);
  sub_BC0119C4((int)v29, "0x%X", v13 - v12);
  sub_BC012F50("initrd_size", v29);
  sub_BC0119C4((int)v29, "0x%08X", *(_DWORD *)(*v7 + 32));
  sub_BC012F50("flash_start", v29);
  sub_BC0119C4((int)v29, "0x%X", *(_DWORD *)(*v7 + 36));
  sub_BC012F50("flash_size", v29);
  dword_BC02F424 = 0x9DE78A2B;
  dword_BC02F428 = 0x9AEFE6D2;
  printfV1("\nStarting kernel ...\n\n");
  return ((int (__fastcall *)(unsigned int, int, int, _DWORD))v30)(0xD417EA18, 0x5DE78A2B, 0x1AEFE6D2, 0);
}

We also have the function that filters the OS image:

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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
int __fastcall sub_BC00A268(int a1)
{
  const char *v2; // $a2
  const char *v3; // $a1
  const char *v4; // $a3
  const char *v5; // $v0
  unsigned int v6; // $a3

  printfV1("   Image Name:   %.*s\n", 32, (const char *)(a1 + 32));
  sub_BC00D7EC("   Image Type:   ");
  switch ( *(_BYTE *)(a1 + 28) )
  {
    case 0:
      v2 = "Invalid OS";
      break;
    case 2:
      v2 = "NetBSD";
      break;
    case 5:
      v2 = "Linux";
      break;
    case 0xE:
      v2 = "VxWorks";
      break;
    case 0x10:
      v2 = "QNX";
      break;
    case 0x11:
      v2 = "U-Boot";
      break;
    case 0x12:
      v2 = "RTEMS";
      break;
    default:
      v2 = "Unknown OS";
      break;
  }
  switch ( *(_BYTE *)(a1 + 29) )
  {
    case 0:
      v3 = "Invalid CPU";
      break;
    case 1:
      v3 = "Alpha";
      break;
    case 2:
      v3 = "ARM";
      break;
    case 3:
      v3 = "Intel x86";
      break;
    case 4:
      v3 = "IA64";
      break;
    case 5:
      v3 = "MIPS";
      break;
    case 6:
      v3 = "MIPS 64 Bit";
      break;
    case 7:
      v3 = "PowerPC";
      break;
    case 8:
      v3 = "IBM S390";
      break;
    case 9:
      v3 = "SuperH";
      break;
    case 0xA:
      v3 = "SPARC";
      break;
    case 0xB:
      v3 = "SPARC 64 Bit";
      break;
    case 0xC:
      v3 = "M68K";
      break;
    case 0xE:
      v3 = "Microblaze";
      break;
    default:
      v3 = "Unknown Architecture";
      break;
  }
  switch ( *(_BYTE *)(a1 + 30) )
  {
    case 0:
      v4 = "Invalid Image";
      break;
    case 1:
      v4 = "Standalone Program";
      break;
    case 2:
      v4 = "Kernel Image";
      break;
    case 3:
      v4 = "RAMDisk Image";
      break;
    case 5:
      v4 = "Firmware";
      break;
    case 6:
      v4 = "Script";
      break;
    default:
      v4 = "Unknown Image";
      break;
  }
  switch ( *(_BYTE *)(a1 + 31) )
  {
    case 0:
      v5 = "uncompressed";
      break;
    case 1:
      v5 = "gzip compressed";
      break;
    case 2:
      v5 = "bzip2 compressed";
      break;
    case 3:
      v5 = "lzma compressed";
      break;
    case 5:
      v5 = "xz compressed";
      break;
    default:
      v5 = "unknown compression";
      break;
  }
  printfV1("%s %s %s (%s)", v3, v2, v4, v5);
  printfV1(
    "\n   Data Size:    %d Bytes = ",
    (*(_DWORD *)(a1 + 12) << 24)
  | ((*(_DWORD *)(a1 + 12) & 0xFF00) << 8)
  | ((*(_DWORD *)(a1 + 12) & 0xFF0000u) >> 8)
  | HIBYTE(*(_DWORD *)(a1 + 12)));
  sub_BC010D20(
    (*(_DWORD *)(a1 + 12) << 24)
  | ((*(_DWORD *)(a1 + 12) & 0xFF00) << 8)
  | ((*(_DWORD *)(a1 + 12) & 0xFF0000u) >> 8)
  | HIBYTE(*(_DWORD *)(a1 + 12)),
    "\n");
  v6 = *(_DWORD *)(a1 + 16);
  return printfV1(
           "   Load Address: %08x\n   Entry Point:  %08x\n",
           (v6 << 24) | ((v6 & 0xFF00) << 8) | ((v6 & 0xFF0000) >> 8) | HIBYTE(v6),
           (*(_DWORD *)(a1 + 20) << 24)
         | ((*(_DWORD *)(a1 + 20) & 0xFF00) << 8)
         | ((*(_DWORD *)(a1 + 20) & 0xFF0000u) >> 8)
         | HIBYTE(*(_DWORD *)(a1 + 20)));
}

we also have a function related to the Microchip:

MT7628

Conclusion

This has been the research on the TL-WR841N router, my first interaction with Hardware Hacking. I am very happy with this research since I learned a lot and it motivates me to tackle more technically difficult projects.

Good morning, and in case I don’t see ya: Good afternoon, good evening, and good night!

This post is licensed under CC BY 4.0 by the author.