[Repost] Reverse Engineering a D-Link Backdoor

All right. It’s Saturday night, I have no date, a two-liter bottle of Shasta and my all-Rush mix-tape…let’s hack.

On a whim I downloaded firmware v1.13 for the DIR-100 revA. Binwalk quickly found and extracted a SquashFS file system, and soon I had the firmware’s web server (/bin/webs) loaded into IDA:

Strings inside /bin/webs

Strings inside /bin/webs

Based on the above strings listing, the /bin/webs binary is a modified version of thttpd which provides the administrative interface for the router. It appears to have been modified by Alphanetworks (a spin-off of D-Link). They were even thoughtful enough to prepend many of their custom function names with the string “alpha”:

Alphanetworks' custom functions

Alphanetworks’ custom functions

The alpha_auth_check function sounds interesting!

This function is called from a couple different locations, most notably from alpha_httpd_parse_request:

Function call to alpha_auth_check

Function call to alpha_auth_check

We can see that alpha_auth_check is passed one argument (whatever is stored in register $s2); if alpha_auth_check returns -1 (0xFFFFFFFF), the code jumps to the end of alpha_httpd_parse_request, otherwise it continues processing the request.

Some further examination of the use of register $s2 prior to the alpha_auth_check call indicates that it is a pointer to a data structure which contains char* pointers to various pieces of the received HTTP request, such as HTTP headers and the requested URL:

$s2 is a pointer to a data structure

$s2 is a pointer to a data structure

We can now define a function prototype for alpha_auth_check and begin to enumerate elements of the data structure:

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 itself is a fairly simple function. It does a few strstr’s and strcmp’s against some pointers in the http_request_t structure, then callscheck_login, which actually does the authentication check. If the calls to any of the strstr’s / strcmp’s or check_login succeed, it returns 1; else, it redirects the browser to the login page and returns -1:

alpha_auth_check code snippet

alpha_auth_check code snippet

Those strstr’s look interesting. They take the requested URL (at offset 0xB8 into the http_request_t data structure, as previously noted) and check to see if it contains the strings “graphic/” or “public/”. These are sub-directories under the device’s web directory, and if the requested URL contains one of those strings, then the request is allowed without authentication.

It is the final strcmp however, which proves a bit more compelling:

An interesting string comparison in alpha_auth_check

An interesting string comparison in alpha_auth_check

This is performing a strcmp between the string pointer at offset 0xD0 inside the http_request_t structure and the string “xmlset_roodkcableoj28840ybtide”; if the strings match, the check_login function call is skipped and alpha_auth_check returns 1 (authentication OK).

A quick Google for the “xmlset_roodkcableoj28840ybtide” string turns up only a single Russian forum post from a few years ago, which notes that this is an “interesting line” inside the /bin/webs binary. I’d have to agree.

So what is this mystery string getting compared against? If we look back in the call tree, we see that the http_request_t structure pointer is passed around by a few functions:


It turns out that the pointer at offset 0xD0 in the http_request_t structure is populated by the httpd_parse_request function:

Checks for the User-Agent HTTP header

Checks for the User-Agent HTTP header

Populates http_request_t + 0xD0 with a pointer to the User-Agent header string

Populates http_request_t + 0xD0 with a pointer to the User-Agent header string

This code is effectively:

if(strstr(header, "User-Agent:") != NULL)
    http_request_t->0xD0 = header + strlen("User-Agent:") + strspn(header, " \t");

Knowing that offset 0xD0 in http_request_t contains a pointer to the User-Agent header, we can now re-construct the alpha_auth_check function:

#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;
        // These arguments are probably user/pass or session info
        if(check_login(request->0xC, request->0xE0) != 0)
            return AUTH_OK;

    return AUTH_FAIL;

In other words, if your browser’s user agent string is “xmlset_roodkcableoj28840ybtide” (no quotes), you can access the web interface without any authentication and view/change the device settings (a DI-524UP is shown, as I don’t have a DIR-100 and the DI-524UP uses the same firmware):

Accessing the admin page of a DI-524UP

Accessing the admin page of a DI-524UP

Based on the source code of the HTML pages and some Shodan search results, it can be reasonably concluded that the following D-Link devices are likely affected:

  • DIR-100
  • DIR-120
  • DI-624S
  • DI-524UP
  • DI-604S
  • DI-604UP
  • DI-604+
  • TM-G5240

Additionally, several Planex routers also appear to use the same firmware:

  • BRL-04R
  • BRL-04UR
  • BRL-04CW

You stay classy, D-Link.


Source: http://www.devttys0.com/2013/10/reverse-engineering-a-d-link-backdoor/

Chinese Translation: http://blog.xieyc.com/reverse-engineering-a-d-link-backdoor/


  1. However, the paperwork and regulations that govern organic
    food production may be too burdensome in the beginning for
    a new business idea in a rural area. Indian shoppers are getting smart by the day, and they want to enjoy everything like their
    western counterparts. One other factor is that when choosing frozen vegetables take care to ensure that the ingredients
    lists only the vegetable itself.

    • Dragon says:

      Your website has to be the eltnorecic Swiss army knife for this topic.

      • Reggie says:

        Horrible picture. Blhar!Geect post though. I love how you always tie everything together. You have great examples that are fresh and not over-done, as you sometimes hear in youth services or youth convetions.

    • aaa Tai jei metro pakeite starta tai kokio velnio ji pirma atidaro ijungus pc? Tai kam tada is vis reikalingas desktop’as jei metro zymiai patogesnis?

    • Great post and just for the record concerning my recent post, I love to laugh and look for any reason to do so. Kids always are good for that because they are able to see the fun in daily life more than we adults tend to.

    • maxpark.com says:

      Ah! I know the perfect person to give this to.I kind of like October. It is still sunny and beautiful (if you catch it on a proper year) but the leaves are all lovely red and you can start wearing sweaters again.

    • Sort –Gates of Vienna’s rules about comments require that they be civil, temperate, on-topic, and show decorum. Your gratuitous insult violated the first of these rules.

    • http://www./ says:

      Thank you for any other informative blog. Where else may I am getting that type of information written in such a perfect manner? I’ve a undertaking that I’m just now working on, and I have been on the look out for such info.

    • http://www./ says:

      I’ve been hearing about the Yakezie group. i think they are the most fast growing. Surely i will get to join the race..-= innocent´s last blog ..How Social Media Sites Make Money Online =-.

  2. filmy online says:

    Hello There. I found your blog the use of msn.

    That is a really neatly written article. I will make sure to bookmark it and return to read extra of your useful information.
    Thank you for the post. I will definitely return.

Leave a Reply

Your email address will not be published. Required fields are marked *

:wink: :-| :-x :twisted: :) 8-O :( :roll: :-P :oops: :-o :mrgreen: :lol: :idea: :-D :evil: :cry: 8) :arrow: :-? :?: :!: