This repository contains the analysis reports, technical details or any tools created for helping in malware analysis. Additionally, the repo contains extracted TTPs with code along with the detection rules
The malware possesses a networking module that enables it to establish connections to remote systems within the local network and scan for SMB shares. The initial step involves sending an ICMP “Ping” to each system in a sequential order and verifying if a response is received. After that, the malware will proceed to examine the system for any open SMB shares, excluding shares with a “$” in their name, which indicates hidden shares. The malware will then accumulate the remaining shares in a list, which will be encrypted at a later stage.
The networking module requires three networking APIs:
#include <WS2tcpip.h>
#include <Windows.h>
#include <iphlpapi.h>
//...
//...
//...
#pragma comment(lib, "Iphlpapi.lib")
#pragma comment(lib, "Ws2_32.lib")
#pragma comment(lib, "Netapi32.lib")
First step is to enumerate network adapters and find current IP range to be scanned for available devices. Once the current IP range is found, we will increment in the IP range and try to ping each IP to check for response as done by MedusaLocker Ransowmare. For pinging IP range, i have used multi-threading for faster operation!
std::string getAdapterInfo() {
PIP_ADAPTER_INFO adapterInfo = nullptr;
PIP_ADAPTER_INFO adapter = nullptr;
DWORD dwSize = sizeof(IP_ADAPTER_INFO);
adapterInfo = (IP_ADAPTER_INFO*)malloc(dwSize);
if (GetAdaptersInfo(adapterInfo, &dwSize) == ERROR_BUFFER_OVERFLOW) {
free(adapterInfo);
adapterInfo = (IP_ADAPTER_INFO*)malloc(dwSize);
}
std::stringstream result;
if (GetAdaptersInfo(adapterInfo, &dwSize) == NO_ERROR) {
adapter = adapterInfo;
while (adapter) {
result << "Adapter Name: " << adapter->AdapterName << std::endl;
result << "IP Address: " << adapter->IpAddressList.IpAddress.String << std::endl;
result << "Subnet Mask: " << adapter->IpAddressList.IpMask.String << std::endl;
// Optionally, calculate and print the IP range
DWORD ipAddr = inet_addr(adapter->IpAddressList.IpAddress.String);
DWORD subnetMask = inet_addr(adapter->IpAddressList.IpMask.String);
DWORD networkAddr = ipAddr & subnetMask;
DWORD broadcastAddr = networkAddr | ~subnetMask;
result << "Network: " << ipAddressToString(networkAddr) << " - Broadcast: " << ipAddressToString(broadcastAddr) << std::endl;
// Enumerating the IP range
std::string network_address_string = ipAddressToString(networkAddr);
int num_threads = 255;
for (int i = 0; i < 255; i++)
{
// increment in IP range
std::string current_ip = network_address_string.replace(network_address_string.find_last_of(".") + 1, std::string::npos, std::to_string(i+1));
// Pinging the IP in an async thread
workers.emplace_back(Ping, current_ip);
}
// Join all the threads
for (auto& t : workers) {
t.join();
}
adapter = adapter->Next;
}
}
if (adapterInfo)
free(adapterInfo);
return result.str();
}
This function pings the provided IP and gives back the boolean true or false. If the IP is available, it is saved in an array to be scanned for network shares.
bool Ping(const std::string& ipAddress)
{
HANDLE hIcmpFile;
unsigned long ipaddr = INADDR_NONE;
DWORD dwRetVal = 0;
char SendData[32] = "Data Buffer";
LPVOID ReplyBuffer = NULL;
DWORD ReplySize = 0;
ipaddr = inet_addr(ipAddress.c_str());
if (ipaddr == INADDR_NONE) {
std::cout << "Invalid IP address" << std::endl;
return false;
}
hIcmpFile = IcmpCreateFile();
if (hIcmpFile == INVALID_HANDLE_VALUE) {
std::cout << "Unable to create handle" << std::endl;
return false;
}
ReplySize = sizeof(ICMP_ECHO_REPLY) + sizeof(SendData);
ReplyBuffer = (VOID*)malloc(ReplySize);
if (ReplyBuffer == NULL) {
std::cout << "Unable to allocate memory" << std::endl;
return false;
}
dwRetVal = IcmpSendEcho(hIcmpFile, ipaddr, SendData, sizeof(SendData),
NULL, ReplyBuffer, ReplySize, 1000);
if (dwRetVal != 0) {
//std::cout << "Ping successful: " << ipAddress << std::endl;
free(ReplyBuffer);
IcmpCloseHandle(hIcmpFile);
available_ips.push_back(ipAddress);
return true;
}
else {
//std::cout << "Ping failed ---> " << ipAddress << std::endl;
free(ReplyBuffer);
IcmpCloseHandle(hIcmpFile);
return false;
}
}
Using the API NetShareEnum, we can find if a provided IP address has any network shares.
bool CheckSmbSharesAvailable(std::string ipAddress)
{
NET_API_STATUS res;
LPSHARE_INFO_2 pShares = NULL;
DWORD dwEntriesRead = 0;
DWORD dwTotalEntries = 0;
DWORD i;
// Call NetShareEnum to retrieve information about available shares.
res = NetShareEnum(ConvertToLPWSTR(ipAddress), 2, (LPBYTE*)&pShares, MAX_PREFERRED_LENGTH, &dwEntriesRead, &dwTotalEntries, NULL);
if (res == NERR_Success) {
// If shares were found, free the memory and return true.
if (dwEntriesRead > 0) {
if (pShares != NULL) {
NetApiBufferFree(pShares);
}
std::cout << " Shares found";
return true;
}
}
else {
// If NetShareEnum failed, print an error message.
//wprintf(L"NetShareEnum failed with error: %u\n", res);
std::cout << "Network path not found";
return false;
}
// Free the memory allocated by NetShareEnum.
if (pShares != NULL) {
NetApiBufferFree(pShares);
}
// If no shares were found or an error occurred, return false.
std::cout << " Shares Not found";
return false;
}
Find Complete Code Click Here: Shaddy43/MalwareAnalaysisSeries
NOTE: Artifacts and code of this repository is intended for educational purposes only !