I spent the morning sorting through samples from all the GRAB honeypots, and settled on a sample that happened to come in via the NYC honeypot. 50/53 detection ratio on VirusTotal, so let’s look into it in more depth.
Static Analysis
Running strings on the sample reveals only four strings that make any sense at all:
MZKERNEL32.DLL
LoadLibraryA
GetProcAddress
FILE
Looks packed to me, but not UPX like the last sample. PEiD identifies the packer as Upack 0.39 beta. I opened the file in PE Explorer and that automatically unpacked the malware (revealing many more strings than before), but I am going to take a shot at manually unpacking it anyway.
Upack is trickier than UPX, in my opinion. Opening the packed sample doesn’t show a clear jump to OEP, so I opened it in Olly and went to where the code for LoadLibraryA is found by pressing ctrl-G and then going to kernel32.LoadLibraryA, then set a breakpoint on the first instruction:
I watch the malware call LoadLibraryA seven times, ending with Mpr.dll, and then hitting run again causes it to run and not hit the breakpoint again. Restoring the VM snapshot, I go back to where Mpr.dll was called and then set another breakpoint on GetProcAddress, and then run through that five times until it appears that GetUserNameEx is the final function called with GetProcAddress before the rest of the program runs and the second breakpoint is no longer hit.
Stepping through the rest of that particular call to GetProcAddress and returning to the rest of the code, I’m ready to start stepping through the remains of the unpacking stub to get to the actual code entry point:
After following a few branches, I see what I believe to be the entry point:
This doesn’t look too typical for me in terms of address and code, but mainly what I was looking at here was a relatively long block of code compared with the branches I just looked at, plus starting at 756AA4E9 you can see what looks like it could be the start of a function with PUSH EBP | MOV EBP, ESP. Trying to dump that as an OEP didn’t really work – I did get something that I could disassemble and also do other analysis on, but this doesn’t seem to be the right place. Using OllyDump and its feature “Find OEP by Section Hop (Trace Over)” got me to this general area which looks much more promising:
Checking this against the automatically unpacked file, this is the entry point area. What’s sort of strange is that whether I dump this process from the other address above (756AA4E9) or the one right here (4023A0), I end up with basically the same dumped file and OllyDump can’t do anything with the import table. ImpRec doesn’t work either, and either way I’m left with something that doesn’t function but nevertheless offers a lot of interesting data statically or in disassembly. Since I was successful with the automated tool, I’m going to move on to static analysis of the unpacked sample that I obtained with PE Explorer.
Going through the meaningful strings from the unpacked malware, we now see a more normal set of sections:
.code
.data
.idata
.rsrc
I don’t typically see a .code section, but this must be the equivalent of the .text section containing the sample’s code. I also don’t usually see .idata, but this should have the import function info which I’m more accustomed to finding in the .rdata section. I’m guessing that something is contained in .rsrc, but we’ll get to that later.
I see some function names, and date/time strings, but then I see a very long list of three digit numbers (here’s just an excerpt):
130
131
132
133
134
137
139
140
143
144
210
200
201
202
203
210
211
218
I wonder if this is being used in some fashion to “construct” IP addresses. I notice that some of the “special” numbers like 239 and 255 are not included in this list, though if this is what it’s being used for, one would think you’d see numbers below 130 also. These could also be ports.
Below this, I see some interesting strings that remind me of some of the stuff revealed in my analysis of Pepex:
gmail-smtp-in.l.google.com
john@barrysworld.com
google.com
wbInfo0801@gmail.com
whInfo0802@gmail.com
That SMTP server is an exact string from the Pepex sample I took apart previously. Those other addresses could make for some interesting signatures once we get to that point. After this, we see many strings of inexcusably horrendous passwords (crap like 1234, angel, password, passwd, BUMBLE, asdf, asdfgh, 4321, db2admin, and so on).
I see what looks like the framework for constructing an IP address dynamically:
%d.%d.%d.%d|
Below that, something very interesting:
QUIT
Subject: Hello
From: <
From: “Microsoft” <information@microsoft.com>
Reply-To: “Microsoft” <microsoft@microsoft.com>
john@barrysworld.com
DATA
RCPT TO:<
MAIL FROM:<
HELO <
209.85.133.114
WUpdate
Windows Genuine Update
Windows Update
SOFTWARE\Microsoft\Windows\CurrentVersion\Run
-i
\lsasvc.exe
This looks EXACTLY like some of the info pulled from Pepex. We see the same email addresses in use as in that other sample. The 209.85.133.114 IP address points to Google. I’m starting to think that this is a Pepex variant, if it wasn’t already pretty clear. Strangely, the antivirus products weren’t too consistent in naming this sample when scanned, though I recall that one of them did identify it as Pepex. I wonder if that lsascv.exe file is what the sample uses to install itself and achieve some stealth, and the Windows Genuine Update string points to additional stealth / persistence methods.
Further on, we see:
c:\winnt\lsass.exe
c:\windows\lsass.exe
%s\c$\winnt\lsass.exe
%s\c$\windows\lsass.exe
Subject: %s|%s|%s
Again, something to keep in mind. This might do something with lsass because of lsass’ privilege levels and API access. Finally, that Subject: %s|%s|%s is the same string we saw in the other Pepex sample for constructing the spam subject line.
We see a bunch of OS names:
WinXp
Win2003
Unkown [sic]
WinVista
WinNt
Win2000
I find it interesting that this is the same list as in the other Pepex sample, however Win7 is not here (which I wouldn’t expect from a sample created in 2004). Perhaps the reason why we had so many problems with the other sample was because someone tried updating the code and screwed up.
I see many imported function names, but I’ll look at those when I view the file in PEview, as it’s an easier interface. One final and very interesting set of strings:
!This program cannot be run in DOS mode.
Rich
S^@
.petite
ERROR!
Corrupt Data!
Looks like we have another file inside. I’m not sure what a .petite section is but it’s not a normal section like .text, .rsrc, .rdata, or others. Some weird error messages follow, so perhaps this is a packed file within the previously packed malware. After that I see a handful of process names and library imports, so I think we’ll need to continue digging to get to the bottom of this.
PEiD doesn’t detect and packers, under any settings. KANAL, however, detects a zlib deflate reference at 0000BE74 / 0040D474. Resource Hacker shows an obvious file stored in the resource section that is named “FILE”:
This file, however, is packed, using Petite 2.x:
KANAL also sees a reference to zlib in this file from the .rsrc section. Depending on how it goes analyzing this malware, I may look at this file in a follow-on analysis. Also, please see the following note from the readme file inclued with the current version of Petite, which is another reason why I’m probably going to tackle this in a subsequent analysis:
Decompression?
==============
There is no Petite decompressor. So if it is not possible for you to
reinstall or recompile a file, then you should keep a backup of the
original incase[sic] you should want to go back to it at any time.
Opening the main malware file in PEview doesn’t reveal anything weird as far as some possible anti-debugging stuff – number of data directories is 0x10 and no TLS table. Imported libraries are Kernel32, User32, AdvApi32, and WS2_32. Here are some of the interesting things that can be seen as imported functions under each library:
AdvApi32
RegOpen/CloseKeyExA, RegSetValueExA, Create/Open/Start/DeleteServiceA: Based on these imports and the prior work done on the other Pepex variant, I’m guessing that this is used to both achieve persistence and also start the malware as a service.
Kernel32
CopyFileA, WriteFile: I see a call to CopyFileA but not to DeleteFileA, so maybe this file makes a copy of itself and then deletes itself some other way when it installs. This also could mean that this file relocates some system file so that it can put itself in between the user and the legitimate file (maybe it gets in between lsass.exe, for instance). I suppose that one clue that this is not the case is that I don’t see any exports, but we still don’t know how the file from the .rsrc section functions yet. WriteFile is always good for looking for file system signatures.
WaitForSingleObject: perhaps this malware creates a mutex.
CreateProcessA: Always good for signatures, and also this means we’ll need to look out for child processes of this main malware process. Could possibly also be used to load drivers.
WS2_32
The interesting thing here is that I’m only seeing client-side functions imported (socket, connect, send, recv) but not server-side functions (like bind, listen, accept).
Dynamic Analysis
For the dynamic analysis, I ran and recorded the packed malware two times – once as a regular user, and once as an administrator.
Watching the run as a regular used showed a ton of activity taking place in Wireshark. RegShot didn’t reveal much going on. There was a UserAssist value added under HKU, but other than that, no other changes in the registry or file system that could be linked to the malware (speaking strictly from the RegShot perspective). Process Explorer revealed only the single malware process being created (PID 2576) but nothing else. It could be we missed other stuff happening in Process Explorer, so we’ll look at Process Monitor and other places too. I’m not seeing anything in Autoruns, so perhaps persistence wasn’t achieved.
Looking in Process Monitor, I see that the malware did not appear to spawn any child processes. The main things observed, some of which match up with the static analysis, include:
– reads the current version of Windows through HKLM
– many registry keys related to networking are queried
– the malware gets the computer name from the registry
– the malware creates 256 threads, and this is the final set of actions recorded by Process Monitor
I’m not seeing any files being written, or any registry entries being added or modified (values or keys). The Wireshark traffic is more interesting. In only a few minutes I could see a few tens of thousands of packets being sent out to apparently random IP addresses. Take a look at the protocols:
Basically all TCP. I didn’t see any addresses resolved, however endpoints revealed something interesting:
Thousands and thousands of lines of traffic on port 445, which is associated with SMB (which is where this sample came from on the honeypot, by the way). Looking over on the UDP tab of this window:
We see traffic on some broadcast IP addresses and on ports 137 and 138 which, for UDP, are associated with SMB also (NetBios API). There’s also traffic on port 1900, which is the UPnP port that we saw a lot of action on in the honeypot statistics.
Reviewing the recorded malware activity that was run as an administrator didn’t reveal any new or different behavior. The same activity both on the host and the network was observed.
I didn’t see any activity on the IP address we found in the strings of the malware (209.85.133.114). I dumped the traffic from Wireshark and then ended up with 39,203 unique IP addresses from that. I did a little research into where these IP addresses were located, and with whatever whois data I was able to obtain, the vast majority of the IP addresses are in the USA with some falling outside the country:
Disassembly and Debugging
Opening the unpacked malware in Ida, the first thing we see the sample do (in winmain) is call WSAstartup, and then then there is a call to a sub at 4020E0 which imports some DLLs. The DLL names are obfuscated, and 4020E0 builds the imports in the same manner as the other Pepex variant. Following some branches, which I’m finding difficult to figure out just using Ida, we either move towards a “scanning” branch (which is the behavior that I’ve observed so far) or towards the installation branch. The installation branch begins with a call to 401950, which starts with loading the binary that is in the .rsrc section and then writing it as %SYSTEM%\lsasvc.exe, which makes for a nice file system signature:
Then, later on in this sub, we see the file being written and then a process being created from it.
The next sub that is called, 4018E0, sets up persistence for the newly installed malware by adding it to the registry (under the name “Windows Update”) to run at startup:
This also makes for a nice host signature under “SOFTWARE\Microsoft\Windows\CurrentVersion\Run”.
Sub 401000 involves some calls to gethostbyname and then a loop that writes a series of IP address strings to a buffer. After this, we see a string being put in a buffer:
Then we see a call to GetVersion and then the system derives an OS name (one of the strings mentioned earlier such as “WinVista”) and this string is passed to the buffer also:
Following this, we see an email address being pushed onto the stack and then we get into some really interesting stuff beginning with a call to 401210:
Before getting into 401210, I’m going to take a quick look at the alternate branch that this sample seemed to follow when I ran it in my test environment. This is the branch that was taken at the conditional jump at 40243F which branched us away from the installation/system inventory/email generation branch and instead did the IP scanning and thread creation.
Going down this alternate branch results in a call to Sleep (for 100ms) and then an indirect call to sub 402C50. This is a somewhat large sub that generates IP addresses through a combination of calls to GetTickCount and generated random numbers. There is a loop related to thread creation, and we can see where the condition jump is put in place in order to create the 256 threads we observed during the dynamic analysis:
Note that I displayed the number in base 10 for clarity.
Also within this overall thread creation/scanning sub, there is a call to a fairly deep branch called sub 402840. This sub begins with establishing some network connectivity and then calls another sub, 401F20. This sub contains several indirect calls (annoying). I see something being done with the string “administrator” so it’s possible that this is some sub that either logs into an account somewhere (or tries to do so). We do see a call to sub 401AE0, though. This sub makes a reference to IPC, and then appears to send system inventory information to the wbInfo0801@gmail.com address:
Then after that we can see stuff being done with lsass.exe (notice also the hard coded directory of \winnt\ rather than an environment variable). Here are another couple of examples of hard-coded directory references:
After setting up with these paths, we see a call to 401800. Here we see the malware being set up and started as a service:
“Windows Genuine Update” and “Wupdate” are nice signatures to be aware of.
Going back to the large branch, where we really get into the heart of this thing, sub 401210 begins with a connection to 209.85.133.114 and then a check of connectivity. If we get past that, then the malware starts to build a set of SMTP commands:
This gets sent, and then checked for errors again:
If at any time we have an error, the sub will exit. Next we see more SMTP commands being built, this one showing that this mail is from john@barrysworld.com:
Continuing through the code, we see where the recipient email address is passed via SMTP, and then we see where the malware starts to build out the area for the body of the email:
After this, we get to an area that I’m not sure I fully understand:
What it looks like is happening here, is that the string “john@barrysworld.com” is pushed onto the stack twice, and then these two strings are compared with a call to strcmpi (which is deprecated according to MSDN). Then, there is a conditional jump based on this comparison – If the strings are the same, then the function should return 0 and therefore this conditional jump should always be followed in this instance, which would take us down the branch on the left. If anyone out there has a better understanding of what is going on here, please let me know, as it appears that we have a situation where there’s a condition jump that is never followed. In any case, on the left branch, we see some more signatures that were common with the other Pepex variant analyzed (microsoft@microsoft.com, information@microsoft.com).
At the end, we see the wrap up of the SMTP traffic and the return:
At this point, I’m done looking at this sample. As we’ve seen, it’s closely related to a prior sample, except that this one actually seems to work so we were able to observe more functionality. I might take a look into manually unpacking the file in the resource section since this is a packer that is new to me and this might make for an interesting analysis.
Findings and observations:
Mass-mailer worm. Similar to the prior sample analyzed, which I believe was derived from this new sample as this sample did not appear to have the execution issues observed previously. Sample appears to both scan new IP addresses, both for remote and local systems, probably with the intent of spreadnig itself. It also contains functionality around reporting system inventory and sending spam messages.
Recommendations:
– Block ports 445, 137, and 138 as this is where this sample was obtained and this sample was observed connecting to remote and local systems on these ports
– Usual recommendations against opening unsolicited mail (especially with attachments)
– Filter email associated with “microsoft@microsoft.com”, “information@microsoft.com”, and “john@barrysworld.com”, “ wbInfo0801@gmail.com”, “wbInfo0802@gmail.com”
Conclusion:
Interesting, old malware. It was good to see this worm running successfully so as to get a better opportunity to view its capabilities.
Report:MalEXE003pdf
Hashes:
Packed:
MD5:7867de13bf22a7f3e3559044053e33e7
SHA1:42e56d72982ac04edba2ce7fb9f4e5048766aa94
SHA256:a29d02251f54567edb1d32f7c17ce4c04d5c54e317eb3b2bea2a068da728e59a
ssdeep:768:WOjL5WyEf531YmKtiZSI1ZOt13hHJ6kekGyQSmOY:WOjsyEfIm0i3ZOt1RWkGyFW
Manually Unpacked:
MD5:30891d0c95aed62d3cbf7a54239eaf17
SHA1:b3d456d0cd871b1ff5f19cd3196ebe4df064f922
SHA256:50f3cd50216c6a4515977f46a737466bb3cc3a3cdf3add771e1e8c138dea91e4
ssdeep:1536:oNx2Tahizzme4WPsyqFg8NIRdcBCaiOjsyEfIm0i3ZOt1RWkGyF3XFuTx+WN:8DYzzNhPJgI3iCaIH0i3ZOt1RWRNB
Automatically Unpacked:
MD5:c6829041ed0a3b1ee41b8aad7e1884b1
SHA1:440c45dff7f43ac6478c44a1c776e643320a8a35
SHA256:6c31f261514aa5d4b9e0098d7362dd8357a71ca9de5d3df984d4dfd80c75690c
ssdeep:768:8HcGaNhoWx2T7Gh8EExZz+v25i6jQSgm51/GVGWsyqAgg8/8WIjl2QDMrL4:7Nx2Tahizz1koOVpsyqFg8NIRd