VC6神迹外挂的DIY
(一)外挂一般都能在游戏的界面中按一个热键(比如F12,HOME等),就可以呼出外挂的窗口,然后在里面进行外挂的功能设置,这个外挂的窗口是怎么弄出来的呢?
要想在游戏里显示出窗口,那么我们要显示的这个窗口就要和游戏本身“混”在一起,也就是说我们的外挂窗口要“混入”游戏的内部,让游戏不排斥外挂窗口,把外挂窗口当做“自己人”,这样我们的外挂才能去“影响”游戏本身的运行。行话把这个叫“注入”。
那怎么“注入”呢?
Windows操作系统有个API函数SetWindowsHookEx,该函数的可以在系统上安装一个“钩子(HOOK)”。也就是把我们自己编写的一个回调函数设置为系统“钩子”。“钩子(HOOK)”有什么用呢?系统发送给各种程序窗口的消息,都要先经过“钩子”先处理之后再送到它本来要去的窗口。而在“钩子”处理来的消息的时候,Windows操作系统就已经自动把“钩子”“钩”在了消息即将到达的目的程序窗口上了,此时“钩子”就已经“混入”了目的窗口的内部了
==========================================
以下shaker注明:
这个教程存在一个漏洞,以使一些对DLL编程不是很了解的人不能顺利的完成编译。
BUG如下:原文中的S3DHOOK.DEF文件中的内容如下
; S3DHook.def : Declares the module parameters for the DLL.
LIBRARY "S3DHook"
DESCRIPTION "S3DHook Windows Dynamic Link Library"
EXPORTS
; Explicit exports can go here
使得生成的DLL没有任何输出函数,在编译EXE工程出现错误,要解决这个问题只要改变原来的S3DHook.def文件的内容如下:
; S3DHook.def : Declares the module parameters for the DLL.
LIBRARY "S3DHook"
DESCRIPTION "S3DHook Windows Dynamic Link Library"
EXPORTS
; Explicit exports can go here
InstallHook
UninstallHook
如此,问题便得到解决!
把有关外挂功能的代码和“钩子”函数一起放到同一个DLL中,那么我们的外挂也就一同被注入到游戏里面去了
在“我的文档”中建立一个文件夹名字叫“神迹外挂”然后打带VC6,建立新工程
点OK,选择
Regular DLL using shared mfc DLL
在S3DHook.h头文件中加入
#ifndef S3DHOOKAPI
#define S3DHOOKAPI extern "C" __declspec(dllimport)
#endif
在S3DHook.cpp中
#include "S3DHook.h"
这一句之前加入
#define S3DHOOKAPI extern "C" __declspec(dllexport)
也就是这个样子成了这个
#define S3DHOOKAPI extern "C" __declspec(dllexport)
#include "S3DHook.h"
在S3DHook.cpp中加入全局共享数据
#pragma comment(linker,"section:Shared,rws")
#pragma data_seg("Shared")
HHOOK g_hhook;
#pragma data_seg()
在S3DHook.cpp加入钩子回调函数
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
BOOL bKeyUp = lParam & (1 << 31);
if (bKeyUp && wParam == VK_F12 && nCode == HC_ACTION) {
AfxMessageBox("ok");
}
return ::CallNextHookEx(g_hhook, nCode, wParam ,lParam);
}
在文件前面加入函数的原形以便后面引用
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
在S3DHook.H里加入“导出(export)”的钩子安装卸载函数原形
S3DHOOKAPI BOOL WINAPI InstallHook();
S3DHOOKAPI BOOL WINAPI UninstallHook();
在S3DHook.CPP里加入钩子安装卸载函数的实现
S3DHOOKAPI BOOL WINAPI InstallHook()
{
if (g_hhook == NULL) {
g_hhook = ::SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)KeyboardProc, theApp.m_hInstance, 0);
if (g_hhook != NULL)
return TRUE;
}
return FALSE;
}
S3DHOOKAPI BOOL WINAPI UninstallHook()
{
return ::UnhookWindowsHookEx(g_hhook);
}
好了,现在我们建立的这个DLL具有基本的键盘钩子的功能,编译生成S3DHook.dll
下面建立一个EXE来调用这个DLL
这个是对话框型的工程
在MainDlg.cpp中加入对DLL的调用
插入头文件包含
#include "../s3dhook/s3dhook.h"
更改工程设置
Project->settings->link->Object/library modules:
输入../s3dhook/debug/s3dhook.lib
在对话框的OnInitDialog中加入InstallHook();安装键盘钩子
在OnClose中加入UninstallHook();关闭程序时卸载键盘钩子
编译这个对话框EXE
把这两个工程生成的S3DHook.dll和Main.exe放到同一个文件夹中,运行
这个是DLLsf_20046314251.rar
这个是EXEsf_200463142551.rar
下面我们在S3DHook这个DLL工程中添加一个从CDialog派生的CS3DHookDlg类
把DIALOG ID改为IDD_S3DHOOK_DIALOG
添加的对话框类的操作如下
主菜单->Insert->New Form
为了方便,把CS3DHookDlg的源程序文件名字分别改为
s3dhook.h
s3dhook.cpp
操作:点上图中的Chang
把刚才自动生成的对话框的Caption改为"外挂呼出窗口"
下面定义一个全局窗口指针来保存我们要生成的这个窗口的指针,以便后面对"外挂呼出窗口"进行控制,把它和全局变量
CS3DHookApp theApp;
写在一起,也就是这个样子
CS3DHookApp theApp;
CS3DHookDlg *pCWndWGMain;
下面对钩子回调函数进行改造,以便使我们的"外挂呼出窗口"能够在按F12时呼出
如下:
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
//按F12弹起时呼出外挂
BOOL bKeyUp = lParam & (1 << 31);
if (bKeyUp && wParam == VK_F12 && nCode == HC_ACTION) {
if (pCWndWGMain == NULL)
{
//更改当前有效模块状态到DLL中
//以便正确的读取对话框的资源
AFX_MANAGE_STATE(AfxGetStaticModuleState());
//找到当前的有效激活窗口
CWnd *pCWnd = CWnd::GetForegroundWindow();
//生成CS3DHookDlg类的对象实例
//此处应该生成一个非模态对话框
pCWndWGMain = new CS3DHookDlg();
pCWndWGMain->Create(IDD_S3DHOOK_DIALOG, pCWnd);
}
else
{
//根据当前呼出窗口的状态来显示或隐藏呼出窗口
pCWndWGMain->ShowWindow(pCWndWGMain->IsWindowVisible() ? SW_HIDE : SW_SHOW);
}
}
return ::CallNextHookEx(g_hhook, nCode, wParam ,lParam);
}
有关上面的这一句
在Regular MFC DLL中使用资源时非常重要
AFX_MANAGE_STATE(AfxGetStaticModuleState());
更多说明请参看
这里
当关掉外挂的主程序时,还要做点善后工作
重载CS3DHookApp类的ExitInstance函数,在其中删除对话框
int CS3DHookApp::ExitInstance()
{
// TODO: Add your specialized code here and/or call the base class
delete pCWndWGMain;
return CWinApp::ExitInstance();
}
重新编译生成S3DHOOK.dll并和Main.exe放到一起,运行它试试看
运行后,随便打开一个其他的什么窗口,按F12,看到什么了?
哈哈,我们的"外挂呼出窗口"呼出来了,真是千呼万唤始出来啊
我在记事本中试了试:
Main.exe和s3dhook.dll在这里: sf_200463194336.rar
要让他只在指定的程序窗口中呼出,每次都进神迹的游戏客户端试验很麻烦
我们就在记事本中试验,让他只能在记事本中呼出,最好还要能像真正的外挂那样
对挂入的程序做点手脚,
说做就做,开工!!!
继续对钩子回调函数进行改造
如下:
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
//按F12弹起时呼出外挂
BOOL bKeyUp = lParam & (1 << 31);
if (bKeyUp && wParam == VK_F12 && nCode == HC_ACTION) {
if (pCWndWGMain == NULL)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CWnd *pCWnd = CWnd::GetForegroundWindow();
//当前窗口是否为记事本窗口
char buf[MAX_PATH];
::GetClassName(pCWnd->GetSafeHwnd(), buf, MAX_PATH);
if (lstrcmpi(buf, "notepad") == 0) {
pCWndWGMain = new CS3DHookDlg();
//创建"外挂呼出窗口"时把记事本窗口作为他的父窗口
pCWndWGMain->Create(IDD_S3DHOOK_DIALOG, pCWnd);
pCWndWGMain->ShowWindow(SW_SHOW);
}
}
else
{
//根据当前呼出窗口的状态来显示或隐藏呼出窗口
pCWndWGMain->ShowWindow(pCWndWGMain->IsWindowVisible() ? SW_HIDE : SW_SHOW);
}
}
return ::CallNextHookEx(g_hhook, nCode, wParam ,lParam);
}
重新编译并运行,我们的"外挂呼出窗口"可以多个记事本中呼出
如图,并还没有发现会造成程序崩溃,有发现的,请告诉我!后面会附上
这里是重新编译的Main.exe和s3dhook.dll
本主题包含附件: sf_200463202334.rar
哈哈,解决了一个小问题,爽!!!!!!!!!!!!!
下面让我们的外挂对记事本做点小动作吧!
做点什么呢?
就让他在记事本的窗口中画个圆,怎么样?
来试试看了
为CS3DHookDlg添加WM_INITDIALOG的消息处理器
并在其中添加一个定时器,同时窗口关闭时要销毁定时器
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
设置
BOOL CS3DHookDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// TODO: Add extra initialization here
SetTimer(1000,100,0);
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~销毁,先要添加WM_CLOSE消息的处理器
void CS3DHookDlg::OnClose()
{
// TODO: Add your message handler code here and/or call default
KillTimer(1000);
CDialog::OnClose();
}
响应CS3DHookDlg的WM_TIMER消息
代码如下:
void CS3DHookDlg::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
//得到父窗口也就是记事本的指针
CWnd *pCWnd = GetParent();
//得到记事本的窗口设备上下文指针
CDC *pDC = pCWnd->GetWindowDC();
//画圆
pDC->Ellipse(100,100,200,200);
CDialog::OnTimer(nIDEvent);
}
效果如图:
下面是重新编译过的程序
本主题包含附件: sf_200463212057.rar
在记事本中的实验非常成功,爽!!!!!!!!
下面让我们的程序只在神迹中呼出
主要是需要改造键盘钩子回调程序
只需要把
lstrcmpi(buf, "notepad")
改为
lstrcmpi(buf, "SG Engine")
就可以了
"SG Engine"是神迹客户端的窗口的类名
重新编译运行,即可在神迹中呼出了,并且也在其中的窗口上画了个圆,
但是画面在闪烁,具体解决方法还没有找到
估计是因为:游戏使用DirectX作图,而我们这里是用GDI作图
先不管它了,留在以后再解决了
暂时我们还不需要在游戏里作图
,把我们程序中刚才有关作图的部分都删除掉,
1.OnInitDialog中的
2.OnClose中的
3.OnTimer删掉
利用madCHook进行API挂接:如:WSASend,WSARecv等
到这里去下载
安装刚才下载的madCollection.exe,安装后注意到在
C:/Program Files/madCollection/madCodeHook/Dll
中有3个文件需要引入到我们的S3DHook.dll工程中去
如下:
madCHook - dynamic.h
madCHook - dynamic - microsoft.lib
madCHook.dll
为了便于使用,把他们的名字改一下,改为:
madCHook.h
madCHook.lib
madCHook.dll
把.h和.lib放到S3DHook工程所在的文件夹中
在S3DHook.cpp中包含madCHook.h头文件,加入
#include "madCHook.h"
在Project->Settings->Link->Object/library modules中
加入madCHook.lib
下面就可以在我们的DLL中使用madCHook对API进行挂接了
注意:编译后要把Main.exe,S3DHook.dll和madCHook.dll放在一起才能运行
下面,正式开始加入代码对WSASend进行挂接
首先在S3DHook.cpp中加入
#include "Winsock2.h"
然后加入对原始API函数的指针及自定义API HOOK函数的原形的声明:
int (WINAPI *oWSASend)(
SOCKET,
LPWSABUF,
DWORD,
LPDWORD,
DWORD,
LPWSAOVERLAPPED,
LPWSAOVERLAPPED_COMPLETION_ROUTINE
);
int cWSASend(
SOCKET s,
LPWSABUF lpBuffers,
DWORD dwBufferCount,
LPDWORD lpNumberOfBytesSent,
DWORD dwFlags,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
这个一定要和原始的API函数WSASend的形参一致才行,可以参看MSDN
为了把截获的数据显示出来,用资源编辑器在S3DHook中的外挂呼出窗口中加入一个ListBox,将其ID改为IDC_LIST_SEND,将其SORT属性去掉,
然后加入自定义API钩子的实现
int cWSASend(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
{
char buf[1024];
lstrcpyn(buf,lpBuffers->buf,lpBuffers->len);
CListBox *pListBox = (CListBox *)pCWndWGMain->GetDlgItem(IDC_LIST_SEND);
pListBox->AddString(buf);
//API钩子返回之前,对原始的API进行调用,
return oWSASend(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpOverlapped, lpCompletionRoutine);
}
下面我们利用madCHook安装WSASend这个API的钩子
成功后,游戏每次调用WSASend这个API的时候,都会去先执行我们写的
cWSASend,在这里,我们就可以截取到游戏发往服务器的数据封包,然后用游戏调用到cWSASend时使用的参数去调用我们刚才写的指向原始WSASend的函数指针oWSASend去调用原始的API将数据发到服务器,这样才能保证游戏能继续正常运行,否则游戏很有可能会掉线
在CS3DHookDlg::OnInitDialog() 加入这一句来安装API钩子
HookAPI("Ws2_32.dll", "WSASend", cWSASend, (PVOID *) &oWSASend);
参数说明:
1.要挂接的API所在的DLL
2.要挂接的API
3.自定义的函数,用来替换要挂接的API:cWSASend//游戏每次调用Ws2_32.dll中的WSASend,就会先进入我们自定义的cWSASend
4.指向原始API函数WSASend的指针//自定义的cWSASend截取封包并进行必要处理后,通过这个指针去调用原始的WSASend@Ws2_32.dll,以保证游戏的正常运行
BOOL CS3DHookDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// TODO: Add extra initialization here
HookAPI("Ws2_32.dll", "WSASend", cWSASend, (PVOID *) &oWSASend);
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
编译之后,把Main.exe S3DHook.dll madCHook.dll放在一起,看看效果
运行Main.exe,启动进入神迹,按F12呼出
令人激动的时刻啊!看到没有?截获的数据封包已经在ListBox控件中显示出来了!!!
其实这才是刚刚开始,要想有强大的功能,后面还要做许多工作
VC6神迹外挂的DIY的更多相关文章
- 【转】VC6.0附带小工具软件一览
)ActiveX Control Test Container称为"ActiveX 控件测试容器",顾名思义,此工具的主要功能就是测试ActiveX 控件,可以通过改变Active ...
- VC6.0开发OCX按钮控件
原文:http://www.cnblogs.com/joinclear/archive/2013/05/21/3091934.html 0前言 1.OCX是典型的ActiveX控件,常见的OCX控件有 ...
- PE经典DIY案例1:全解开方案让量产PE也能
更新说明:因未来的uefi似乎并不能识别并引导ud区,但能识别和引导量产和u+B+隐藏或高端隐藏区,故解决量产PE对u+B+隐藏区的支持,并增加对UEFI启动支持,已经成为PE制作的最主流技术. PE ...
- X86逆向6:易语言程序的DIY
易语言程序在中国的用户量还是很大的,广泛用于外挂的开发,和一些小工具的编写,今天我们就来看下如何给易语言程序DIY,这里是用的易语言演示,当然这门技术也是可以应用到任何一门编译型语言中的,只要掌握合适 ...
- 从零开始,DIY一个jQuery(1)
从本篇开始会陪大家一起从零开始走一遍 jQuery 的奇妙旅途,在整个系列的实践中,我们会把 jQuery 的主要功能模块都了解和实现一遍. 这会是一段很长的历程,但也会很有意思 —— 作为前端领域的 ...
- [展示]手把手教你如何diy门户幻灯片
第一步后台新建页面:这个就不用说了大家都会 新建后FTP里面会出现如下一个模板页面 第二步从ftp里面下载 template的index.htm文件 给首页模板页面添加JS代码 如下 将这段jS ...
- 用python DIY一个图片转pdf工具并打包成exe
最近因为想要看漫画,无奈下载的漫画是jpg的格式,网上的转换器还没一个好用的,于是乎就打算用python自己DIY一下: 这里主要用了reportlab.开始打算随便写几行,结果为若干坑纠结了挺久,于 ...
- Genesis2000用c#开发外挂
先上官方的说明 gateway is a command line utility for sending messages and commands to Genesis processes. Th ...
- 联想A880 DIY 换触摸屏屏幕
今年初入手的Lenovo A880手机,由于摔坏了屏幕不过能正常显示,咨询了联想的售后,说触摸屏和显示屏是分离的,换触摸屏需要280左右 为发挥DIY的精神,准备自己来处理这个屏幕 第一步:购买屏幕, ...
随机推荐
- OCP prepare 20140703
1. trim trim('aaa' from 'aaabbbccc') 这个是错误的.ora-30001: trim set should have only one character 2. in ...
- 使用meaven打包过程中遇到的一些问题
开始使用如下代码进行打包 <build> <!-- mvn assembly:assembly -Dmaven.test.skip=true --> <plugins&g ...
- centos安装中文支持(转)
安装中文支持包. yum install fonts-chineseyum install fonts-ISO8859-2 -------- 一.安装中文支持方法1.在安装光盘中找到一下包进行安装.r ...
- jquery实现点击改变背景色,点击其他恢复原来背景色,被点击的改变背景色
实现这个功能很简单,可是之前自己不怎么熟悉jquery,感觉各种乱写.现在终于整理好了思路. html: <div class="managementPanel"> & ...
- JavaWeb基础之tomcat部署
有些东西,看起来简单,做起来也简单,简单的你并不一定知道! 问题:如何将一个java project转变为 web project,并使其自动部署到tomcat? 1.先建立一个Java Projec ...
- 剑指offer——已知二叉树的先序和中序排列,重构二叉树
这是剑指offer中关于二叉树重构的一道题.题目原型为: 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1,2, ...
- SQL Server 一些重要视图2
1. sys.dm_tran_session_transactions 为每一个没有关闭的事务返回一行.session_id 可以与sys.dm_exec_connections.session_id ...
- Android学习笔记:利用httpclient和AsyncTask 发起网络http post操作
1.在android4中,发起网络http操作,不能在Activity的事件(即主线程)中进行,必须在单独的线程中操作. 另外进行网络操作,需要在manifest文件中增加如下的权限: <use ...
- Android系统Recovery工作原理之使用update.zip升级过程---updater-script脚本语法简介以及执行流程(转)
目前update-script脚本格式是edify,其与amend有何区别,暂不讨论,我们只分析其中主要的语法,以及脚本的流程控制. 一.update-script脚本语法简介: 我们顺着所生成的脚本 ...
- 如何自定义Intent.createChooser的显示结果
Intent是android核心的概念之一,Intent为android系统提供了真正的开放.android的姿态是开放了,但却没有做到位. 拿“发邮件”这一功能来说,为了使用Intent机制来发送邮 ...