Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (WinAPI, Konsole) » Problem beim API-HOOKING

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 < [ 2 ]
000
14.12.2004, 22:49 Uhr
DieRuhevordemSturm



Hallöchen ^^

Ich hab ein kleines Problem mein API-Hooking... hier erstmal die Quelle wo ihr bissel lesen könnt worum sichs dreht -> www.devx.com/Intel/Article/21023

das hier ist meine dll ... ( hab GetSystemPowerStatus durch MessageBox ersetzt, weil ich kein Laptop hab )


C++:

#include <windows.h>
#include <iostream>
BOOL WINAPI hackedMsg(HWND hwnd,LPSTR a, LPSTR b,UINT uType)
{
    MessageBox(NULL,"Hack","Sucess",MB_OK);
// Your replacement code goes here.
return TRUE;
}


BOOL InterceptAPI(HMODULE hLocalModule, const char* c_szDllName,
const char* c_szApiName, DWORD dwReplaced)
{    
    DWORD dwOldProtect;
    DWORD dwAddressToIntercept = (DWORD)GetProcAddress(
    GetModuleHandle((char*)c_szDllName), (char*)c_szApiName);

    BYTE *pbTargetCode = (BYTE *) dwAddressToIntercept;

    BYTE *pbReplaced = (BYTE *) dwReplaced;

    VirtualProtect((void *) dwAddressToIntercept, 5, PAGE_WRITECOPY, &dwOldProtect);

    *pbTargetCode++ = 0xE9; // jump rel32

    *((signed int *)(pbTargetCode)) = pbReplaced - (pbTargetCode +4);
    VirtualProtect((void *) dwAddressToIntercept, 5, PAGE_EXECUTE, &dwOldProtect);
    FlushInstructionCache(GetCurrentProcess(), NULL, NULL);
return TRUE;
}


BOOL WINAPI DllMain(HINSTANCE hInst, DWORD dwReason, LPVOID reserved)
{
    if (dwReason == DLL_PROCESS_ATTACH)
    {
        InterceptAPI(hInst,"user32.dll","MessageBox",(DWORD) hackedMsg);
    }
    else if (dwReason == DLL_PROCESS_DETACH) {
    // Cleanup
    }
return TRUE;
}



Also vom Code her ist mir eigentlich alles klar bis auf das:

*((signed int *)(pbTargetCode)) = pbReplaced - (pbTargetCode +4);

Was macht das ? Meine Vermutung ist bis jetzt das er den jmp in den Speicher schreibt und das diese "Konstrukt" die Zieladresse sein soll Was mich daran aber stört ist das er kein

*pbTargetCode++ = *((signed int *)(pbTargetCode)) = pbReplaced - (pbTargetCode +4);

schreibt. So wie ich die Zeile bis jetzt verstehe rechnet er die Adresse zwar aus aber die schwebt dann in der Luft und wird nirgend gespeichert / vergessen.

So hier das ist jetze die loader.exe die den Müll aufruft:


C++:
#include <windows.h>
#include <iostream>
using namespace std;

int main()
{
    MessageBox(NULL,"Normal","Normal",MB_OK);
    return 0;
}




die dll ist statisch zur main gelinkt. Trotzdem erscheint die MsgBox "Normal" "Normal"


WIESO ist das so ?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
15.12.2004, 13:00 Uhr
Spacelord
Hoffnungsloser Fall


Was verstehst du unter "die Dll ist statisch zur main gelinkt"?
Du kannst eine Dll nicht statisch linken.Die kannst du implizit binden indem du die Lib(!) mitlinkst dann generiert der linker automatisch Verweise auf die Funktion in der Dll die in deinem Programm genutzt werden.Aber da du in deinem main Programm keine Funktion aus der Dll nutzt,glaube ich kaum dass diese überhaupt in den Adressraum deiner Anwendung geladen wird. Warum sollte der Linker eine Dll in den Importabschnitt packen die vom Programm nie genutzt wird?

MfG Spacelord
--
.....Ich mach jetzt nämlich mein Jodeldiplom.Dann hab ich endlich was Eigenes.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
18.12.2004, 15:55 Uhr
Spacelord
Hoffnungsloser Fall


Trotz der umwerfenden Resonanz von der RuheVorDemSturm werde ich nochmal darauf eingehen.
Das Beispiel oben enthält mehrere Fehler.
Zum ersten wird die Dll natürlich nur in den Adressraum der Anwendung eingeblendet wenn man eine der exportierbaren Funktionen(in diesem Fall gibt es ja keine) nutzt oder die Dll explizit mit LoadLibrary lädt.

Zweitens ist MessageBox nur ein Makro,dass je nachdem ob die Anwendung Unicode nutzt oder nicht unterschiedlich ausgewertet wird.

Aus Winuser.h:

C++:
#ifdef UNICODE
#define MessageBox  MessageBoxW
#else
#define MessageBox  MessageBoxA
#endif // !UNICODE



Also wird der Aufruf von GetProcAdress mit der Zeichenfolge "MessageBox" nie erfolgreich sein weil es in der user32.dll keine Funktion MessageBox gibt!!

Drittens ruft die Ersatzfunktion erneut MessageBox auf was bei dieser Form des API Hookings aber zu einer Endlosschleife führt.

Vom Prinzip her passiert dann folgendes:
Die Anwendung ruft MessageBox auf(welches vom Präprocessor zur Übersetzungszeit zu MessageBoxA bzw. MessageBoxW erweitert wurde).

Die Hook-Dll hat aber beim Laden seine DllMain ausgeführt(was alle Dlls machen bevor in die main Funktion der Anwendung gesprungen wird) und dadurch an die Einsprungadresse von MessageBox einen bedingungslosen Sprung mit einem Offset geschrieben,der genau zu der Funktion springt die wirklich ausgeführt werden soll.
Das sind in dem Beispiel diese beiden Zeilen:

C++:
    *pbTargetCode++ = 0xE9;

    *((signed int *)(pbTargetCode)) = pbReplaced - (pbTargetCode +4);


Die erste Anweisung schreibt den Maschinencode für den Sprung,an die Einsprungadresse der original MessageBox Funktion,und erhöht sich anschliessend selber .
In der folgenden Anweisung wird mit pbReplaced - (pbTargetCode +4) der Offset berechnet und in die Speicheradresse hinter dem Sprungbefehl geschrieben.

C++:
*((signed int *)(pbTargetCode))


Dieser Code ist eigentlich nichts anderes als eine Dereferenzierung des,zu signend int* ,gecasteten pbTargetCode Pointers.Der Offset wird also als "Inhalt" von pbTargetCode,welcher durch den Cast auf ein signed int zeigt, gespeichert.
(Die Klammern um pbTargetCode sind in diesem Fall überflüssig und verwirrend)
Folgendes ist äquivalent dazu:

C++:
*(reinterpret_cast<signed int *>(pbTargetCode))



Naja,wie dem auch sei.Auf jeden Fall springt die Anwendung dann zur Ersatzfunktion und wenn diese dann widerum MessageBox aufruft wird wieder in der Thunktabelle die Einsprungadresse von MessageBox gesucht,an der aber ja wieder nur der Sprung zur Ersatzfunktion steht usw. usw. usw.


MfG Spacelord
--
.....Ich mach jetzt nämlich mein Jodeldiplom.Dann hab ich endlich was Eigenes.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
18.12.2004, 16:08 Uhr
FloSoft
Medialer Over-Flow
(Administrator)


das problem ist das er die user32.dll nicht attached...

er nimmt immer die aus dem systemverzeichnis...

wenn man nun z.b


C++:
#include "stdafx.h"

int main()
{
  LoadLibrary("test.dll");
  MessageBoxA(NULL,"Normal","Normal",MB_OK);
  return 0;
}



macht und die dll test.dll heißt, dann funktioniert es
--
class God : public ChuckNorris { };

Dieser Post wurde am 18.12.2004 um 16:17 Uhr von FloSoft editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
18.12.2004, 16:42 Uhr
Spacelord
Hoffnungsloser Fall


Nee,
das kann nicht funktionieren weil der Aufruf von GetProcAdress in der Dll Funktion InterceptAPI mit dem Parameter MessageBox nie eine gültigen Zeiger liefern wird.

Dass das explizite Laden der Dll in diesem einfachen Beispiel Pflicht ist,damit die DllMain überhaupt ausgeführt wird hab ich ja mittlerweile auch schon mehrfach erwähnt.

Was du mit "dass er die user32.dll nicht attached" meinst kann ich gerade nicht so ganz nachvollziehen.In dem Augenblich wo er MessageBox benutzt wandert die user32.dll in den Importabschnitt und wird beim Programmstart eingeblendet.

MfG Spacelord
--
.....Ich mach jetzt nämlich mein Jodeldiplom.Dann hab ich endlich was Eigenes.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
18.12.2004, 16:52 Uhr
FloSoft
Medialer Over-Flow
(Administrator)


naja bei mir wird schon eine user32.dll geladen, nur nicht die aus dem programmverzeichnis...

Jedenfalls hab ichs nun mal so gemacht: (nach dem Link da oben)

Loader.exe

C++:
#include "stdafx.h"

int main()
{
  STARTUPINFO si;
  PROCESS_INFORMATION pi;

  ZeroMemory( &si, sizeof(si) );
  si.cb = sizeof(si);
  ZeroMemory( &pi, sizeof(pi) );

  if( !CreateProcess( NULL, "Test.exe",NULL,NULL,FALSE,0,NULL,NULL,&si,&pi ))
  {
    printf("CreateProcess failed.");
  }
  InjectLib(pi.dwProcessId,"test.dll"); // aus den beiden dateien im listing
  return 0;
}



Test.exe

C++:
#include "stdafx.h"

int main(int argc, char* argv[])
{
  MessageBox(NULL,"Normal","Normal",MB_OK);
  return 0;
}



test.dll

C++:
#include "stdafx.h"

BOOL WINAPI hackedMsg(HWND hwnd,LPSTR a, LPSTR b,UINT uType)
{
  MessageBoxW(NULL,L"Hack",L"Success",MB_OK);
  return TRUE;
}

BOOL InterceptAPI(HMODULE hLocalModule, const char* c_szDllName, const char* c_szApiName, DWORD dwReplaced)
{    
  DWORD dwOldProtect;
  DWORD dwAddressToIntercept = (DWORD)GetProcAddress(
    GetModuleHandle((char*)c_szDllName), (char*)c_szApiName);

  BYTE *pbTargetCode = (BYTE *) dwAddressToIntercept;

  BYTE *pbReplaced = (BYTE *) dwReplaced;

  VirtualProtect((void *) dwAddressToIntercept, 5, PAGE_WRITECOPY, &dwOldProtect);

  *pbTargetCode++ = 0xE9; // jump rel32

  *((signed int *)(pbTargetCode)) = pbReplaced - (pbTargetCode +4);
  VirtualProtect((void *) dwAddressToIntercept, 5, PAGE_EXECUTE, &dwOldProtect);
  FlushInstructionCache(GetCurrentProcess(), NULL, NULL);
  return TRUE;
}

BOOL WINAPI DllMain(HINSTANCE hInst, DWORD dwReason, LPVOID reserved)
{
  if (dwReason == DLL_PROCESS_ATTACH)
  {
    InterceptAPI(hInst,"user32.dll","MessageBoxA",(DWORD) hackedMsg);
  }
  else if (dwReason == DLL_PROCESS_DETACH) {
    // Cleanup
  }
  return TRUE;
}



und so kommt "Hack/Success" beim start über Loader.exe
--
class God : public ChuckNorris { };

Dieser Post wurde am 18.12.2004 um 16:53 Uhr von FloSoft editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
18.12.2004, 16:59 Uhr
FloSoft
Medialer Over-Flow
(Administrator)


was ich noch sagen wollte, ich hab schon öfters gesehen das man einfach die "falsche" dll ins anwendungsverzeichnis gelegt hat, z.b riched20.dll und er hat dann die "falsche" geladen. Wie macht man sowas? oder geht das bei user32.dll und konsorten nicht?
--
class God : public ChuckNorris { };

Dieser Post wurde am 18.12.2004 um 17:00 Uhr von FloSoft editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
18.12.2004, 17:23 Uhr
Spacelord
Hoffnungsloser Fall


Erstmal hast du ja oben nen kleinen "Kunstgriff" genutzt und MessageBoxW genommen um die Endlosschleife zu umgehen.

Nach wie vor kann ich nicht nachvollziehen was an der user32.dll falsch sein soll und warum du den Umweg über CreateProcess gehst?

Also,im Prinzip läuft es ja so dass,wenn das Programm MessageBox(A/W) nutzt wandert die user32.dll in den Importabschnitt der Anwendung und wird beim Programmstart in den virtuellen Adressraum der Anwendung eingeblendet.
Normalerweise werden die RAM-Speicherseiten in denen die Dll´s (und Exefiles) gespeichert sind einfach wieder verworfen und bei Bedarf einfach (von Festplatte) nachgeladen.
Eingeblendet heisst ja im Endeffekt nichts anderes als das der virtuelle Adressraum so tut als wenn die physisch gespeicherte Datei auf der Festplatte ein Teil des Adressraumes wäre.
Da aber der user32.dll-Code der in den Adressbereich der Probeanwendung liegt,mit dem Seitenschutzattribut PAGE_WRITECOPY ausgestattet wird,wird bei der Sprung-Schreibaktion nicht das Original auf der Festplatte geändert sondern eine Kopie angelegt.Diese wird dann geändert und von jetzt an wird auch mit dieser Kopie weiter gearbeitet.Die Kopie wird also bei Bedarf in die Auslagerungsdatei geschrieben und auch wieder von dort ausgelesen.
Also wie gesagt mit deiner modifizierten ApiHook Dll von da oben müsste das Testprogramm auch ohne den "Starter" laufen.
Aber irgendwie habe ich das Gefühl dass wir aneinander vorbei reden(vielleicht,aber auch nur ganz vielleicht sind nicht unwesentliche Mengen Glühwein daran schuld )

MfG Spacelord
--
.....Ich mach jetzt nämlich mein Jodeldiplom.Dann hab ich endlich was Eigenes.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
18.12.2004, 18:05 Uhr
FloSoft
Medialer Over-Flow
(Administrator)


ok also:

Verzeichnis
|-Test.exe
|-user32.dll (<- fakedll)

aufruf mit Test.exe <- %windir%\system32\user32.dll wird geladen und nicht .\user32.dll.
Und das ist das Problem, eigentlich müsste das gehen, aber evtl liegts ja eben daran das es user32.dll eine systemdll ist und er deshalb die IMMER aus dem sys-verzeichnis holt?
--
class God : public ChuckNorris { };
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
18.12.2004, 18:13 Uhr
FloSoft
Medialer Over-Flow
(Administrator)


also ich hab das nun mal ausprobiert, er läd alle dlls außer user32.dll, kernel32.dll, ntdll.dll aus dem arbeitsverzeichnis, nur eben diese 3 nicht (mehr als diese 3 hab ich an sys-dll's nicht ausprobiert)
--
class God : public ChuckNorris { };
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 < [ 2 ]     [ C / C++ (WinAPI, Konsole) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: