OALabs / hashdb-ghidra

Ghidra plugin for HashDB
BSD 3-Clause "New" or "Revised" License
19 stars 2 forks source link

hashdb-ghidra

This is a Ghidra plugin for HashDB. It allows you to compile a list of API hashes and then to query the HashDB web service for possible matching strings. It collects these associations into an enum or a struct. From there on, you are on your own.

Installation

Two options:

  1. Copy HashDB.java to your ghidra_script directory.
  2. Add the location where HashDB.java is located to your script directory search path in Ghidra's ScriptManager.

We recommend to bind the HashDB.java script's execution to a hotkey, preferably F3.

Usage

The plugin consists of a single window containing a table showing the "currently collected" hashes. You can bring up the window by executing the script (i.e. hitting F3). In addition to opening the window (or showing it, if it was hidden) the script will do different things depending on where your cursor is:

The GUI is actually perfect and completely intuitive to use with a great UX. But since we are also amazing at documentation, we include the following guidance:

Example Workflow: Netwalker

Consider the sample with the following SHA256 hash

de04d2402154f676f757cf1380671f396f3fc9f7dbb683d9461edd2718c4e09d

and navigate to the function at 0x00401360. The code will look like the following:

iVar1 = FUN_00401220(0x84c05e40);
if (iVar1 != 0) {
  pcVar2 = (code *)FUN_00401000(iVar1,-0x5e2ba68c);
  if (pcVar2 != (code *)0x0) {
    uVar6 = 0x254;
    uVar5 = 8;
    uVar3 = FUN_00406a40();
    DAT_00417194 = (int *)(*pcVar2)(uVar3,uVar5,uVar6);
    if (DAT_00417194 != (int *)0x0) {
      iVar4 = FUN_00401000(iVar1,-0x5e2ba68c);
      *DAT_00417194 = iVar4;
      iVar4 = FUN_00401000(iVar1,-0x50ee43dc);
      DAT_00417194[1] = iVar4;
      iVar4 = FUN_00401000(iVar1,-0x468c4724);
      DAT_00417194[2] = iVar4;
      iVar4 = FUN_00401000(iVar1,-0x7b9c69f6);
/* ... */

You can either click on 0x84C05E40, hit F3; click on -0x5E2BA68C, hit F3, and so on and so forth, until you are ready to "Query!". Alternatively you can double click FUN_00401000 and then hit F3 to bring up the scan function tab. Confirm that the pre-populated value in the "Parameter" field is correct, hit "Scan" and grab a cold cup of water.

Example Workflow: REvil

Consider the sample with the following SHA256 hash

5f56d5748940e4039053f85978074bde16d64bd5ba97f6f0026ba8172cb29e93

and navigate to the memory region 0x004113F8 and convert it to an array of 140 DWORDs and hit F3. This memory region contains all API hashes. Our goal is to create a struct that has the corresponding API function pointers in the exact same location. This way, changing the type of this global constant to the struct will make the code all pretty.

REvil's API hashing requires that you figure out a transformation that it applies to the hash. For this sample, the transformation is the following:

((((X ^ 0x76C7) << 0x10) ^ X) ^ 0xAFB9) & 0x1FFFFF /*REvil*/

It will be different for other REvil samples. Make sure to select "Generate Struct" in the "Output" tab and "Query!". When it is done, change the type of 0x004113F8 to HashDB. Happy times.

Contributors

Contact us on Twitter

or join the OALabs Discord oalabs-dev channel.