怎样实现在“内存”和“缓存”中查找字符串并替换?
例如:一运行中的软件有“鸳鸯刀”,我在内存中找到后如何才能把它修改为“流星剑”。
好象动态汉化的软件也是这样的吧!
麻烦高手给段示例代码!谢谢

解决方案 »

  1.   

    参考远程线程插入的相关帖子,进到进程的地址空间,才可以合法访问。
    《windows核心编程》里讲的很清楚了。自己看看。
      

  2.   

    留下EMAIL吧。给你点参考的。没现成的。哈哈
      

  3.   

    //Author : FF.Blue Light at KiboSoft
    //Ver : 1.0
    unit ProcessMemExpand;interfaceuses
      Windows;Function  OpenProcessMemory(PID : integer) : integer;
    Function  ChangeMemory(OldValue , NewValue : String) : integer;
    Procedure CloseProcessMemory;implementationvar
      BaseAddress : array of Pointer;
      RegionSize  : array of integer;
      Readed      : Boolean = False;
      PHandle     : THandle;Function  OpenProcessMemory(PID : integer) : integer;
    var
      StartPos    : LongWord;
      Buffer      : TMemoryBasicInformation;
      SysInfo     : TSystemInfo;
    begin
      Result := -1;
      GetSystemInfo(SysInfo);
      StartPos  := LongWord(SysInfo.lpMinimumApplicationAddress);
      ZeroMemory(@Buffer,Sizeof(Buffer));
      PHandle := OpenProcess(PROCESS_ALL_ACCESS,True,PID);
      //如果要申请特权,写在这里
      if PHandle<=0 then exit;
      SetLength(BaseAddress,0);
      SetLength(RegionSize,0);  while not VirtualQueryEx(PHandle,
                            Ptr(StartPos),
                            Buffer,
                            Sizeof(Buffer))>0 do begin
        StartPos := LongWord(Buffer.BaseAddress) + LongWord(Buffer.RegionSize);
        if StartPos > LongWord(SysInfo.lpMaximumApplicationAddress) then Break;
        if Buffer.State = MEM_COMMIT then begin
          if BOOL(Buffer.Protect and (PAGE_READWRITE or PAGE_EXECUTE_READWRITE or PAGE_EXECUTE_WRITECOPY)) Then begin
            SetLength(BaseAddress,Length(BaseAddress)+1);
            BaseAddress[High(BaseAddress)] := Buffer.BaseAddress;
            SetLength(RegionSize,Length(RegionSize)+1);
            RegionSize[High(RegionSize)] := Buffer.RegionSize;
          end;
        end;
      end;
      Result := 0;
      Readed := True;
    end;Function  PosStr(Key , Sour : PChar; KeyLen , SourLen : integer) : integer ; stdcall;
    asm
      PUSH ESI;
      PUSH EDI;
      PUSH EBX;
      PUSH ECX;
      PUSH EDX;  MOV  ESI , [Sour];
      MOV  EDI , [Key];
      MOV  ECX , 0;
      MOV  EAX , 0;
      MOV  BL  , [EDI];  @Loop1:
        CMP  EAX , SourLen;
        JZ   @NoFindExit;
        CMP  BL , ESI[EAX];
        JNZ  @NextLoop;
          MOV  EDX , 0;
          @Loop2:
            CMP  EDX , KeyLen;
            JZ   @ExitThisProc;
            MOV  ECX , EDX;
            ADD  ECX , EAX;
            MOV  BH , ESI[ECX];
            CMP  BH , EDI[EDX];
            JNZ  @ExitLoop2;
            INC  EDX;
            JMP @Loop2;
          @ExitLoop2:
        @NextLoop:
        Inc  EAX;
        JMP  @Loop1;   @NoFindExit :
        MOV  EAX , -1;
      @ExitThisProc:
      
      POP  EDX;
      POP  ECX;
      POP  EBX;
      POP  EDI;
      POP  ESI;
    end;
    Function ChangeMemory(OldValue , NewValue : String) : integer;
    var
      Buf : PChar;
      i , Len , Pos : integer;
      lpNumberOfBytesRead : DWORD;
    begin
      if Not Readed then begin
        Result := -1;
        Exit;
      end;
      Result := 0;
      Len := Length(OldValue);  for i:=0 to High(BaseAddress) do begin
        GetMem(Buf,RegionSize[i]);
        ZeroMemory(Buf,RegionSize[i]);
        ReadProcessMemory(PHandle,BaseAddress[i],Buf,RegionSize[i],lpNumberOfBytesRead);
        if lpNumberOfBytesRead>0 then begin
          Pos := PosStr(@OldValue[1],Buf,Len,RegionSize[i]);
          if Pos<>-1 then begin
            WriteProcessMemory(PHandle,
                               Ptr(LongWord(BaseAddress[i])+LongWord(Pos)),
                               @NewValue[1],
                               Len,
                               lpNumberOfBytesRead);
          end;
        end;
        FreeMem(Buf);
      end;
      
    end;Procedure CloseProcessMemory;
    begin
      CloseHandle(PHandle);
      SetLength(BaseAddress,0);
      SetLength(RegionSize,0);
      Readed := False;
    end;end.
      
    //使用时首先调用打开,然后修改,然后关闭就OK了
    注意新旧字符串最好一致,否则将要覆盖其他地方。