Lazarus obfuscation in Feb 2019
Starting off, I’d like to give a shot-out to Brian Bartholomew (Twitter: @Mao_Ware) for his general awesomeness and for his post on 30 January from which this research starts.
Using this as a base for the following Yara rule, I found a similar sample (SHA256: 625f63364312cec78a4c91abedba868d551d79185ff73e388f561017b13347f0
) also packed with UPX.
1 | rule LazarusDocJan2019_01 |
As with the sample Brian identified, the control server is not obfuscated in the binary:
Sandboxing of the sample, confirms the malware beacons to this URL:
1 | GET /intro/info/info.asp?id=dn678 HTTP/1.1. |
In IDA, we can see the malware uses the standard LoadLibrary
/ GetProcessAddress
method for dynamically loading some key function calls. Shown below, the encoded string y8zS2vHp8PLx//rK8dj38vvf
is base64 decoded and XORed by 0x9E
, resulting in the string URLDownloadToFileA
that is passed to GetProcAddress
.
The data returned by the control server is decoded using the same method as the URLDownloadToFileA
(shown below).
The decoded contents are written to disk for execution, unless the response starts with sleep
, which will cause the sample to pause for 60000ms
, before retrying the request.
Sandboxing also showed the sample made several other HTTP calls to the same URL with the parameter string search=2tjbpK6urq6urq6u.
1 | GET /intro/info/info.asp?search=2tjbpK6urq6urq6u HTTP/1.1. |
In IDA, we can see that the ?search=
is concatenated to end of the URL along with a value that is XOR-encoded using a key of 0x9E and then base64 encoded, shown below.
Knowing the obfuscation is trivial, in a few lines of Python — the value being sent was DFE:00000000
1 | Python 2.7.15rc1 (default, Nov 12 2018, 14:31:15) |
However, outside of the novel ability to decode something arbitrarily encode, this doesn’t provide any insight about functionality or purpose. Turning back to IDA, we can see the string DFE:%08x is a format string that takes an unsigned int. Looking at where this string is defined, we can see there are several similar strings.
1 | .rdata:00417644 aIdDn678 db '?id=dn678' |
For each of these, the associated derived from GetLastError()
(shown below).
Running through the rest of the file, the strings correlate as follows - https://gist.githubusercontent.com/silascutler/4245513e2dc1a7a9fc3d73346dd0cd12/raw/17d5bea8f80e73ca84a4ca0f36f19209c271f267/strfmt.csv
(Post migrated from Medium - https://medium.com/emptyregisters/lazarus-downloader-brief-analy-17875f342d96 )