API Crypting: Antiviren-Programme austricksen

Antiviren-Programme werden immer effektiver. Viele Hersteller geben an, dass ihre Software auch unbekannte Malware durch verdächtiges Verhalten aufspüren kann.

Unter anderem werden bestimmte Funktionen im Programmcode erkannt, die auch oft in Malware verwendet werden. Das ist natürlich besonders ärgerlich für diejenigen, die legale Software entwickeln, diese Funktionen aber nutzen wollen.

In diesem Artikel zeige ich euch, wie einfach dieser Schutz umgangen werden kann.

WinAPI-Funktionen

Das WinAPI (Windows Application Programming Interface) ist eine Programmierschnittstelle von Microsoft, die Programmierer nutzen können, um unter Windows Software zu entwickeln. In der MSDN Library werden unter anderem sehr viele WinAPI-Funktionen und deren Parameter (falls vorhanden) genauer erklärt. Einige dieser Funktionen werden von Antiviren-Programmen als potenziell gefährlich eingestuft, da sie häufig in Malware verwendet werden. Zum Beispiel Funktionen, die es ermöglichen eigenen Programmcode in einem fremden Prozess zu injizieren.

URLDownloadToFile

Mit der WinAPI-Funktion URLDownloadToFile kann man durch einen simplen Aufruf eine Datei aus dem Internet herunterladen und sie auf dem lokalen Rechner speichern.

Dies ist eine solche Funktion, die von den meisten Antiviren-Programmen ohne Vorwarnung blockiert wird. Auch nicht ohne Grund, denn schließlich kann somit jede beliebige Datei heruntergeladen und evtl. anschließend auf dem Rechner ausgeführt werden. Allderdings kann es auch vorkommen, dass man (als Programmierer) diese Funktion für legale Zwecke verwenden will. Zum Beispiel, um neue Updates herunterzuladen.

So könnte der Funktionsaufruf in der Programmiersprache C aussehen:

#include <windows.h>
#include <urlmon.h>

int main()
{
  HRESULT hDownload = URLDownloadToFile(NULL, "URL", "SPEICHERORT", 0, NULL);

  if(hDownload != S_OK)
    return 1;

  return 0;
}

Wobei URL und SPEICHERORT durch richtige Angaben ersetzt werden müssen. Ich möchte aber nicht weiter darauf eingehen, da es nur eine Demonstration darstellt.

In diesem Fall erkennt das Antiviren-Programm den Aufruf bzw. den Funktionsnamen der URLDownloadToFile Funktion und schlägt Alarm.

Funktionsnamen verschlüsseln

Da die meisten Antiviren-Programme keine Schwierigkeit darin haben den Funktionsnamen aus der Datei zu lesen, kann man als ersten Schritt diesen Funktionsnamen verschlüsseln.

Dabei sind dem Programmierer keine Grenzen gesetzt. Es genügt aber meistens eine sehr einfache Verschlüsselung. In diesem Beispiel wird einfach jeder Buchstabe des Funktionsnamens alphabetisch erhöht. Das heißt aus A wird B, aus B wird C, usw.

URLDownloadToFile wird also zu VSMEpxompbeUpGjmfB.
Das Antiviren-Programm erkennt somit den eigentlichen Funktionsnamen nicht mehr.

Funktionsnamen entschlüsseln & Speicheradresse aus DLL laden

Da der Funktionsname verschlüsselt und somit verändert wurde, müssen wir diesen wieder entschlüsseln, damit wir die Funktion URLDownloadToFile auch aufrufen können. Dies machen wir wie bei der Verschlüsselung - nur andersrum.

Aus VSMEpxompbeUpGjmfB wird also wieder URLDownloadToFile. Was dieses hin und her bewirkt? Ganz einfach: Der Funktionsname URLDownloadToFile wird nicht mehr direkt im Programm verwendet, sondern der Verschlüsselte, der wiederum später zur Laufzeit zu dem eigentlichen Funktionsnamen entschlüsselt wird.

Nun, irgendwie müssen wir die URLDownloadToFile Funktion ja aufrufen. Was bringt uns der Funktionsname? Das ist ja keine Funktion, sondern nur eine Zeichenkette.

In Windows werden DLL-Dateien verwendet, welche unter anderem Speicheradressen von bestimmten Funktionen beinhalten. Durch diese Speicheradressen können wir auf die Funktionen zugreifen. Die Adresse der Funktion URLDownloadToFile befindet sich in der urlmon.dll Datei, welche sich in einem Windows System-Ordner befindet. Diese Adresse können wir mit der WinAPI-Funktion GetProcAddress auslesen.

Wir laden die Datei urlmon.dll mithilfe der WinAPI-Funktion LoadLibrary zur Laufzeit des Programms und lesen anschließend mit GetProcAddress die Speicheradresse der URLDownloadToFile Funktion aus. Um die Adresse der Funktion zu erhalten, müssen wir als zweiten Parameter der GetProcAddress Funktion den Funktionsnamen angeben.

Zur Erinnerung: Diesen hatten wir zuvor wieder entschlüsselt.

Somit erhalten wir also die Adresse der Funktion URLDownloadToFile und können diese in einem eigenen Funktionsaufruf verwenden.

Hier nun ein Beispiel mit Kommentaren:

#include <windows.h>
#include <string.h>
#include <stdio.h>

int entschluesseln(char*);

int main()
{
  // Verschluesselter Funktionsname von URLDownloadToFile
  char funktionsname[] = "VSMEpxompbeUpGjmfB";

  HINSTANCE hDLL;
  // Dieser Variable weisen wir spaeter die Adresse zu
  FARPROC Download;

  // Hier entschluesseln wir den verschluesselten Funktionsnamen
  entschluesseln(funktionsname);

  // Wir laden die DLL-Datei urlmon.dll dynamisch zur Laufzeit
  hDLL = LoadLibrary("URLMON_DLL");

  if(hDLL == NULL)
  {
    FreeLibrary(hDLL);
    return 1;
  }

  // Hier lesen wir die Adresse der URLDownloadToFile Funktion aus
  // und weisen sie der Variable Download zu
  Download = GetProcAddress(hDLL, funktionsname);

  if(Download == NULL)
  {
    FreeLibrary(hDLL);
    return 2;
  }

  // Hier ist nun der Aufruf der Funktion URLDownloadToFile
  // Wir koennen hier unsere Variable "Download" verwenden
  // da diese die Speicheradresse von URLDownloadToFile enthaelt
  Download(NULL, "URL", "SPEICHERORT", 0, NULL);

  FreeLibrary(hDLL);

  return 0;
}

// Die Funktion zur Entschluesselung
int entschluesseln(char *str)
{
  char buchstabe;
  int i, dezimalwert;

  // Verschluesselter Funktionsname wird Buchstabe fuer Buchstabe entschluesselt
  // Aus VSMEpxompbeUpGjmfB wird also wieder URLDownloadToFile
  for(i = 0; i < strlen(str); i++)
  {
    dezimalwert = (int)str[i];
    dezimalwert -= 1;
    buchstabe = (char)dezimalwert;
    str[i] = buchstabe;
  }

  return 0;
}

URLMON_DLL, URL und SPEICHERORT müssen wieder entsprechend durch korrekte Angaben ersetzt werden. Die urlmon.dll befindet sich normalerweise im system32 Ordner. Ihr könnt sie aber auch einfach mit der Windows Suchfunktion suchen.

In diesem Beispiel verwenden wir nicht mehr direkt die URLDownloadToFile Funktion, sondern ermitteln einfach die Speicheradresse dieser Funktion. Dadurch können wir einen eigenen Funktionsnamen für diese Funktion verwenden. In diesem Fall “Download”.

Da hier kein direkter Aufruf der URLDownloadToFile Funktion mehr erfolgt und der eigentliche Funktionsname nicht mehr im Programm verwendet wird, erkennt das Antiviren-Programm auch nichts mehr.

Fazit

Die meisten Antiviren-Programme lassen sich durch sehr einfache Verschlüsselungen und durch dynamische Funktionsaufrufe austricksen. Man sollte nicht zu sehr darauf vertrauen, aber sie auch nicht zu sehr unterschätzen.

Hier nochmal die Schritte im Überblick:

  1. Funktionsname verschlüsseln
  2. Funktionsname zur Laufzeit wieder entschlüsseln
  3. Benötigte DLL-Datei ebenfalls zur Laufzeit mit LoadLibrary laden
  4. Speicheradresse der Funktion mit GetProcAddress aus der DLL-Datei lesen
  5. Funktion mit einem eigenen Funktionsnamen mithilfe der Speicheradresse aufrufen
Dir hat der Artikel gefallen? Dann abonniere doch einfach den RSS-Feed, damit du immer auf dem Laufenden bleibst und über neue Einträge kostenlos informiert wirst.

Diesen Artikel weiterempfehlen:
TwitterFacebookDeliciousTechnoratiMister WongWikio

2 Reaktionen zu “API Crypting: Antiviren-Programme austricksen”

Kommentare (0)

Für diesen Artikel sind bisher nur Trackbacks vorhanden.

Kommentar hinterlassen