Ergebnis 1 bis 4 von 4

Thema: Vorgänge in einem Programm automatisieren

  1. #1

    Vorgänge in einem Programm automatisieren

    Aloa liebes PGM Forum,

    Die Vorerklärung:

    für die folgende Problembeschreibung muss ich etwas ausholen. Im Moment arbeiten ein guter Freund und ich mithilfe eines Spieleeditors an einem Freewarespielchen. Dieses besitzt bereits viele fertige Funktionen wie auch z.B. ein Lade/Speichersystem. Diese System kann am Anfang über ein Menü erreicht werden.
    Das ganze sieht in etwa so aus:



    Dieses Menü lässt sich über die Pfeiltasten bedienen. Sobald man per "New Game" ins Spiel gelangt, kann man mit der Funktionstaste "F12" wieder zurück in das abgebildete Menü wechseln. Sobald man "Load Game" anwählt, taucht ein Ladescreen auf. In diesem können mehrere Spielstände ausgewählt werden.


    Was ich nun möchte:

    Ich möchte gerne den Vorgang :

    "F12 drücken -> "Load Game" auswählen -> Enter drücken" automatisieren. Ich müsste also dem Programm auf irgendeine Art und Weise mitteilen das es ins Hauptmenü zurückspringen soll(eventuell ja über F12) und dann entsprechend auf den "Load Game" Eintrag zu navigieren. Dort brauche ich dann noch einen Enter Tastendruck.
    Die Sache ist nun nur: wie soll ich das bewerkstelligen?

    Ich habe ein Programm gesehen welches genau dies tut. Jedoch funktioniert es für die Version des Editors die ich benutze leider nicht. Der Autor des Programms lässt zur Benutzung über ein weiteres Miniprogramm ersteinmal einen Offsetwert ermitteln. Dieser scheint mit der EXE des Spieles zusammenzuhängen. Jedoch beginnt ab hier absolutes Neuland für mich. Wenn er das ganze über den Arbeitsspeicher realisiert, dann weiß ich leider nicht wie er in diesen Vorgang genau ins Rollen bringt.

    Ich erhoffe mir nun also von den Antworten hier das mir jemand einen Weg zeigen kann wie ich die eben beschriebene Automatisierung verwirklichen kann. Ob dies nun über den Arbeitsspeicher passiert oder auf anderem Wege ist mir dabei egal.

    Als kleine Zusatzfrage:

    Das eben erwähnte Editorsystem hat zur Realisierung des eigenen Spiels natürlich auch eine Funktion mit der man Variablen anlegen kann. Diese Variablen sind dabei entweder vom Typ Boolean oder eine Art Integer.
    Kann man diese Variablen die sich wahrscheinlich während der Laufzeit des Programms im Speicher befinden dürften irgendwie auslesen? Kann man eventuell auch die Variablen des Programms im Speicher selbst modifizieren? Während das Programm läuft?


    Das war es dann nun auch endlich mit einer Anfrage. Ich hoffe trotz der Menge an Text auf Antworten. An sich ist mir jeder Weg lieb der hier jemandem einfällt. Falls ich etwas vergessen haben sollte zu erwähnen, dann werde ich es natürlich nennen.


    PS: Bei dem Editor handelt es sich um den RPG Maker 2003. Jedoch geht hierbei ja nicht um den Editor an sich. Hoffe das die Frage damit trotzdem legitim ist. Ich wüsste nicht nämlich außer der Programmierung keine Zuflucht für dieses Problem. Ich habe es selbst schon mit Java versucht. Jedoch bietet dieses leider keine Methoden um den Speicher in irgendeiner Weise auszulesen. :/


    MFG Makenshi

    Geändert von makenshi (17.03.2007 um 12:14 Uhr)

  2. #2
    Wie wäre es mit http://multimediaxis.net/search.php.
    z.B. hier aus diesem Thread
    edit: Ach ja der letze Satz bezog sich darauf das er absolut keine Ahnung hatte und am Ende, wie du selbst lesen kannst, etwas unhöglich wurde.

    Java ist für sowas sowieso fehl am Platz (meiner persönlichen Meinung nach ist Java immer fehl am Platz). Speicherzugriffe kann man recht leicht in C machen, wenn du es einfacher haben willst würde ich Delphi nehmen, wenn du es schwer willst Assembler. Alle drei Sprachen wirst du kostenlos beziehen können (Nur nimm bei C(++) bitte nicht ein Microsoft Produkt, sonst wirst du enttäuscht werden - garantiert).
    Also an sich ist es möglich, aber wenn du schon nicht weißt wie du es machen musst, informiere dich ab Besten vorher über alles mögliche und überlege dir gut ob du wirklich denkst du kannst es, sonst verschwendest du nur deine Zeit.

    Geändert von Crash-Override (17.03.2007 um 16:55 Uhr)

  3. #3
    genau mit dem selben Krempel habe ich mich auch schon fuer den rm2k rumgeschlagen fuer meine Patches .. und bei allen habe ich dann aus Zeitmangel aufgegeben.

    Ich hatte sigar mal eine Loesung fuer F12+runter+enter, aber dort war das Problem dann, dass das timing exakt stimmen musste. Also hab ich die funktion irgendwann ausgebaut, weil es einfach zu kompliziert war, die tastendruecke in exakt dem richtigen moment zu senden.

    Fuer das Load Problem waere es wohl eine loesung, wenn man im Spiel die Addresse der Load Subroutine mit einem Debugger oder einem Disassembler rausbekommen wuerde, und dann in einer dll (z.B. dem Tastenpatch), die vom rm2k geladen wird (-> gleicher addressraum) als funktionspointer aufruft. Allerdings hab ich das noch nicht probiert, da ich mich mit debuggern nicht so sonderlich auskenne und keine Zeit hab zum einarbeiten ...

    Beim rm2k3 sieht es noch schlechter aus, da dort die moeglichkeit wegfaellt, ueber eine DLL freien Zugriff auf die Programmbibliotheken zu bekommen ...

    Das Problem mit dem Aendern der Variablen ist aehnlich vertrackt. Zwar kannst du mit Read/WriteProcessMemory daten lesen und schreiben, das Problem ist allerdings, zu wissen, wo die Daten stehen. Da der maker seinen Speicher dynamisch alloziiert, stehen die bei jedem Start idR wo anders im speicher. Zwar sollte es eine konstante Addresse geben (die pointervariable zum Speicherbereich) die die addresse enthaellt, und ich konnte auch schon die Routine ermitteln (rm2k), in der die Variablen geaendert werden, doch fehlte mir dann zeit und ausdauer, den schritt zu komplementieren.

    Alles in allem ein kompliziertes Problem, selbst fuer mich.

    Ich kann ja mal posten, was ich damals so rausbekommen habe ...
    Vielleicht nuetzt es ja einem. Alle Angaben natuerlich ohne Gewähr.

    Code:
    Speicherauszug aus RPG_RT.EXE
    
    0046a047    8BD6                            mov edx,esi
    0046a049    C1E202                          shl edx,0x2
    0046a04c    8D4328                          lea eax,[ebx+0x28]
    0046a04f    E8DC86F9FF                      call 0x00402730
    0046a054    8B5324                          mov edx,[ebx+0x24]
    0046a057    8BC6                            mov eax,esi
    0046a059    48                              dec eax
    0046a05a    2BC2                            sub eax,edx
    0046a05c    7C0D                            jl short 0x0046A06B
    0046a05e    40                              inc eax
    0046a05f    8B4B28                          mov ecx,[ebx+0x28]
    0046a062    33FF                            xor edi,edi
    0046a064    893C91                          mov [ecx+edx*4],edi
    0046a067    42                              inc edx
    0046a068    48                              dec eax
    0046a069    75F4                            jnz short 0x0046A05F
    0046a06b    897324                          mov [ebx+0x24],esi
    0046a06e    5F                              pop edi
    0046a06f    5E                              pop esi
    0046a070    5B                              pop ebx
    0046a071    C3                              retn
    0046a072    8BC0                            mov eax,eax
    0046a074    83FA01                          cmp edx,0x1
    0046a077    7C05                            jl short 0x0046A07E
    0046a079    3B5024                          cmp edx,[eax+0x24]
    0046a07c    7E03                            jle short 0x0046A081
    0046a07e    33C0                            xor eax,eax
    0046a080    C3                              retn
    0046a081    8B4028                          mov eax,[eax+0x28]
    0046a084    8B4490FC                        mov eax,[eax+edx*4-0x4]
    0046a088    C3                              retn
    0046a089    8D4000                          lea eax,[eax]		eax=eax^	<---- Begin Subrotine ?
    0046a08c    53                              push ebx			speichern ebx
    0046a08d    56                              push esi			speichern esi
    0046a08e    57                              push edi			speichern edi
    0046a08f    8BF9                            mov edi,ecx			edi=ecx
    0046a091    8BF2                            mov esi,edx			esi=edx
    0046a093    8BD8                            mov ebx,eax			ebx=eax
    0046a095    83FE01                          cmp esi,0x1			esi-1
    0046a098    7C15                            jl short 0x0046A0AF		? < 0 goto pops
    0046a09a    3B7324                          cmp esi,[ebx+0x24]		esi - (ebx+0x24)^	<---- Begin Patch
    0046a09d    7E09                            jle short 0x0046A0A8	? <=0 ueberspringe call
    0046a09f    8BD6                            mov edx,esi			edx=esi
    0046a0a1    8BC3                            mov eax,ebx			eax=ebx
    0046a0a3    E898FFFFFF                      call 0x0046A040		Unterprogramm 0046A040
    0046a0a8    8B4328                          mov eax,[ebx+0x28]		eax=(ebx+0x28)^	<---- Ende Patch
    0046a0ab    897CB0FC                        mov [eax+esi*4-0x4],edi     (eax+esi*4-0x4)^=edi --> v[esi]=wert
    0046a0af    5F                              pop edi			reload edi
    0046a0b0    5E                              pop esi			reload esi
    0046a0b1    5B                              pop ebx			reload ebx
    0046a0b2    C3                              retn			fertsch	<---- Ende Subrotine ??
    0046a0b3    90                              nop
    0046a0b4    53                              push ebx
    0046a0b5    56                              push esi
    0046a0b6    8BF1                            mov esi,ecx
    0046a0b8    8BDA                            mov ebx,edx
    0046a0ba    6A01                            push 0x1
    0046a0bc    56                              push esi
    0046a0bd    8B0DE4AE4900                    mov ecx,[0x49AEE4]
    0046a0c3    BADCA04600                      mov edx,0x46A0DC
    0046a0c8    8BC3                            mov eax,ebx
    0046a0ca    E899F8FEFF                      call 0x00459968
    0046a0cf    5E                              pop esi
    0046a0d0    5B                              pop ebx
    0046a0d1    C3                              retn
    0046a0d2    0000                            add [eax],al
    0046a0d4    FFFF                            ???
    0046a0d6    FFFF                            ???
    0046a0d8    050000004D                      add eax,0x4D000000
    0046a0dd    7573                            jnz short 0x0046A152
    0046a0df    6963000000558B                  imul esp,[ebx],0x8B550000
    0046a0e6    EC                              in al,dx
    0046a0e7    83C4F8                          add esp,-0x8
    0046a0ea    53                              push ebx
    0046a0eb    56                              push esi
    0046a0ec    33DB                            xor ebx,ebx
    0046a0ee    895DF8                          mov [ebp-0x8],ebx
    0046a0f1    884DFF                          mov [ebp-0x1],cl
    
    Patch Ansatz ....
    
    Original:
    0x46A09A:
    3B 73 24 7E 09 8B D6 8B C3 E8 98 FF FF FF 8B 43 28  
    
    Modifiziert:
    0x46A09A:
    90 90 90 90 90 8B D6 8B C3 8B 43 28 A3 9A A0 46 00  
    
    danach steht pointer auf v[1] in 0x46A09A
    
    0x46A09A
    asm original                asm modifiziert
    
    3B                          90  nop         <--- Hier kommt die Addr rein
    73                          90  nop
    24  cmp esi,[ebx+0x24]      90  nop
    7E                          90  nop         <--- 32 Bit = Ende Addresse
    09  jle short 0x0046A0A8    90  nop
    8B                          8B
    D6  mov edx,esi             D6  mov edx,esi
    8B                          8B	
    C3  mov eax,ebx             C3  mov eax,ebx
    E8                          8B
    98                          43
    FF                     +--> 28  mov eax,[ebx+0x28]  <--- Addresse steht nun in eax
    FF                     |    A3
    FF  call 0x0046A040    |    9A
    8B                     |    A0
    43                     |    46
    28  mov eax,[ebx+0x28] +--+ 00	mov [0x46A09A],eax  <--- Addresse speichern in 0x46A09A
    *************************************************************************
    89	
    7C
    B0
    FC	mov [eax+esi*4-0x4],edi
    5F	pop edi
    5E	pop esi
    5B	pop ebx
    C3	retn
    Bitte nicht schlagen .. ich hab den Code vor Jahren geschrieben, und war damals noch dumm und unwissend ^^

    Ziel war es also, beim ersten Aufruf von ChangeVariable im Spiel nach injektion des neuen codes den wert des Pointers zu bekommen. Den habe ich kurzerhand im Programmsegment nops ueberschreiben lassen, weil ich dann genau wusste, wo er steht. nach dem change Variable, wenn ich den pointer hatte, ersetzte ich den veraenderten code wieder durch das original. Das Problem watr aber immer, man brauchte Change Variable dazu, wobei die ausfuehrung exakt einmal kommen musste. wuerde in der zeit vor der wiederherstellung nochmal change variable durchgefuehrt, haette man das Programm ins Nirvana geschickt.

    Das Verfahren hat wirklich funktioniert, allerdings war es mir fuer den allgemeinen Markt zu unsicher.

    Geändert von Ineluki (17.03.2007 um 18:15 Uhr)

  4. #4
    Ersteinmal: vielen Dank an dich Ineluki und auch an Crash-Override.
    Besonderes letzterer hat mir netterweise per Messenger ausgeholfen.

    Im Endeffekt hat sich nun eine entsprechend modifizierte EXE gefunden die die Grundlage bot um die gewünschten Effekte umzusetzen. Mit ein paar Zusatzexen konnten auch die fehlenden Bestandteile eingefügt werden. Im großen und ganzen kann ich mich also nur nochmals bedanken.

    In diesem Sinne -> der Thread kann gern geschlossen werde.

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •