Analysis Walkthrough — Fun ClientRun (Part 1)

asuna amawaka
insomniacs
Published in
8 min readFeb 12, 2020

This is my first attempt at writing a walkthrough of my analysis process of a binary file. Let’s get started!

The file I’m analyzing is first mentioned by Ashley Shen from FireEye, in her presentation on IceFog last year (https://speakerdeck.com/ashley920/into-the-fog-the-return-of-icefog-apt). One of the binaries named was “FunRun”, and this caught my attention. Have decided to have a go at analyzing it because I cant find any analysis of this malware family online (unlike the other families mentioned in the same presentation).

MD5 Hash: A0389879EA435E647D29F6966B1D601F

Let’s first take a preliminary look at the file.

Hmm. Ok, I see two typos, but they may or may not mean anything. Could help in finding related files though, we shall see.

Pretty old file, but still does not diminish the value of the learning points from this piece.

Entropy of the file looks pretty normal, a good sign that it is not packed.

Looks like there’s stuff in the resources. I’ll take a closer look at how these come into play in abit.

‘IDR_BINSIGNEXE’ looks like a PE file, with intact MZ header. I shall dump this out for further analysis later.

‘IDR_BINDATA’ does not seem to contain any magic headers. Judging by its size, it did not seem like simply configuration data.

Scrolling down… there seems to be signs that this ‘IDR_BINDATA’ is also another PE file (or a file that contains another embedded PE file named ‘ClientDll.dll’), but without the MZ header. More on this later.

Strings are valuable information in binaries that are not packed and are great for giving clues on what behavioral traits to look out for during next level analysis. There are very interesting strings found within this binary — at this point I’m guessing that I’m going to be looking out for some bat file (like %ssec%08x.bat), as well as some DLL (OUTLLIB.dll) and a TMP file (like DF1F892346495762%02X.TMP). There might be a Rundll process coming up, so I’ll take note of that too.

This set of strings is found beyond the data section of the binary. On closer look, they are in fact found within the embedded file in the resources. Looks like this embedded file might have some network capabilities, and maybe even some anti-vm checks?

What did we gather so far from preliminary analysis

  • 2 embedded files in ‘Resources’

— ‘IDR_BINSIGNEXE’ is definitely a PE file, with MZ header

— ‘IDR_BINDATA’ resembles an executable, first half of the file does not follow clear “PE Structure” while second half contains strings that are typically found in an executable e.g. function names.

  • Original filename of the binary is “ClientRun.exe”
  • Filenames that are potentially involved (either dropped or presence checked) during execution:

— OUTLLIB.DLL

— ~DF1F892346495762%02X.TMP

— %ssec%08x.bat

— ClientDll.dll

Now, I can dive into the binary, using the above findings as guiding pointers. My aim is to find out how the binary works towards its goal.

The ‘WinMain’ function contains two glaring function calls: “SetUnhandledExceptionFilter” and “CreateThread”.

I’m not too certain if “SetUnhandledExceptionFilter” is a commonly seen function in legitimate files, but I’m sure something is fishy when the address for the filter fed to this function points to code that uses the “IDR_BINDATA” in the Resource section.

Following after “CreateThread” is successful, the code proceeds to perform SHA1 hashing on some partially hardcoded value, checks the hash and then followed by a “ShellExecute” if checking fails. If the hash matches an expected value, then some value is copied into memory.

I can broadly break down this binary into 2 analysis parts:

  • new thread
  • exception handler

Let’s take a look at each of these 2 parts.

Within the new thread

Nothing exciting in here, just a layer of “anti-analysis” to detect when the binary is being debugged by detecting changes to the .text section.

Within exception handler (we can find out how an exception is invoked later)

Look for “IDR_BINDATA” in the resource section and copy its entirety into allocated memory.

Then the interesting function comes: sub_401DC6. The algorithm within this function is a XOR-swap (which means, using 3 consecutive XORs to perform swap(S[i],S[j])) implementation of RC4. One of the characteristics of XOR-swap is that when 2 positions containing the same value are “swapped”, the value is zeroed out. Due to this characteristics, it is necessary to write some quick code in python myself since the ARC4 library does not use XOR-swaps.

The key used in the RC4 decryption is derived within the WinMain function (after “CreateThread” is successful) like this:

the part of function that performs derivation of RC4 key
deriving RC4 key
  • a random byte is generated, this value is then divided by 0x32.
  • The binary contains hardcoded 7-bytes 8B 9F 09 F6 31 65 B3
  • SHA1 hash generated on 8 bytes value, made up of 7-bytes hardcoded + 1-byte remainder from division
  • SHA1 hash is expected to match 60 77 0F EC BE 05 2C EF 3F 1F 1B F4 76 37 0D 18 FF F2 EC 23
  • The only value of “remainder” that can generate this SHA1 hash is 0x18 (through some trial and error tests)
  • The first 8 bytes of the SHA1 hash are checked to matched against 60 77 0F EC BE 05 2C EF
  • The first 4 bytes of the fixed 7-bytes 8B 9F 09 F6 is XORed with the next 4 bytes of the SHA1 hash 3F 1F 1B F4, to get B4 80 12 02
  • The next 4 bytes of the fixed 7-bytes + 1-byte remainder 31 65 B3 18 is XORed with the next 4 bytes of the SHA1 hash 76 37 0D 18, to get 47 52 BE 00
  • If all of the above are correct (stemming from getting the correct remainder value), the RC4 key is thus B4 80 12 02 47 52 BE 00

Applying this key with XOR-swap RC4 on the contents of “IDR_BINDATA” would give us an intact PE file with MZ header:

decrypted IDR_BINDATA

I think the sole reason for this complex key “hiding” process is to make researchers’s life harder than it already is. But hey, this ain’t that difficult to reverse.

Interestingly, after this key is “retrieved” and put in place, the exception is created with a direct “int 3” opcode — and this triggers the exception handler to run!

Let’s get back to the exception handler to see what happens now.

After “IDR_BINDATA” is decrypted in memory, the binary proceeds to check for a byte value at offset 0x138D0. Depending on the value, the binary branches to do different things. It looks like the binary is looking for three particular values — 0x1, 0x2 and 0x4. Let’s call this value “marker”.

If marker is 0x2:

— Search for 8byte pattern “27 AA 5C BC 56 8C 1C DA” within decrypted IDR_BINDATA in memory, replace at found position with “nwsapagent”. This is required as a parameter to “RunInstall” during execution.

— Create %appdata%\Microsoft\Service\nwsapagent.dll and write modified decrypted IDR_BINDATA contents into file.

— Create new process to install service: %system%\cmd.exe /c Rundll32.exe “%appdata%\Microsoft\Service\nwsapagent.dll”,RunInstall nwsapagent

— Create %temp%\sec<8 char hex number>.bat and write the following contents into it:

@echo off
net start nwsapagent
del “%temp%\\sec<8 char hex number>.bat” /Q

— Execute the bat file. Even if execution failed, the bat file will be deleted.

If marker is 0x4:

— Read resource IDR_BINSIGNEXE and write contents into %appdata%\Microsoft\OutLook\OUTLOOK.exe

— Decrypted IDR_BINDATA is written into %appdata%\Microsoft\OutLook\OUTLLIB.dll

— Execute OUTLOOK.exe

This manner of execution would use “Search Order Hijacking” technique to execute OUTLLIB.dll.

If marker is 0x1:

— Decrypted IDR_BINDATA is written into %temp%\~DF1F892346495762<random 2 char hex number>.TMP

— The file is directly loaded in the current process with LoadLibraryA, and then “CheckUpdate” is directly executed by calling its address (retrieved with GetProcAddress)

If marker is none of the above:

— Create %temp%\sec<8 char hex number>.bat and write the following contents into it:

@echo off
:start
if not exist
goto done
del <path to exe of curr process> /Q
goto start
:done
del “%temp%\\sec<8 char hex number>.bat” /Q

— Execute the bat file. Even if execution failed, the bat file will be deleted.

This means that if the marker is not of expected values, the original binary will be deleted and no other actions will be triggered.

In our particular binary, the marker is hardcoded as 0x4 so it looks like the OUTLOOK.exe path will be taken.

We confirmed the following observations made preliminary analysis

  • 2 embedded files in ‘Resources’

— ‘IDR_BINSIGNEXE’ is definitely a PE file, with MZ header

This file is in fact the legitimate OUTLOOK.exe from Microsoft, and its role is simply to launch Search Order Hijacking to execute the real payload OUTLLIB.dll.

— ‘IDR_BINDATA’ resembles an executable, first half of the file does not follow clear “PE Structure” while second half contains strings that are typically found in an executable e.g. function names.

Yup, turns out the file is XOR-swapped RC4 encrypted. Also found the key to decrypt it on the side with python, did not even need to dig it out from memory!

  • Filenames that are potentially involved (either dropped or presence checked) during execution:

— OUTLLIB.DLL

This is the name of the dropped file on disk, if the marker value is 0x4.

— ~DF1F892346495762%02X.TMP

This is the formatted name of the dropped file on disk, if the marker value is 0x1.

— %ssec%08x.bat

This is the formatted name of the bat file used to start the service to execute the dropped file if the marker is 0x2, or to clean up the binary if marker is not 0x1, 0x2 or 0x4.

— ClientDll.dll

This is the exported library name of the dropped file

That’s all there is to the binary. Looks like a simple drop-and-execute-payload, and even comes with 3 methods to drop its payload.

In the next part, we shall take a look at the payload!

~~

Drop me a DM if you would like to share findings or samples ;)

--

--