首页
社区
课程
招聘
[旧帖] [原创]新思路。自写[仙剑奇侠传4]无限物品修改器过程及代码 0.00雪花
发表于: 2010-7-11 10:12 1440

[旧帖] [原创]新思路。自写[仙剑奇侠传4]无限物品修改器过程及代码 0.00雪花

2010-7-11 10:12
1440
这个是半年多前写的了,今天第一次发贴,看看能不能混个邀请码。嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿

    有天同学下了一个仙剑奇侠传4,我也就顺手拿来玩完了。刚开始还好,东西啊什么的都够用,到后来就麻烦了,打BOSS时东西总是不够吃,无奈拿出金山游侠修改,郁闷的是竟然找不到内存地址,试了几次还是不行,后来上网找了个FPE修改器终于找到了,哈哈,然后我把物品的数量调到几万,本来想着这辈子都吃不完了,谁知道当我用了一个之后,他竟然变成99个了,看来有限制。想想还是算了,以后用修改器锁定就行了,然后保存地址,关机。等到晚上再来玩时,发现修改器竟然不能修改了,我以为是修改器的问题,可是试了很多次还是不行,上网看了看,才发现是因为游戏的地址会变的缘故,有些人还提供了一些地址,说是有50%的机会是对的,可是我试了很多次就是没办法修改。
    后来想到一种方法,就是你内存地址会变,难道你游戏代码还会变么?只要找到你修改内存的代码在哪不是就行了么?于是用OD载入,进入游戏之后用FPE找出现在内存的地址,回到OD中,去到刚才找到的地址下内存写入断点,回到游戏中使用一次那个物品(后来发现使用什么都可以),游戏被OD断了,记下那个地址。这时已经可以很清楚的看到ECX寄存器中就是我们使用的物品的数量了,下面就简单了,写个小程序在那里下断点,断下来之后修改ECX寄存器的内容就行了。
    我写了一个,但是好像这里不可以上传附件,那我还是贴一段代码吧,DELPHI7+WINXP下正常。技术有限,代码写得很差,大家将就着看吧。
    对了,还有一个问题,这个游戏好像加过壳,用OD可以跟到入口点,但是脱壳时会弹出一个框框,大意就是什么打击盗版之类的话,然后OD就挂了。壳脱不了就不脱了,在写的程序里加了一段代码,就是等你壳脱完了在修改代码下断点,哈哈,偷懒了。。

program PAL4change;

uses
  windows,SysUtils;

{$R *.res}
var
  hOpen:thandle;

  function OpenThread(dwDesiredAccess: DWORD; bInheritHandle: BOOL; dwThreadId: DWORD): THandle; stdcall;external 'kernel32' name 'OpenThread';

function Find:bool;
var
  read:byte;
  lpNumberOfBytesWritten: DWORD;
begin
  result:=true;
  while true do
    begin
      ReadProcessMemory(hOpen,pointer($4C6B03),@read,1,lpNumberOfBytesWritten);
      if read=$5D then
        begin
          read:=$cc;
          writeprocessmemory(hOpen,pointer($4C6B03),@read,1,lpNumberOfBytesWritten);
          exit;
        end;
      sleep(1000);        //每过一秒钟检查一次是否脱完壳,反正从开始到进入游戏时间长的很
    end;
end;

var
  si:STARTUPINFO;
  pi:PROCESS_INFORMATION;
  cc:context;
  d:DEBUG_EVENT;
  ht:thandle;
  write:byte;
  lpNumberOfBytesWritten: DWORD;
  id: DWORD;
begin
  ZeroMemory(@si, sizeof(si) );
  si.cb := sizeof(si);
  CreateProcess( nil,'PAL4.exe',nil,nil,FALSE,DEBUG_PROCESS,nil,nil,si,pi );
  hOpen:=OpenProcess(process_all_access,FALSE,pi.dwProcessId);
  if hopen<>0 then
    begin
      Createthread(nil,0,@find,nil,0,id);
      WaitForDebugEvent(d,INFINITE);
      while d.dwDebugEventCode<>EXIT_PROCESS_DEBUG_EVENT do
        begin
          if d.dwDebugEventCode=EXCEPTION_DEBUG_EVENT then
            begin
              ht:=OpenThread($FF,FALSE,d.dwThreadId);
              cc.ContextFlags:=CONTEXT_FULL;
              GetThreadContext(ht,cc);
              if cc.Eip=$4C6B04 then
                begin
                  cc.Ecx:=1234567;
                  write:=$5d;
                  writeprocessmemory(hOpen,pointer($4C6B03),@write,1,lpNumberOfBytesWritten);
                  write:=$cc;
                  writeprocessmemory(hOpen,pointer($4C6B04),@write,1,lpNumberOfBytesWritten);
                  cc.Eip:=cc.Eip-1;
                  SetThreadContext(ht,cc);
                end;
              if cc.Eip=$4C6B05 then
                begin
                  write:=$cc;
                  writeprocessmemory(hOpen,pointer($4C6B03),@write,1,lpNumberOfBytesWritten);
                  write:=$89;
                  writeprocessmemory(hOpen,pointer($4C6B04),@write,1,lpNumberOfBytesWritten);
                  cc.Eip:=cc.Eip-1;
                  SetThreadContext(ht,cc);
                end;
            end;
          ContinueDebugEvent(d.dwProcessId,d.dwThreadId,DBG_CONTINUE);
          WaitForDebugEvent(d,INFINITE);
        end;
      ContinueDebugEvent(d.dwProcessId,d.dwThreadId,DBG_CONTINUE);
    end;
end.

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//