Home > Uncategorized > Fingerprinting the author of the ZeuS Botnet

Fingerprinting the author of the ZeuS Botnet

May 11, 2011

The source code of the ZeuS Botnet is now available for download. I imagine there are a few organizations who would like to talk to the author(s) of this code.

All developers have coding habits, that is they usually have a particular way of writing each coding construct. Different developers have different sets of habits and sometimes individual developers have a way of writing some language construct that is rarely used by other developers. Are developer habits sufficiently unique that they can be used to identify individuals from their code? I don’t have enough data to answer that question. Reading through the C++ source of ZeuS I spotted a few unusual usage patterns (I don’t know enough about common usage patterns in PHP to say much about this source) which readers might like to look for in code they encounter, perhaps putting name to the author of this code.

The source is written in C++ (32.5 KLOC of client source) and PHP (7.5KLOC of server source) and is of high quality (the C++ code could do with more comments, say to the level given in the PHP code), many companies could increase the quality of their code by following the coding standard that this author seems to be following. The source is well laid out and there are plenty of meaningful variable names.

So what can we tell about the person(s) who wrote this code?

  • There is one author; this is based on consistent usage patterns and nothing jumping out at me as being sufficiently different that it could be written by somebody else,
  • The author is fluent in English; based on the fact that I did not spot any identifiers spelled using unusual word combinations that often occur when a developer has a poor grasp of English. Update 16-May: skier.su spotted four instances of the debug message “Request sended.” which suggests the author is not as fluent as I first thought.
  • The usage that jumped out at me the most is:
    for(;; p++)if(*p == '\\' || *p == '/' || *p == 0)
      {
    ...

    This is taking to an extreme the idea that if a ‘control header’ has a single statement associated with it, then they both appear on the same line; this usage commonly occurs with if-statements and this for/while-statement usage is very rare (this usage also occurs in the PHP code),

  • The usage of true/false in conditionals is similar to that of newbie developers, for instance writing:
    return CWA(kernel32, RemoveDirectoryW)(path) == FALSE ? false : true;
    // and
    return CWA(shlwapi, PathCombineW)(dest, dir, p) == NULL ? false : true;
    // also
    return CWA(kernel32, DeleteFileW)(file) ? true : false;

    in a function returning bool instead of:

    return CWA(kernel32, RemoveDirectoryW)(path);
    //and
    return CWA(shlwapi, PathCombineW)(dest, dir, p) != NULL
    // and
    return CWA(kernel32, DeleteFileW)(file);

    The author is not a newbie developer, perhaps sometime in the past they were badly bitten by a Microsoft C++ compiler bug, found that this usage worked around the problem and have used it ever since,

  • The author vertically aligns the assignment operator in statement sequences but not in a sequence of definitions containing an initializer:
    // = not vertically aligned here
        DWORD itemMask = curItem->flags & ITEMF_IS_MASK;
        ITEM *cloneOfItem = curItem;
    // but is vertically aligned here:
        desiredAccess       |= GENERIC_WRITE;
        creationDisposition  = OPEN_ALWAYS;

    Vertical alignment is not common and I would have said that alignment was more often seen in definitions than statements, the reverse of what is seen in this code,

  • Non-terminating loops are created using for(;;) rather than the more commonly seen while(TRUE),
  • The author is happy to use goto to jump to the end of a function, not a rare habit but lots of developers have been taught that such usage is bad practice (I would say it depends, but that discussion belongs in another post),
  • Unnecessary casts often appear on negative constants (unnecessary in the sense that the compiler is required to implicitly do the conversion). This could be another instance of a previous Microsoft compiler bug causing a developer to adopt a coding habit to work around the problem.

Could the source have been processed by an code formatter to remove fingerprint information? I think not. There are small inconsistencies in layout here and there that suggest human error, also automatic layout tends to have a ‘template’ look to it that this code does not have.

Update 16 May: One source file stands out as being the only one that does not make extensive use of camelCase and a quick search finds that it is derived from the ucl compression library.

  1. Sertys
    May 16, 2011 09:25 | #1

    Such code fingerprinting is very, very unclear. It points to nothing more than an off-the-charts wild guess. People don’t grow their coding habbits from scratch, but instead follow tutorials/lectures/howto and build-up logic based on that.

  2. May 16, 2011 15:04 | #2

    @Sertys Measurements of source code show that every language construct has a common usage pattern; a collection of uncommon code usage patterns may not be as unique as a fingerprint but it is certainly enough to narrow down the likely set of suspects (the place to look is existing source, the author did not suddenly start writing code and previously written source cannot be obfuscated once it is released).

    Everybody grows their coding habits from scratch and the growth process is usually very ad-hoc. People acquire a small set of techniques that work for them and rarely spend much time learning anything new. Developers quickly learn that spending time solving application problems is much more productive than learning new coding techniques. Some companies do audit the code written by their employees, but I doubt the author of the Zeus Botnet works in that kind of environment.

  3. May 17, 2011 13:38 | #3

    Have you seen usage of leetspeak in comments or names?

    I’m asking because I noticed the .suo file contains references to C:Usersjam3sDesktopZeus

Comments are closed.