Entwickler-Ecke

Windows API - Rückgabewert von LoadLibrary über CreateRemoteThread


Cypher2000 - Fr 07.08.09 19:18
Titel: Rückgabewert von LoadLibrary über CreateRemoteThread
Hallo Delphi-freunde!

Derzeit schlage ich mich mit DLL injections und anderen Dingen rum.


Den folgenden Code habe ich auf irgendeinem Delphi board gefunden (Danke an den Autor! :D ) und an sich funktioniert er auch einwandfrei:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
function TForm1.InjectIntoProcess(lpProcessID: Cardinal; lpDllname: String):Boolean;
var
  hProc: Cardinal;
  oAlloc: Pointer;
  cWPM: Cardinal;
  hRemThread: Cardinal;
begin
  result := false;
  SetLastError(ERROR_SUCCESS);
  hProc := OpenProcess(PROCESS_ALL_ACCESS, false, lpProcessID);
  if hProc <> 0 then
  begin
    oAlloc := VirtualAllocEx(hProc, nil, length(lpDllname), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if oAlloc <> nil then
    begin
      if WriteProcessMemory(hProc, oAlloc, PChar(lpDllName), length(lpDllName), cWPM) = true then
      begin
        CreateRemoteThread(hProc, nil0, GetProcAddress(GetModuleHandle('kernel32.dll'), 'LoadLibraryA'), oAlloc, 0, hRemThread);
        if GetLastError = ERROR_SUCCESS then
        begin
          result := true;
        end;
      end;
    end;
  end;
  CloseHandle(hProc);
end;


Mein Problem ist, dass ich gerne den Rückgabewert der "LoadLibraryA" irgendwie abrufen möchte die in "CreateRemoteThread" aufgerufen wurde. Jedoch habe ich keine Ahnung wie. Zuerst dachte ich das es möglich ist einfach den Rückgabewert von CreateRemoteThread zu übernehmen aber diese Funktion liefert mir ja nur den thread handle zurück, soweit ich das richtig gelesen und verstanden habe.

Kann mir da jemand helfen?

Vielen Dank! :D


AHT - Fr 07.08.09 19:33

An EAX kommst du über GetThreadContext. Ich schau morgen mal nach, ob das geht oder der Wert zu flüchtig ist.


uall@ogc - Sa 08.08.09 15:02

Also wenn die dllmain keine endlosschleife beinhaltet und der Thread beendet ist kannst du mittels WaitForSingleObject auf das Threadende warten. Anschließend mit GetExitCodeThread bekommst du den ExitCode -> der sollte EAX zurückliefern, welches dem DLLHandle entspricht. Ansonsten shcau die mal die ToolHelp-API an (tlhelp32)


Cypher2000 - Di 11.08.09 14:10

Hallo!

Vielen Dank AHT und uall@ogc für eure Hilfe. :)
Leider kann ich mit diesem "EAX" nicht viel anfangen und war auch nicht erfolgreich damit. Aber mit tlhelp32 hab ich dann alles hinbekommen. :) (Hätte ich nur geahnt dass das so einfach geht... ;) )

Falls später jemand danach suchen sollte, hier der Code den ich in ähnlicher Form nach dem Injecten der DLL (siehe oben für Inject code) ausführe:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
procedure TForm1.Button2Click(Sender: TObject);
var
  psnap,msnap: THandle;
  pe32: TProcessEntry32;
  me32: TModuleEntry32;

  buffer: Array [0..255of Byte;
  readbytes: Cardinal;

  foundp: Boolean;
begin
  psnap:=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
  pe32.dwSize := SizeOf(pe32);

  foundp:=false;

  if Process32First(psnap,pe32)=true then begin
    while Process32Next(psnap,pe32) do
      if LowerCase(pe32.szExeFile)='programmname.exe' then begin
        foundp:=true;
        break;
      end;
    CloseHandle(psnap);

    if foundp=true then begin
      me32.dwSize:=sizeof(me32);
      msnap:=CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,pe32.th32ProcessID);
      if Module32First(msnap,me32)=true then begin
        while Module32Next(msnap,me32)=true do begin
          if lowercase(me32.szModule)='dllname.dll' then begin

//an dieser stelle ist oder sollte in me32.modBaseAddr die basis adresse der "dllname.dll" sein die im prozess "programmname.exe" läuft

            break;
          end;
        end;
        CloseHandle(msnap);
      end;
    end;
  end;
end;


Leider weiß ich bis jetzt noch nicht zu 100% ob das alles korrekt läuft, da ich es mit ReadProcessMemory nicht testen kann.
Hier der neue Thread mit dem neuen Problem: http://www.delphi-forum.de/viewtopic.php?p=574073

Also wie gesagt: Vielen Dank für eure Hilfe! :)


uall@ogc - Mi 12.08.09 19:08


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
program test;

uses
  Windows, Sysutils;

{$APPTYPE CONSOLE}

function InjectIntoProcess(lpProcessID: Cardinal; lpDllname: String): DWord;
var
  pWriteProcessMemory: function(hProcess: THandle; const lpBaseAddress: Pointer; lpBuffer: Pointer;
    nSize: DWORD; var lpNumberOfBytesWritten: DWORD): BOOL; stdcall;

  pCreateRemoteThread: function(hProcess: THandle; lpThreadAttributes: Pointer;
    dwStackSize: DWORD; lpStartAddress: TFNThreadStartRoutine; lpParameter: Pointer;
    dwCreationFlags: DWORD; var lpThreadId: DWORD): THandle; stdcall;

  pLoadLibraryA: function(lpLibFileName: PAnsiChar): HMODULE; stdcall;

  hProc: Cardinal;
  oAlloc: Pointer;
  cWPM: Cardinal;
  hRemThread: Cardinal;
  hThreadHandle: Cardinal;
  Modulhandle: Cardinal;

  hKernelhandle: Cardinal;
begin
  Result := 0;
  hKernelHandle := GetModuleHandle('kernel32.dll');
  if hKernelHandle <> 0 then
  begin
    pWriteProcessMemory := GetProcAddress(hKernelHandle, 'WriteProcessMemory');
    pCreateRemoteThread := GetProcAddress(hKernelHandle, 'CreateRemoteThread');
    pLoadLibraryA := GetProcAddress(hKernelHandle, 'LoadLibraryA');
    if (@pWriteProcessMemory <> niland (@pCreateRemoteThread <> niland (@pLoadLibraryA <> nilthen
    begin
      hProc := OpenProcess(PROCESS_ALL_ACCESS, false, lpProcessID);
      if hProc <> 0 then
      begin
        oAlloc := VirtualAllocEx(hProc, nil, length(lpDllname)+1, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
        if oAlloc <> nil then
        begin
          if pWriteProcessMemory(hProc, oAlloc, PChar(lpDllName), length(lpDllName), cWPM) then
          begin
            hThreadHandle := pCreateRemoteThread(hProc, nil0, @pLoadLibraryA, oAlloc, 0, hRemThread);
            if hThreadhandle <> 0 then
            begin
              WaitForSingleObject(hThreadhandle, INFINITE);
              VirtualFreeEx(hProc, oAlloc, 0, MEM_RELEASE);
              if GetExitCodeThread(hThreadHandle, ModulHandle) then
                Result := ModulHandle;
              CloseHandle(hThreadHandle);
            end;
          end;
        end;
        CloseHandle(hProc);
      end;
    end;
  end;
end;

begin
  Writeln(IntToHex(InjectIntoProcess(GetCurrentProcessID, 'opengl32.dll'),8));
  Writeln(IntToHex(GetModuleHandle('opengl32.dll'), 8));
  readLn;
end.


Update:
wichtige Funktionen werden dynamisch geladen, da bei WriteProcessMemory + CreateRemoteThread bei AntiVir ein Virus vermutet wird (da in der Import-Tabelle geladen), dynamisch wird dann nicht mehr gemeckert :)