最近经朋友介绍开始玩 密传 网络游戏
升级升级,突然觉得太费键盘,于是自己用C#写了一个程序,想代替我的操作,自己去打怪物,自己升级
用这个东西升了好多级了,现在把源码贴出来,和大家共享,欢迎大家批评指正,感激不尽。
程序大概分成两个部分,一个部分是类库,一个是应用程序
大概的思路就是找到游戏进程的主窗口句柄,然后发送游戏按键消息(模拟按键)。
XDF.GamePlugInCommon 类库项目//API.cs 文件,定义一些常用API函数及常量using System;
using System.IO;
using System.Threading;
using System.Diagnostics;
using System.Runtime.InteropServices;namespace XDF.GamePlugInCommon
{
/// <summary>
/// API 的摘要说明。
/// </summary>
public sealed class API
{
public static int WM_KEYDOWN = 0x0100;
public static int WM_KEYUP = 0x0101;
public static int WM_SYSKEYDOWN = 0x0104;
public static int WM_SYSKEYUP = 0x0105; public static int WM_MOUSEMOVE = 0x0200;
public static int WM_LBUTTONDOWN = 0x0201;
public static int WM_LBUTTONUP = 0x0202;
public static int WM_LBUTTONDBLCLK = 0x0203;
public static int WM_RBUTTONDOWN = 0x0204;
public static int WM_RBUTTONUP = 0x0205;
public static int WM_RBUTTONDBLCLK = 0x0206;
public static int WM_USER = 0x0400; public static int MK_LBUTTON = 0x0001;
public static int MK_RBUTTON = 0x0002;
public static int MK_SHIFT = 0x0004;
public static int MK_CONTROL = 0x0008;
public static int MK_MBUTTON = 0x0010; public static int MK_XBUTTON1 = 0x0020;
public static int MK_XBUTTON2 = 0x0040; [DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd,int Msg,int wParam,int lParam); //此处主要用来让窗口置于最前(SetWindowPos(this.Handle,-1,0,0,0,0,0x4000|0x0001|0x0002);)
[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern bool SetWindowPos(IntPtr hWnd,
int hWndInsertAfter,
int X,
int Y,
int cx,
int cy,
int uFlags
); /// <summary>
/// 窗口置前
/// </summary>
/// <param name="hWnd"></param>
public static void SetWindowPos(IntPtr hWnd)
{
SetWindowPos(hWnd,-1,0,0,0,0,0x4000|0x0001|0x0002);
}

/// <summary>
/// 
/// </summary>
/// <param name="processName"></param>
/// <returns></returns>
public static Process GetGameProcess(string processName)
{
Process pro = null;
Process[] pros = Process.GetProcessesByName(processName);
if(pros.Length > 0)
{
pro = pros[0];
}
return pro;
}
}
}

解决方案 »

  1.   

    项目(应用程序)
    XDF.TantraPlugIn
    //ControlItem.cs
    using System;
    using System.IO;
    using System.Xml.Serialization;namespace XDF.TantraPlugIn
    {
    /// <summary>
    /// ControlItem 的摘要说明。
    /// </summary>
    [Serializable]
    public sealed class ControlItem
    {
    private string m_Name = "";
    public string Name
    {
    get
    {
    return this.m_Name;
    }
    set
    {
    this.m_Name = value;
    }
    }
    private char m_KeyChar = 'a';
    public char KeyChar
    {
    get
    {
    return this.m_KeyChar;
    }
    set
    {
    this.m_KeyChar = value;
    }
    }
    private int m_DelayTime = 100;
    public int DelayTime
    {
    get
    {
    return this.m_DelayTime;
    }
    set
    {
    this.m_DelayTime = value;
    }
    }
    public ControlItem()
    {

    }
    }
    [Serializable]
    public sealed class ControlItemCollection : System.Collections.CollectionBase
    {
    public ControlItem this[int index]
    {
    get
    {
    return (ControlItem)List[index];
    }
    set
    {
    List[index] = value;
    }
    }
    public ControlItemCollection()
    {
    }
    public int Add(ControlItem item)
    {
    return List.Add(item);
    }
    public void Remove(ControlItem item)
    {
    List.Remove(item);
    }
    }
    }
      

  2.   

    //TantraConfig.cs
    using System;
    using System.IO;
    using System.Xml.Serialization;namespace XDF.TantraPlugIn
    {
    /// <summary>
    /// TantraConfig 的摘要说明。
    /// </summary>
    [Serializable]
    public class TantraConfig
    {
    private ControlItemCollection m_KillControls = new ControlItemCollection();
    public ControlItemCollection KillControls
    {
    get
    {
    return this.m_KillControls;
    }
    set
    {
    this.m_KillControls = value;
    }
    }
    private ControlItemCollection m_BloodControls = new ControlItemCollection();
    public ControlItemCollection BloodControls
    {
    get
    {
    return this.m_BloodControls;
    }
    set
    {
    this.m_BloodControls = value;
    }
    } private int m_BloodRate = 25; public int BloodRate
    {
    get
    {
    return this.m_BloodRate;
    }
    set
    {
    this.m_BloodRate = value;
    }
    } private string m_ProcessName = "HTLauncher"; public string ProcessName
    {
    get
    {
    return this.m_ProcessName;
    }
    set
    {
    this.m_ProcessName = value;
    }
    } public TantraConfig()
    {

    } public bool Save(string file)
    {
    bool result = false;
    try
    {
    FileStream fs = new FileStream(file,FileMode.Create,FileAccess.Write);
    XmlSerializer xsl = new XmlSerializer(this.GetType());
    xsl.Serialize(fs,this);
    fs.Close();
    result = true;
    }
    catch
    {
    result = false;
    }
    return result;
    }
    public static TantraConfig LoadFromFile(string file)
    {
    TantraConfig config = null;
    try
    {
    FileStream fs = new FileStream(file,FileMode.Open,FileAccess.Read);
    XmlSerializer xsl = new XmlSerializer(typeof(TantraConfig));
    config = (TantraConfig)xsl.Deserialize(fs);
    fs.Close();
    }
    catch
    {

    }
    return config;
    }
    }
    }
      

  3.   

    //Frmmain.cs
    using System;
    using System.Drawing;
    using System.Collections;
    using System.ComponentModel;
    using System.Windows.Forms;
    using System.Data;
    using System.Threading;using XDF.GamePlugInCommon;namespace XDF.TantraPlugIn
    {
    /// <summary>
    /// Form1 的摘要说明。
    /// </summary>
    public class Frmmain : System.Windows.Forms.Form
    {
    private System.Windows.Forms.Button btnSetup;
    private System.Windows.Forms.Timer timerMain;
    private System.Windows.Forms.Button btnStart;
    private System.ComponentModel.IContainer components; public Frmmain()
    {
    //
    // Windows 窗体设计器支持所必需的
    //
    InitializeComponent();
    this.Closing +=new CancelEventHandler(Frmmain_Closing);
    } /// <summary>
    /// 清理所有正在使用的资源。
    /// </summary>
    protected override void Dispose( bool disposing )
    {
    if( disposing )
    {
    if (components != null) 
    {
    components.Dispose();
    }
    }
    base.Dispose( disposing );
    } #region Windows 窗体设计器生成的代码
    /// <summary>
    /// 设计器支持所需的方法 - 不要使用代码编辑器修改
    /// 此方法的内容。
    /// </summary>
    private void InitializeComponent()
    {
    this.components = new System.ComponentModel.Container();
    System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(Frmmain));
    this.btnStart = new System.Windows.Forms.Button();
    this.btnSetup = new System.Windows.Forms.Button();
    this.timerMain = new System.Windows.Forms.Timer(this.components);
    this.SuspendLayout();
    // 
    // btnStart
    // 
    this.btnStart.Location = new System.Drawing.Point(8, 16);
    this.btnStart.Name = "btnStart";
    this.btnStart.Size = new System.Drawing.Size(65, 22);
    this.btnStart.TabIndex = 0;
    this.btnStart.Text = "开始(&S)";
    this.btnStart.Click += new System.EventHandler(this.btnStart_Click);
    // 
    // btnSetup
    // 
    this.btnSetup.Location = new System.Drawing.Point(152, 16);
    this.btnSetup.Name = "btnSetup";
    this.btnSetup.Size = new System.Drawing.Size(65, 22);
    this.btnSetup.TabIndex = 1;
    this.btnSetup.Text = "设置(&C)";
    this.btnSetup.Click += new System.EventHandler(this.btnSetup_Click);
    // 
    // Frmmain
    // 
    this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
    this.ClientSize = new System.Drawing.Size(226, 55);
    this.Controls.Add(this.btnSetup);
    this.Controls.Add(this.btnStart);
    this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
    this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
    this.MaximizeBox = false;
    this.MinimizeBox = false;
    this.Name = "Frmmain";
    this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
    this.Text = "Tantra PlugIn beta1";
    this.ResumeLayout(false); }
    #endregion /// <summary>
    /// 应用程序的主入口点。
    /// </summary>
    [STAThread]
    static void Main() 
    {
    Application.Run(new Frmmain());
    } private TantraConfig m_TantraConfig = null;
    private Thread m_Thread = null;
    private bool m_Stop = true;
    private IntPtr m_GameMainWindowHandle = IntPtr.Zero; private void btnSetup_Click(object sender, System.EventArgs e)
    {
    TantraConfig config = new TantraConfig(); ControlItemCollection items = config.KillControls; ControlItem item_e = new ControlItem();
    item_e.DelayTime = 50;
    item_e.KeyChar = 'E';
    item_e.Name = "选择最近的攻击目标";
    items.Add(item_e);

    ControlItem item_r = new ControlItem();
    item_r.DelayTime = 6000;
    item_r.KeyChar = 'R';
    item_r.Name = "攻击选定的目标";
    items.Add(item_r); ControlItem item_f = new ControlItem();
    item_f.DelayTime = 500;
    item_f.KeyChar = 'F';
    item_f.Name = "捡起打完怪物掉下的物品";
    items.Add(item_f); ControlItem item_f2 = new ControlItem();
    item_f2.DelayTime = 500;
    item_f2.KeyChar = 'F';
    item_f2.Name = "捡起打完怪物掉下的金币";
    items.Add(item_f2); ControlItem item_blood = new ControlItem();
    item_blood.DelayTime = 1000;
    item_blood.KeyChar = '1';
    item_blood.Name = "自动增加体能秘技";
    config.BloodControls.Add(item_blood); config.Save("c:\\tantra.xml"); } private void btnStart_Click(object sender, System.EventArgs e)
    {
    if(this.m_Stop)
    {
    this.StartControl();
    }
    else
    {
    this.StopControl();
    }
    this.btnStart.Text = (this.m_Stop)?"开始(&S)":"停止(&S)";
    } private void StartControl()
    {
    string file = Environment.CurrentDirectory + "\\tantra.xml";
    this.m_TantraConfig = TantraConfig.LoadFromFile(file);
    if(this.m_TantraConfig == null)
    {
    MessageBox.Show("配置文件未找到,无法启动!");
    return;
    } //HTLauncher
    //string proname = "TantraPlugIn";
    System.Diagnostics.Process pro = API.GetGameProcess(this.m_TantraConfig.ProcessName);
    if(pro == null)
    {
    MessageBox.Show("游戏进程 "+this.m_TantraConfig.ProcessName+" 未找到,无法启动!");
    return;
    }
    this.m_GameMainWindowHandle = pro.MainWindowHandle;
    this.Text = "Game name:" + pro.ProcessName;
    this.m_Stop = false;
    this.m_Thread = new Thread(
    new ThreadStart(TantraControl));

    this.m_Thread.Start();
    } private void StopControl()
    {
    if(this.m_Thread != null)
    {
    this.m_Stop = true;
    this.m_Thread.Abort();
    }
    } private void TantraControl()
    {
    int count = 0;
    while(!this.m_Stop)
    {
    for(int i=0;i<this.m_TantraConfig.KillControls.Count;i++)
    {
    API.SendMessage(this.m_GameMainWindowHandle,API.WM_KEYDOWN,
    Convert.ToInt32(this.m_TantraConfig.KillControls[i].KeyChar),0);
    Thread.Sleep(this.m_TantraConfig.KillControls[i].DelayTime);
    }
    count ++;
    if(count >= this.m_TantraConfig.BloodRate)
    {
    count = 0;
    for(int i=0;i<this.m_TantraConfig.BloodControls.Count;i++)
    {
    API.SendMessage(this.m_GameMainWindowHandle,API.WM_KEYDOWN,
    Convert.ToInt32(this.m_TantraConfig.BloodControls[i].KeyChar),0);
    Thread.Sleep(this.m_TantraConfig.BloodControls[i].DelayTime);
    }
    }
    }
    }

    protected override void WndProc(ref Message m)
    {
    base.WndProc (ref m);
    if(m.Msg == API.WM_KEYDOWN)
    {
    this.Text = m.WParam.ToInt32().ToString();
    if(this.Text == "1")
    {
    MessageBox.Show("blood");
    }
    }
    } private void Frmmain_Closing(object sender, CancelEventArgs e)
    {
    try
    {
    this.StopControl();
    }
    catch
    {
    }
    } }
    }以上是全部代码
    设置功能未完善,可以通过手动修改XML配置文件实现其他类似游戏的外挂
    附带典型(12级)外挂配置,配置文件随着各人级别不同和技能不同自己做修改。
      

  4.   

    附加我从12级开始外挂的配置文件<?xml version="1.0"?>
    <TantraConfig xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <KillControls>
        <ControlItem>
          <Name>选择最近的攻击目标</Name>
          <KeyChar>69</KeyChar>
          <DelayTime>50</DelayTime>
        </ControlItem>
        <ControlItem>
          <Name>攻击选定的目标</Name>
          <KeyChar>82</KeyChar>
          <DelayTime>5000</DelayTime>
        </ControlItem>
        <ControlItem>
          <Name>捡起打完怪物掉下的物品</Name>
          <KeyChar>70</KeyChar>
          <DelayTime>500</DelayTime>
        </ControlItem>
        <ControlItem>
          <Name>捡起打完怪物掉下的金币</Name>
          <KeyChar>70</KeyChar>
          <DelayTime>500</DelayTime>
        </ControlItem>
      </KillControls>
      <BloodControls>
        <ControlItem>
          <Name>自动增加体能秘技</Name>
          <KeyChar>49</KeyChar>
          <DelayTime>1000</DelayTime>
        </ControlItem>
      </BloodControls>
      <BloodRate>20</BloodRate>
      <ProcessName>HTLauncher</ProcessName>
    </TantraConfig>严重推荐兄弟们累的时候,玩玩这个游戏,号称永久免费的哦
      

  5.   

    广义上的外挂吧,严格算只是bot的一种。不过确实蛮强的,学习。
      

  6.   

    开发游戏吧,money多,前景好
      

  7.   

    妈的欢乐数码以前出了个命运~类型和奇迹(mu)1样的~推出的时候朋友叫我玩~偶玩了~就是欢乐代理的太垃圾了~朋友现在在玩MU~还挂了6个号~日
      

  8.   

    tantra.ys168.com
    我用bcb写的键盘模拟工具 hp和地图坐标可以从内存中读取
    通过hook call的方法可以作的更多 比如地上掉落物品的提示,110出现的提示
    最近工作忙没时间弄它了
    我已经解开几个消息的格式了
      

  9.   

    up
    没想到几天不见xiongchen(二氧化鬼) ( ) 升成猩猩了
      

  10.   

    up
    没想到几天不见xiongchen(二氧化鬼) ( ) 升成猩猩了
      

  11.   

    又看了一遍,用到的知识还真是不少啊。索引器,xml,串行化,多线程。。 先赞一个:)不过好像没有热键??
    另外你这个程序是不是只能打开一次运行到底?那个线程abort以后还能启动么?
      

  12.   

    牛人就是牛人,以后就写外挂吧,也可以收费挣很多money的!!!顶一下!!!
      

  13.   

    E键选择最近目标,R键攻击
    加血的功能需要将快捷键加到快捷栏里面
    比如我有两种加血,一种自动加血,持续3分钟,一种每次都加血
    第一个快捷键1,第二个快捷键2
    致命一击我定义为3,那个XML文件自己根据情况手动修改即可如果真想判断自己的血在什么状况,我的想法是截取血那部分的图片(局部截图,速度很快的)
    然后用象素计算的方式能算出血损失了多少,还剩下多少(百分比)
    但是我要提醒的是,网络状况不好的情况下,往往你的血是满的,突然一下子就挂了
    没有办法
    另外也可以用RAWSOCKET 截获数据包,分析自己的血的状况,当然处理的方法比较麻烦
    需要摸索出数据包的格式,你有兴趣可以自己研究一下哦注意我的标题(朋友定义为外挂,按键精灵)
    是否外挂不重要,重要的是写程序的那种乐趣,那种可以动作的快感,然否?
      

  14.   

    注册热键用registerhotkey unregisterhotkey就可以,好像没问题
      

  15.   

    回复人: web_gus(penny 突然发现自己其实什么都不会。) ( ) 信誉:100  2005-03-15 18:14:00  得分: 0  
     
     
       注册热键用registerhotkey unregisterhotkey就可以,好像没问题
      
    这位仁兄,你看看这个帖子,我就是用这两个API,有时候就是没法激活,不知道什么问题
    现在想想可能是因为我把窗体隐藏了,可是为啥有时候又行呢?http://community.csdn.net/Expert/topic/3852/3852784.xml?temp=.989895
      

  16.   

    回复人: web_gus(penny 突然发现自己其实什么都不会。) ( ) 信誉:100  2005-03-15 09:22:00  得分: 0  
     
     
       呵呵,我也在做这个,把游戏隐藏起来,然后对他发消息,现在遇到一个问题,隐藏了以后按一些键,游戏里会有反应。。现在准备用钩子试试看。各位有没有好方法?
      
     
    前段时间玩了一下钩子,发现加了钩子比较耗CPU时间,尤其是全局钩子
    隐藏游戏的窗口应该还是能够接到消息的,感觉可以用热键试试看,用钩子感觉耗资源
      

  17.   

    为啥下面的这个帖子没人看呢http://community.csdn.net/Expert/topic/3852/3852784.xml?temp=.989895郁闷ING
      

  18.   

    QSWW21CN(QSWW21CN):
    向太傅。终于找到你了。我是请操啊。啥意思啊?我好久不来这里了,老友我忘记了,真是汗~!==============================================================
    看看寻秦记就知道了
      

  19.   

    我做过一个侍魂2 PC版的自动发招程序,大概的方法就是Hook住一个key的消息,然后用keybd_event模拟键盘的消息。我觉得sendMessage不一定有用,因为很多时候directX的程序是不看winMessage的,而是直接读设备。所以还是推荐用keybd_event。http://www.codeproject.com/csharp/globalhook.asp 这个能帮你实现Hook
    至于keybd_event很简单的。比如这就是天霸封神斩的发招方法:
    [DllImport("user32.dll", EntryPoint="keybd_event")]
    public static extern void keybd_event (
    byte bVk,
    byte bScan,
    int dwFlags,
    int dwExtraInfo
    );

    private const int KEYEVENTF_EXTENDEDKEY = 0x1;
    private const int KEYEVENTF_KEYUP = 0x2;
    private const int KEYEVENTF_KEYDOWN = 0x00; private const int KEY_A = 0x41;
    private const int KEY_S = 0x53;
    private const int KEY_D = 0x44;
    private const int KEY_W = 0x57; private const int KEY_J = 0x4A;
    private const int KEY_K = 0x4B;
    private const int KEY_L = 0x4C; private const int KEY_U = 0x55;
    private const int KEY_I = 0x49;
    private const int KEY_O = 0x4F; #region SimulateKey
    private void OneKey(byte VirtualKey, int _interval, int KeyUpDown)
    {
    keybd_event(VirtualKey, 0, KeyUpDown, 0);
    Thread.Sleep(_interval);
    } private void TowKey(byte VirtualKey1, byte VirtualKey2, int _interval, int KeyUpDown)
    {
    keybd_event(VirtualKey1, 0, KeyUpDown, 0);
    keybd_event(VirtualKey2, 0, KeyUpDown, 0);
    Thread.Sleep(_interval);
    }
    #endregion SimulateKey #region Actions
    private void ToRight_Action01(int Interval)
    {
    int _interval = Interval; OneKey(KEY_D, _interval, KEYEVENTF_KEYDOWN);
    OneKey(KEY_S, _interval, KEYEVENTF_KEYDOWN);
    OneKey(KEY_D, _interval, KEYEVENTF_KEYUP);
    OneKey(KEY_S, _interval, KEYEVENTF_KEYUP);
                   
    OneKey(KEY_A, _interval, KEYEVENTF_KEYDOWN);
    OneKey(KEY_S, _interval, KEYEVENTF_KEYDOWN);
    OneKey(KEY_A, _interval, KEYEVENTF_KEYUP);
    OneKey(KEY_D, _interval, KEYEVENTF_KEYDOWN);
    OneKey(KEY_S, _interval, KEYEVENTF_KEYUP);
    OneKey(KEY_D, _interval, KEYEVENTF_KEYUP); OneKey(KEY_A, _interval, KEYEVENTF_KEYDOWN);
    OneKey(KEY_A, _interval, KEYEVENTF_KEYUP);
    OneKey(KEY_S, _interval, KEYEVENTF_KEYDOWN);
    OneKey(KEY_A, _interval, KEYEVENTF_KEYDOWN);
    OneKey(KEY_S, _interval, KEYEVENTF_KEYUP);
    OneKey(KEY_A, _interval, KEYEVENTF_KEYUP);

    TowKey(KEY_K, KEY_U,_interval, KEYEVENTF_KEYDOWN);
    TowKey(KEY_K, KEY_U,_interval, KEYEVENTF_KEYUP);
    } private void ToLeft_Action01(int Interval)
    {
    int _interval = Interval; OneKey(KEY_A, _interval, KEYEVENTF_KEYDOWN);
    OneKey(KEY_S, _interval, KEYEVENTF_KEYDOWN);
    OneKey(KEY_A, _interval, KEYEVENTF_KEYUP);
    OneKey(KEY_S, _interval, KEYEVENTF_KEYUP);
                   
    OneKey(KEY_D, _interval, KEYEVENTF_KEYDOWN);
    OneKey(KEY_S, _interval, KEYEVENTF_KEYDOWN);
    OneKey(KEY_D, _interval, KEYEVENTF_KEYUP);
    OneKey(KEY_A, _interval, KEYEVENTF_KEYDOWN);
    OneKey(KEY_S, _interval, KEYEVENTF_KEYUP);
    OneKey(KEY_A, _interval, KEYEVENTF_KEYUP); OneKey(KEY_D, _interval, KEYEVENTF_KEYDOWN);
    OneKey(KEY_D, _interval, KEYEVENTF_KEYUP);
    OneKey(KEY_S, _interval, KEYEVENTF_KEYDOWN);
    OneKey(KEY_D, _interval, KEYEVENTF_KEYDOWN);
    OneKey(KEY_S, _interval, KEYEVENTF_KEYUP);
    OneKey(KEY_D, _interval, KEYEVENTF_KEYUP);

    TowKey(KEY_K, KEY_U,_interval, KEYEVENTF_KEYDOWN);
    TowKey(KEY_K, KEY_U,_interval, KEYEVENTF_KEYUP);
    }
    #endregion Actions
      

  20.   

    请问楼主,!~~配置文件中<DelayTime>.....</DelayTime>这个延迟时间是怎么一回事呀?还有怎么才能自动加血呀?