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.
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:
GET /intro/info/info.asp?id=dn678 HTTP/1.1.
In IDA, we can see the malware uses the standard
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
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.
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
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.
.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 )