Binary starts fixing the API calls.

After fixing up the imports, the Reg32 path is retrieved. Default heap is accessed, and Socket / MAC addresses are retrieved. The MAC address is not used in the c2 packet but is used in exception handler and exception data is sent to c2.

Here in this subroutine, c2 is notified about the crash:

A number of initialization calls are made after this event

call
GetOSVersion

mov OSVersion,
eax

call
SetMaxUSerPort

call
SetMutex_AllocateChunks

call
AllocHugeBuffer

test
eax, eax

GetOSVersion() reads the OS version from registry SOFTWARE\Microsoft\OSVersion

Configuration to the binary is set in SetConfig() function . It decodes a configuration from binary using a simple xor algorithm

An IDC script can be used to statically recover decoded data

#include <idc.idc>

static GeneratedString( Offset_)

{


auto String1 =
“”;


auto i =0
;


auto String2 =
“”;


for
(i =
0; i < 7416; i++) String1[i]
= String1[i]
+ Byte(0x13158000 + i);


for
(i =
0; i < 2855; i++) String2[i]
= String2[i]
+ Byte(0x13159CF8 + i);


//Message(“First Byte = %s\n”, String1);


auto Salt1 =
gcguIgMY2yinkfEZPE9nXLpsYZ7X3CSp8;
//< 217


auto Salt2 =         uCiG9Lw2V4hguufVQoHNkelYsI5iHN1Q8JFUOoTYDeakWgZKo1QOg7KoZxAQRWfqKc8rU;


auto len = Offset_;


auto buff =
“”;


auto cur_len =
0;


if
(len <
217)


{

buff = String1[(len *
34)
:(len *
34)
+ 34

];


//Message(“%s”, buff);


//memcpy(buff, String1 + (len * 34), 34);

cur_len =
34
1;


}


else{

buff = String2[((len
0x26)
*
70)
1:
((len
0x26)
*
70)
1

+         70];


//memcpy(buff, String2 + ((len – 0x26) * 70), 70);

cur_len =
70
1;


}

i =
0;


while
(i < cur_len)


{


if
(cur_len ==
33)
{ buff[i]
= ord(buff[i])
^ ord(Salt1[i]);

i++;


}


else{

buff[i]
= ord(buff[i])
^ ord(Salt2[i]);

i++;


}


}


return buff;

}

static
main()

{


if
(strstr(GetDisasm(ScreenEA()),
PUSH))


{


auto psDisasm = GetDisasm(ScreenEA());


auto num =
long((psDisasm[strlen(push ):strlen(psDisasm)]
));


auto psChunk = GeneratedString(num);

MakeComm( ScreenEA()
,
Decoded String =
+ psChunk );


}

}

The list is saved in following linked list format

struct typeinfo

{


LPVOID Pointer


DWORD Length;

}

It also sets a maxuserport constant to MAX_UNSIGNEDSHORT. Mutex’s are set, and a huge buffer is allocated. After the initialization, a call to a function is made which is responsible for creating few threads. The first thread is responsible for retrieving OSVersion from registry:

Another thread is responsible for making connections to some known hard coded mail servers

alt4.gmail-smtp-in.l.google.com

n1.smtp.messagingengine.com

mail7.digitalwaves.co.nz

and makes a connection to following domains on port 25 and wait till cmp Specifier_connection, bx is set which means the connection was successful, if not it will go into a timer state for 120 seconds till other thread functions are created.

Ethical Hacking Training – Resources (InfoSec)

There is one more dummy thread which is used to look up on thread ID of the same thread. It checks if it is zero or not

Other two threads are responsible for email parsing and spamming and Querying Root DNS servers for COM and RU domains

Connection to c2 is made in MainC2Subroutine

First 7 DWORD;s from OS version are combined in a buffer and encoded using the following algorithm and offset 223 is used to get the encoding key, and 224 is used to decode the data. Following is the C representation of that algorithm:

#include <stdio.h>

// Encoding Key 223 == eto ochen prostoarelkioiqyrut

unsigned
char
*EncodeKey =
eto ochen prostoarelkioiqyrut;

#define KEY_SIZE 29

void encode(unsigned
char *
input,
int len )

{


unsigned
int i =
0;


unsigned
int j =
0;


unsigned
char tmp ;


unsigned
int total_len =
29;


unsigned
int index =
0;


if
(len >
29)


{


while
(1)


{


for
(i =
0; i < KEY_SIZE; i++)


{

input[i]
^= EncodeKey[i];


}


for
(j =
0; j < 14
; j++)


{

tmp = input[j];

input[j]
= input[i];

input[i]
= tmp;
// Swap bytes

i;


}


// JA || JZ


if
((index &
1))


{


for
(i =0; i < 29; i++) input[i]
=
!input[i];


}

index = index +
29;

total_len = total_len +
29;


if
(total_len >= len)
break;


}


}


if
(total_len = total_len %
29)


{


for
(i = index ; i < total_len; i++)


{

input[i]
=
!input[i];


}


}

}

Communication synchronization

Only first 8 bytes are retrieved first which has the following structure:

DWORD len;
// Length of packet

DWORD CommandType;
// Command Type

after receiving the 8 bytes, rest of the bytes are retrieved in a loop

Following are the commands types present in the binary:

8 – Spam Email retrieval

5 – DNS Change

4 – Update Binary

7 – Download and execute from HTTP