CreateRemoteThread - Exception im Remote Thread
-
hallöchen,
mein Vorhaben ist es, eigenen Code in einen fremden Prozess mittels der Funktion CreateRemoteThread einzuschleusen. Dazu allokiere ich Speicher im Prozess mit VirtualAllocEx für den Code und ein Struct, das als Argument übergeben wird.
Das ist mein Struct, das als Argument übergeben wird:
typedef HINSTANCE (WINAPI *pLoadLibFunc)(PCSTR); typedef HINSTANCE (WINAPI *pGetProcAddrFunc)(HMODULE,PCSTR); typedef HINSTANCE (WINAPI *pFreeLibFunc)(HMODULE); typedef BOOL (WINAPI *pBeepFunc)(DWORD,DWORD); struct ThreadData { pLoadLibFunc pLoadLibrary; pGetProcAddrFunc pGetProcAddress; pFreeLibFunc pFreeLibrary; pBeepFunc pBeep; pSleepFunc pSleep; pVoidFunc pDebugBreak; //pDllFunc pHalloDllMain; //CHAR strDllPath[30]; //CHAR strDllPath[30]; //CHAR strDllFuncName[30]; //CHAR strFuncName[30]; //PVOID pUserData; };Meine Funktion, die injected wird, sieht wie folgt aus:
static DWORD WINAPI ThreadStart(ThreadData* pData ) { //pData->pDebugBreak(); __asm { NOP NOP NOP NOP NOP } pData->pBeep(700,1000); __asm { NOP NOP NOP NOP NOP } return 123; }Beim Aufruf der CreateRemoteThread-Funktion, die ich an calc.exe ausprobiert habe, höre ich das Piepen und danach kommt es in calc.exe zu einem Speicherzugriffsfehler. In der Disassembly sieht meine eingeschleuste Funktion so aus:
003A0058 push ebp 003A0059 mov ebp,esp 003A005B sub esp,0CCh 003A0061 push ebx 003A0062 push esi 003A0063 push edi 003A0064 lea edi,[ebp-0CCh] 003A006A mov ecx,33h 003A006F mov eax,0CCCCCCCCh 003A0074 rep stos dword ptr [edi] 003A0076 nop 003A0077 nop 003A0078 nop 003A0079 nop 003A007A nop 003A007B mov esi,esp 003A007D push 3E8h 003A0082 push 2BCh 003A0087 mov eax,dword ptr [ebp+8] 003A008A call dword ptr [eax+0Ch] 003A008D cmp esi,esp 003A008F call 003A0556 003A0094 mov dword ptr [ebp-8],eax 003A0097 nop 003A0098 nop 003A0099 nop 003A009A nop 003A009B nop 003A009C mov eax,7Bh 003A00A1 pop edi 003A00A2 pop esi 003A00A3 pop ebx 003A00A4 add esp,0CCh 003A00AA cmp ebp,esp 003A00AC call 003A0556 003A00B1 mov esp,ebp 003A00B3 pop ebp 003A00B4 ret 4 003A00B7 int 3Der Fehler tritt beim Aufruf der Funktion 003A0556 auf, da an der Stelle nur Nullbytes im Speicher sind.
Wäre schön, wenn jemand eine Erklärung dafür hat, warum der Compiler diese seltsamen Funktionsaufrufe dort eingebaut hat, ich habe sämtliche Optimierungen, etc deaktiviert.Danke schonmal im Voraus

PS: Ich habe nicht vor, Malware zu programmieren, bin hier nur ein bisschen am Rumprobieren

-
Ich hatte mit Remote-Threads ein ähnliches Problem.
Ich habs so gelöst:
Ich starte den Thread und lade eine von mir geschriebene DLL
In der DLL kann ich dann belibigen code von mir aus führenhier der Code dazu: (für VC++)
So geht der Aufruf:
RmtResetParam();
RmtSetCallType(TYPE_CDECL);
RmtAddParam("Hallo");// void __cdecl meine_funktion(char *text) in meine.dll aufrufen
bOk=RmtStart("calc.exe","meine.dll","meine_funktion");//***************************************************************************** //* //* //* RemoteThread.h //* //* //***************************************************************************** #ifndef __REMOTETHRED_H__ #define __REMOTETHRED_H__ BOOL RmtStart (DWORD dwProcess,LPCSTR pDllName,LPCSTR pProcName,HANDLE *pHandel=0); BOOL RmtStart (HANDLE hProcess ,LPCSTR pDllName,LPCSTR pProcName,HANDLE *pHandel=0); BOOL RmtStart (LPCSTR pProcess ,LPCSTR pDllName,LPCSTR pProcName,HANDLE *pHandel=0); VOID RmtSetCallType(int iType); VOID RmtResetParam(); BOOL RmtAddValue(DWORD dwParam); BOOL RmtAddParam(void *pParam); BOOL RmtAddParam(LPCSTR pParam); BOOL RmtAddParam(void *pParam,unsigned uSize); #ifndef TYPE_CDECL #define TYPE_CDECL 0 #endif #ifndef TYPE_STDCALL #define TYPE_STDCALL 1 #endif #endif //***************************************************************************** //* //* //* RemoteThread.cpp //* //* //***************************************************************************** #include <stddef.h> #include <string.h> #include <windows.h> #include <tlhelp32.h> #include "RemoteThread.h" typedef int (WINAPI *TypMessageBoxA)(HWND,LPCTSTR,LPCTSTR,UINT); typedef HMODULE (WINAPI *TypGetModuleHandleA)(LPCTSTR); typedef HINSTANCE (WINAPI *TypLoadLibraryA)(LPCTSTR); typedef BOOL (WINAPI *TypFreeLibrary)(HMODULE); typedef FARPROC (WINAPI *TypGetProcAddressA)(HMODULE,LPCSTR); #define PROC_SIZE 0x10000 #define DATA_SIZE 0x1000 #define MAX_PARAM 8 typedef struct { HMODULE hKernel32; // HMODULE von Kernel32.dll char cDllName[256]; // Name der zu ladenden Dll char cProcName[64]; // Name der Prozedur in der Dll TypFreeLibrary FreeLibrary; // Zeiger auf FreeLibrary TypLoadLibraryA LoadLibrary; // Zeiger auf LoadLibraryA TypGetProcAddressA GetProcAddress; // Zeiger auf GetProcAddress unsigned char ucData[DATA_SIZE]; // Lokaler Datenspeicher für Parameter DWORD dwParam[MAX_PARAM]; // Parameter int iParamCount; // Anzahl der übergabe Parameter int iCallType; // 0=cdecl 1=stdcall }LocalData; static unsigned char ucData[DATA_SIZE]; // Speicher für Parameter static unsigned int uiDataOffset=0; // Offset im Speicher static unsigned int uiParamCount=0; // Anzahl der Parameter static unsigned int uiParamData[MAX_PARAM]; // Werte der Parameter static unsigned int uiParamType[MAX_PARAM]; // 0=Wert 1=Pointer static unsigned int uiCallType=0; // 0=cdecl 1=stdcall //***************************************************************************** //* //* RmtThreadProc //* //***************************************************************************** static __declspec(naked) DWORD __stdcall WINAPI RmtThreadProc(LPVOID pParam) { _asm{ push ebp ;// Initialisiere Stack mov ebp,esp ;// * mov ecx,[ebp+8] ;// Hole pParam mov eax,[ecx]LocalData.LoadLibrary ;// Dll laden lea ebx,[ecx]LocalData.cDllName ;// * push ecx ;// * push ebx ;// * call eax ;// * pop ecx ;// * cmp eax,0 ;// * je J3 ;// * mov edx,[ecx]LocalData.GetProcAddress ;// Prozeturadresse laden lea ebx,[ecx]LocalData.cProcName ;// * push ecx ;// * push ebx ;// * push eax ;// * call edx ;// * pop ecx ;// * cmp eax,0 ;// * je J3 ;// * cmp [ecx]LocalData.iCallType,0 ;// Welcher Prozetur Typ push ecx ;// * jne J2 ;// * mov ebp,ecx ;// CDECL Prozetur starten lea ebx,[ecx]LocalData.dwParam ;// * mov ecx,[ecx]LocalData.iParamCount ;// * lea ebx,[ebx+ecx*4-4]; ;// * jcxz cc ;// * cn: push [ebx] ;// * sub ebx,4 ;// * loop cn ;// * cc: call eax ;// * mov edx,[ebp]LocalData.iParamCount ;// * shl edx,2 ;// * add esp,edx ;// * pop ecx ;// * jmp J3 ;// * J2: lea ebx,[ecx]LocalData.dwParam ;// STDCALL Prozetur starten mov ecx,[ecx]LocalData.iParamCount ;// * lea ebx,[ebx+ecx*4-4]; ;// * jcxz sc ;// * sn: push [ebx] ;// * sub ebx,4 ;// * loop sn ;// * sc: call eax ;// * pop ecx ;// * J3: pop ebp ;// Register wieder herstellen ret 4 ;// * } } //***************************************************************************** //* //* RmtSetCallType //* //***************************************************************************** // Die Aufrufart für die Dll Funktion festlegen // iType : 0=cdecl 1=stdcall // TYPE_CDECL // TYPE_STDCALL VOID RmtSetCallType(int iType) { uiCallType=iType; } //***************************************************************************** //* //* RmtResetParam //* //***************************************************************************** // Rücksetzen aller Parameter VOID RmtResetParam() { uiParamCount=0; uiDataOffset=0; } //***************************************************************************** //* //* RmtAddValue //* //***************************************************************************** // Anhängen eines Zahlen-Parameters // Ergibt TRUE wenn erfolgreich BOOL RmtAddValue(DWORD dwParam) { if(uiParamCount>=MAX_PARAM)return FALSE; uiParamData[uiParamCount] = dwParam; uiParamType[uiParamCount] = 0; uiParamCount++; return TRUE; } //***************************************************************************** //* //* RmtAddParam //* //***************************************************************************** // Anhängen eines Zeiger-Parameters // Ergibt TRUE wenn erfolgreich BOOL RmtAddParam(void *pParam) { if(uiParamCount>=MAX_PARAM)return FALSE; uiParamData[uiParamCount] = (DWORD)pParam; uiParamType[uiParamCount] = 0; uiParamCount++; return TRUE; } //***************************************************************************** //* //* RmtAddParam //* //***************************************************************************** // Anhängen eines Zeiger-Parameters // Ergibt TRUE wenn erfolgreich BOOL RmtAddParam(LPCSTR pParam) { return RmtAddParam((void*)pParam,strlen(pParam)+1); return TRUE; } BOOL RmtAddParam(void *pParam,unsigned int uSize) { if(uiParamCount>=MAX_PARAM)return FALSE; if(uiDataOffset+uSize>DATA_SIZE)return FALSE; uiParamData[uiParamCount] = uiDataOffset; uiParamType[uiParamCount] = 1; uiParamCount++; memcpy(ucData+uiDataOffset,pParam,uSize); uiDataOffset+=uSize; uiDataOffset+=3; uiDataOffset&=~3; return TRUE; } //***************************************************************************** //* //* RmtStart //* //***************************************************************************** // Startet den einen Remote Thread // dwProcess : Process ID des Prozesses in dem der Thread gestartet wird // hProcess : Process Handle des Prozesses in dem der Thread gestartet wird // pDllName : Name der Dll die geladen wird // pProcName : Name der Prozedur die gestartet wird // pHandel : Wenn ungleich 0 dann wird heir das Thread Handle gespeichert // (ab Win2000) // Ergibt TRUE wenn erfolgreich BOOL RmtStart(LPCSTR pProcess,LPCSTR pDllName,LPCSTR pProcName,HANDLE *pHandel) { BOOL bOk=FALSE; HANDLE hSnapshot; PROCESSENTRY32 sData; hSnapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); sData.dwSize=sizeof(sData); if(!Process32First(hSnapshot,&sData))return FALSE; do { if(stricmp(pProcess,sData.szExeFile))continue; bOk=RmtStart(sData.th32ProcessID,pDllName,pProcName); break; }while(Process32Next(hSnapshot,&sData)); CloseHandle(hSnapshot); return bOk; } BOOL RmtStart(DWORD dwProcess,LPCSTR pDllName,LPCSTR pProcName,HANDLE *pHandel) { BOOL bOk; HANDLE hProcess; hProcess=OpenProcess(PROCESS_ALL_ACCESS|PROCESS_VM_OPERATION| PROCESS_VM_READ | PROCESS_VM_WRITE,TRUE,dwProcess); if(!hProcess)return FALSE; bOk=RmtStart(hProcess,pDllName,pProcName,pHandel); CloseHandle(hProcess); return bOk; } BOOL RmtStart(HANDLE hProcess,LPCSTR pDllName,LPCSTR pProcName,HANDLE *pHandel) { LPVOID pProc,pLocal; DWORD dwBytes,dwId; LocalData sLocal; HANDLE hThread; int i; pProc=VirtualAllocEx(hProcess,NULL,PROC_SIZE,MEM_COMMIT,PAGE_EXECUTE_READWRITE); if(!pProc)return FALSE; pLocal=VirtualAllocEx(hProcess,NULL,sizeof(LocalData),MEM_COMMIT,PAGE_READWRITE); if(!pLocal) { VirtualFreeEx(hProcess,pProc,PROC_SIZE,MEM_RELEASE); return FALSE; } memset(&sLocal,0,sizeof(sLocal)); sLocal.hKernel32 = GetModuleHandle("KERNEL32"); sLocal.FreeLibrary = (TypFreeLibrary )GetProcAddress(sLocal.hKernel32,"FreeLibrary"); sLocal.LoadLibrary = (TypLoadLibraryA )GetProcAddress(sLocal.hKernel32,"LoadLibraryA"); sLocal.GetProcAddress = (TypGetProcAddressA )GetProcAddress(sLocal.hKernel32,"GetProcAddress"); strncpy(sLocal.cDllName ,pDllName ,sizeof(sLocal.cDllName )-1); strncpy(sLocal.cProcName,pProcName,sizeof(sLocal.cProcName)-1); memcpy (sLocal.ucData,ucData,uiDataOffset); sLocal.iCallType=uiCallType; // 0=cdecl 1=stdcall sLocal.iParamCount=uiParamCount; for(i=0;i<sLocal.iParamCount;i++) { sLocal.dwParam[i]=uiParamData[i]; if(uiParamType[i])sLocal.dwParam[i]+=(DWORD)pLocal+offsetof(LocalData,ucData); } if(!WriteProcessMemory(hProcess,pProc,RmtThreadProc,PROC_SIZE,&dwBytes)) { VirtualFreeEx(hProcess,pLocal,sizeof(LocalData),MEM_RELEASE); VirtualFreeEx(hProcess,pProc ,PROC_SIZE,MEM_RELEASE); return FALSE; } if(!WriteProcessMemory(hProcess,pLocal,&sLocal,sizeof(LocalData),&dwBytes)) { VirtualFreeEx(hProcess,pLocal,sizeof(LocalData),MEM_RELEASE); VirtualFreeEx(hProcess,pProc ,PROC_SIZE,MEM_RELEASE); return FALSE; } hThread=CreateRemoteThread(hProcess,0,0x40000,(LPTHREAD_START_ROUTINE)pProc,pLocal,0,&dwId); if(!hThread)return FALSE; if(pHandel)*pHandel=hThread; else CloseHandle(hThread); return TRUE; }Meine Homepage:
-
ja, danke erstmal
Ich hatte ja auch vor, eine DLL zu laden und dann die Hautpfunktion aus der DLL aufzurufen. Dafür müssen aber erstmal meine Funktionspointer auf GetProcAddress, LoadLibrary und FreeLibrary funktionieren. Die Beep-Funktion funktioniert ja in meinem Fall auch, das einzige Problem ist der Funktionsaufruf in's Nichts, den VS.NET 2003 (ohne optimierungen) dort einfügt. Du hast ja dieses Problem nicht, weil du es in Assembler gemacht hast
Naja, werde ich mal weitersehen oder deinen Loader verwenden

-
Ich habe das Problem jetzt gelöst. Die Funktion, die aufgerufen wurde, war _RTC_CheckEsp, da ich versehentlich bei der Release-Projektkonfiguration die falschen Einstellungen gewählt habe. Und der Pointer ist natürlich im anderen Prozess nicht gültig. Jetzt funktioniert alles wie erwartet.