跨越内存禁区修改游戏数据(2001年第2期)
http://www.csdn.net/magazine/source/2/Hero.doc
unit uheromate;//本单元与uheromate窗体相对应
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Menus, ComCtrls, Grids, ExtCtrls,ShellApi;
type
TModifyThread = class(TThread) //新建线程类,用于修改英雄属性页的设置
private
{ Private declarations }
protected
procedure Execute; override;
end;
TForm1 = class(TForm)
Label1: TLabel;
PageControl1: TPageControl;
TabSheet1: TTabSheet;
Label3: TLabel;
Edit1: TEdit;
UpDown1: TUpDown;
Edit2: TEdit;
UpDown2: TUpDown;
Edit3: TEdit;
UpDown3: TUpDown;
Edit4: TEdit;
UpDown4: TUpDown;
CheckBox1: TCheckBox; //英雄技能页-是否增加所有第二技能
CheckBox2: TCheckBox; //英雄技能页-是否修改四项第一技能
TabSheet2: TTabSheet;
TabSheet3: TTabSheet;
TabSheet4: TTabSheet;
ComboBox1: TComboBox; //英雄技能页-下拉框,用于选择英雄
Label2: TLabel;
B_skill: TButton; //英雄技能页-变更英雄属性按钮
B_nolimit: TButton; //机动力页-使英雄机动力无限按钮
B_allday: TButton;// 机动力页-锁定英雄机动力按钮
Timer1: TTimer;
ListBox1: TListBox;
B_okToAddArtifact: TButton; //宝物页-根据列表框中宝物修改游戏内存
B_add: TButton;//宝物页-增加宝物到列表框按钮
Label4: TLabel;
ComboBox2: TComboBox; //宝物页-宝物列表框
B_return: TButton; //返回游戏按钮
B_Remove: TButton; //宝物页-从列表框中减少宝物
procedure B_skillClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure ComboBox1Change(Sender: TObject);
procedure CheckBox2Click(Sender: TObject);
procedure B_nolimitClick(Sender: TObject);
procedure B_alldayClick(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure B_okToAddArtifactClick(Sender: TObject);
procedure B_addClick(Sender: TObject);
procedure B_returnClick(Sender: TObject);
procedure B_RemoveClick(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
heroname:pchar; //当前修改的英雄名
heroBaseAdd,heroAdd:integer; //第一个英雄的地址和当前英雄的序号
heros:array[0..180] of pchar; //英雄名序列
isdebug:integer; //是否已用OpenProcess函数打开游戏进程
winhwnd:hwnd; //游戏窗口句柄
pId,threadId:Integer; //拥有游戏主窗口的进程和线程ID
hProcess: THandle; //用OpenProcess函数游戏进程的句柄
str1:string='锁定机动力';
str2:string='取消锁定';
implementation
{$R *.DFM}
procedure TForm1.B_skillClick(Sender: TObject);//修改英雄属性页设置
var
threadNew:TModifyThread;
begin
threadNew:=TModifyThread.Create(false);
threadNew.Execute;
if not SetForegroundWindow(winhWnd) then
showmessage(inttostr(getlasterror));
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
isdebug:=0;
heroBaseAdd:=$015c7f63; //<--光盘版$015d7f63;//硬盘版 $015c7f63;
heros[0]:='Orrin'; heros[1]:='Valeska'; heros[2]:='Edric'; heros[3]:='Sylvia';
heros[4]:='Lord Haart(1)';heros[5]:='Sorsha'; heros[6]:='Christian'; heros[7]:='Tyris';
heros[8]:='Rion'; heros[9]:='Adela'; heros[10]:='Cuthbert'; heros[11]:='Adelaide';
heros[12]:='Ingham'; heros[13]:='Sanya'; heros[14]:='Loynis'; heros[15]:='Caitlin';
heros[16]:='Mephala'; heros[17]:='Ufretin'; heros[18]:='Jenova'; heros[19]:='Ryland';
heros[20]:='Thorgrim'; heros[21]:='Ivor'; heros[22]:='Clancy'; heros[23]:='Kyrre';
heros[24]:='Coronius'; heros[25]:='Uland'; heros[26]:='Elleshar'; heros[27]:='Gem';
heros[28]:='Malcom'; heros[29]:='Melodia'; heros[30]:='Alagar'; heros[31]:='Aeris';
heros[32]:='Piquedram'; heros[33]:='Thane'; heros[34]:='Josephine'; heros[35]:='Neela';
heros[36]:='Torosar'; heros[37]:='Fafner'; heros[38]:='Rissa'; heros[39]:='Iona';
heros[40]:='Astral'; heros[41]:='Halon'; heros[42]:='Serena'; heros[43]:='Daremyth';
heros[44]:='Theodorus'; heros[45]:='Solmyr'; heros[46]:='Cyra'; heros[47]:='Aine';
heros[48]:='Fiona'; heros[49]:='Rashka'; heros[50]:='Marius'; heros[51]:='Ignatius';
heros[52]:='Octavia'; heros[53]:='Calh'; heros[54]:='Pyre'; heros[55]:='Nymus';
heros[56]:='Ayden'; heros[57]:='Xyron'; heros[58]:='Axsis'; heros[59]:='Olema';
heros[60]:='Calid'; heros[61]:='Ash'; heros[62]:='Zydar'; heros[63]:='Xarfax';
heros[64]:='Straker'; heros[65]:='Vokial'; heros[66]:='Moandor'; heros[67]:='Charna';
heros[68]:='TamikaIsra'; heros[69]:='Isra'; heros[70]:='Clavius'; heros[71]:='Galthran';
heros[72]:='Septienna'; heros[73]:='Aislinn'; heros[74]:='Sandro'; heros[75]:='Nimbus';
heros[76]:='Thant'; heros[77]:='Xsi'; heros[78]:='Vidomina'; heros[79]:='Nagash';
heros[80]:='Lorelei'; heros[81]:='Arlach'; heros[82]:='Dace'; heros[83]:='Ajit';
heros[84]:='Damacon'; heros[85]:='Gunnar'; heros[86]:='Synca'; heros[87]:='Shakti';
heros[88]:='Alamar'; heros[89]:='Jaegar'; heros[90]:='Malekith'; heros[91]:='Jeddite';
heros[92]:='Geon'; heros[93]:='Deemer'; heros[94]:='Sephinroth'; heros[95]:='Darkstorn';
heros[96]:='Yog'; heros[97]:='Gurnisson'; heros[98]:='Jabarkas'; heros[99]:='Shiva';
heros[100]:='Gretchin'; heros[101]:='Krellion'; heros[102]:='Crag Hack';heros[103]:='Tyraxor';
heros[104]:='Gird'; heros[105]:='Vey'; heros[106]:='Dessa'; heros[107]:='Terek';
heros[108]:='Zubin'; heros[109]:='Gundula'; heros[110]:='Oris'; heros[111]:='Saurug';
heros[112]:='Bron'; heros[113]:='Drakon'; heros[114]:='Wystan'; heros[115]:='Tazar';
heros[116]:='Alkin'; heros[117]:='Korbac'; heros[118]:='Gerwulf'; heros[119]:='Broghild';
heros[120]:='Mirlanda'; heros[121]:='Rosic'; heros[122]:='Voy'; heros[123]:='Verdish';
heros[124]:='Merist'; heros[125]:='Styg'; heros[126]:='Andra'; heros[127]:='Tiva';
heros[128]:='Pasis'; heros[129]:='Thunar'; heros[130]:='Ignissa'; heros[131]:='Lacus';
heros[132]:='Monere'; heros[133]:='Erdamon'; heros[134]:='Fiur'; heros[135]:='Kalt';
heros[136]:='Luna'; heros[137]:='Brissa'; heros[138]:='Ciele'; heros[139]:='Labetha';
heros[140]:='Inteus'; heros[141]:='Aenain'; heros[142]:='Gelare'; heros[143]:='Grindan';
heros[144]:='Sir Mullich';heros[145]:='Adrienne';heros[146]:='Catherine'; heros[147]:='Dracon';
heros[148]:='Gelu'; heros[149]:='Kilgor'; heros[150]:='Lord Haart';heros[151]:='Mutare';
heros[152]:='Roland'; heros[153]:='Mutare Drake';heros[154]:='Boragus';heros[155]:='Xeron';
end;
procedure TForm1.ComboBox1Change(Sender: TObject); //取得当前英雄的内存地址
var
OrrinBuffer:array[0..4] of byte;
i:integer;
lpNumberOfBytesWritten: DWORD;
begin
ListBox1.Items.Clear;
if isdebug=0 then //未执行OpenProcess
begin
winhwnd:=FindWindow(NIL,'Heroes of Might and Magic III: Armageddon''s Blade');
if winhwnd=0 then winhwnd:=FindWindow(NIL,'Heroes of Might and Magic III');
if winhwnd=0 then showmessage('Heroes III is not running');
threadId:=GetWindowThreadProcessId(winhwnd,@pId) ;
if threadId=0 then showmessage('not find id');
hProcess:=OpenProcess(PROCESS_ALL_ACCESS,true, pId);
isdebug:=1;
//查找英雄数据区基地址heroBaseAdd
for i:=5 to 20 do //in least add 600000
begin
ReadProcessMemory(hProcess,ptr(heroBaseAdd), @OrrinBuffer,5, lpNumberOfBytesWritten);
//英雄数据区基地址处的值应是第一个英雄的名字:"Orrin"
if (OrrinBuffer[0]=79) and (OrrinBuffer[1]=114)
and (OrrinBuffer[2]=114) and (OrrinBuffer[3]=105)
and (OrrinBuffer[4]=110) then break;
if (i mod 2)=1 then //
heroBaseAdd:=heroBaseAdd+$10000 // <--光盘版比硬盘版多$10000
else
heroBaseAdd:=$015c7f63+$100000*(i div 2) +$30000; //硬盘版
end;
end;
//得到欲修改的英雄的序号
heroname:=Pchar(combobox1.text);
for i :=0 to 165 do
begin
if strcomp(heros[i],heroname)=0 then
begin
heroadd:=i;
exit;
end;
end;
end;
procedure TModifyThread.Execute; //修改英雄属性页的设置
var
lpBuffer: array[0..56] of byte;
four: array[0..3] of byte;
lpNumberOfBytesWritten: DWORD;
i:integer;
begin
for i := 0 to 27 do
begin
lpBuffer[i]:=3;
end;
for i := 28 to 35 do
begin
lpBuffer[i]:=i-27;
end;
lpBuffer[56]:=27; //总共有27项魔法
lpBuffer[12]:=0; //不设置招魂术
four[0]:=Form1.UpDown1.Position;
four[1]:=Form1.UpDown2.Position;
four[2]:=Form1.UpDown3.Position;
four[3]:=Form1.UpDown4.Position;
if Form1.CheckBox1.Checked=true then //增加第二技能
begin
if not WriteProcessMemory(hProcess,ptr(heroBaseAdd+heroadd*$492+$A6), @lpBuffer,
57, lpNumberOfBytesWritten) then
showmessage('Write mem Error');
end;
if Form1.CheckBox2.Checked=true then //设置第一技能
begin
if not WriteProcessMemory(hProcess,ptr(heroBaseAdd+heroadd*$492+$453), @four,
4, lpNumberOfBytesWritten) then
showmessage('Write mem Error');
end;
end;
procedure TForm1.CheckBox2Click(Sender: TObject);
begin
edit1.Enabled:=not(edit1.Enabled);
edit2.Enabled:=not(edit2.Enabled);
edit3.Enabled:=not(edit3.Enabled);
edit4.Enabled:=not(edit4.Enabled);
updown1.Enabled:=not(updown1.Enabled);
updown2.Enabled:=not(updown2.Enabled);
updown3.Enabled:=not(updown3.Enabled);
updown4.Enabled:=not(updown4.Enabled);
end;
procedure TForm1.B_nolimitClick(Sender: TObject); //无限机动力
var
newdistance: array[0..1] of byte;
lpNumberOfBytesWritten: DWORD;
begin
newdistance[0]:=$99;
newdistance[1]:=$99;
if not WriteProcessMemory(hProcess,ptr(heroBaseAdd+heroadd*$492+$2A), @newdistance,
2, lpNumberOfBytesWritten) then
showmessage(inttostr(getlasterror)+'Write mem Error');
if not SetForegroundWindow(winhWnd) then
showmessage(inttostr(getlasterror));
end;
procedure TForm1.B_alldayClick(Sender: TObject); //锁定机动力
begin
if B_allday.Caption=str1 then
begin
B_allday.Caption:=str2;
Timer1.Enabled:=true;
end
else
begin
B_allday.Caption:=str1;
Timer1.Enabled:=False;
end;
end;
procedure TForm1.Timer1Timer(Sender: TObject); //锁定机动力
var
olddistance: array[0..1] of byte;
newdistance: array[0..1] of byte;
lpNumberOfBytesWritten: DWORD;
begin
if not ReadProcessMemory(hProcess,ptr(heroBaseAdd+heroadd*$492+$26), @olddistance,
2, lpNumberOfBytesWritten) then
showmessage(inttostr(getlasterror)+'Read mem Error');
newdistance[0]:=olddistance[0];
newdistance[1]:=olddistance[1];
if not WriteProcessMemory(hProcess,ptr(heroBaseAdd+heroadd*$492+$2A), @newdistance,
2, lpNumberOfBytesWritten) then
showmessage(inttostr(getlasterror)+'Write mem Error');
if not SetForegroundWindow(winhWnd) then
showmessage(inttostr(getlasterror));
end;
procedure TForm1.B_okToAddArtifactClick(Sender: TObject); //增加宝物
var
i:integer;
Artifact:array[0..7] of byte;
lpNumberOfBytesWritten: DWORD;
begin
Artifact[1]:=0; Artifact[2]:=0; Artifact[3]:=0;
Artifact[4]:=$FF; Artifact[5]:=$FF; Artifact[6]:=$FF; Artifact[7]:=$FF;
for i:=0 to Form1.ListBox1.Items.Count-1 do
begin
Artifact[0]:=ComboBox2.Items.IndexOf(listbox1.Items.Strings[i])+2;
if Artifact[0]<>2 then
Artifact[0]:=Artifact[0]+4;
if not WriteProcessMemory(hProcess,ptr(heroBaseAdd+heroadd*$492+$1B1+8*i), @Artifact,
8, lpNumberOfBytesWritten) then
showmessage(inttostr(getlasterror)+'Write mem Error');
end;
if not SetForegroundWindow(winhWnd) then
showmessage(inttostr(getlasterror));
end;
procedure TForm1.B_addClick(Sender: TObject);
begin
ListBox1.Items.Add(ComboBox2.Text);
end;
procedure TForm1.B_returnClick(Sender: TObject);
begin
showwindow(winhwnd,SW_MAXIMIZE);
end;
procedure TForm1.B_RemoveClick(Sender: TObject);
begin
ListBox1.Items.Delete(ListBox1.ItemIndex);
ListBox1.ItemIndex:=0;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
if hProcess <>0 then closehandle(hProcess); //关闭句柄
end;
end.