I think this is just a test sample for OS/X ransomware.
I made a quick look on the malware and here's my findings:
1. The malware gets the Primary MAC Address using the following using API IOServiceMatching("IOEthernetInterface") and given the iterator it will use the API's IORegistryEntryGetParentEntry(infService, "IOService", &controllerService) and IORegistryEntryCreateCFProperty(controllerService, CFSTR("IOMACAddress"), *kCFAllocatorDefault_ptr, 0LL) to return the mac address.
Snippet:
GetMacAddress()
Code: Select all_BYTE *__cdecl GetMacAddress()
{
signed int counter; // [rsp+4h] [rbp-1Ch]@3
_BYTE *result; // [rsp+8h] [rbp-18h]@1
char tmp_result[6]; // [rsp+12h] [rbp-Eh]@2
unsigned int intFIterator; // [rsp+18h] [rbp-8h]@1
kern_return_t kernResult; // [rsp+1Ch] [rbp-4h]@1
kernResult = 0;
result = malloc(6uLL);
kernResult = FindEthernetInterfaces(&intFIterator);
if ( !kernResult )
{
kernResult = getMacAddress(intFIterator, tmp_result, 6LL);
if ( !kernResult )
{
for ( counter = 0; counter < 6; ++counter )
result[counter] = tmp_result[counter];
}
}
IOObjectRelease(intFIterator);
return result;
}
FindEthernetInterfaces
Code: Select allkern_return_t __fastcall FindEthernetInterfaces(__int64 matchingServices)
{
__int64 _propertyMatchDict; // [rsp+0h] [rbp-20h]@2
__int64 matchingDict; // [rsp+8h] [rbp-18h]@1
matchingDict = IOServiceMatching("IOEthernetInterface");
if ( matchingDict )
{
_propertyMatchDict = CFDictionaryCreateMutable(
*kCFAllocatorDefault_ptr,
0LL,
kCFTypeDictionaryKeyCallBacks_ptr,
kCFTypeDictionaryValueCallBacks_ptr);
if ( _propertyMatchDict )
{
CFDictionarySetValue(_propertyMatchDict, CFSTR("IOPrimaryInterface"), *kCFBooleanTrue_ptr);
CFDictionarySetValue(matchingDict, CFSTR("IOPropertyMatch"), _propertyMatchDict);
CFRelease(_propertyMatchDict);
}
}
return IOServiceGetMatchingServices(*kIOMasterPortDefault_ptr, matchingDict, matchingServices);
}
getMacAddress
Code: Select all while ( 1 )
{
infService = IOIteratorNext(v11, v3);
if ( !infService )
break;
v3 = "IOService";
v6 = IORegistryEntryGetParentEntry(infService, "IOService", &controllerService);
if ( !v6 )
{
v3 = CFSTR("IOMACAddress");
v5 = IORegistryEntryCreateCFProperty(controllerService, CFSTR("IOMACAddress"), *kCFAllocatorDefault_ptr, 0LL);
if ( v5 )
{
v16 = 0LL;
v15 = 6LL;
v13 = 0LL;
v14 = 6LL;
v18 = 6LL;
v17 = 0LL;
v3 = 0LL;
CFDataGetBytes(v5, 0LL, 6LL, v10);
CFRelease(v5);
}
IOObjectRelease(controllerService);
}
IOObjectRelease(infService);
}
2. It will look for the file "PANW_Top_Secret_Sauce.jpg" in the current directory, this is the one to be encrypted.:
Code: Select allconst char *__fastcall getFileToDecrypt(char **curDir, __int64 len)
{
char *buff; // ST30_8@10
const char *result; // rax@13
const char *v4; // [rsp+38h] [rbp-438h]@7
struct dirent *dp; // [rsp+40h] [rbp-430h]@2
DIR *dir; // [rsp+48h] [rbp-428h]@1
const char *_result; // [rsp+58h] [rbp-418h]@8
char *filepath[129]; // [rsp+60h] [rbp-410h]@7
__int64 v9; // [rsp+468h] [rbp-8h]@1
v9 = *__stack_chk_guard_ptr;
dir = opendir_INODE64(curDir, len);
if ( dir )
{
while ( 1 )
{
dp = readdir_INODE64(dir);
if ( !dp )
break;
if ( strcmp(dp->d_name, ".") && strcmp(dp->d_name, "..") )
{
if ( !strcmp(dp->d_name, "PANW_Top_Secret_Sauce.jpg") )
{
buff = malloc(0x400uLL);
__snprintf_chk(buff, 0x400uLL, 0, 0xFFFFFFFFFFFFFFFFLL, "%s/%s", curDir, dp->d_name);
_result = buff;
goto return;
}
__snprintf_chk(filepath, 0x400uLL, 0, 0x400uLL, "%s/%s", curDir, dp->d_name);
v4 = getFileToDecrypt(filepath, 1024LL);
if ( v4 )
{
_result = v4;
goto return;
}
}
}
closedir(dir);
_result = 0LL;
}
else
{
_result = 0LL;
}
return:
result = *__stack_chk_guard_ptr;
if ( *__stack_chk_guard_ptr == v9 )
result = _result;
return result;
}
3. It also check if the file is running inside virtual machine (VirtualBox VMware) using the command
ioreg -l | grep -e Manufacturer -e 'Vendor Name' | grep -e 'Parallels' -e VMware -e Fusion -e 'Virtual Box'
Code: Select all strCommand = "ioreg -l | grep -e Manufacturer -e 'Vendor Name' | grep -e 'Parallels' -e VMware -e Fusion -e 'Virtual Box'";
pStream = popen(
"ioreg -l | grep -e Manufacturer -e 'Vendor Name' | grep -e 'Parallels' -e VMware -e Fusion -e 'Virtual Box'",
"r");
if ( pStream )
{
v1 = BUFSIZE;
if ( fgets(v10, BUFSIZE, pStream) )
{
v15 = 999;
v11 = 1;
}
else if ( pclose(pStream) )
{
v2 = printf("Command not found or exited with error status\n", v1);
v15 = -1;
v11 = 1;
v8 = v2;
}
4.The malware will generate the key by creating a buffer with a size of 256 that contains [0-0x100] (like buffer[0]=0 buffer[1] = 1 etc) and swapping the value based on MAC Address. (I can't explain it well, english is not my native language. can someone explain this? hehe)
Code: Select all__int64 __fastcall generateKey(char *buff, char *mac, int len)
{
__int64 result; // rax@4
signed int i; // [rsp+4h] [rbp-1Ch]@1
signed int counter; // [rsp+4h] [rbp-1Ch]@4
unsigned __int8 x; // [rsp+Bh] [rbp-15h]@4
int _len; // [rsp+Ch] [rbp-14h]@1
_len = len;
for ( i = 0; i < 256; ++i )
buff[i] = i;
buff[256] = 0;
result = buff;
buff[257] = 0;
counter = 0;
x = 0;
while ( counter < 256 )
{
x += mac[counter % _len] + buff[counter];
swap(&buff[counter], &buff[x]);
result = (counter++ + 1);
}
return result;
}
5. Once the key is generate, it will now encrypt the data using the key. see the encryption algorithm below:
Code: Select all__int64 __fastcall generateEncryptedData(char *key, char *buffRead, char *newEncData, int fsize)
{
__int64 result; // rax@2
int i; // [rsp+10h] [rbp-20h]@1
int size; // [rsp+14h] [rbp-1Ch]@1
char *_newBuff; // [rsp+18h] [rbp-18h]@1
_newBuff = newEncData;
size = fsize;
for ( i = 0; ; ++i )
{
result = i;
if ( i >= size )
break;
key[257] += key[++key[256]];
swap(&key[key[256]], &key[key[257]]);
_newBuff[i] = key[(key[key[257]] + key[key[256]])] ^ buffRead[i];
}
return result;
}
6. It also generates an identifier for the encrypted file based on getMD5(generateID(MAC Address)):
Code: Select all_DWORD *__fastcall generateID(__int64 mac)
{
_DWORD *result; // rax@7
signed int j; // [rsp+28h] [rbp-88h]@3
signed int i; // [rsp+2Ch] [rbp-84h]@1
_DWORD *v4; // [rsp+30h] [rbp-80h]@1
char _key[104]; // [rsp+40h] [rbp-70h]@1
__int64 v6; // [rsp+A8h] [rbp-8h]@1
v6 = *__stack_chk_guard_ptr;
memcpy(_key, key, 0x64uLL);
v4 = calloc(4uLL, 5uLL);
for ( i = 0; i < 5; ++i )
{
for ( j = 0; j < 5; ++j )
v4[i] += *&_key[20 * j + 4 * i] * *(mac + j);
v4[i] %= 0xFBu;
}
result = *__stack_chk_guard_ptr;
if ( *__stack_chk_guard_ptr == v6 )
result = v4;
return result;
}
That's all.