Parameter und Calling Conversation zu einer Funktion finden? (Olly Debugger)

Hallo Hackerboard Community,

ich bin neu hier und wollte erstmal sagen, dass das hier eine wunderschöne Community ist.

Nun zu meinem Problem:

Ich arbeite mit OllyDBG und habe in einem Modul eine Funktion gefunden. Ich muss jetzt die Parameter der Funktion finden und die Calling Conversation.

Die Funktion:
Code:
PUSH EBP
MOV EBP,ESP 
SUB ESP,8 
PUSH EBX 
MOV DWORD PTR SS:[EBP-8],ECX 
MOV EAX,DWORD PTR SS:[EBP+8]
MOV DWORD PTR SS:[EBP-4],EAX 
\MOV ECX,DWORD PTR SS:[EBP+C] 
MOV EDX,DWORD PTR SS:[EBP+C] 
SUB EDX,1 
MOV DWORD PTR SS:[EBP+C],EDX 
TEST ECX,ECX 
JE SHORT ****** 
MOV EAX,DWORD PTR SS:[EBP+10] 
MOV ECX,DWORD PTR DS:[EAX] 
SHR ECX,8 
MOV EDX,DWORD PTR SS:[EBP+10] 
MOV EAX,DWORD PTR DS:[EDX] 
AND EAX,0FF 
MOV EDX,DWORD PTR SS:[EBP-4] 
XOR EBX,EBX 
MOV BL,BYTE PTR DS:[EDX] 
XOR EAX,EBX 
MOV EDX,DWORD PTR SS:[EBP+14] 
XOR ECX,DWORD PTR DS:[EDX+EAX*4] 
MOV EAX,DWORD PTR SS:[EBP+10] 
MOV DWORD PTR DS:[EAX],ECX 
MOV ECX,DWORD PTR SS:[EBP-4] 
ADD ECX,1 
MOV DWORD PTR SS:[EBP-4],ECX 
\JMP SHORT ***** 
POP EBX 
MOV ESP,EBP 
POP EBP 
RETN 10

Es sollten 6 Parameter sein oder? (hat mir jemand gesagt)
Und was hat es mit Calling Conversation auf sich? Also stdcall/fastcall/cdecl?
Ich weiß nur, das diese Parameter in umgekehrter Reihenfolge dem Stack übergibt .

Sinn und Zweck ist, diese Funktion später zu detouren. Mir wurde dabei gesagt, dass ich die Anfangsadresse, die Parameteranzahl und die Calling Conversation brauche.
Die Anfangsadresse habe ich (die wäre bei PUSH EBP) und die Parameteranzahl auch, insofern 6 stimmt.

Ich hoffe jemand nimmt sich Zeit für mich und hilft mir :)

Schon mal Danke im Voraus

P.S.: Wenn das hier die falsche Sektion ist, bitte ich um Verzeihung
 
hi

Also in deinem konkreten Bsp. (es heißt übrigens calling convention ;) ) wäre die Parameterzahl
4, die convention stdcall.

RETN 0x10 -> 0x10 (16) / 4 ==> 4

Zu den Calling conventions liest du dir am besten das mal durch:
http://en.wikipedia.org/wiki/Calling_convention

Falls du noch zum Thema Detours Fragen hast, gerne..

mfg
 
Einmal danke für deine Antwort.

Ich hätte gleich mal eine Frage dazu:
Ich denke mal du hast die 0x10 von Hex in Dezimalform umgewandelt (16) und sie dann durch 4 geteilt. Doch warum 4? Hat das einen bestimmten Grund oder ist das immer so?

Nehmen wir mal an, es würde am Schluss RETN 4 stehen, dann würde das so aussehen?

RETN 4 -> 0x4 -> 4 -> 4/4 = 1

Oder irr ich mich da?

Und stdcall kann man auch von RETN 10 ablesen oder?

Zum Thema Detour:

Ich bräuchte ein detourjmp :)
Vielleicht ein kleines Beispiel mit Erklärung. Wenn das ginge, wäre es super, denn ich habe jetzt eigentlich alles was ich dafür brauche.

Danke nochmal, super Community hier
 
Ich habe angenommen, dass die Disassembly von einem Windows System X86 32bit stammt, und Windows Funktionen verlangen ein DWORD alignment (4byte) des Stacks. (ein fehler der mir schon einmal ziemlich viel Zeit gekostet hat) -> deshalb das Teilen durch 4 .
Das RETN 4 ergibt 1 Parameter, das stimmt in diesem Fall. Vereinfacht gesagt kannst du durch das RETN 10 die stdcall convention ablesen.

Zum DetourJmp:

Hier ist ein Bsp. wie man einen Detourjmp erstellt:

parameter *from: wäre im obigen fall die addresse an der "PUSH EBP" steht
*to die addresse an der der JMP "springen" soll. Hier sollte dann die Addresse einer Art Proxy Funktion mit 4 Parametern stehen.

Code:
// function to calculate end place a jump i386 (JMP) 
// AT *from with destination address *to  
static void write_rel_jmp(void *to,void *from) 
{  
 *(BYTE *)(from)=0xE9; // assemble jump  
 *(DWORD *)((DWORD)(from)+1)=((DWORD)to-(DWORD)from)-5; // calc rel jmp  
}

write_rel_jmp überschreibt dann die ersten 5 bytes deiner Funktion mit einem JMP zu deiner Funktion, die Parameter loggt, verändern kann... etc..

Nur ist es damit noch nicht abgetan, zuerst sollten noch die überschriebenen Bytes der original Funktion gesichert werden.. aber nicht nur 5 sondern in ganzen Instruktionen , dazu bedarf es eines Length Disassemblers.
Danach muss am Ende der gesicherten instructions noch ein jmp zu der original funktion+anzahl gesichterter bytes stehen.. usw..

Wie du siehst, lässt sich das nicht in ein paar Minuten zur vollsten Zufriedenheit erklären. Ein wenig Zeit mit Olly,Assembler,MSDN,.. muss man dabei investieren, um sich selbst eine kleine Detour Lib zu basteln. Oder man greift z.B. zu MS-DETOURS um schneller Ergebnisse zu haben:

http://research.microsoft.com/en-us/projects/detours/

mfg
 
Doch warum 4? Hat das einen bestimmten Grund oder ist das immer so?
4 Bytes ist die Registerbreite. Damit arbeiten auch die Stackoperationen (Push/Pop) - womit auch die Parameter übereben werden. D.h dass die Anzahl der auf dem Stack "abgelegt" Parameter-Bytes ein Vielfaches von 4 ist (von irgendwelchen exotischen Methoden mal abgesehen).

zum Stdcall: streng genommen wäre dieser Link interessanter ;)
http://en.wikipedia.org/wiki/X86_calling_conventions

Btw: wenn man den "dirty-way" nimmt, kann man einfach die ersten 6 Bytes sichern und mit dem JMP überschreiben.
Code:
PUSH EBP
MOV EBP,ESP 
SUB ESP,8
Sofern man eine bestimmte Funktion hooken möchte, muss die Umsetzung nicht allgemeingültig sein - es reicht aus, wenn diese Anweisungen letzendlich noch ausgeführt werden.
 
Einmal vielen Dank für eure Hilfe, es hat mir echt geholfen.

Zu meinem Detour Problem:
void *DetourFunc(BYTE *src, const BYTE *dst, const int len)
{
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] = 0x50;
src[1] = 0x58;
src[2] = 0xE9;
*(DWORD*)(&src[3]) = (DWORD)(dst - src) - 7;
for (int i=7; i<len; i++) src = 0x90;
VirtualProtect(src, len, dwBack, &dwBack);
return (jmp-len);
}


void Newfunc(int par1, int par2, int par3, int par4)
{
}

void Detour()
{
DetourFunc((PBYTE)0xAdress, (PBYTE)Newfunc, 6);
}


Das ist mein bisheriger "Erstversuch" in Sachen Detouren :)

Nur es funktioniert nicht wirklich, das Programm crasht.
Mir wurde nun gesagt, das der Funktionstyp nicht stimmt, die calling conversation cdecl ist und ich die Originalfunktion in meiner gehookten Funktion aufrufen sollte.

Leider wurde ich aus dem nicht schlauer, vielleicht hat hier jemand Rat und Lösung dazu :)

Danke nochmal
 
So..

Ich hab jetzt mal ein _einfachst_ gehaltenes Bsp zusammengestöpselt.
Mit mingw32-gcc als compiler sollt es funktionieren.
Ich hoffe es dient dem einen oder anderen für weitere Experimente.

mfg

Code:
// detour hooking in a very simple! form ;)

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

#define JMP_LEN 5
#define JMP_OPC 0xE9

// function to calculate end place a jump i386 (JMP)
// AT *from with destination address *to

static void write_rel_jmp(void *to,void *from)
{
 *(BYTE *)(from)=0xE9; // assemble jump
 *(DWORD *)((DWORD)(from)+1)=((DWORD)to-(DWORD)from)-5; // calc rel jmp 
}

// function for hooking via so called detours

static int detour_hook_func (void *func_addr, void *handler,void *gateway)
{
int c=0;
 

 // bytes to copy ==> length of push ebp, mov ebp,esp sub esp,8 !

 c=6;

 // save orig bytes
 memcpy(gateway,func_addr,c);
 
 // calc && place jmp from func_to_hook TO our handler function
 write_rel_jmp(handler,func_addr); 
 
 // at last place jmp at end of origbytes to orig_func_addr + disassed bytes
 write_rel_jmp((BYTE*)((int)func_addr+c),(BYTE*)((int)gateway+c)); 

 return(0);
}
 

// function to modify page write permissions
// set make_writable to TRUE for write_execute_read permission
// set make_writable to FALSE for restoring original protection

int protect_page(void *pageaddr,DWORD *old_prot,BOOL make_writeable)
{
MEMORY_BASIC_INFORMATION mbi;
DWORD tmp_prot;

 VirtualQuery(pageaddr,&mbi,sizeof(mbi));

 if (make_writeable == TRUE) // set PAGE_EXECUTE_READWRITE flags
  VirtualProtect(mbi.BaseAddress,mbi.RegionSize,PAGE_EXECUTE_READWRITE,old_prot);
 else                      // restore set page flags
  VirtualProtect(mbi.BaseAddress,mbi.RegionSize,*old_prot,&tmp_prot);

 return(0);
}

// our "gateway" where original instructions + linking jump are stored
// used to call original function

typedef int (*sub_stdcall)();

static BYTE g_gateway_for_testapi[30];

DWORD WINAPI testapi(int p1,int p2,int p3,int p4)
{
 printf("\n called testapi");
 return(1);
}

DWORD WINAPI testapi_detoured(int p1,int p2,int p3,int p4)
{
DWORD retval_of_testapi;
 
 printf("\n params of testapi: %d %d %d %d",p1,p2,p3,p4);
 retval_of_testapi=((sub_stdcall)g_gateway_for_testapi)(p1,p2,p3,p4);
 printf("\n testapi returned: %d ",retval_of_testapi);
}

int main(int argc,char *argv[])
{
 DWORD old_prot;
 
 protect_page(&testapi,old_prot,TRUE);
 detour_hook_func(&testapi,&testapi_detoured,&g_gateway_for_testapi);
 protect_page(&testapi,old_prot,FALSE);

 testapi(1,2,3,4);

 return(0);
}
 
Vielen Dank für eure Hilfe, vorallem an ss5 :)

Habs zwar noch nicht ganz geschafft, hab aber einiges mehr verstanden.

Danke
 
Zurück
Oben