Entwickler-Ecke

Windows API - DLL injection


uall@ogc - So 29.08.04 22:08
Titel: DLL injection
ich mach mal nen neuen thread auf / diesmal gehts im DLL laden in anderen prozessen,
leider gehts nicht mit CreateRemoteThread auf win98/95 bzw. OpenThread und es fehlt ebenfalls VirtualAllocEx

aber hab hier mal was gebastelt ;>
morgen gibbet den code für die eigentliche DLL injection


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
function FindProcess(ExeNames: pchar): cardinal; stdcall;
{findet einen prozess mit hilfe des EXEnamen,
man kann mit dem semikolon auch mehrere exenamen angeben
rückgabe wert ist ein NICHT geöffneter prozess -> OpenProcess benutzen}


function myCreateRemoteThread(pid: cardinal; addr: pointer; NTuseCRT: boolean): cardinal; stdcall;
{erstellt anhand der prozess id (egal ob geöffneter prozess oder nicht)
einen thread in diesem prozess,
PID = prozessID
addr = startadresse des threads
NTuseCRT = wenn wahr dann benutzt ein NT system CreateRemoteThread
bei win98/95 wird diese variable ignoriert}


function isNT: boolean; stdcall;
{wenn NT system dann WAHR ansonsten FALSCH}

function myVirtualAllocEx(pid: cardinal; Size: cardinal): pointer; stdcall;
{Reserviert speicher in einem prozess,
PID: prozessID
Size: speichergröße die reserviert werden soll
rückgabewert ist die adresse des reservierten speichers}



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:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
function FindProcess(ExeNames: pchar): cardinal; stdcall;
  function ExtractFileName(s: String): string;
  var i, j: integer;
  begin
    j := 1;
    for i := 1 to length(s) do
      if (s[i] = '\'then j := i;
    s := copy(s,j,length(s));

    for i := 1 to length(s) do
      if (s[i] = '.'then j := i;
    if j = 1 then j := length(s);
    result := copy(s,1,j-1);
  end;
  function DeleteExe(s: string): string;
  var i, j: integer;
  begin
    setlength(result,length(s));
    result := '';
    j := 0;
    for i := 1 to length(s) do
    begin
      if (copy(s,i,5) = '.EXE;'then
        j := 4;
      if (j > 0then
        dec(j) else result := result+s[i];
    end;
  end;
var
  FSnapshotHandle: THandle;
  FProcessEntry32: TProcessEntry32;
  ContinueLoop: BOOL;
  exesearch,exeprocess: string;
  i: integer;
begin
  result := 0;
  exesearch := deleteexe(uppercase(';'+exenames+';'));
  FSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
  FProcessEntry32.dwSize := Sizeof(FProcessEntry32);
  ContinueLoop := Process32First(FSnapshotHandle,FProcessEntry32);
  while ContinueLoop do
  begin
    exeprocess := uppercase(extractfilename(FProcessEntry32.szExeFile));
    i := pos(exeprocess,exesearch);
    if (i <> 0and
       (exesearch[i-1] = ';'and
       (exesearch[i+length(exeprocess)] = ';'then
      result := FProcessEntry32.th32ProcessID;
    ContinueLoop := Process32Next(FSnapshotHandle,FProcessEntry32);
  end;
  CloseHandle(FSnapshotHandle);
end;

function isNT: boolean; stdcall;
var
  OSVersionInfo: TOSVersionInfo;
begin
  result := true;
  OSVersionInfo.dwOSVersionInfoSize := SizeOf(OSVersionInfo);
  if GetVersionEx(OSVersionInfo) then
  result := OSVersionInfo.dwPlatformId = 2;
end;

function myVirtualAllocEx(pid: cardinal; Size: cardinal): pointer; stdcall;
var pid2: cardinal;
begin
  pid2 := openprocess(PROCESS_ALL_ACCESS,false,pid);
  if (pid2 <> 0then pid := pid2;
  if (not isNT) then
    result := VirtualAlloc(nil,size,$80000000 or MEM_COMMIT,PAGE_EXECUTE_READWRITE) else
    result := VirtualAllocEx(pid,nil,size,MEM_RESERVE or MEM_COMMIT,PAGE_EXECUTE_READWRITE);
  if pid2 <> 0 then closehandle(pid);
end;

function myCreateRemoteThread(pid: cardinal; addr: pointer; NTuseCRT: boolean): cardinal; stdcall;
  procedure CRTinjectbegin; assembler;
  asm
    push ebx
    push eax

    push eax

    push esp
    push 0
    push 0
    push [00000000]
    push 0
    push 0
    call [00000016]
    pop eax

    mov eax, [00000004]
    mov ebx, [00000008]
    mov [eax], ebx
    add eax, 4
    mov ebx, [00000012]
    mov [eax], ebx

    pop eax
    pop ebx
    jmp [00000004]
  end;
  procedure CRTinjectend; assembler;
  begin
  end;
  //0 = addr create thread
  //4 = addr Translate Message
  //8 = 1. 4 bytes
  //12 = 2. 4 bytes
type tjmpcode = packed record
                JMPbyte: byte;
                distance: cardinal;
              end;

var jmpaddr, memaddr, ct, cpyasm: pointer;
    tid, pid2, old, codesize, written: cardinal;
    cchange: ^cardinal;
    jmpcode: tjmpcode;
begin
  pid2 := openprocess(PROCESS_ALL_ACCESS,false,pid);
  if pid2 = 0 then pid := pid;
  if isNT and NTuseCRT then
  begin
    result := CreateRemoteThread(pid,nil,0,addr,nil,0,tid);
  end else
  begin
    ct := @createthread;
    codesize := cardinal(@CRTinjectend)-cardinal(@CRTinjectbegin);
    result := 0;
    jmpaddr := getprocaddress(getmodulehandle('user32.dll'),'TranslateMessage');
    memaddr := myVirtualAllocEx(pid,5*4+codesize);
    virtualprotect(@CRTinjectbegin,codesize,PAGE_EXECUTE_READWRITE,old);
    if (pid <> 0then
    begin
      virtualprotectex(pid,jmpaddr,8,PAGE_EXECUTE_READWRITE,old);
      getmem(cpyasm,codesize);
      memcopy(cpyasm,@CRTinjectbegin,codesize);
      if (writeprocessmemory(pid,pointer(cardinal(memaddr)+0+codesize),@addr,4,written)) and
        (writeprocessmemory(pid,pointer(cardinal(memaddr)+4+codesize),@jmpaddr,4,written)) and
        (writeprocessmemory(pid,pointer(cardinal(memaddr)+8+codesize),jmpaddr,8,written)) and
        (writeprocessmemory(pid,pointer(cardinal(memaddr)+16+codesize),@ct,4,written)) then
      begin
        cchange := pointer(cardinal(cpyasm)+10);
        cchange^ := cchange^+cardinal(memaddr)+codesize;
        cchange := pointer(cardinal(cpyasm)+20);
        cchange^ := cchange^+cardinal(memaddr)+codesize;
        cchange := pointer(cardinal(cpyasm)+27);
        cchange^ := cchange^+cardinal(memaddr)+codesize;
        cchange := pointer(cardinal(cpyasm)+33);
        cchange^ := cchange^+cardinal(memaddr)+codesize;
        cchange := pointer(cardinal(cpyasm)+44);
        cchange^ := cchange^+cardinal(memaddr)+codesize;
        cchange := pointer(cardinal(cpyasm)+54);
        cchange^ := cchange^+cardinal(memaddr)+codesize;
        jmpcode.JMPbyte := $E9;
        jmpcode.distance := cardinal(memaddr)-cardinal(jmpaddr)-5;
        if (writeprocessmemory(pid,memaddr,cpyasm,codesize,written)) and
          (writeprocessmemory(pid,jmpaddr,@jmpcode,sizeof(jmpcode),written)) then
          result := 1;
      end;
      freemem(cpyasm);
    end;
  end;
  if pid2 <> 0 then closehandle(pid);
end;


Viper - So 29.08.04 22:20

Hallo.

Hast du dazu eine Frage? Ansonsten bist du in der falschen Sparte gelandet.


uall@ogc - Mo 30.08.04 16:48

nein ich habe keine frage, hab ja auch kein rotes ? gesetzt ;>

"Windows API
Alles zur systemnahen Windows-Programmierung mit API-Befehlen (ohne Verwendung von VCLs) auf direktester Ebene."

steht nicht das nur fragen gepostet werden dürfen, wo könnte man deiner meinung nach besser sowas posten? wenn ein neuer user kommt und im forum nach API hook / DLL injection oder sowas sucht, wird er halt mein thema finden und braucht nicht erst noch fragen wie man sowas realisieren kann

wenn ein admin anderer meinung ist und ich sowas nicht mehr (hier) posten soll werde ich mich dran halten :)


Viper - Mo 30.08.04 19:00

Hallo.

Das sieht für mich verflixt nach einer Unit aus. Also würde ich es in die Sparte Open Source Units [http://www.delphi-forum.de/forum_Open+Source+Units_46.html] packen.
Wenn jemand danach sucht, wird er garantiert über die Suchfunktion im Forum deine Unit dann finden.


BenBE - Mo 30.08.04 20:50

Ansonsten bietet sich ja noch ein Verweis im API Hook-Thread an, da dort genau dieses Thema diskutiert wird.


tommie-lie - Mo 30.08.04 22:58

Wenn du so lieb wärst und den Code als vollständige Unit bereitstellst (und nicht als getrennten (und gekürzten) implementation- und interface-Teil), dann verschieb' ich's in die OpenSource-Units. Allerdings wäre es wünschenswert, wenn es dann komplett wäre, wenn du also noch irgendwas diesbezüglich nachliefern willst, du das ;-)


Und VirtualAllocEx() kann man unter Win9x einigermaßen mit MMFs "nachbasteln", zumindest kriegt man so einen Speicherbereich, der von allen anderen Prozessen direkt ohne Address Mapping dereferenzierbar ist.


uall@ogc - Do 02.09.04 18:37

hab ich @ http://www.arschvoll.net/myhook.txt


toms - Di 07.09.04 16:47

Hi,

Ich könnte mir denken, dass einige User ein kleines Anwendungsbeispiel hätten.
Könntest du bei Gelegenheit mal ein Demo App hochladenn?


uall@ogc - Di 07.09.04 21:04

jo wird alles gemacht, muss noch alles kommentierne usw weil das in die unit section komm hab nur wenig eit im mom (bind @ bund) am WE ist was fertig

nen anwendungsbeispiel hier:

http://www.arschvoll.net/blub.rar

is nen wallhack für CS, der Cheatind-Death (anti cheat tool) sicher ist aber im mom nur auf meinem treiber funzt
abr wie man die funktionen beutzt sollte daraus klar sein, aber ich adde noch beispiele wie gesagt ^^


Dwing - Sa 18.12.04 14:43

Funktioniert gut :)
Habe mir damit einen Loader für automatische Screenshots gemacht.

Eine Frage, wie kann ich die DLL als Ressource einbinden?


Delete - Sa 18.12.04 15:07

Ich kann mich schwach daran erinner, dass NicoDE mal CreateRemoteThread für Windows 9x portiert hatte. Aber ich glaube, ich habe das nur mal auf seinem Rechne rgesehen. Veröffentlicht hat er es wohl nicht.


wulfskin - Sa 18.12.04 16:24

Dwing hat folgendes geschrieben:
Funktioniert gut :)
Habe mir damit einen Loader für automatische Screenshots gemacht.

Eine Frage, wie kann ich die DLL als Ressource einbinden?
Ich verweise einfach mal auf Assarbads-DLL-Turorial [http://assarbad.net/de/stuff/tutorials/dll_tutorial/] (Abschnitt: DLL Huckepack).

Gruß Hape!


Dwing - So 19.12.04 15:35

super, danke


EUOCheffe - Do 23.12.04 04:46

...