首页
社区
课程
招聘
[求助]如何用delphi 对其它程进行反汇编修改
发表于: 2009-4-24 10:57 4000

[求助]如何用delphi 对其它程进行反汇编修改

2009-4-24 10:57
4000
我想用delphi反汇编更改仙剑 4的游戏。

  其中有一个值是这样 510bed  mov [ecx+66],eax

  我用CE可以把eax改成1或者其它数字。
但是我用delphi  这样写就不对了。为什么。能不能教教我怎么写。

我想更改这段汇编代码  .而且我如何能把eax改成我需要的数。比如。我填1  ecx+66的值就是1  输入4就把4传给他。

procedure TForm_main.Bu tton15Click(Sender: TObject);
var
      Address:pointer;
begin

    Address:=Pointer($510bed  );
    asm
      pushad
      mov [ecx+00000066],1
      popad
      end;

end

希望高手们有时间。帮忙解释一下原理就可以了。

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (9)
雪    币: 2110
活跃值: (21)
能力值: (RANK:260 )
在线值:
发帖
回帖
粉丝
2
不不懂DELPHI的内嵌汇编,单从汇编语法上,你的代码存在以下问题:

如果没有寄存器操作数而使用立即数来写入内存单元,需要指出内存操作数的位宽度

mov dword ptr [ecx+00000066],1

因为eax是32位寄存器,用eax时已经包含了位宽信息,所以不用写dword ptr ,而用立即数时不包含位宽信息,所以必须显式地写出来。
2009-4-24 12:40
0
雪    币: 124
活跃值: (54)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
书大哥,你能回我贴真是荣幸。我是这样的。这段代码我是在玩仙剑4里面。找到的一个地址。

用的是CE。然后找到谁在读这个地址。  出来了这一段。然后我在CE里面直接修改了。可以实现我想要的效果。让ecx+66  的结果等于我想给的值。

  我只是想问。如果像这种代码段。如果通过程序来直接修改他。可以实现吗?需不需要找什么基址之类的?
2009-4-24 13:15
0
雪    币: 2110
活跃值: (21)
能力值: (RANK:260 )
在线值:
发帖
回帖
粉丝
4
如果你想直接修改程序代码,这两条指令的长度不同。

“mov [ecx+0x66],eax” 是3个字节,而“mov dword ptr [ecx+0x66],1” 是8个字节。所以,必须通过jmp的方式来实现。

而且你在自己的程序中asm的代码,并不对其它进程产生任何影响啊!

你要实现自己控制写入的值,可以通过修改CONTEXT中的EAX来间接地实现。

或者,通过直接将机器码写入目标进程的代码段中来实现。

你用asm写的代码是在自己的进程中,不是在目标进程中。
2009-4-24 13:33
0
雪    币: 124
活跃值: (54)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
我是用的看雪大哥在加密解密里面用的DLL劫持方法。让仙剑程序呼出我的DLL。。如果是这样。是不是可以当作是它的程序?
2009-4-24 13:35
0
雪    币: 124
活跃值: (54)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
还有。如果您不忙的话。能不能写一段示例给我看下。不论是什么语言都行。我只是想学习一下。谢谢了。
2009-4-24 13:38
0
雪    币: 2384
活跃值: (766)
能力值: (RANK:410 )
在线值:
发帖
回帖
粉丝
7
// CE具有将汇编指令转换成机器码的能力,所以你可以在CE里直接使用汇编指令修改程序。而Delphi可不带有这个功能。像你这样写只是你的Delphi程序有这段代码存在,和你要修改的程序完全没有关系联系。要修改其他程序,要像下面的代码那样写才行(注:下面的代码机器码指令长度比原来的指令长度要长,肯定会破坏你的游戏后面的指令完整性,如果你修改时不注意这个,估计这样修改会Down掉你的游戏,而如果你在CE里这样修改不会出错,应该是CE里用NOP处理了被破坏的指令,这样做结果程序是不会Down掉,但执行指令也肯定已经缺少一两条指令了。

var lpAsmByte:Array[1..7] of Byte = ($C7,$41,$66,01,00,00,00); // 全局变量,是mov DWORD ptr [ecx+66],1的机器码

var dwProcessID,NumberOfBytesWritten:DWORD;
      hProcess:THANDLE;
begin
   hWindow := FindWindow('游戏窗口类名','游戏窗口标题名');  // 根据游戏窗口类名或游戏窗口标题名找到要修改的游戏窗口句柄。
  GetWindowThreadProcessId(hWindow,dwProcessID); // 取得游戏窗口进程ID
   hProcess := OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwProcessID); // 打开游戏进程,以便下面进行修改游戏。
  WriteProcessMemory(hProcess,Pointer($510bed),@lpAsmByte,sizeof(lpAsmByte),NumberOfBytesWritten); // 在510bed处写入mov dword ptr [ecx+66],1指令。
end;
2009-4-24 13:56
0
雪    币: 2110
活跃值: (21)
能力值: (RANK:260 )
在线值:
发帖
回帖
粉丝
8
如果已经进入了目标进程的地址空间,事情就比较简单了。

以下代码没有经过测试,仅供参考,注意红字部分需要根据具体程序进行修改:

// 这是要修改的地址
const	void*	patchAddress		= 0x510bed;

// 这是下一条指令的地址,我们的代码执行完成后要回到这里
const	void*	nextInstructionAddress	= [COLOR="Red"]0xXXXXXXXX[/COLOR];


// 这是自已的代码
__declspec(naked)	void	MyHook(void)
{
	__asm
	{
		// [COLOR="Red"]这里要先补上被JMP指令破坏的指令[/COLOR]
		mov	dword ptr [ecx+0x66], 1
		push	nextInstructionAddress
		retn
	}
}


// 执行这个函数来修改代码
void	InstallPacth(void)
{
	
	*(BYTE*)(patchAddress)		= 0xE9;						// opcode of JMP
	*(DWORD*)(patchAddress+1)	= (DWORD) ((void*)MyHook - (patchAddress + 5));	// offset of JMP
	
}
2009-4-24 14:14
0
雪    币: 124
活跃值: (54)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
谢谢小虾大哥和书大哥,受益颇多。非常感谢。
2009-4-24 14:42
0
雪    币: 129
活跃值: (31)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
有必要这么麻烦吗?

mov [ecx+66],eax

这么一句,要把EAX给定一个自定义的值..很多方法..也可以直接给内存敷值...

比如当时ecx = 00400000..

那就可以这样 00400000+66 = 00400066

可以直接把你要的数值写进00400066下就实现了,和上面这段代码没区别啊.
他就是一个敷值而已..

或许只有当运行这个函数时,才可以给这个内存敷值才会有效果,那你可以把这段汇编改一下,
改成CALL  你的函数指针,当程序运行到这里的时候去调你的一个函数,然后你可以随便给一个值写进那内存就行了...
2009-4-24 17:05
0
游客
登录 | 注册 方可回帖
返回
//