我是如何反編譯D-Link路由器固件程序并發現它的后門的

jopen 11年前發布 | 6K 次閱讀 程序員

英文原文: Reverse Engineering a D-Link Backdoor

        OK,又是周末晚上,沒有約會,只有一大瓶 Shasta 汽水和全是快節奏的音樂…那就研究一下程序吧

        一時興起,我下載了D-link 無線路由器(型號:DIR-100 revA)的固件程序 v1.13。使用工具 Binwalk,很快的就從中發現并提取出一個只讀 SquashFS 文件系統,沒用多大功夫我就將這個固件程序的 web server (/bin/webs)加載到了 IDA 中:

我是如何反編譯D-Link路由器固件程序并發現它的后門的

/bin/webs 中的字符信息

        基于上面的字符信息可以看出,這個/bin/webs 二進制程序是一個修改版的 thttpd,提供路由器管理員界面操作功能。看起來是經過了臺灣明泰科技(D-Link 的一個子公司)的修改。他們甚至很有心計的將他們很多自定義的函數名都輔以“alpha”前綴:

我是如何反編譯D-Link路由器固件程序并發現它的后門的

明泰科技的自定義函數

        這個alpha_auth_check函數看起來很有意思!

        這個函數被很多地方調用,最明顯的一個是來自alpha_httpd_parse_request函數:

我是如何反編譯D-Link路由器固件程序并發現它的后門的

調用 alpha_auth_check 函數

        我們可以看到alpha_auth_check函數接收一個參數(是存放在寄存器$s2 里);如果alpha_auth_check返回-1(0xFFFFFFFF),程序將會跳到alpha_httpd_parse_request的結尾處,否則,它將繼續處理請求。

        寄存器$s2 在被alpha_auth_check函數使用前的一些操作代碼顯示,它是一個指向一個數據結構體的指針,里面有一個 char*指針,會指向從 HTTP 請求里接收到的各種數據;比如 HTTP 頭信息和請求地址 URL:

我是如何反編譯D-Link路由器固件程序并發現它的后門的

$s2 是一個指向一個數據結構體的指針

        我們現在可以模擬出alpha_auth_check函數和數據結構體的大概樣子:

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);</pre>

        alpha_auth_check本身是一個非常簡單的函數。它會針對http_request_t結構體里的一些指針進行字符串strcmp比較操作,然后調用check_login函數,實際上就是身份驗證檢查。如果一旦有字符串比較成功或check_login成功,它會返回1;否者,它會重定向瀏覽器到登錄頁,返回-1;

我是如何反編譯D-Link路由器固件程序并發現它的后門的

alpha_auth_check 函數代碼片段

        這些字符串比較過程看起來非常有趣。它們提取請求的 URL 地址(在http_request_t數據結構體的偏移量 0xB8 處),檢查它們是否含有字符串“graphic/” 或 “public/”。這些都是位于路由器的 Web 目錄下的公開子目錄,如果請求地址包含這樣的字符串,這些請求就可以不經身份認證就能執行。

        然而,這最后一個 strcmp 卻是相當的吸引眼球:

我是如何反編譯D-Link路由器固件程序并發現它的后門的

alpha_auth_check 函數中一個非常有趣的字符串比較

        這個操作是將http_request_t結構體中偏移量 0xD0 的字符串指針和字符串“xmlset_roodkcableoj28840ybtide”比較,如果字符匹配,就會跳過check_login函數,alpha_auth_check操作返回1(認證通過)。

        我在谷歌上搜索了一下“xmlset_roodkcableoj28840ybtide”字符串,只發現在一個俄羅斯論壇里提到過它,說這是一個在/bin/webs 里一個“非常有趣”的一行。我非常同意。

        那么,這個神秘的字符串究竟是和什么東西進行比較?如果回顧一下調用路徑,我們會發現http_request_t結構體被傳進了好幾個函數:

我是如何反編譯D-Link路由器固件程序并發現它的后門的

        事實證明,http_request_t結構體中處在偏移量 0xD0 處的指針是由httpd_parse_request函數賦值的:

我是如何反編譯D-Link路由器固件程序并發現它的后門的

檢查 HTTP 頭信息中的 User-Agent 值

我是如何反編譯D-Link路由器固件程序并發現它的后門的

將 http_request_t + 0xD0 指針指向頭信息 User-Agent 字符串

        這代碼實際上就是:

 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函數的結構:

 #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;

}</pre>

        換句話說,如果瀏覽器的 User-Agent 值是“xmlset_roodkcableoj28840ybtide”(不帶引號),你就可以不經任何認證而能訪問 web 控制界面,能夠查看/修改路由器的設置(下面是D-Link 路由器(DI-524UP)的截圖,我沒有 DIR-100 型號的,但 DI-524UP 型號使用的是相同的固件):

我是如何反編譯D-Link路由器固件程序并發現它的后門的

訪問型號 DI-524UP 路由器的主界面

        基于 HTML 頁上的源代碼信息和 Shodan 搜索結果,差不多可以得出這樣的結論:下面的這些型號的D-Link 路由器將會受到影響:

  • DIR-100
  • DI-524
  • DI-524UP
  • DI-604S
  • DI-604UP
  • DI-604+
  • TM-G5240
  • </ul>

            除此之外,幾款 Planex 路由器顯然也是用的同樣的固件程序:

    • BRL-04UR
    • BRL-04CW
    • </ul>

              你很酷呀,D-Link。

              腳注:萬能的網友指出,字符串“xmlset_roodkcableoj28840ybtide”是一個倒 序文,反過來讀就是“editby04882joelbackdoor_teslmx”——edit by 04882joel backdoor _teslmx,這個后門的作者真是位天才!

       本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
       轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
       本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!