游戏程序每次启动后,它的某个参数所在的内存地址都会改变,我想写个内存修改器,主要任务是确定那个参数所在的内存地址,我认为,虽然每次地址都会改变,但是相对于整个游戏程序的内存起始地址应该是固定的吧。那么我想,只要找到了游戏程序在内存中的起始地址,就可以根据偏移量得到我所要的参数的内存地址了,关键是这个程序在内存中的“起始内存地址”可以得到吗?如何得到?
谢谢各位的帮助

解决方案 »

  1.   

    内存修改器,是你给个值然后找到存那个值的地址,只好帮你UUP啊
      

  2.   

    copymemory这个api函数的作用最大,具体的内容可以参看www.google.com的具体搜索内容!
      

  3.   

    不是的,源码空间有个游戏修改器,你可以下载看看,不过它用了Rx Lib,写得还算能用
      

  4.   

    // 读取内存进程空间内的数据
    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      StdCtrls, Mask, tlhelp32;type
      TForm1 = class(TForm)
        Button1: TButton;
        Memo1: TMemo;
        ComboBox1: TComboBox;
        MaskEdit1: TMaskEdit;
        Label1: TLabel;
        Label2: TLabel;
        MaskEdit2: TMaskEdit;
        Label3: TLabel;
        procedure Button1Click(Sender: TObject);
        procedure FormCreate(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
        IsLoad: boolean;
        FSnapshotHandle: THandle;
        function GetProcessID(var List: TStringList; FileName: string = ''): TProcessEntry32;
      end;var
      Form1: TForm1;
    implementation{$R *.DFM}function HexToInt(HexStr: string): Int64;
    var RetVar: Int64;
      i: byte;
    begin
      HexStr := UpperCase(HexStr);
      if HexStr[length(HexStr)] = 'H' then
        Delete(HexStr, length(HexStr), 1);
      RetVar := 0;
      for i := 1 to length(HexStr) do begin
        RetVar := RetVar shl 4;
        if HexStr[i] in ['0'..'9'] then
          RetVar := RetVar + (byte(HexStr[i]) - 48)
        else
          if HexStr[i] in ['A'..'F'] then
            RetVar := RetVar + (byte(HexStr[i]) - 55)
          else begin
            Retvar := 0;
            break;
          end;
      end;  Result := RetVar;
    end;procedure TForm1.Button1Click(Sender: TObject);
    var
      FProcessEntry32: TProcessEntry32;
      ProcessID: integer;
      ProcessHandle: THandle;
      lpBuffer: pchar;
      nSize: DWORD;
      lpNumberOfBytes: DWORD;
      i: integer;
      addr:dword;
      s: string;
      List: TStringList;
      mbi_thunk:TMemoryBasicInformation;
      dwOldProtect:dword;  
    begin
      if Combobox1.itemindex = -1 then exit;
      List := TStringList.Create;
      FProcessEntry32 := GetProcessID(List, Combobox1.text);
      if FProcessEntry32.th32ProcessID=0 then exit;
      ProcessID := FProcessEntry32.th32ProcessID;
      Memo1.Lines.Clear;
      memo1.lines.add('Process ID ' + IntToHex(FProcessEntry32.th32ProcessID, 8));
      memo1.lines.Add('File name ' + FProcessEntry32.szExeFile);  ProcessHandle := OpenProcess(PROCESS_ALL_ACCESS, false, ProcessID);
      memo1.Lines.Add('Process Handle ' + intTohex(ProcessHandle, 8));
      Memo1.Lines.Add('虚拟内存中的数据:');
      addr:=HexToInt(MaskEdit1.text);
      nSize:=HexToInt(MaskEdit2.text)-addr+1;
      if HexToInt(MaskEdit2.text)>addr then
      begin
         lpBuffer := AllocMem(nSize);
         if(not ReadProcessMemory(ProcessHandle, Pointer(addr), lpBuffer, nSize, lpNumberOfBytes))
            or(nSize<>lpNumberOfBytes) then
         begin
            showmessage('读数据出错,可能是指定的地址不存在.');
            exit;
         end;
         s:='';
         for i :=0  to nSize-1 do
         begin
           s := s + format('%.2X ',[ord(lpBuffer[i])]);
           {读取内容}
           if ((i mod 16 ) = 15)or(i=nSize-1) then
           begin
              Memo1.Lines.Add(s);
              s := '';
           end;
         end;
         VirtualQueryEx(ProcessHandle,Pointer(addr),mbi_thunk, sizeof(TMemoryBasicInformation));
         VirtualProtectEx(ProcessHandle,Pointer(addr),nSize,PAGE_EXECUTE_READWRITE,mbi_thunk.Protect);
         if(not WriteProcessMemory(ProcessHandle, Pointer(addr), lpBuffer, nSize, lpNumberOfBytes))
             then
         begin
            showmessage('写数据出错,可能是该地址不允许写。如果该处不是Rom,可以通过Ring0或其它特权写该内存。');
         end;
         VirtualProtectEx(ProcessHandle,Pointer(addr), nSize, mbi_thunk.Protect,dwOldProtect);
         FreeMem(lpBuffer, nSize);
      end;
      CloseHandle(ProcessHandle);
      List.free;
    end;function Tform1.GetProcessID(var List: TStringList; FileName: string = ''): TProcessEntry32;
    var
      Ret: BOOL;
      s: string;
      FProcessEntry32: TProcessEntry32;
    begin
      FSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
      FProcessEntry32.dwSize := Sizeof(FProcessEntry32);
      Ret := Process32First(FSnapshotHandle, FProcessEntry32);
      while Ret do
      begin
        s := ExtractFileName(FProcessEntry32.szExeFile);
        if (FileName = '') then
        begin
          List.Add(Pchar(s));
        end
        else if (AnsiCompareText(Trim(s),Trim(FileName))=0) and (FileName <> '') then
        begin
          List.Add(Pchar(s));
          result := FProcessEntry32;
          break;
        end;
        Ret := Process32Next(FSnapshotHandle, FProcessEntry32);
      end;
      CloseHandle(FSnapshotHandle);
    end;procedure TForm1.FormCreate(Sender: TObject);
    var
      List: TStringList;
      i: integer;
    begin
      Combobox1.clear;
      List := TStringList.Create;
      GetProcessID(List);
      for i := 0 to List.Count - 1 do
      begin
        Combobox1.items.add(Trim(List.strings[i]));
      end;
      List.Free;
      Combobox1.itemindex := 0;
    end;end.
      

  5.   

    //2000系统 枚举内存堆unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      StdCtrls,TLHelp32, ComCtrls;
    type
     TForm1 = class(TForm)
        Button1: TButton;
        ComboBox1: TComboBox;
        ListView1: TListView;
        Button2: TButton;
        procedure FormCreate(Sender: TObject);
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
        IsBreak:boolean;
      end;var
      Form1: TForm1;implementation{$R *.DFM}function GetProcessID(var List:TStringList;FileName:string=''):TProcessEntry32;
    var
         Ret : BOOL;
         s:string;
         FProcessEntry32:TProcessEntry32;
         FSnapshotHandle:THandle;
    begin
        FSnapshotHandle:=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
        FProcessEntry32.dwSize:=Sizeof(FProcessEntry32);
        Ret:=Process32First(FSnapshotHandle,FProcessEntry32);
        while Ret do
        begin
          s:=ExtractFileName(FProcessEntry32.szExeFile);
          if (FileName='') then
          begin
             List.Add(Pchar(s));
          end
          else if (AnsicompareText(Trim(s),Trim(FileName))=0)and(FileName<>'')then
          begin
             List.Add(Pchar(s));
             result:=FProcessEntry32;
             break;
          end;
          Ret:=Process32Next(FSnapshotHandle,FProcessEntry32);
        end;
        CloseHandle(FSnapshotHandle);
    end;procedure TForm1.FormCreate(Sender: TObject);
    var
      List:TStringList;
      i:integer;
    begin
      Combobox1.clear;
      List:=TStringList.Create;
      GetProcessID(List);
      for i:=0 to List.Count-1 do
        Combobox1.items.add(Trim(List.strings[i]));
      List.Free;
      Combobox1.itemindex:=0;
    end;procedure TForm1.Button1Click(Sender: TObject);
    var
     FProcessEntry32:TProcessEntry32;
     PID : integer;
     List:TStringList;
     HeapListHandle:Thandle;
     HeapStruct:THeapEntry32;
     HeapList:THeapList32;
     IsHeapFinish,IsListFinish:boolean;
     ListItem:TListItem;
     flagStr:string;
    begin
        Isbreak:=false;
        ListView1.Items.clear;
        if Combobox1.itemindex=-1 then exit;
        List:=TStringList.Create;
        FProcessEntry32:=GetProcessID(List,Combobox1.text);
        if FProcessEntry32.th32ProcessID=0 then exit;
        PID:=FProcessEntry32.th32ProcessID;
        HeapListHandle:=CreateToolhelp32Snapshot(TH32CS_SNAPHeaplist,PID);
        HeapList.dwSize:=sizeof(THeapList32);
        IsListFinish:=Heap32ListFirst(HeapListhandle,HeapList);
        while IsListFinish do
        begin
          Application.ProcessMessages;
          if IsBreak then break;
          HeapStruct.dwSize:=SizeOf(THEAPENTRY32);
          IsHeapFinish:=Heap32First(HeapStruct,PID,HeapList.th32HeapID);
          while IsHeapFinish do
          begin
             Application.ProcessMessages;
             if IsBreak then break;
             try
                 ListView1.Items.BeginUpdate;
                 ListItem:=ListView1.Items.add;
                 ListItem.Caption:=IntTostr(HeapList.th32HeapId);
                 Listitem.SubItems.Add(format('$%p',[Pointer(HeapStruct.dwAddress)]));
                 ListItem.SubItems.add(format('%d字节',[HeapStruct.dwBlockSize]));
                 case HeapStruct.dwFlags of
                   LF32_FIXED:
                      flagStr:='固定块';
                   LF32_FREE:
                      flagstr:='空闲块';
                   LF32_MOVEABLE:
                      flagstr:='可移动块';
                 end;
                 ListItem.SubItems.add(flagstr);
              finally
                 Listview1.Items.EndUpdate;
              end;
             IsHeapFinish:=Heap32Next(HeapStruct);
            end;
           IsListFinish:=Heap32ListNext(HeapListHandle,HeapList);
        end;
        closehandle(HeapListHandle);
        List.Free;
    end;procedure TForm1.Button2Click(Sender: TObject);
    begin
      IsBreak:=true;
    end;end.
      

  6.   

    //读写物理内存 一unit Unit1;interfaceuses
        Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
        Dialogs, StdCtrls,Aclapi,Accctrl;type
        TForm1 = class(TForm)
            Button1: TButton;
        Edit2: TEdit;
            Label1: TLabel;
        Edit1: TEdit;
            Label2: TLabel;
        ListBox1: TListBox;
            procedure Button1Click(Sender: TObject);
        procedure FormCreate(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
        private
        public
        end;
        PUnicodeString = ^TUnicodeString;
        TUnicodeString = packed record
            Length: Word;
            MaximumLength: Word;
            Buffer: PWideChar;
        end;
        NTSTATUS = Integer;
        PObjectAttributes = ^TObjectAttributes;
        TObjectAttributes = packed record
            Length: DWORD;
            RootDirectory: THandle;
            ObjectName: PUnicodeString;
            Attributes: DWORD;
            SecurityDescriptor: PSecurityDescriptor;
            SecurityQualityOfService: PSecurityQualityOfService;
        end;    TZwOpenSection = function(var SectionHandle: THandle;
            DesiredAccess: ACCESS_MASK;
            var ObjectAttributes: TObjectAttributes): NTSTATUS;stdcall;
        TzwClose=procedure(Sectionhandle:Thandle);stdcall;
        TRtlInitUnicodeString = procedure(var DestinationString: TUnicodeString;
            vSourceString: WideString);stdcall;
    const
        STATUS_SUCCESS = NTSTATUS(0);
        STATUS_INVALID_HANDLE = NTSTATUS($C0000008);
        STATUS_ACCESS_DENIED = NTSTATUS($C0000022);
        OBJ_INHERIT = $00000002;
        OBJ_PERMANENT = $00000010;
        OBJ_EXCLUSIVE = $00000020;
        OBJ_CASE_INSENSITIVE = $00000040;
        OBJ_OPENIF = $00000080;
        OBJ_OPENLINK = $00000100;
        OBJ_KERNEL_HANDLE = $00000200;
        OBJ_VALID_ATTRIBUTES = $000003F2;
        ObjectPhysicalMemoryDeviceName = '\Device\Physicalmemory';
        ntdll = 'ntdll.dll';
    var
        ZwOpenSection: TZwOpenSection;
        zwClose:TzwClose;
        RtlInitUnicodeString: TRtlInitUnicodeString;
    var
        Form1: TForm1;
        NtLayer: HMODULE;
    implementation
    {$R *.dfm}
    function NT_SUCCESS(var Status: longint): boolean;
    begin
        result := longint(Status) >= 0;
    end;procedure InitializeObjectAttributes(var p: TOBJECTATTRIBUTES; n: PUNICODESTRING;
        a: DWORD; r: Thandle; s: PSecurityDescriptor);
    begin
        p.Length := sizeof(TOBJECTATTRIBUTES);
        p.RootDirectory := r;
        p.Attributes := a;
        p.ObjectName := n;
        p.SecurityDescriptor := s;
        p.SecurityQualityOfService := nil;
    end;function SetPhyscialMemorySectionCanBeWrited(hSection:Thandle):boolean;
    var
      pDacl:PACL;
      pNewDacl:PACL;
      pSD:PPSECURITY_DESCRIPTOR;
      dwRes:cardinal;
      ea:EXPLICIT_ACCESS_A;
      label CleanUp;
    begin
          result:=false;
          pDacl:=nil;
          pNewDacl:=nil;
          pSD:=nil;
          dwres:=GetSecurityInfo(hSection,SE_KERNEL_OBJECT,DACL_SECURITY_INFORMATION,nil,nil,@pDacl,nil,pSD);
          if(dwres<>ERROR_SUCCESS)  then
          begin
             goto CleanUp;
          end;
          Fillchar(ea, sizeof(EXPLICIT_ACCESS),0);
          ea.grfAccessPermissions := SECTION_MAP_WRITE;
          ea.grfAccessMode := GRANT_ACCESS;
          ea.grfInheritance:= NO_INHERITANCE;
          ea.Trustee.TrusteeForm := TRUSTEE_IS_NAME;
          ea.Trustee.TrusteeType := TRUSTEE_IS_USER;
          ea.Trustee.ptstrName := 'CURRENT_USER';
          
          dwRes:=SetEntriesInAcl(1,@ea,nil,pNewDacl);
          dwRes:=SetSecurityInfo(hSection,SE_KERNEL_OBJECT,DACL_SECURITY_INFORMATION,nil,nil,pNewDacl,nil);
          if(dwRes=ERROR_SUCCESS) then
          begin
              goto CleanUp;
          end;
          result:=true;
      CleanUp:
          if(pSD<>nil) then
             LocalFree(cardinal(pSD^));
          if(pNewDacl<>nil) then
             LocalFree(cardinal(psD^));
    end;function OpenPhysicalMemory(ReadOrNot:boolean): Thandle;
    var
        status: NTSTATUS;
        physmem: Thandle;
        physmemString: TUnicodeString;
        attributes: TObjectAttributes;
        SectionAttrib:integer;
        physmemName: WideString;
    begin
        result:=0;
        physmemName := ObjectPhysicalMemoryDeviceName;
        RtlInitUnicodeString(physmemString, physmemName);
        InitializeObjectAttributes(attributes, @physmemString,
            OBJ_CASE_INSENSITIVE or OBJ_KERNEL_HANDLE, 0, nil);
        if ReadorNot then
           SectionAttrib:=SECTION_MAP_READ
        else SectionAttrib:=SECTION_MAP_READ or SECTION_MAP_WRITE;
        status := ZwOpenSection(physmem, SectionAttrib, attributes);
        if not ReadorNot then
        begin
           if(status=STATUS_ACCESS_DENIED)then
           begin
              status := ZwOpenSection(physmem,READ_CONTROL or WRITE_DAC,Attributes);
              SetPhyscialMemorySectionCanBeWrited(physmem);
              zwClose(physmem);
              status :=ZwOpenSection(physmem,SectionAttrib,Attributes);
           end;
        end;
        if (not NT_SUCCESS(status)) then
           exit;
        result := physmem;
    end;function MapPhysicalMemory(ReadOrNot:boolean;PhysicalMemory:THandle;Address,
       Length:DWORD;var VirtualAddress: Pchar): boolean;
    var
       Access:Cardinal;
    begin    if ReadOrNot then Access:=FILE_MAP_READ
        else Access:=FILE_MAP_READ or FILE_MAP_WRITE;
        VirtualAddress:=MapViewOfFile(PhysicalMemory,Access,0,Address,Length);
        inc(DWORD(VirtualAddress) , Address mod $1000);
        result:=true;
    end;procedure UnmapPhysicalMemory(Address: Pointer);
    begin
       UnMapViewOfFile(Address);
    end;function LocateNtdllEntryPoints: BOOLEAN;
    begin
        NtLayer := GetModuleHandle(ntdll);
        if NtLayer = 0 then
        begin
            SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
            result := false;
            exit;
        end
        else
        begin
            if not Assigned(ZwOpenSection) then
                ZwOpenSection := GetProcAddress(NtLayer, 'ZwOpenSection');
            if not assigned(zwClose) then
                zwClose:=GetProcAddress(ntlayer,'ZwClose');
            if not Assigned(RtlInitUnicodeString) then
                RtlInitUnicodeString := GetProcAddress(NtLayer,
                    'RtlInitUnicodeString');
        end;
        result := true;
    end;
    //后接
      

  7.   

    谢谢楼上所有的朋友的帮助!
    特别感谢xiangwangz(&lt;*敝屣荣华 浮云生死 此身何惧*&gt;) 兄,你的资料对我帮助很大,谢谢!(结贴)