诛仙外挂学习一

unit Unit1;       //文件名

interface         //接口

uses            //引用单元文件,包含的库文件 相当于c里面的include
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls;

type             //定义一个窗体类,包含各种控件及事件过程。以下是你再form中方的控件申明,系统自动生成,不用管的
  TForm1 = class(TForm)
    PageControl1: TPageControl;
    TabSheet1: TTabSheet;
    GroupBox1: TGroupBox;
    TabSheet2: TTabSheet;
    TabSheet3: TTabSheet;
    TabSheet4: TTabSheet;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    EditName: TEdit;
    EditHP: TEdit;
    EditMP: TEdit;
    Label4: TLabel;
    EDIT1: TEdit;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);

private            //私有变量声明
{ Private declarations }
  public           //公共变量声明
    { Public declarations }
  end;

var               //定义全局变量
  Form1: TForm1;
  Base0,Base1,BaseT1:Integer;  //内存地址
  HP,MP:Integer;               //血、魔法量

  MYHwnd:Hwnd;   //Hwnd:窗口的句柄 handle of window
  hProcess_N:Thandle;    //线程号
  ThreadAdd,ParamAdd:pointer;
  ThreadID:DWORD;  //双字节变量
  MemSize,JNID:DWORD;
  ByteRead:Cardinal;
 
implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
myHwnd:=FindWindow(nil,'诛仙');                             //找到游戏
GetWindowThreadProcessID(MYHwnd,@ThreadID);                 //获取进程ID
hProcess_N:=openprocess(process_all_access,false,threadid); //打开进程
  if hProcess_N=0 then
  begin                                                     //以下错误提示
    Messagebox(handle, '游戏未运行,请退出本程序。','提示',MB_OK+MB_IconError);
    exit;
  end
  else
  begin
  Edit1.TEXT:=inttostr(myhwnd)
  end;

  Base0:=$A43D84;              // 基址
  MemSize:=128;                // 128的空间已足够,无须4096这么浪费

//开辟全局内存
  ThreadAdd := VirtualAllocEx(hProcess_N, nil, MemSize, MEM_COMMIT, PAGE_READWRITE);    //申请具有读写权限的函数内存空间,返回地址
  ParamAdd := VirtualAllocEx(hProcess_N, nil, 20, MEM_COMMIT, PAGE_READWRITE);          //申请具有读写权限的参数内存空间,返回地址
  end;

procedure TForm1.FormDestroy(Sender: TObject);    //关闭程序时释放所有的资源
begin
  VirtualFreeEx(hProcess_N, ThreadAdd, MemSize, MEM_RELEASE);  //释放相应函数内存
  VirtualFreeEx(hProcess_N, ParamAdd, 20, MEM_RELEASE);        //释放相应参数内存
  CloseHandle(hProcess_N);                                     //释放句柄
end;


procedure InjectFunc(Func: Pointer; Param: Pointer; ParamSize: DWORD); //开始调用注入函数,传值:句柄,被注入函数指针,参数指
var
  hThread: THandle;
  lpNumberOfBytes: DWORD;

begin
  if hProcess_N<>0 then
  begin
    // ---- 写入函数地址
    WriteProcessMemory(hProcess_N, ThreadAdd, Func, MemSize, lpNumberOfBytes);
    // ---- 写入参数地址
    WriteProcessMemory(hProcess_N, ParamAdd, Param, ParamSize, lpNumberOfBytes);
    // ---- 创建远程线程
    hThread := CreateRemoteThread(hProcess_N, nil, 0, ThreadAdd, ParamAdd, 0, lpNumberOfBytes);
    // ---- 等待线程结束
    WaitForSingleObject(hThread, INFINITE);
    CloseHandle(hThread);
  end;
end;

// ---- 死亡回城 CALL  注意,下面只有一个Address的CALL入口地址,没其他参数

procedure MyCall1; Stdcall;
var
   Address:Pointer;
begin
address:=pointer($d2293d4);
  asm
    pushad
    call Address
    popad
  end;


   end;
end.

 

 

 

 

总结:

通过网上的外挂实例,得出以下思路

首先,要取得游戏窗口句柄、线程;

其次,注入,在目标线程中获得内存空间,并具有最高权限;

然后开始注入,使用CALL;

感觉查找地址难度比较大,需要耐心,而之后的CALL的方法在网上都有,

目前疑惑的是,如何应对游戏的更新比较方便(如写出自动找地址的程序)、防止游戏封挂具体是怎么回事,以上问题待深入后希望能得到答案。

posted on 2009-06-26 10:20  悍牛  阅读(644)  评论(0)    收藏  举报

导航