Entwickler-Ecke

Algorithmen, Optimierung und Assembler - SendInput & Assambler


Terra - Sa 03.06.06 12:25
Titel: SendInput & Assambler
Hallo,

kann mir jemand weiterhelfen, der sich mit Assambler auskennt oder weiss, wie ich diesen Code in Delphi einbinde ???


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
SendInput proc cInputs, nInputs, cbSize
    
    push cbSize
    push nInputs
    push cInputs
    call Tunnel
    ret
    
  Tunnel:
    
    mov eax, 11F6h
    mov edx, 7FFE0300h
    call dword ptr [edx]
    ret 0Ch
    
  SendInput endp


habs schonmal so ausprobiert aber ich bekomm eine Fehlermeldung, das TUNNEL ein undeklarierter Bezeichner ist.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
procedure sendinputtunnel(cInputs, nInputs, cbSize: Word);
begin
  asm
    push cbSize
    push nInputs
    push cInputs
    call Tunnel
    ret
  Tunnel:
    mov eax, 11F6h
    mov edx, 7FFE0300h
    call dword ptr [edx]
    ret 0Ch
  end;
end;


Was muss ich denn bei tunnel noch deklarieren? Kenn mich mit Assambler numal garnicht aus.
Und ist mein vorgehen so überhaupt richtig? Will halt das SendInput von delphi mit dieser Procedure ersetzen.


Terra


Moderiert von user profile iconAXMD: Topic aus Sonstiges (Delphi) verschoben am Sa 03.06.2006 um 12:44
Moderiert von user profile iconAXMD: Code- durch Delphi-Tags ersetzt


BenBE - Sa 03.06.06 12:42

Das Problem mit unbekannten Labels hatten wir gestern erst. Wenn Du in Delphi Labels ohne @ am Anfang angibst, sind dies Prozedur-lokale Label und müssen deklariert werden. Wenn Du ein Label nur innerhalb eines Asm-Blocks brauchst, kannst Du einfach 2 @-Zeichen voranstellen.


Terra - Sa 03.06.06 12:47

Also so: ?


Delphi-Quelltext
1:
2:
3:
4:
  call Tunnel
  ret
  @@Tunnel
  mov eax, 11F6h


dabei macht der mir den gleichen fehler...

Terra

PS: Danke für die schnelle Antwort.

PPS: Ach habs jetzt so gemacht ohne eine Fehlermeldung .. ist das so richtig? Möchte nichts kaputt machen. Wie gesagt, kenne mich mit Assambler kein Stück aus und hab schon viel darüber gehört.
Hab die Procedure rein Instinktiv erstellt und habe eigentlich garkeine Ahnung obs so richtig ist.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
procedure sendinputtunnel(cInputs, nInputs, cbSize: Word);
begin
  asm
    push cbSize
    push nInputs
    push cInputs
    call @@Tunnel
    ret
  @@Tunnel:
    mov eax, 11F6h
    mov edx, 7FFE0300h
    call dword ptr [edx]
    ret 0Ch
  end;
end;


BenBE - Sa 03.06.06 13:02
Titel: Re: SendInput & Assambler
Nein ;-)

Aus
user profile iconTerra hat folgendes geschrieben:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
procedure sendinputtunnel(cInputs, nInputs, cbSize: Word);
begin
  asm
    push cbSize
    push nInputs
    push cInputs
    call Tunnel
    ret
  Tunnel:
    mov eax, 11F6h
    mov edx, 7FFE0300h
    call dword ptr [edx]
    ret 0Ch
  end;
end;

wird einfach

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
procedure sendinputtunnel(cInputs, nInputs, cbSize: Word);
asm
    push cbSize
    push nInputs
    push cInputs
    call @@Tunnel
    ret

@@Tunnel:
    mov eax, 11F6h
    mov edx, 7FFE0300h
    call dword ptr [edx]
    ret 0Ch
end;


Terra - Sa 03.06.06 13:10

Hab ichs also oben doch noch richtig rausbekommen. So schwer ist Assambler ja garnicht. Dann schreib ich jetzt ein Betriebsystem *rofl*

Dann werd ich jetzt mal meine erste Assambler Prozedure ausprobieren... wenn ich mich nie wieder melde könnt ihr euch denken warum ^^

Kannste mir da noch ein bissel weiterhelfen ???

habe in delphi folgenden Aufruf:


Delphi-Quelltext
1:
2:
3:
4:
    Inp.Itype := INPUT_KEYBOARD;
    Inp.ki.wVk := Ord(UpCase(Str[xxi]));
    Inp.ki.dwFlags := 0;
    SendInputTunnel(1, Inp, SizeOf(Inp)); //<----- sende String


Allerdingst sagt mir Delphi jetzt, das bei SendInputTunnel ein (Incompatible type: "Word" and "tagINPUT") besteht. Ich peil das net... was mach ich denn jetzt?

Terra


BenBE - Sa 03.06.06 13:23

Dazu bräuchte ich mal die Deklaration deiner Input-Params.


Terra - Sa 03.06.06 13:28

OK, geb dir mal die relevanten Daten:


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:
procedure sendinputtunnel(cInputs: word; nInputs, cbSize: Word);
begin
  asm
    push cbSize
    push nInputs
    push cInputs
    call @@Tunnel
    ret
  @@Tunnel:
    mov eax, 11F6h
    mov edx, 7FFE0300h
    call dword ptr [edx]
    ret 0Ch
  end;
end;

procedure TForm1.Timer5Timer(Sender: TObject);
var
    wnd5, wnd5_0: HWND;
    mx, my, I, w1, w2, xxi: integer;
    List: TList;
    ProcessId: DWORD;
    bsb1, bsb2: string;
    bsb11, bsb12: pansichar;
    Inp: TInput;
const
   Str: string = 'Terra'// nur test - wird durch edit-einträge ersetzt...
begin
  wnd5_0 := FindWindow('-/-','-/-');
  wnd5_0 := FindWindowEx(wnd5_0, 0'Edit'nil);
  wnd5 :=  FindWindow('-/-''-/-');

  if IsWindowVisible(wnd5_0) then
  if wnd5 <> 0 then
  begin
    Memo1.Lines.Add(find_LoginScreen_txt);
    sleep(200);
    Memo1.Lines.Add('drücke button'); //test
    

 ShowWindow(wnd5, SW_SHOW);

 for xxI := 1 to Length(Str) do
  begin
    // drücken
    Inp.Itype := INPUT_KEYBOARD;
    Inp.ki.wVk := Ord(UpCase(Str[xxi]));
    Inp.ki.dwFlags := 0;
    SendInputTunnel(1, Inp, SizeOf(Inp));

    // loslassen
    Inp.Itype := INPUT_KEYBOARD;
    Inp.ki.wVk := Ord(UpCase(Str[xxi]));
    Inp.ki.dwFlags := KEYEVENTF_KEYUP;
    SendInputTunnel(1, Inp, SizeOf(Inp));

    Application.ProcessMessages;
    Sleep(80);
  end;

   Timer5.Enabled := false;
  end;
end;


Ich hoffe das reicht insgesammt. Ansonsten musst du mir bitte nochmal genau sagen was du bräuchtest.

Terra


BenBE - Sa 03.06.06 13:32

Zeile 2 und 15 MÜSSEN weg, weil Du sonst Probleme mit den Stackframes bekommst. Daher war das bewusst bei mir ohne Begin\End geschrieben ;-)

Anonsten bräuchte ich die Deklaration von TInput.


Terra - Sa 03.06.06 13:47

Achsoooooo .. das ist mir garnicht aufgefallen ^^ *peinlich*

Ömpf ... woher bekomm ich denn die dekleration von TInput? .. das ist doch eine fertige Definition von Delphi oder sehe ich das Falsch? .. In der Hilfe konnte ich auch nix finden.

Oder bin ich jetzt so durch den Wind das ich vor lauter Bäumen den Wald nicht mehr sehe ???
Sorry, aber mich verfolgt ein Problem schon seit über 3 Wochen, wo ich jetzt hoffe mit dem Assambler Code diesen zu lösen.

Terra


BenBE - Sa 03.06.06 13:53

Einfachster Fall: Änder die Deklaration der Prozedur in procedure sendinputtunnel(cInputs: Dword; nInputs: Pointer; cbSize: Integer); ab und ergänze jeweils vor Inp in den Aufrufen ein @-Zeichen (also @Inp)... Dann sollte es gehen.


Terra - Sa 03.06.06 14:13

Herrlich .. keine Fehlermeldung mehr beim compilieren... soweit Danke.

Bekomm jetzt nur noch ein Fehler beim aufruf. (sobald das Programm auf den Assambler-Code zugreifen soll.

Zitat:
Access violation at address 34FD48B. Read of address 34FD48B.


Und nü? Nicht das ich zu faul wäre zu suchen aber in solchen sachen bin ich ein absoluter Noob.

Habs so gemacht wie du sagtest:

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:
procedure sendinputtunnel(cInputs: word; nInputs: Pointer; cbSize: Integer);
  asm
    push cbSize
    push nInputs
    push cInputs
    call @@Tunnel
    ret
  @@Tunnel:
    mov eax, 11F6h
    mov edx, 7FFE0300h
    call dword ptr [edx]
    ret 0Ch
  end;

-----------------------------------------------------

for xxI := 1 to Length(Str) do
  begin
    // press
    Inp.Itype := INPUT_KEYBOARD;
    Inp.ki.wVk := Ord(UpCase(Str[xxi]));
    Inp.ki.dwFlags := 0;
    SendInputTunnel(1, @Inp, SizeOf(@Inp));

    // release
    Inp.Itype := INPUT_KEYBOARD;
    Inp.ki.wVk := Ord(UpCase(Str[xxi])); // setzte ich vor Inp ein @ gibbet ein Fehler
    Inp.ki.dwFlags := KEYEVENTF_KEYUP;
    SendInputTunnel(1, @Inp, SizeOf(@Inp)); // das @ vor Inp geht klar

    Application.ProcessMessages;
    Sleep(80);
  end;


Kannst du mir nur mal nebenbei mal was erklären, da du dich ja anscheinend mit Assambler auskennst.

ich habe das hier im Forum gefunden:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
unction Calc(x: Integer) : Integer;
asm
  MOV ECX, EAX
  JMP @@in

@@sumup:
  ADD EAX, ECX

@@in:
  DEC ECX
  JNZ @@sumup
end;

function Calc2(x: Integer): Integer;
asm
  MOV EDX, EAX
  IMUL EAX, EDX
  ADD EAX, EDX
  SHR EAX, 1
end;


In dem Code sind ja auch Sprunganweisungen angegeben "JMP", "JNZ". Kann ich auch einfach mit JMP @@Tunnel im Assamblercode eingeben anstelle von CALL. Wo liegen da die unterschiede?


Terra


uall@ogc - Sa 03.06.06 14:58

In Delphi gibt es SendInput ganz normal, das ist ein einfacher user32.dll export. Ich weiß nicht was du da für nen krüppel code zusammen bastelst...


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
function SendInput(cInputs: UINT; var pInputs: TInput; cbSize: Integer): UINT; stdcall;
asm
  mov eax, $11F6
  mov edx, $7FFE0300
  call dword ptr [edx]
end;


da ist der Nachbau, Funktioniert nur auf WindowsXP SP2 weils nen Fastcall benutzt


Terra - Sa 03.06.06 15:17

Wie muss man denn den ASM-Code umschreiben, damit er auf allen XP-Rechnern läuft ????

Der "krüppel code" soll den nprotect/GameGuard tunneln, so das ich aus meinem Programm die Login-Daten an das Spiel senden kann. Mit dem normalen SendInput oder was noch von der user32.dll gehandelt wird funktioniert ja net bzw. wird vom GameGuard geblockt.

Da mir bis dato nichts dazu eingefallen ist das Problem zu lösen war ich auf der suche nach alternativen und habe halt den ASM-Code gefunden. Was dabei rausgekommen ist siehste ja oben.

Terra


uall@ogc - Sa 03.06.06 16:15

Schau an welche Servicenummer das unter 2k XPSp1 usw ist. also das MOV EAX, ...


Terra - Sa 03.06.06 16:39

Ich hätte absolut kein Plan wonach ich suchen müsste. Kannst du mir da weiterhelfen ??

Terra


uall@ogc - Sa 03.06.06 18:43

Rufst du das SendInout in deinem oder in dem Programm was geschützt ist auf?


ReDoX - Sa 03.06.06 18:59

user profile iconuall@ogc hat folgendes geschrieben:
Schau an welche Servicenummer das unter 2k XPSp1 usw ist. also das MOV EAX, ...


Wo kann man das denn nachgucken, gibts da ne Liste oder sowas in der Art?


Terra - Sa 03.06.06 20:03

user profile iconuall@ogc hat folgendes geschrieben:
Rufst du das SendInout in deinem oder in dem Programm was geschützt ist auf?


Ich rufe SendInput in meinem Programm auf. Es soll somit ein Text aus einem Edit-Feld an das "Edit"-Feld im geschützem Programm gesendet werden.

Terra


uall@ogc - Sa 03.06.06 20:06

Dann wird das auch nicht mit einem Nachbau der Funktion gehen.


Terra - Sa 03.06.06 22:41

Naja, es sollte ja mit:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
@@Tunnel:
    mov eax, 11F6h
    mov edx, 7FFE0300h
    call dword ptr [edx]
    ret 0Ch
  end;

... getunnelt werden. Aber ich bekomm nur eine Fehlermeldung bei dem aufruf ...

Hat jemand eine Idee wie das anders gelöst werden kann. Irgendwie muss es funktionieren, da ich schonmal ein Programm gesehen habe, der das kann, was ich vorhabe.
(Ich würde es aber gerne selber programmieren)

Terra


uall@ogc - So 04.06.06 14:45

Ich glaube nicht, dass GameGuard in jedem Prozess die funktion hookt bzw zerstört, so dass sie nicht mehr benutzt werden kann. Demnach ist das nachbauen der Funktion sinnlos da du gleich den user32.dll export benutzen kannst. Und wenn der nicht geht, geht der nachbau ebenso nicht. Wenn GameGuard sogar einen Treiber lädt, dann kannst du das mit einem UserMode Programm eh vergessen.

Also schau einfach mal nach ob bei dem user32 export eben dieser code noch steht. Wenn schon brauchste das nicht alles nachbauen, weils dann sinnlos ist. Das kannst du ruhig im Delphi internen Debugger machen.

Und versuch mal Assembler richtig zu schreiben, und schau dir die Grundlagen an. Du versuchst wieder etwas zu 'knacken' was für dich wohl anscheinend noch zu hoch ist.


Terra - Mo 05.06.06 21:37

user profile iconuall@ogc hat folgendes geschrieben:
Ich glaube nicht, dass GameGuard in jedem Prozess die funktion hookt bzw zerstört, so dass sie nicht mehr benutzt werden kann. Demnach ist das nachbauen der Funktion sinnlos da du gleich den user32.dll export benutzen kannst. Und wenn der nicht geht, geht der nachbau ebenso nicht. Wenn GameGuard sogar einen Treiber lädt, dann kannst du das mit einem UserMode Programm eh vergessen.

Also schau einfach mal nach ob bei dem user32 export eben dieser code noch steht. Wenn schon brauchste das nicht alles nachbauen, weils dann sinnlos ist. Das kannst du ruhig im Delphi internen Debugger machen.

Und versuch mal Assembler richtig zu schreiben, und schau dir die Grundlagen an. Du versuchst wieder etwas zu 'knacken' was für dich wohl anscheinend noch zu hoch ist.


Wie auch immer ... ich weis, das mein Programm den Text sendet. Ich habs mal mit dem Texteditor von Windows probiert und dort hats geklappt ...

Zitat:
da du gleich den user32.dll export benutzen kannst.

Ich gehe mal davon aus, du meinst die eingebaute Funktion in der user32.dll, die dazu verwendet werden kann die SendInput Funktion auszuführen.

Kann dazu nur sagen, die wird wohl vorhanden sein.

Zitat:
Wenn GameGuard sogar einen Treiber lädt, dann kannst du das mit einem UserMode Programm eh vergessen.

Erlich gesagt habe ich davon kein Plan wie ich das ändern kann aber gehen muss es da es andere auch geschafft haben. Wie kann ich allerdingst nicht sagen.

Zitat:
Du versuchst wieder etwas zu 'knacken' was für dich wohl anscheinend noch zu hoch ist.

Das mag wohl so sein aber wozu gibt es solche Foren hier wo man sich Informationen verschaffen kann, die andere evtl. schon kennen? Oder sind alle so egoistisch und wollen ihre Erfahrungen für sich behalten. Wenn das so ist hab ich wohl das falsche Forum erwischt.

Ich habe mir von der ganzen Sache nur erhofft, das jemand die gleichen erfahrungen gemacht hat und mir da weiterhelfen könnte. Vielleicht einfach auch nur sagen könnte, das ich an der ganzen Sache falsch drangehe und wie ich es besser machen könnte.

Ich habe mich halt bemüht und schon (wie schonmal gesagt) über Wochen hinweg nach eine Lösung gesucht. Nur dabei ist es halt auch geblieben.
Ich bin eigentlich ein Designer und kein Programmierer. Nur es Interessiert mich halt knifflige Sachen zu Lösen. Sei es wie man "a" und "b" multipliziert oder wie man den GameGuard umgehen kann. Auch wenn ich von anderen die Hilfe benötige aber da sind wir ja schon wieder beim obrigen Thema.

Wie auch immer. Vielleicht ist jemand so Frei und hilft mir weiter.

Terra


uall@ogc - Mi 07.06.06 18:32

Es gibt eine Funktion "SendInput" die du einfach benutzen kannst. Funktioniert das nicht, so brauchst du diese auch nicht nachbauene (das macht der Assembler code von dir). Da du diese ja in deinem Programm aufrufst, wird sie sofern GameGuard nur im Usermode läuft dort nicht gehookt sein, und sollte somit funktionieren. Hat GameGuard einen Treiber, brauchst du gar nicht erst mit einem Usermode Programm anfangen, es wird dir nichts bringen.
Und um programmieren zu lernen, sollte Delphi erstmal reichen, da brauchst du weder Assembler noch gleich GameGuard umgehen.