Aurora Stealer
Introduction
Aurora Stealer is an information stealer Written in GO. It is a commercial stealer that costs around 250$ per month. The malware can steal Browser password and saved cookies, crypto information (Desktop and Web), Telegram, Steam and Specific files from the victim machine and can take a screenshot from it.
Basic information
The icon of the executable gives us a hit about how this is spreading. It has Photoshop icon, most probably it was spreading using Malvertising.
Binary Identification
First we want to know some basic information about the file so I will use DiE to do so.
It was identified as GO binary. .symtab
is a legacy section in GO binaries. In GO binaries prior to Version 1.3 .symtab
section hold the symbol table but it is no longer filed with anything useful.
Without Symbols, the reversing will be so hard as a simple Hello world program in GO has about 2000 function this is a result of that GO compiler statically linking all the needed libraries. Later, I will try to tackle this problem using existed Tools.
An important aspect of the basic Triaging of a Malware is to check the readable Strings of the file. But GO is different in everything. The strings has a part of that too.
In GO, the strings are stored in Unicode format without null terminating character so many tools will handle that wrong. Also, the existence of this large number of library functions will make it worse. The resulting number of lines using strings utility in Die is 7371 line. We can reduce this number by matching for the library functions like the following Regex
|
|
this matches the lines that contains runtime, usr and root. this filters around 2500 line but still around 5000 line. these lines contains the function imported in program, you can check them but it will be so exhausting to get information from it. Let’s Continue our analysis using the disassembler.
Code Analysis
I will upload the sample to IDA to explore it. In the old versions of IDA, Library functions will not be recognized and renamed. Also the types will be mostly wrong.
To handle this there is some tools you can use to fix the types and names. I’ve used GoReSym.
This is a standalone executable you can run with following parameters
|
|
for more info about the available parameters, Check the repo of the tool.
content of the output is in JSON format so I saved it to use it in this IDA Script to rename the functions and correct the types in IDA database.
NOTE: -t
parameter fix the types information but if you the decompiler will fail to decompile it.
If you want to know how this tool is working, Check this article. Basically it search for pclntab
structure by searching for a magic header and follow the pointer to symbols table.
|
|
This is also used by the go parser itself in order to locate the function, For more info here
Another set of scripts available we can use it doing the same thing is Alphagolang
I will use Alphagolang here but both will provide similar result.
First I used recreate_pclntab.py script to recreate pclntab
structure.
Second, I used function_discovery_and_renaming.py script to rename the functions.
Third, I used categorize_go_folders.py to categorize the functions and pack them in folders, This will be very helpful to focus on user-code.
Fourth, I used string_cast.py to fix string references.
Fifth, I used extract_types.py to correct the types information by applying C like types to the used structures.
The result
Now, We have a better environment so we can start exploring the code efficiently.
Calling Conventions in GO
In function calls, GO has a different calling convention.
All the argument are passed using the stack from the left to right. The following assembly code is in Go assembler format
|
|
|
|
the compiler have to make sure that there is enough space on the stack to accommodate all the arguments and return values.
Strings in GO
Go stores strings in a Unicode -UTF-8- format without null terminating characters in a section contain all the strings but.
Strings in go stored in structure of value and length pair called StringHeader
. So, in all the function where a string argument is passed, you will see an extra argument contain the length of the string.
|
|
First we start with main_init
function (sub_595590
). In GO, init()
is a predefined function that takes no argument, Return no values. And Runs before any code in the package.
The block number 1 shows that it loads some DLLs and functions.
DLL | Function |
---|---|
user32.dll | GetDesktopWindow |
user32.dll | EnumDisplayMonitors |
user32.dll | GetMonitorInfoW |
user32.dll | EnumDisplaySettingsW |
kernel32.dll | LocalFree |
Crypt32.dll | CryptUnprotectData |
In Block number 2, It Reads the the environment Variable USERPROFILE
and concatenate \\APPDATA\\LOCAL\
and \\APPDATA\\ROAMING\
and save the new string to the memory.
In block 3, It did the same thing to get the Paths C:\\Users\\{user}\\APPDATA\\ROAMING,<Local>\\
but it replaces the string C:\\Users
with C:\\windows.old\Users
with Replace function from strings package
|
|
this location is created when the user update from one version to another and it contains all the old information from the previous installation.
moving to main_main
(sub_595470
). It creates a new procedure by making a call to newproc
function from runtime
package.
Connect To server
following the code to main_ConnectToServer
(sub_58ABE0
). This function has some interesting functionality we will explore next.
In block 1, the malware sleeps for 1000000000 nanoseconds -I tried a simple program with the same call to sleep and it was equivalent to time.Nanosecond -
Then it establishes a TCP connection to 82.115.223.249:8081
IP address using function Dial
from net
package. Then it Reads the Received packet. the Dial
function in GO returns 2 values, Conn
interface and Error, which IDA cannot recognize so, I will follow my intuition. If the connection returned error, it will try to reconnect again.
In Block 2, The connection was established but it first checks the response from the remote IP. If it was blocked due to the geo location, as the IP is Russian, it will try to reconnect.
If the response was WORK
string, the connection is established successfully and the malware can continue with its functionality as shown in block 3 and 4
Collect victim information
Moving to main_GetInfoUser()
(sub_58B880
). The first Lines in this subroutine takes us to another function, main_MachineID
(sub_5897A0
)
The malware Runs the command cmd.exe /c wmic csproduct get uuid
to get UUID of the device. Returning to main_GetInfoUser
.
It retrieves the screen width and height using win32 API GetSystemMetrics
, GO allow using third-party packages directly from GitHub and the the cause of the function naming. The screen resolution is represented in the format <width>x<height>
.
The next call is to main_GetOS
(sub_58A530
).
This function retrieves the OS version using wmic command wmic os get Caption
. and filter the output based on the form it is printed to format is in a space separated string.
Returning back to main_GetInfoUser
a call to main_getGPU
(sub_58A200
) is made.
The GPU information retrieved by executing the command cmd /C wmic path win32_VideoController get name
Using the same method in main_getCPU
(sub_589F10
). It gets CPU information with command cmd /c wmic cpu get name
in main_sysTotalMemory
(sub_58B550
)It gets the memory status by executing GlobalMemoryStatusEx
function.
main_CMD_SHELL
is called to execute cmd /c systeminfo
that gets all the specs of the device.
That was the last thing the function main_GetInfoUser
do.
Back in main_main
, the function main_grab
(sub_593E80
) is called. This function responsible for doing the main goal of the malware, Stealing.
panic
function is used to check for unexpected errors. common use of panic is to abort if a function returns an error value that we don’t want to handle.
File grabber
Going to the first function main_file_grabber
(sub_594110
)
this function search for a specific file taken from the C2 server and it is base64 encoded and in JSON format.
Then, It search for the file in some predefined directories and location.
the function io_ioutil_ReadDir
reads the content of the directory and stores the output in a fs.fileinfo
structure , sorted by the filename
|
|
Then it walks through the returned structure and reads the file of interest
then it encode the file content in Base64 and adds the tags used in the JSON formatted packet content to be sent to the remote system
Browser data
We will visit SendToServer
latter. Now, lets go back to the caller function and explore the next function, main_Grab_func3
(sub_58F0B0
).
This function goes through the %APPDATA%Roaming directory and calls another function. the function path_filepath_Walk
walks the directory from the Root passed in the second parameter calling a function fn.WinDirFunc
at each file and directory in it including the Root.
|
|
|
|
So, Next one to visit is WalkFunc
used main_Grab_func3_2
(sub_58DED0
).
This function steals the Browser information stored
For Chromium based browsers it gets the Local State file and calls main_getMasterKey
that as the name suggest, Gets the master key and decode it .then, decrypts it by calling CryptUnprotectData
which is called from main_xDecrypt
It handles the case of using Opera and Firefox browsers
Back to the caller function, The malware steals the password and cookies from the browser data and adds the tags of the JSON file to be sent to the C2 server.
Crypto
Then, It goes through the %USERPROFILE% searching for any Crypto wallets information
It Looks for PC applications and Web based wallets and add its associated type and name to the JSON data to be sent
Screenshot Capture
function main_Grab_func_7
(sub_591D50
) is used to take a screenshot from the victim system
The PNG file is then base64 encoded and add the value to the tag screenshot
to be sent.
Telegram Data
The next targeted information is Telegram, It did the same procedure discussed before with telegram data folder at main_Grab_func_6
(sub_591980
)
WalkFunc
→ main_Grab_func_6_2
(sub_591120
)
Steam data
function main_Grab_func9
(sub_593B30
) steals steam data in the same way
send To server
main_SendToServer_NEW
(sub_594DD0
) is used to send the collected data to the server.
The collected information stored in JSON format. the Data then compressed using gzip
compression algorithm and encoded with Base64 encoding to be sent to the server using the previously established TCP connection.
Network Analysis
we can look at the network communication using PCAP file provided by Any Run sandbox.
By opening the file in Wireshark and filter using the IP 82.115.223.249
Following the TCP stream
The first packet received is WORK indicates that the connection is successful and the malware then begin to collect the required data and compress it and send it to the server. At the last packet received from the the C2 server is Thanks
.
we can use Cyberchef to decode and decompress the data.
the Error list include the files that the malware cannot read or access. On of the packets has a very large size, as the screenshot field has a very large Base64 encoded data
the screenshot:
Sample JSON file can be found here https://pastebin.com/YpTwAC94
Conclusion
Aurora stealer is a new commercial infostealer. Most of it’s capabilities are typical things that can be found in most of the stealers. it can grab Browser saved password/cookies and Cryptocurrency wallets information from Desktop applications and Web based wallets. Also, it can grab a files from the victim machine and take a screenshot. The communication with C2 server is done over TCP protocol. Most of these things can be found in most of the stealer But being written in GO makes it special, even it has a plaintext strings, The reversing process is quite annoying as most of the tools cannot handle GO binaries in a right way.
IOCs:
- 29339458f4a33ee922f25d36b83f19797a15a279634e9c44ebd3816866a541cb
- 82.115.223[.]249:8081
Yara Rule
|
|
References
- https://gist.github.com/alexander-hanel/59af86b0154df44a2c9cebfba4996073
- The Go Programming Language
- https://pkg.go.dev/
- PCAP file
- https://dr-knz.net/go-calling-convention-x86-64.html
- https://dr-knz.net/go-calling-convention-x86-64-2020.html
- Aurora: a rising stealer flying under the radar - SEKOIA.IO Blog