C++ Detour & Dll

09/12/2012 14:08 Shadow992#1
Ich stehe gerade vor einem mir unerklärlichem Problem.
Bis gerade eben dachte ich noch es liegt an meiner Unfähigkeit mit Detorus umzugehen bzw. meinen Reversing Künsten, aber jetzt ist mir aufgefallen, dass es scheinbar gar nicht direkt an den Detour-Funktionen liegt, sondern an meiner Dll.

Um das ganze ein bisschen genauer zu beschreiben:

Ich wollte endlich mal mit dem Thema Detours anfangen, klingt auch alles soweit logisch und ich glaube auch es verstanden zu haben. Also habe ich mir nach einem Tutorial von "xNopex" ([Only registered and activated users can see links. Click Here To Register...]) eine Opferanwendung geschrieben (wie beschrieben).

Dann habe ich WinInject genommen und einen selbstgemachten und dann noch einen selbstkopierten Injector. Alle sagen mir, dass die Dll erfolgreich injeziert wurde und meine Dll wird auch als Modul aufgeführt in der Exe, aber komischerweise wird sie nicht ausgeführt:

Dll:

Code:
#include <iostream>
#include <windows.h>

bool DetourFunc( BYTE* oldFunc, BYTE* newFunc, DWORD len )
{
    BYTE* newMem4base = NULL;
    DWORD dwOld;

    newMem4base = ( BYTE* )malloc( 5+len );

    if( newMem4base == NULL )
        return false;

    for( DWORD i = 0; i < ( len+5 ); i++ )
        newMem4base[i] = 0x90;

    VirtualProtect( oldFunc, len, PAGE_READWRITE, &dwOld );

    memcpy( newMem4base, oldFunc, len );
    oldFunc[0] = 0xE8;
    *( DWORD* )( oldFunc+0x01 ) = DWORD( newFunc-oldFunc-5 );
    oldFunc[5] = 0xE9;
    *( DWORD* )( oldFunc+0x06 ) = DWORD( newMem4base-( oldFunc+0x5 )-5 );
    newMem4base += len;
    newMem4base[0] = 0xE9;
    *( DWORD* )( newMem4base+0x01 ) = DWORD( ( oldFunc+10 )-newMem4base-5 );

    for( DWORD i = 10; i <len; i++ )
        oldFunc[i] = 0x90;

    return true;
}

void *DetourFunc2(BYTE *src, const BYTE *dst, const int len) // credits to gamedeception
{
    BYTE *jmp = (BYTE*)malloc(len+5);
    DWORD dwback;
    VirtualProtect(src, len, PAGE_READWRITE, &dwback);
    memcpy(jmp, src, len); jmp += len;
    jmp[0] = 0xE9;
    *(DWORD*)(jmp+1) = (DWORD)(src+len - jmp) - 5;
    src[0] = 0xE9;
    *(DWORD*)(src+1) = (DWORD)(dst - src) - 5;
    VirtualProtect(src, len, dwback, &dwback);
    return (jmp-len);
}

void test()
{
    MessageBox(0, "Detour was succesful", "Started", 0);
    std::cout<<"detour works";
}

DWORD WINAPI Thread( LPVOID lpParam )
{
    DetourFunc2((BYTE*) 0x0040134C,(BYTE*) &test,14);
	return 0;
}

int WINAPI DllMain(HINSTANCE hInst,DWORD reason,LPVOID reserved)
{
    MessageBox(0, "Dll injected", "Started", 0);
	if( reason == DLL_PROCESS_ATTACH )
	{
        MessageBox(0, "Detour started", "Started", 0);
		HANDLE hThread = CreateThread( NULL, 0, Thread, NULL, 0, NULL );
		CloseHandle( hThread );
	}

	return TRUE;
}
Meine Exe:

Code:
#include <iostream>
#include <windows.h>

using namespace std;

void NormaleFunc()
{
    cout << "Von EXE\n";
}

int main( int argc, char** argv )
{
    while( true )
    {
        NormaleFunc();
        Sleep( 250 );
    }

    return 0;
}
Meine gefundene Stelle in der Exe für die Funktion:

[Only registered and activated users can see links. Click Here To Register...]

Ich muss vielleicht noch anmerken, dass mir OLLY folgende Warnung gibt, wenn ich versuche die Exe zu disassemblen:

[Only registered and activated users can see links. Click Here To Register...]

Und wenn ich jetzt die Dll in diesen Prozess injiziere, passiert nichts, wirklich gar nichts, es wird nicht einmal die MessageBox am Anfang gezeigt, aber das sollte sie ja eigentlich auf jeden Fall:

Code:
int WINAPI DllMain(HINSTANCE hInst,DWORD reason,LPVOID reserved)
{
    MessageBox(0, "Dll injected", "Started", 0);
	if( reason == DLL_PROCESS_ATTACH )
	{
        MessageBox(0, "Detour started", "Started", 0);
		HANDLE hThread = CreateThread( NULL, 0, Thread, NULL, 0, NULL );
		CloseHandle( hThread );
	}

	return TRUE;
}
Als Compiler wurde GCC verwendet (müsste der bei Code::Blocks mitgelieferte sein).

So und jetzt meine Frage:
Wieso passiert da nix? :D

Edit:
Keine Ahnung obs hilft, aber ich benutze Win XP SP 3, 32Bit.

Edit2:
Habe versucht dieselbe Dll mal in Opera.exe zu injecten, in Notepad, in Wordpad, usw.
und das Ergebnis ist dasselbe, nämlich es passiert nichts, also was ist mit dieser Dll los?
09/12/2012 17:58 Nightblizard#2
Wurde die User32.dll in das Programm geladen? Wenn nicht, dann hast du hier einen Deadlock kreiert.

Etwas Infomaterial dazu:
[Only registered and activated users can see links. Click Here To Register...]
[Only registered and activated users can see links. Click Here To Register...]
[Only registered and activated users can see links. Click Here To Register...]
[Only registered and activated users can see links. Click Here To Register...]

Oder in kurz:
Ruf nichts in DllMain auf, was nicht aus der kernel32 dll kommt. Auch vom Erstellen eines Threads wird abgeraten (hat in dem Fall aber nichts damit zu tun).

Abgesehen davon und ein paar memoryleaks sehe ich aber spontan nichts. Häng dich mal mit nem Debugger an den Prozess und schau nach, ob die dll überhaupt injiziert wird.
09/12/2012 21:39 Shadow992#3
Quote:
Originally Posted by Nightblizard View Post
Wurde die User32.dll in das Programm geladen? Wenn nicht, dann hast du hier einen Deadlock kreiert.

Etwas Infomaterial dazu:
[Only registered and activated users can see links. Click Here To Register...]
[Only registered and activated users can see links. Click Here To Register...]
[Only registered and activated users can see links. Click Here To Register...]
[Only registered and activated users can see links. Click Here To Register...]

Oder in kurz:
Ruf nichts in DllMain auf, was nicht aus der kernel32 dll kommt. Auch vom Erstellen eines Threads wird abgeraten (hat in dem Fall aber nichts damit zu tun).

Abgesehen davon und ein paar memoryleaks sehe ich aber spontan nichts. Häng dich mal mit nem Debugger an den Prozess und schau nach, ob die dll überhaupt injiziert wird.

Wurde die User32.dll in das Programm geladen? Wenn nicht, dann hast du hier einen Deadlock kreiert.

Etwas Infomaterial dazu:
[Only registered and activated users can see links. Click Here To Register...]
[Only registered and activated users can see links. Click Here To Register...]
[Only registered and activated users can see links. Click Here To Register...]
[Only registered and activated users can see links. Click Here To Register...]

Oder in kurz:
Ruf nichts in DllMain auf, was nicht aus der kernel32 dll kommt. Auch vom Erstellen eines Threads wird abgeraten (hat in dem Fall aber nichts damit zu tun).

Abgesehen davon und ein paar memoryleaks sehe ich aber spontan nichts. Häng dich mal mit nem Debugger an den Prozess und schau nach, ob die dll überhaupt injiziert wird.
Wenn ich das richtig verstanden habe, verfällt mein Programm in diesen Zustand, weil es entweder sofort wieder detached wird oder weil es nen deadlock bekommt wodurch es pausiert wird. Deadlocks können durch Zugriffe auf gemeinsame Ressourcen usw. entstehen (was ja bei den DetourFuncs) passiert.

Jo die User32.dll wird geladen in das Projekt.
Meine Dll ist auch im geladenen Zustand, wenn ich sie injected habe.

Und wie behebe ich das Problem jetzt genau?
09/12/2012 22:11 SmackJew#4
Also soweit ich das sehen kann fehlt dir einfach der Jump zurück, ich bin zwar extrem bekifft aber versuch's mal so:

Code:
...
int (__stdcall* MessageBoxOrig)(HWND, LPCTSTR, LPCTSTR, UINT) = NULL;
...
MessageBoxOrig = (int (__stdcall* MessageBoxOrig)(HWND, LPCTSTR, LPCTSTR, UINT))DetourFunc2((BYTE*) 0x0040134C,(BYTE*) &test,14);
...
void test()
{
    MessageBox(0, "Detour was succesful", "Started", 0);
    std::cout<<"detour works";
    MessageBoxOrig(0. "Back", "back", 0);
}
09/12/2012 23:00 Shadow992#5
Quote:
Originally Posted by SmackJew View Post
Also soweit ich das sehen kann fehlt dir einfach der Jump zurück, ich bin zwar extrem bekifft aber versuch's mal so:

Code:
...
int (__stdcall* MessageBoxOrig)(HWND, LPCTSTR, LPCTSTR, UINT) = NULL;
...
MessageBoxOrig = (int (__stdcall* MessageBoxOrig)(HWND, LPCTSTR, LPCTSTR, UINT))DetourFunc2((BYTE*) 0x0040134C,(BYTE*) &test,14);
...
void test()
{
    MessageBox(0, "Detour was succesful", "Started", 0);
    std::cout<<"detour works";
    MessageBoxOrig(0. "Back", "back", 0);
}
Die Original-Funktion ist "cout", bzw. genaugenommen an der Stelle "0x0040134C" zu finden.
Und prinzipiell dürfte das ja nichts dran ändern, dass die andere MessageBox nicht angezeigt wird oder? Eine Messagebox, die nicht injected wurde hingegen geht ohne Probleme. Also muss da irgendetwas mit der DLL nicht stimmen.

Wenn ich Detouring bisher nicht falsch verstanden habe müsste der JMP zurück ja folgendes sein:

Code:
oldFunc[5] = 0xE9;
bzw.
Code:
src[0] = 0xE9;
09/13/2012 13:47 Dr. Coxxy#6
also kommt noch nichtmal eine der msgboxen am anfang?

1. wie nightblizzard schon gesagt hat, sollte man in dll main nur funktionen aus kernel32.dll benutzen
2. dll und ziel exe gleich bittigkeit?
3. antivirs ausschalten
09/13/2012 18:57 Shadow992#7
Quote:
Originally Posted by Dr. Coxxy View Post
also kommt noch nichtmal eine der msgboxen am anfang?

1. wie nightblizzard schon gesagt hat, sollte man in dll main nur funktionen aus kernel32.dll benutzen
2. dll und ziel exe gleich bittigkeit?
3. antivirs ausschalten
1. Alles klar, habe die Main abgeändert:

Code:
int WINAPI DllMain(HINSTANCE hInst,DWORD reason,LPVOID reserved)
{
    MessageBox(0, "Dll injected", "Started", 0);
	if( reason == DLL_PROCESS_ATTACH )
	{
        MessageBox(0, "Detour started", "Started", 0);
		Thread();
	}

	return TRUE;
}
2. Wenn du damit meinst ob beides x86 compiliert ist, dann ist die Antwort ja.
3. Gemacht.

Nur die Msgbox am Anfang des Codes wird immer noch nicht angezeigt, was ist da los?
09/14/2012 17:31 tnd0#8
Generell sollte DllMain BOOL zurückgeben, was zwar im prinzip aufs selbe rauskommt, aber best-practise ist BOOL WINAPI DllMain(..). Weiß ja nicht was deine benutzten "Injectors" so können, aber richtig machst du es nur, wenn mit WaitForSingleObjectEx auf den loader-thread wartest und das ergebnis mit WAIT_OBJECT_0 abgleichst. Und das passiert erst wenn die MessageBox weggeklickt wurde, denn MessageBox() blockt den Thread bis der User die Box schließt.
So sieht es bei mir aus wenn ich das hier:

Code:
#include <iostream>
#include <Windows.h>

BOOL WINAPI DllMain(HINSTANCE hInst,DWORD reason,LPVOID reserved)
{
	if( reason == DLL_PROCESS_ATTACH )
	{
        MessageBox(0, "Detour started", "Started", 0);
	}

	return TRUE;
}
in das windows-notepad injecte. Und ja, ich sehe dann eine MessageBox.
[Only registered and activated users can see links. Click Here To Register...]

Dann solltest du beachten, dass du deine DLL mit /MT compilest - also MultiThreaded Static Link ohne Debug Info. In VS2010/VS2012 heisst die Option "Runtime Library".