如何修改内存?(50分)

  • 主题发起人 主题发起人 zhoufujin
  • 开始时间 开始时间
Z

zhoufujin

Unregistered / Unconfirmed
GUEST, unregistred user!
有过程Proceduce AAA;
已经知道他的地址和大小
如何修改Proceduce AAA;的所有代码?
我写了代码结果如下:
在D7 IDE下可以修改,并且可以恢复,恢复后
运行结果正确,但是脱离IDE后
可以修改,恢复但是结果不正确
为什么?
 
ReadProcessMemory
WriteProcessMemory
这两个api可以
 
您能给个Demo吗?
 
unit Unit1;
(*
An example of self-modifying code.
Tested with Delphi 4 on Windows 98 and NT 4.
You may use this code freely, but make sure you
know what you aredo
ing.
Global disclaimer: It's not my fault! ;-)
Feb '99 - Marcus Moennig - minibbjd@gmx.de
*)
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'sdo
n't get optimized out of the compiled exe
procedure TForm1.CallModifiedCode(Sender: TObject);
var b:boolean;
c:TColor;
label 1;
begin
c:=clgreen;
b:=true;
// The next line will get modified in memory.
// The comments show what the asm code and the hexadecimal
// representation of the asm code in the compiled exe will look like.
// You can set a breakpoint on the next line and open Delphi's CPU view
// to see the change.
if b then
goto 1;
// "jnz SOME_ADDRESS" "$75 SOME_ADDRESS"
// We will modify the line above to:
// "jz SOME_ADDRESS" "$74 SOME_ADDRESS" what means:
// if NOT(b) then
goto 1;
// The following asm codedo
es nothing (nop=no operation).
// It's simply used as a marker to find the position
// of the jump above in memory.
asm
nop // $90
nop // $90
nop // $90
nop // $90
nop // $90
nop // $90
end;
c:=clred;
1:
form1.Color:=c;
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);
// return number of bytes read
ReadBufferFromMemory := cnt;
end;

procedure WriteByteToMemory(ad:cardinal;rt:byte);
var cnt:cardinal;
oldprotect:dword;
begin
//make sure we have write access to this address
VirtualProtect(pointer(ad),sizeof(rt),PAGE_EXECUTE_READWRITE,@oldprotect);
WriteProcessMemory(Getcurrentprocess, pointer(ad), @rt, sizeof(rt), cnt);
//restore the previous access protection
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
//define the "search term"
st[0]:=$90;
//in asm this means: nop
st[1]:=$90;
st[2]:=$90;
st[3]:=$90;
st[4]:=$90;
st[5]:=$90;
stCount:=6;
//replace term depending on which button was clicked
if (sender=red) then
rt:=$74 // in asm: jz
else
rt:=$75;
// in asm: jnz
//address range to be searched
sad:=($00400000);
ead:=($7fffffff);
//current address
ad:=sad;
found:=false;
repeat
//read one block of length BUFFMAX from the current address ad
BytesRead:=ReadBufferFromMemory(ad, BUFFMAX, MemBlock);
//no bytes read;
so get out
if BytesRead=0 then
break;
// make sure wedo
n't miss the search term when it spans two blocks
If BytesRead=BUFFMAX then
BytesRead:=BytesRead-stCount;
// search this MemoryBlock
// cycle through the MemoryBlock
For x:=0 To BytesRead-1do
begin
found:=true;
// check for search term
For y:=0 To stCount-1do
If MemBlock[x+y]<>st[y] then
begin
found:=false;
break;
end;
If found then
begin
// the search term starts at ad+x+y-stcount
z:=ad+x+y-stcount;
// the code we want to replace starts 2 bytes before
WriteByteToMemory(z-2,rt);
break;
// stop searching
end;
end;
ad:=ad+BytesRead;
until (ad>=ead) or found;
end;

end.
 
有意思的问题!!:)
 
上边的例子如何解决我的问题?
 
是中途截断函数或过程,用自己的函数或过程地址代替之,用完后再恢复的技术吧。
一般是由于 IDE 在调试状态下会额外增加一些过程调用,造成函数或过程的实际地
址与非 IDE 状态下的地址存在不同,尤其是 dll 加载。所以我也 up 。
 
用winhex softice可以
 
你是怎么做的?
这样的问题就是用writeProcessMemory。如果在2000下还要修改内存的属性为可写。
首先你要得到进程句柄,然后writeProcessMemory就Ok了。
 
To 薄荷:
我没用"writeProcessMemory"方法,
您能给我一个DEMO吗?
假设:
Procedure AAA 的地址 P 已经知道,
Procedure AAA 的大小 Size 已经知道,
那么修改内存的过程 :
Proceddure ModifyAddress(P:Pointer;Size:DWord);
begin
....?
end;
谢谢.
 
有意思。
 
除了要知道地址,还要知道AAA所在的进程句柄。如果就是本进程的,那就是一句话:
writeProcessMemory(handle, Address,...);
 
再议论一下啊
 
多人接受答案了。
 
后退
顶部