CreateRemoteThread stürtzt ab



  • Hallo weiss jemand was an meinem Code falsch ist?
    Der Windows Taschenrechner stürtzt immer ab ...

    Der Thread scheint ja an einer falschen Stelle im Virutal Address Space im Windows Taschenrechner erstellt zu werden.

    Meine Idee war schon im Windows Taschenrechner mit VirtualAllocEx einfach speicher zu reservieren aber da habe ich dann das Problem das ich nicht weiss wie ich mit CreateRemoteThread den Speicher von VirtualAlloc benutzen kann.

    #include <windows>
    #include <iostream>
    #include <TlHelp32.h>
    using namespace std;
    
    void Msg();
    void function();
    unsigned GetProcessIdByProcessName( string AppName );
    void GetDebugPrivileges();
    
    int main(int argc, char* argv)
    {
    
            GetDebugPrivileges();
    
            DWORD ID = GetProcessIdByProcessName("calc.exe");
            HANDLE handle = OpenProcess(PROCESS_CREATE_THREAD|PROCESS_QUERY_INFORMATION
                                       |PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_READ, false, ID);
            if ( handle == 0 ){
                 cout<<"OpenProcess error: " << GetLastError()<<endl;
            }
    
          //  void *addr = VirtualAllocEx(handle,0,1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
    
            HANDLE thread = CreateRemoteThread(handle,0,0,(LPTHREAD_START_ROUTINE)function,0,0,0);
    
            if(thread==0){
             cout<<"CreateRemoteThread error: " << GetLastError()<<endl;
            }
    
             bool set = SetThreadPriority(thread, THREAD_PRIORITY_LOWEST);
            if(set==false){
              cout<<"SetThreadPriority error: " << GetLastError()<<endl;
            }
    
    system("PAUSE");
    }
    
    unsigned GetProcessIdByProcessName( string AppName )
    {
    bool ProcessExists = false;
    HANDLE snap;
    PROCESSENTRY32 lppe;
    snap =  CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
            if ( snap == INVALID_HANDLE_VALUE )
    		{
    			cout<<"Konnte kein Snapshot machen Fehler code: " << GetLastError() << endl;
                return 0;
            }
            lppe.dwSize = sizeof(PROCESSENTRY32);
            Process32First(  snap, &lppe );
            do
            {
                     if( ! strcmp(lppe.szExeFile, AppName.c_str()  ) )
                     {
                       cout<<lppe.szExeFile << "  Prozess ID: "  << lppe.th32ProcessID << endl;
                       ProcessExists = true;
                       break;
                    }
            }
            while ( Process32Next ( snap , &lppe ) == 1 ) ;
            if ( ProcessExists == false )
            {
                  return 0;
            }
    return lppe.th32ProcessID;
    }
    
    void function()
    {
                Msg();
    }
    
    void Msg()
    {
       MessageBoxW(0,L"ok",L"ok",0);
    }
    
    void GetDebugPrivileges()
    {
    HANDLE TokenHandle;
    bool OpenTokenBool = OpenProcessToken( GetCurrentProcess()  ,TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY ,& TokenHandle );
    
            if ( OpenTokenBool==false ){
                    cout<<"OpenProcessToken error, error code: "<< GetLastError()<<endl; return ;
            }
    
    TOKEN_PRIVILEGES TokPrev;
    LUID_AND_ATTRIBUTES LUIDAttrib;
    TokPrev.PrivilegeCount=1;
    TokPrev.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
    
    bool LookUpBool = LookupPrivilegeValue(0, "SeDebugPrivilege", &TokPrev.Privileges[0].Luid );
    
            if ( LookUpBool==false ){
                    cout<<"LookupPrivilegeValue error, error code: "<< GetLastError()<<endl; return ;
            }
    
    bool adjust =  AdjustTokenPrivileges( TokenHandle,false, &TokPrev, sizeof(TOKEN_PRIVILEGES),0,0 );
    
            if ( adjust==false ){
                    cout<<"AdjustTokenPrivileges, error code: "<< GetLastError()<<endl; return ;
            }
    }
    


  • überleg dir mal ob die Funktion die der RemoteThread aufrufen soll, auch "remote" exisitiert

    greetz KN4CK3R



  • Naja warscheinlich wird mein Code da wohl ehr nicht existieren ...
    Ich habe jetzt folgendes gemacht:

    Meine Funktion void function(); sieht jetzt so aus:

    MessageBoxA(0,"ok","ok",0);
    

    Mit ReadProcessMemory habe ich die Opcodes meiner Funktion void function(); ausgelesen.

    Die ausgelesenen Opcodes habe ich in den Virtual Address Space von calc.exe geschrieben.

    addr enthält hier die Adresse vom Virtual Address Space.

    HANDLE thread = CreateRemoteThread(handle,0,0,(LPTHREAD_START_ROUTINE)addr,0,0,0);
    

    Was bis jetzt funktioniert hat:
    In der calc.exe wird zu meiner Funktion gesprungen.

    Im Virtual Address Space von calc.exe sieht es jetzt so aus:

    00950000   55               PUSH EBP
    00950001   8BEC             MOV EBP,ESP
    00950003   6A 00            PUSH 0
    00950005   68 9D414000      PUSH 40419D
    0095000A   68 98414000      PUSH 404198
    0095000F   6A 00            PUSH 0
    00950011   E8 96120000      CALL 009512AC
    

    Das funktioniert natürlich nicht alleine schon der CALL ist hier falsch.

    Bin ich auf dem richtigen Weg oder ist das sowieso total falsch wie ich es gerade versuche?



  • der Weg an sich ist schon "richtiger" als der vorherige, aber wie du siehst, bekommst du massive Probleme damit, da du dauernd auf Speicher zugreifen willst, der nur in deinem AddressSpace existiert. Das Problem könntest du umgehen, indem du deine Funktion geschickt in Assembler "vorprogrammierst" oder du gehst den einfacheren Weg und benutzt gleich DLL Injection. (je nachdem, was du überhaupt erreichen willst)

    Edit: siehe auch http://www.c-plusplus.net/forum/301481

    greetz KN4CK3R



  • Das Stichwort DLL-Injection hat mich schonmal etwas weiter gebracht.
    Nach etwas herum gegoogel habe ich jetzt folgendes Programm:

    #include <windows>
    #include <iostream>
    #include <TlHelp32.h>
    using namespace std;
    
    void GetDebugPrivileges();
    unsigned GetProcessIdByProcessName( string AppName );
    
    char *DLL_NAME ="MessageBox.dll";
    
    int main(int argc, char* argv)
    {
    
    	 GetDebugPrivileges();
             DWORD ID = GetProcessIdByProcessName("calc.exe");
    
    	 HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, false, ID);
    
             if(handle == 0)
             {
                    cout<<"OpenProcess fehler: " << GetLastError();
                    return 0;
             }
    
    	void *addr = VirtualAllocEx(handle, 0, strlen(DLL_NAME) , MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    	cout<<"VirtualAllocEx: " << hex<< addr <<endl;
    
            cout<<"Adresse die den DLL Namen enthaelt: " << (void*)DLL_NAME << endl;
    
            bool ret = WriteProcessMemory(handle, (void*)addr, (void*)DLL_NAME,  strlen(DLL_NAME), 0);
    
            if(ret == false)
            {
                    cout<<"WriteProcessMemory fehler: " << GetLastError();
                    return 0;
            }
    
    	cout<<"WriteProcessMemory: " << ret << endl;
    
    	handle=CreateRemoteThread(handle, 0, 0, (LPTHREAD_START_ROUTINE) GetProcAddress(GetModuleHandle("kernel32.dll"),"LoadLibraryA"), addr, 0, 0);
    	cout<<"CreateRemoteThread: " << handle << endl;
    
            return 0;
    }
    
    unsigned GetProcessIdByProcessName( string AppName )
    {
    bool ProcessExists = false;
    HANDLE snap;
    PROCESSENTRY32 lppe;
    snap =  CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
            if ( snap == INVALID_HANDLE_VALUE )
            {
                cout<<"Konnte kein Snapshot machen Fehler code: " << GetLastError() << endl;
                return 0;
            }
            lppe.dwSize = sizeof(PROCESSENTRY32);
            Process32First(  snap, &lppe );
            do
            {
                     if( ! strcmp(lppe.szExeFile, AppName.c_str()  ) )
                     {
                       cout<<lppe.szExeFile << "  Prozess ID: "  << lppe.th32ProcessID << endl;
                       ProcessExists = true;
                       break;
                    }
            }
            while ( Process32Next ( snap , &lppe ) == 1 ) ;
            if ( ProcessExists == false )
            {
                  return 0;
            }
    return lppe.th32ProcessID;
    }
    
    void GetDebugPrivileges()
     {
     HANDLE TokenHandle;
    bool OpenTokenBool = OpenProcessToken( GetCurrentProcess()  ,TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY ,& TokenHandle );
    
             if ( OpenTokenBool==false ){
                     cout<<"OpenProcessToken error, error code: "<< GetLastError()<<endl; return ;
             }
    
            TOKEN_PRIVILEGES TokPrev;
            LUID_AND_ATTRIBUTES LUIDAttrib;
            TokPrev.PrivilegeCount=1;
            TokPrev.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
    
    bool LookUpBool = LookupPrivilegeValue(0, "SeDebugPrivilege", &TokPrev.Privileges[0].Luid );
    
             if ( LookUpBool==false ){
                     cout<<"LookupPrivilegeValue error, error code: "<< GetLastError()<<endl; return ;
             }
    
    bool adjust =  AdjustTokenPrivileges( TokenHandle,false, &TokPrev, sizeof(TOKEN_PRIVILEGES),0,0 );
    
             if ( adjust==false ){
                     cout<<"AdjustTokenPrivileges, error code: "<< GetLastError()<<endl; return ;
             } 
     }
    

    Und es funktioniert alles ohne Probleme ich hatte mich nur erst gewundert warum es nicht ging (keine Fehlermeldungen oder so es funktionierte einfach nicht GetLastError hatte sich auch nich beschwert) bis ich auf die Idee kam mal den Windows Taschenrechner in den Ordner zu kopieren wo der Injector liegt danach ging es.

    Jetzt würde mich nur mal interessieren wie CreateRemoteThread intern arbeitet.

    Zum test habe ich mir noch ein einfaches Programm geschrieben welches in einer Endlosschleife läuft und jede Sekunde einen Text ausgibt.

    Folgendes konnte ich mit einem Debugger nachvollziehen:
    - Ich konnte in den Virutal Address Space von meinem Programm schauen und sehen wie WriteProcessMemory darein geschrieben hat.

    - Ich hab einen Breakpoint innerhalb der Endlosschleife gesetzt und ca. 6 mal die Schleife manuell durchgesteppt. Aber meine MessageBox Funktion wurde nicht ausgeführt, erst als ich den Breakpoint entfernt habe und das Programm normal hab weiterlaufen lassen dann wurde auch die Funktion aus der DLL aufgerufen.

    Kann mir vielleicht wer erklären wie die Funktion intern funktioniert?
    Bei Wikipedia habe ich ein Buch von Matt Pietrek (Windows 95 System Programming Secrets) gefunden dort steht aber:

    The key difference is that Richter's method uses the
    CreateRemoteThread function, which isn't available in Win32s or Windows
    95
    

    Das Buch ist wohl etwas zu alt und hilft mir da nicht weiter ...



  • ich nehme an, dass es Zufall ist, ob der eine Thread in der Zeit weiterläuft während du in dem anderen durchstepst

    greetz KN4CK3R



  • Hallo Proc!

    Ich habe mich auch schon viel mit DLL-Injektion beschäftigt, weil ich das Thema einfach unglaublich interessant finde - der Gedanke, ein anderes Programm dein eigenen Code ausführen zu lassen.

    Jedenfalls hatte auch ich am Anfang einige Probleme:

    proc schrieb:

    Und es funktioniert alles ohne Probleme ich hatte mich nur erst gewundert warum es nicht ging (keine Fehlermeldungen oder so es funktionierte einfach nicht GetLastError hatte sich auch nich beschwert) bis ich auf die Idee kam mal den Windows Taschenrechner in den Ordner zu kopieren wo der Injector liegt danach ging es.

    Du musst den Pfad der DLL absolut angeben, also, wenn zum Beispiel deine Bibliothek im Order C:\Programmierung\C++\DllInjektion\ liegt, musst du alle Ordner auch angeben.

    char *DLL_NAME = "C:\\Programmierung\\C++\\DllInjektion\\myDll.dll"
    

    Wichtig: Denk an die doppelten '\'. Das sind Escape-Characters und wenn du sie nicht doppelt schreibst, weiß Windows nicht was Du meinst bzw. versteht Dich falsch.

    CreateRemoteThread bewirkt, dass ein Thread - ich hoffe mal Du weißt was das ist . - in dem Zielprozess erstellt. Dafür musst du nur die nötigen Rechte für den Process haben, nämlich

    http://msdn.microsoft.com/ schrieb:

    PROCESS_CREATE_THREAD, PROCESS_QUERY_INFORMATION, PROCESS_VM_OPERATION, PROCESS_VM_WRITE, and PROCESS_VM_READ

    . Da der Thread in dem virtuellen Speicherraum des Zielprozesses gestartet wird, hat er auch Zugriff auf mit VirtualAllocEx-allokierten Speicher, womit letztendlich Deine DLL-Injektion funktioniert.

    Ich hoffe ich konnte Dir helfen!
    LG DerCoder


Anmelden zum Antworten