Autor Beitrag
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Do 09.09.04 16:59 
Ne, das Debug-Priviledge ist nur für Admins verfügbar (oder wenn man's anderen Usern gibt. Bei Delphi funzt das Debuggen auch nur, da die Prozesse die Security-Einstellungen der IDE erben und damit die IDE das Recht hat drauf zuzugreifen.

Um meine Frage mal umzuformulieren: Ich suche was, was es mir erlaubt, die Funktionalität von Assabad's CMD_SVC direkt über nen DLL Injection auszuführen.
Hintergrund: Möchte paar Klassenkammeraden mal etwas verarschen, indem ihre Rechner ferngesteuert runterfahren. Funzt als Admin auf meinem Sys auch ganz fein, jedoch nur, wenn ich mich auf dem Remote-System als Admin authentifiziere (oder anderer Account mit RemoteShutdownPriv) -> Ich muss lokal einen Account haben, der bei Remote-Anmeldung die SeRemoteShutdownPriv hat. Und das ist eben entweder LocalSystem oder Admin. Und da ich den Admin-Account nicht knacken will oder sonstewie die Konfig ändern darf, bleibt nur der Weg über die System-Prozesse.

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Fr 10.09.04 20:28 
Also gut, hab nochmal einen anderen Ansatz versucht, der theoretisch funktionieren sollte, jedoch an den Speicher-Berechtigungen scheitert.

ausblenden volle Höhe 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:
Function HookApi(my, old: Pointer; Var Next: Pointer): Boolean; StdcallAssembler;
Asm
  //Prüfen, ob die Function über statisch per JMP DWORD PTR [] eingebunden ist
  MOV    EAX, DWORD PTR [Old]
  CMP   WORD PTR [EAX], $25FF
  JNZ    @@RetFailure

  //Größe der Routine berechnen
  MOV   ECX, OFFSET @@ASMHookLoader_End
  SUB   ECX, OFFSET @@ASMHookLoader_Start

  //Größe Speichern
  PUSH  ECX

  //Speicher reservieren:
  PUSH  PAGE_EXECUTE_READWRITE      //flProtect
  PUSH   MEM_COMMIT or MEM_RESERVE    //flAllocationType
  PUSH  ECX                //dwSize
  PUSH   $00000000            //lpDesiredAddress
  CALL  VirtualAlloc

  //Größe wieder in Speicher holen
  POP    ECX
  
  TEST   EAX, EAX
  JZ    @@Ret              //EAX = $00000000, daher einfach beenden

  //Routine an entsprechende Stelle im Speicher kopieren
  MOV   EDI, EAX            //Zieladresse setzen
  LEA   ESI, @@ASMHookLoader_Start    //Quelldaten laden
  REPNZ   MOVSB              //Block kopieren

//  //Speicher-Schreibschutz entfernen
//  PUSH  PAGE_EXECUTE_READWRITE      //Vollzugriff auf den Speicherbereich
//  PUSH  MEM_COMMIT AND MEM_RESERVE
//  PUSH  $00000006            //Nur die Jump-Instruction
//  PUSH  DWORD PTR [Old]
//  CALL   VirtualAlloc
//  TEST  EAX, EAX                        //Auf Erfolg prüfen
//  JZ    @@RetProtectionError      ///Fehler bei Zugriffssteuerung
  
  //Zeiger-Daten neu initialisieren
  MOV    EDI, EAX            //Routinen-Block laden
  MOV    ESI, DWORD PTR [Old]      //Jump-Instruction der alten Routine laden
  
  //Zeiger auf alte Prozedur lesen und neu setzen
  MOV    ECX, OFFSET @@ASMHookLoader_OldProc
  SUB    ECX, OFFSET @@ASMHookLoader_Start
  MOV    EDX, DWORD PTR [ESI+$00000002]  //Quellpointer lesen
  MOV   DWORD PTR [ESI+$00000002], EAX  //Neue Funktionsadresse schreiben
  MOV    DWORD PTR [EDI+ECX], EDX    //Zeiger zur alten Prozedur schreiben

//  //Speicher-Schutz zurücksetzen
//  PUSH  MEM_DECOMMIT OR MEM_RELEASE    //Speicher wieder freigeben
//  PUSH  $00000006            //Nur die Jump-Instruction
//  PUSH  DWORD PTR [Old]          //Speicher von LibPtr
//  CALL   VirtualFree                     //Speicher wieder freigeben.
  
  //Zeiger auf neue Prozedure setzen
  MOV    ECX, OFFSET @@ASMHookLoader_ProcPtr
  SUB    ECX, OFFSET @@ASMHookLoader_Start
  MOV    EDX, DWORD PTR [My]        //Zeiger auf neue Procedure lesen
  MOV    DWORD PTR [EDI+ECX], EDX    //Zeiger auf neue Procedure schreiben
  
  //Functionsadresse für Aufruf der alten Funktion zurückgeben.
  MOV    ECX, OFFSET @@ASMHookLoader_JumpInstruction
  SUB    ECX, OFFSET @@ASMHookLoader_Start
  LEA    EDX, DWORD PTR [EDI+ECX]    //Offset ermitteln
  MOV   DWORD PTR [Next], EAX      //Zeiger

  //Set Last Error Code
  PUSH  ERROR_SUCCESS
  CALL  SetLastError

  //Return True
  XOR   EAX, EAX            
  INC    EAX
  JMP   @@Ret

@@ASMHookLoader_Start:
  PUSH  EAX                //Wert von EAX sichern
  CALL  @@ASMHookLoader_GetMemPos    //Aktuelle Position im Speicher lesen
@@ASMHookLoader_Relative:          //Bezugslabel für alle Offsets
  ADD   EAX, OFFSET @@ASMHookLoader_ProcPtr  //Displacement von ProcPtr berechnen
  SUB   EAX, OFFSET @@ASMHookLoader_Relative
  MOV   EAX, DWORD PTR [EAX]            //Adresse der gehookten Funktion lesen
  XCHG  EAX, [ESP]            //Wert von EAX wiederherstellen, Zieladresse für RET setzen
  RET
@@ASMHookLoader_JumpInstruction:      //Daten für die Jump-Instruction für CallNext
  PUSH  EAX                //Wert von EAX sichern
  CALL  @@ASMHookLoader_GetMemPos    //Aktuelle Position im Speicher lesen
@@ASMHookLoader_OldRelative:          //Bezugslabel für alle Offsets
  ADD   EAX, OFFSET @@ASMHookLoader_OldProc  //Displacement von ProcPtr berechnen
  SUB   EAX, OFFSET @@ASMHookLoader_OldRelative
  MOV   EAX, DWORD PTR [EAX]            //Adresse der gehookten Funktion lesen
  XCHG  EAX, [ESP]            //Wert von EAX wiederherstellen, Zieladresse für RET setzen
  RET
@@ASMHookLoader_ProcPtr:          //Zeiger auf neue Procedure\Function
  DD    $00000000
@@ASMHookLoader_OldProc:          //Zeiger auf die alte Procedure
  DD    $00000000
@@ASMHookLoader_GetMemPos:          //Legt die Rücksprungadresse in EAX
  POP   EAX
  PUSH   EAX
  RET
@@ASMHookLoader_End:

@@OldLibraryProtection:            //Variable, die den alten ProtectionStatus
  DD    $00000000            //Des Imports enthält

@@RetProtectionError:
  //Set Last Error Code
  PUSH  ERROR_ACCESS_DENIED
  CALL  SetLastError
  XOR   EAX, EAX
  JMP    @@Ret

@@RetFailure:                //Signal an error
  //Set Last Error Code
  PUSH  ERROR_NOT_SUPPORTED
  CALL  SetLastError
  XOR   EAX, EAX
@@Ret:                    //Ende Routine
End;


Die Auskommentierten Zeilen sind meine Versuche, Windows doch dazu zu bewegen, mir Schreibzugriff auf DWORD PTR [ESI+$02] zu geben, die aber leider Erfolglos blieben.
Die Routine funktioniert nur mit statisch importierten Funktionen (wenn es funzen würde) und behebt ein Problem vom oben aufgeführten API-Hook von uall@ogc, der bei diesen Funktionen zu AccessViolations führt (zumindest bei mir):
ausblenden Testcode mit meinem Versuch GetLastError etwas Windows-Gerechter zu Schreiben
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
procedure TForm1.Button1Click(Sender: TObject);
type
  TGetLastErrorProc = function:DWORD;stdcall;
var
  OldGetLastErr:TGetLastErrorProc;
  function MyGetLastError:DWORD;stdcall;
  begin
    Result := Random(65536);
  end;
begin
  HookApi(@MyGetLastError, @GetLastError, @OldGetLastErr);
  Caption := IntToStr(GetLastError);
  UnHookApi(@OldGetLastErr);
end;

AV kommt, wenn Delphi versucht mit Call TComponent.SetCaption den Text zuzuweisen. Außerdem wird im Import-Modul die nächste Funktion durch die ASM-Routine überschrieben.

Wäre dankbar, wenn sich das mal jemand angucken könnte, um mir Tips zu geben, was ich vor dem Zugriff auf den LibPtr noch beantragen muss.

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
uall@ogc Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1826
Erhaltene Danke: 11

Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
BeitragVerfasst: Sa 11.09.04 11:35 
Naja zu deiner Methode:

1. hat sie mit meiner fast net mehr soviel gemeinsam, deine kann "nur" statische imports hooken, meine sollte (funzt in deinem bsp net) alle APIs hooken können :)

2. crasht deine routine bei mir genauso wie meine ^^

3. solltest auf die OLD funktion am anfang nen virtualprotect machen, kann ja sein das jemand die lese/schreibrechte auf die page genommen hat

4. wünsch ich mir mal nen ASM forum

5. wenn ich falsch liegen sollte dann plz schreiben! ;>

EDIT:
naja wenn ich mir zuerst mal deinen text dazu durchgelesen hätte und ent auf die funktion geguckt hätte, wüßte ich das du shcon auf punkt 1/2 eingegangen bist - *aufschlägewart*

EDIT2:

gnaa wasn das bidde?

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
//   //Speicher-Schreibschutz entfernen 
//   PUSH   PAGE_EXECUTE_READWRITE         //Vollzugriff auf den Speicherbereich 
//   PUSH   MEM_COMMIT AND MEM_RESERVE 
//   PUSH   $00000006                  //Nur die Jump-Instruction 
//   PUSH   DWORD PTR [Old] 
//   CALL    VirtualAlloc 
//   TEST   EAX, EAX                        //Auf Erfolg prüfen 
//   JZ      @@RetProtectionError         ///Fehler bei Zugriffssteuerung


wie willst denn auf nen reservierten speicher nochmal den speicher reservieren?

willst net lieber VirtualProtect nehmen? ;)

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
//   PUSH   EAX
//   PUSH   ESI
//   PUSH   PAGE_EXECUTE_READWRITE         //Vollzugriff auf den Speicherbereich 
//   PUSH   $00000006                  //Nur die Jump-Instruction 
//   PUSH   DWORD PTR [Old] 
//   CALL   VirtualProtect
//   TEST   EAX, EAX                        //Auf Erfolg prüfen 
//   POP    EAX
//   JZ      @@RetProtectionError         ///Fehler bei Zugriffssteuerung



btw. solltest das schon direkt am anfang machen bevor du überhaupt guckst ob die old funktion nen statischer import ist!
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Sa 11.09.04 18:47 
Werd mir das mit dem VirtualProtect mal ansehen. Meld mich evtl. nochmal.

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
uall@ogc Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1826
Erhaltene Danke: 11

Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
BeitragVerfasst: So 12.09.04 14:40 
nur zur info:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
{excpetion, da keine schreibrechte}
procedure _exception;
var p: pointer;
    old: cardinal;
    b: ^byte;
begin
  p := virtualalloc(nil,$1000,MEM_COMMIT OR MEM_RESERVE,PAGE_NOACCESS);
  b := pointer(integer(p)+10);
  b^ := $50;
end;


ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
{keine exception obwohl EXECUTE_READ_WRITE rechte nur auf
  den ersten 6 bytes, windows arbeitet mit seiten (pages)
  die immer $1000 groß sind, von daher ist
  bei virtualprotect(p,6,PAGE_EXECUTE_READWRITE,old);
  die ganze seite beschreibbar}

procedure _noexception;
var p: pointer;
    old: cardinal;
    b: ^byte;
begin
  p := virtualalloc(nil,$1000,MEM_COMMIT OR MEM_RESERVE,PAGE_NOACCESS);
  virtualprotect(p,6,PAGE_EXECUTE_READWRITE,old);
  b := pointer(integer(p)+10);
  b^ := $50;
end;
Kedariodakon
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 30



BeitragVerfasst: Mi 19.01.05 10:38 
morgen :D
Wollte mich mal bedanken für den souce...
Bin gerade dabei das alles zu verstehen :shock:

Aber frage mich gerade, was die Funktion überhaupt bekommt, da sie ja 3 Addressen will...

ausblenden Delphi-Quelltext
1:
function HookApi(my, old: pointer; var next: pointer): boolean; stdcallassembler;					

Und die zum unhooken will auch eine :roll:
ausblenden Delphi-Quelltext
1:
UnhookApi(next: pointer): boolean; stdcallassembler;					


Was bekommen die da übergeben?
Brauch ich noch mehr als die beiden?

Arbeite bisjetzt nur mit der Mad-Komponente, da is das ein klein wenig anders...
Möchte sie aber gern gegen Source ersetzen...

Bin leider kein Licht in Assembeler...

Wie testet ihr die Funktionen? Runtime-debugger? könnt ihr da einen empfehlen?
Hatte früher mal Softice gehabt, war net schlecht, glaub ich zumindest ^^
Aber was nimmt man heute zu WinXP-SP2 Zeiten?


Bye
BeautifulRuby
Hält's aus hier
Beiträge: 1



BeitragVerfasst: Do 20.01.05 01:53 
Kann mir einer ein Beispiel geben, wie man Systemweit ein Hook macht?

Einfach eine veränderte MessageBox-Funktion, wo egal wer MessageBox aufruft, der Inhalt verändert dargestellt wird, also aus "Wollen Sie die Datei speichern?" wird "Wollen Sie die Datei speichern? - TEST!"

Die Demos die ich im Internet gefunden habe, funktionierten bei mir nicht: entweder brauchte man fremdkomponente oder Unit fehlte oder auch System stürzte ab.
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Do 20.01.05 02:46 
BenBE hat folgendes geschrieben:
Ne, das Debug-Priviledge ist nur für Admins verfügbar (oder wenn man's anderen Usern gibt. Bei Delphi funzt das Debuggen auch nur, da die Prozesse die Security-Einstellungen der IDE erben und damit die IDE das Recht hat drauf zuzugreifen.

Und woher erbt das Token des IDE-Prozesses das Privileg? Richtig, von der Logon-Session. Und wenn du als einfacher Benutzer angemeldet bist, läuft die IDE mit deinen Rechten und Privilegien. Und eigene Prozesse darfst du immer debuggen. Ich kann nämlich sehr wohl als benutzer mit dem Delphi Debugger meine Anwendungen debuggen. Mit dem Debug-Privileg darfst du das eben auch für Prozesse, die nicht von dir sind.
uall@ogc Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1826
Erhaltene Danke: 11

Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
BeitragVerfasst: Do 20.01.05 13:40 
@Kedariodakon:

function HookApi(my, old: pointer; var next: pointer): boolean; stdcall; assembler;

my = eigene funktion die aufgerufen werden soll
old = funktion die gehookt werden soll
next = neue funktion die man in der my funktion aufrufen kann

bsp:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
var oldMessageBoxA: function (i: integer; a,b: pchar; j: integer): integer; stdcall;
    nextMessageBoxA: function(i: integer; a,b: pchar; j: integer): integer; stdcall;

function myMessageBoxA(i: integer; a,b: pchar; j: integer): integer; stdcall;
begin
  result := nextMessageBoxA(i,pchar(a+' test'),b,j);
end;

procedure InstallHook;
begin
  @oldMessageBoxA := getprocaddress(getmodulehandle('user32.dll'),'MessageBoxA');
  HookAPI(@myMessageBoxA,@oldMessageBoxA,@nextMessageBoxA);
end;

bei der oldMessageBoxA wird ein jump gesetzt zu myMessageBoxA und damit keine endlosscheife auftritt muss man nextMessageBoxA aufrufen