[asm] Czytanie adresu z pamięci

0

Witam,
Dodałem to do działu delphi/pascal, bo chyba w pascalu/delphi jest najczęściej wykorzystywany Assembler, a ja chce zrobić progs w delphi.

Otóż chciałbym się zająć pisaniem programiku podobnego do T-Search, aczkolwiek mniej zaawansowanego, i pomyślałem, że czytanie adresu z pamięci jakiegoś programu możnaby zrobić za pomocą ASM (jednak nie jestem pewien, bo dawno tegoż języka nie używałem). Czy ktoś byłby na tyle miły i mi pomógł?

Dla tych nie wiedzących, co to jest T-Search, jest to program, dzięki któremu możemy wyczytać, zmienić zawartość adresu z pamięci jakiegoś programu (ale się powtarzam), przydatny przy robieniu trainerów do gier. Po więcej info, "Google".

Jak zwykle, z góry thx :D

P.S. Jak coś nadal jest nie jasne, to chętnie wytłumaczę się z mej zbrodni :-)

0

Asm za wiele z tym wspolnego nie ma, wszystko to o ile sie da zrobisz przy pomocy HLLa. Poszukaj na MSDNie jak w Windowsie mapuje sie pamiec innej aplikacji i wsio, potem robisz se wskaznik na cos co chcesz odczytac i juz.

0

nie wiem czy ten kod ci pomoże, na forme tylko 3 guziki jak widać.

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Green: TButton;
    Red: TButton;
    procedure CallModifiedCode(Sender: TObject);
    procedure ModifyCode(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

{$O-} //make sure nop's don't get optimized out of the compiled exe
procedure TForm1.CallModifiedCode(Sender: TObject);
  var b         : boolean;
      frmColour : TColor;
  label 1;
begin
  frmColour := clGreen;
  b         := true;

  { Nastepna linia zostanie zmodyfikowana w pamieci.
    Komentarze pokazuja jak wyglada kod asemblera i jego
    Heksadecymalna reprezentacja.
    Mozesz ustawic breakpoint na nastepna linie i otworzyc Delphi CPU view,
    aby zobaczyc zmiane.
  }


  if b then goto 1;      // "jnz SOME_ADDRESS"  "$75 SOME_ADDRESS"
 {
  Zmodyfikujemy powyzsza linie na:
  "jz SOME_ADDRESS"  "$74 SOME_ADDRESS" co oznacza:
  if NOT(b) then goto 1;
 }


 { Nastepujacy kod asemblera nie robi nic (nop = no operation).
  Jest to poprostu uzyte jako znacznik, aby znalezc pozycje
  skoku powyzej w pamieci
 }

  asm
   nop        // $90
   nop        // $90
   nop        // $90
   nop        // $90
   nop        // $90
   nop        // $90
  end;

  frmColour := clRed;

  1:
    Form1.Color := frmColour;
    
end;


procedure TForm1.ModifyCode(Sender: TObject);

const BUFFMAX=65536;

type TBytes6=Array[0..5] of byte;
     TMemblock=array[0..BUFFMAX-1] of byte;

  Function ReadBufferFromMemory(ad, size:integer; var MB:TMemBlock):cardinal;
  var cnt:cardinal;
  begin
  ReadProcessMemory(Getcurrentprocess, pointer(ad), @MB[0], size, cnt);
  // otrzymana ilosc bajtow odczytanych
  ReadBufferFromMemory := cnt;
  End;

  procedure WriteByteToMemory(ad:cardinal;rt:byte);
  var cnt:cardinal;
      oldprotect:dword;
  begin
  //upewniamy sie,ze mamy dostep do adresu

  VirtualProtect(pointer(ad),sizeof(rt),PAGE_EXECUTE_READWRITE,@oldprotect);
  WriteProcessMemory(Getcurrentprocess, pointer(ad), @rt, sizeof(rt), cnt);
  //przywracamy poprzednia ochrone dostepu
  VirtualProtect(pointer(ad),sizeof(rt),oldprotect,@oldprotect);
  End;

var st         : TBytes6;
    rt         : Byte;
    stcount    : word;
    BytesRead  : cardinal;
    sad,ead,ad : cardinal;
    x,y,z      : cardinal;
    found      : boolean;
    MemBlock   : TMemBlock;
begin
  {definiujemy co ma znalezione - w tym wypadku blok instrukcji
   nop        // $90
   nop        // $90
   nop        // $90
   nop        // $90
   nop        // $90
   nop        // $90}

  st[0]:=$90;       // nop
  st[1]:=$90;
  st[2]:=$90;
  st[3]:=$90;
  st[4]:=$90;
  st[5]:=$90;
  stCount:=6;
  {zmienniamy instrukcje w zaleznosci ktory przycisk zostal wcisniety}

  if (sender = red) then rt := $74  //  asm: jz
                    else rt := $75; //  asm: jnz

  //zakres adresu, ktory ma byc przeszukany
  sad := ($00400000);
  ead := ($7fffffff);
  //aktualny adres
  ad    := sad;
  found := false;
  
  repeat
    // odczyta jeden blok o dlugosci BUFFMAX od aktualnego adresu ad
    BytesRead := ReadBufferFromMemory(ad, BUFFMAX, MemBlock);
    //zadnych bajtow odczytanych;wynosimy sie
    if BytesRead = 0 then break;
    // upewniamy sie, ze nie ominelismy nieczego gdy mamy dwa bloki pamieci;
    If BytesRead = BUFFMAX Then BytesRead := BytesRead-stCount;
    // przeszukujemy Blok Pamieci
    For x := 0 To BytesRead-1 do
        begin
          found := true;
          // sprawdzamy czy znaleziono
          For y := 0 To stCount-1 do
              If MemBlock[x+y] <> st[y] then
              begin
                found := false;
                break;
              end;
          If found Then
          begin
            // to co znalezlismy zaczyna sie od ad+x+y-stcount
            z := ad+x+y-stcount;
            // kod, ktory chcemy zamienic zaczyna sie 2 bajty wczwsniej
            //Zamiana kodu
            WriteByteToMemory(z-2,rt);
            break; // Koniec poszukiwan
          end;
      end;
   ad := ad+BytesRead;
   until (ad >= ead) or found;
end;

end.
0

dzięks, jak tylko będę miał czas, to zobaczę, o co chodzi w twoim kodzie :d.

Nie było na to jakichś gotowych funkcji w delphi przypadkiem?

0

Nie ja to wymyśliłem, więc jak bedziesz miał jakieś pytania co do tego, to nie do mnie. Jest tu kilku "wszystko wiedzących" :D

1 użytkowników online, w tym zalogowanych: 0, gości: 1