做反外挂运营,特别是游戏方面反外挂需要具备哪些知识啊?特别是编程,学习哪种语言最好?
的有关信息介绍如下:先学习网络安全的基础知识,包括计算机网络,密码学和操作系统原理
掌握端游,页游和手游的安全编程。腾讯游戏很多安全问题是用假网页盗QQ或者微信号,是产品体系设计的安全问题。
再了解内挂注入,键盘挂脚本和抓包的原理
反外挂技术有客户端反外挂和服务器端反外挂。后者技术要求高但效果好,基本能达反外挂的最终目的
现如今,有很多游戏外挂软件,它们可以修改游戏显示的数据和内部代码,来达到谋取利益的目的。在实现反外挂技术前,我先介绍一下常见的三种外挂:
1.模拟类外挂:该外挂可以说是最早的外挂了,它是往游戏发送伪造的按键消息来模拟人的手工操作。实现的思路为:
1.在Ring3层使用SendMassage、PostMassage、keybd_event、mouse_event等向消息队列中发送按键消息
2.使用回调函数KeyboardClassServiceCallback和MouseClassServiceCallback往类驱动输入摁键消息。
2.内部Call调用外挂:使用逆向技术分析出游戏内部的汇编代码,把里面对游戏玩家有利的函数作为外挂的实现功能。实现的思路为:
1.使用逆向工具,去除壳和里面的反调试功能
2.分析游戏的使用过程、玩家自身的信息、背包信息、敌人信息等
3.逆向分析出游戏的明文发包功能
4.根据游戏的明文发包函数和报文信息分析游戏内部功能实现的函数
3.脱机外挂:分析出游戏客户端和服务端之间的通信逻辑,使用自己发送和接受数据来跟服务端进行交互。实现的思路如下:
1.使用逆向工具,去除壳和里面的反调试功能
2.逆向分析游戏中的汇编代码,分析出加解密算法及各种资源信息
3.分析出登录封包,获取各种跟游戏相关的信息
4.整合寻路算法,实现挂机
保护call函数和基址数据
1.最近玩植物大战僵尸和连连看等游戏的时候发现,这些游戏需要通过启动程序才能正常运行,那么我突发奇想,如果在程序运行前,修改游戏中的部分代码段数据,等需要运行游戏时再通过另一个程序恢复代码段数据,那么就可以起到保护游戏的作用。
2.对于游戏外挂制作者,他们经常习惯性的使用OD工具和CE工具、ida工具等,找出游戏的基址数据(也为全局变量)和内部call,然后修改基址数据或者修改执行流程,调用内部call。那么在游戏运行前就对基址数据地址和某些call后接地址进行修改,等需要运行游戏时,再修改回基址地址和call调用的地址,就可以起到反外挂的作用。
3.接下来,介绍一下这样做的作用:
4.简单介绍一下实现的流程:1.读取PE文件信息到内存中,遍历PE文件中的代码段,找到函数头部地址和使用的全局变量地址;2.在代码段中,找出调用函数的call指令,把call后接地址进行修改,对于数据,找到使用全局变量的mov指令,修改地址操作数;3.运行时,使用CreateProcess函数创建线程并挂起,然后恢复代码段中的数据并运行进程
5.我开发了一款反游戏外挂工具(该工具及其源码可在文章末尾下载)来模拟这个过程,在文件选择框选择要保护的PE文件,把需要保护的函数及数据添加到左边栏中,执行保护时,在PE文件目录下会生成已保护的PE文件,点击运行时,就能正常运行。
检测代码段
1.在游戏没有运行之前,修改、添加或删除PE文件的二进制信息可以起到修改程序流程的作用,从而起到外挂的作用。实现的技术有:在代码段的空白区域添加"洞穴代码",修改OEP的值,让程序跳转到洞穴代码;使用Inline HOOK执行外挂功能函数;修改代码段中的跳转指令和call后接地址,执行游戏内部汇编指令或者调动内部call等
2.在游戏运行时,通过外挂工具动态修改、添加或删除进程代码段数据或者动态注入shellcode同样也能起到修改程序流程的作用,那么需要校验PE文件和游戏内存数据就可以检测出游戏外挂。
3.在实际运用中,可以计算出PE文件的校验值,存放在游戏第三方程序的数据段中或者存放在游戏的服务器端,那么在游戏运行前校验PE文件值和运行时动态检验进程内存,接下来使用工具来模拟这个过程:1.选择PE文件计算PE文件校验值和记录代码段数据;2.选择需要校验的文件,同样也计算出校验值并比较是否变化;3.选择正在运行的进程,比较代码段数据是否变化。
4.实现的思路为:1.使用MD5算法计算出前后PE文件的校验值,并进行比较;2.先使用数组存放PE文件代码段数据,后读取进程内存中的代码段数据,然后比较数组数据是否相同
5.在游戏运行时,把游戏运行过程中使用过的函数及其相关的寄存器信息存放在服务端,在服务端检测函数的调用流程,就可以判断游戏内部call有没有非法调用。不过我这里模拟这个过程的方式是把函数运行时的信息写到日志文件中,查看日志信息来判断游戏内部call是否被非法调用。
6.实现的思路为:1.调式进程,循环接受调式事件;2.在刚开始调式时,把函数头部修改为CC;3.当发现中断时,判断发生中断的地址是否为函数头部地址,是的话,把线程上下文信息记录在日志文件中
//调式进程
DebugActiveProcess(pid):
//循环等待调式事件
while (WaitForDebugEvent(de, INFINITE))
{
......
PEXCEPTION_RECORD per = pde->u.Exception.ExceptionRecord;
//触发创建调式进程事件时
if (CREATE_PROCESS_DEBUG_EVENT == de.dwDebugEventCode)
//修改函数头部
SetUserFunc(de);
//触发异常事件时
else if (EXCEPTION_DEBUG_EVENT == de.dwDebugEventCode)
//判断触发异常地址
if (OnExceptionDebugEvent(de))
continue;
//继续接受调式事件
ContinueDebugEvent(de.dwProcessId, de.dwThreadId, dwContinueStatus);
}
HOOK检测
1.现在,有各种各样的HOOK技术,包括 InLine HOOK、IAT HOOK、API HOOK等,其中大部分需要注入dll来实现HOOK功能,那么游戏运行时,服务端或者游戏第三方程序可以检测有无dll注入,有的话,及时清除掉。实现的思路为:1.先记录游戏运行过程中用的dll文件名;2.游戏运行时遍历进程使用的dll文件名,若遇到不名dll文件名,则进行释放;
2.使用工具模拟这个过程:选择进程,选中dll文件所在目录,点击检测dll,就可检测出进程中是否有dll注入。
3.那么,除了检测dll文件外,还可以检测 IAT表和函数内部代码的跳转指令来判断游戏中是否有IAT HOOK或者InLine HOOK(跟API HOOK差不多,范围比API HOOK小,我这里就不介绍了),实现的过程为:1.选中游戏PE文件后,定位到导入表目录,遍历INT表中的_IMAGE_THUNK_DATA,通过里面的联合体u1,来获取游戏运行后IAT表中的函数地址;2.选中进程,读取进程内存中IAT表信息并比较函数地址,不同则说明有 IAT HOOK;3.对于InLine HOOK,读取进程代码段中函数区域的跳转指令操作数,若发现跳转到别的函数区域,则说明有InLine HOOK;
4.使用工具模拟这个过程:选中进程和PE文件,再点击 IAT HOOK按钮或者InLine HOOK按钮就可进行检测。
多开检测和动态调式工具检测
1.现在的打金工作室可以同时开多个号来刷金币,那么需要限制游戏多开,当动态调式进程时,在任务管理器中可以看到调式工具的主线程成了调式进程,那么调式器内存里面必然会有调式进程的内存信息,那么找到调式工具后再查找里面是否含有游戏进程的内存信息,若有则可以判断,游戏处于调式状态。
2.对于防多开,经常会用到下面的代码,那么外挂制作者修改跳转指令或者NOP掉汇编代码就可以实现多开。为了防止这种情况,我这里把CreateMutex函数头部修改为CC,使用调式器的方式不断监控异常事件,当CreateMutex函数头部触发中断异常时,获取互斥体变量名(地址为:ESP+8),并判断该变量名是否出现过,若出现过,则检测出进程出现多开。实现的关键代码如下:
//创建互斥体
HANDLE hMutex = CreateMutex(NULL,FALSE,"XXXXXX");
DWORD dret = GetLastError();
if(hMutex)
{
if (ERROR_ALREADY_EXISTS == dret)
{
CloseHandle(hMutex);
return 0;
}
}
.............
//WaitForSingleObject(hMutex,INFINITE);
............
ReleaseMutex(hMutex);
return 0;
}
检测多开的关键代码:
//解除HOOK 恢复原值
WriteProcessMemory(pde->dwProcessId, g_pCreateMutex,g_Orignal,sizeof(BYTE),NULL);
//获取线程上下文
ctx.ContextFlags = CONTEXT_CONTROL;
GetThreadContext(g_cpdi2.hThread,ctx);
//得到ESP+8的值
ReadProcessMemory(g_cpdi2.hProcess, LPVOID(ctx.Esp + 0x8), EspContent, sizeof(DWORD), NULL);
printf("EspContent: %x\n", EspContent);
//取出地址并获取字符串
Name[NameNum++] = (char*)(EspContent);
//判断有无重复互斥名
list list1;
for (int i = 0; i < NameNum; i++)
{
list1.push_back(Name[i]);
}
int len1 = list1.size();
list1.unique();
int len2 = list1.size();
//长度不等,则有重复元素
if (len1 != len2)
{
IsOpenMore = 1;
return -1;
}
//让EIP为当前地址
ctx.Eip = (DWORD)g_pCreateMutex;
//设置线程上下文
SetThreadContext(g_cpdi2.hThread, ctx);
//继续调式
ContinueDebugEvent(pde->dwProcessId, pde->dwThreadId, DBG_CONTINUE);
3.对于多开检测,我还想出了三种检测方法:1.获取进程代码段信息,使用代码段信息匹配的方式来判断是否有相同的进程运行;2.获取进程所有的窗口句柄,匹配查找有无跟窗口标题相同的窗口,有则说明多开;3.对进程名进行匹配;
4.对于调式工具检测,还是使用代码段识别法:获取OD工具中代码段信息匹配寻找相同进程,若有,则再识别内部有无游戏进程的内存信息并且再判断调式进程是否为调式工具的子进程,两者有一成立,则说明游戏进程处于调式状态,实现的关键代码如下:
void ToolAndOpenMore::GetToolCode(BYTE* ToolCode, CString strPath)
{
//把PE文件加载到内存中
PVOID PeBuffer =PEFileToMemory(CStringToCharSz(strPath));
//PE文件头
pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)PeBuffer + pDosHeader->e_lfanew + 0x4);
//节表数量
DWORD SectionNum = pPEHeader->NumberOfSections;
//PE可选头
pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
DWORD EP = pOptionHeader->AddressOfEntryPoint;
//代码段节表头
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);
tpSectionHeader = pSectionHeader;
int j = 0;
//遍历OEP之后的代码段数据
for (int i = tpSectionHeader->PointerToRawData; i < tpSectionHeader->PointerToRawData + tpSectionHeader->SizeOfRawData j
{
if (DataHs.FoaToRva(PeBuffer, i) < EP)
continue;
ToolCode[j++] = *((BYTE*)((DWORD)PeBuffer + i));
}
return;
}
5.接下来,使用工具进行检测:多开检测只需选中进程点击“多开检测”按钮即可;调式工具检测要选中进程和调式工具,操作情况如下所示:
添加反调式法
1.在游戏的PE文件中添加反调试,不为是一种较好的反外挂方法。在PE文件中修改TLS表信息,扩大最后一个节表并在空白区域添加PIMAGE_TLS_DIRECTORY结构信息、TLS回调函数,并在TLS回调函数中添加反调试功能即可实现反调试。
2.实现反调试的思路为:1.把PE文件加载到内存中,使用偏移的方式定位到TLS数据目录,修改其中的 RVA字段值和Size字段值,让 RVA指向PIMAGE_TLS_DIRECTORY起始地址;2.定位到最后的节表结构并增加SizeOfRawData的值和修改Characteristics的值,使最后的节表具有可执行特性。3.最后把生成的PIMAGE_TLS_DIRECTORY结构数据和回调函数ShellCode复制到最后的节表中。
3.除了往PE文件添加TLS反调式外,还可以添加SEH反调试,实现的思路为:1.先在代码段,寻找足够大的空闲区域,若没有找到,则新增最后节表大小;2.确定空闲区域开始地址,修改OEP的值,在空闲区域添加触发SEH异常的Shellcode,在该Shellcode中有异常处理函数,该异常处理函数会判断游戏是否处于调式中,如果没有处于调式状态则跳回OEP中,否则中止;
4.接下来使用工具添加反调试,选中文件,点击按钮即可。
个人觉得反外挂运营最主要是要对游戏的异常数据敏感,能估计出大概的外挂影响。具体反外挂找专业的反外挂公司来做比较好。这样搭配可以让效率和效益最大化
反外挂技术细节分析
1.反外挂系统主要是通过对libmono.so加壳来启动反外挂功能,当游戏启动后加载libmono.so时会先执行initarray中的初始化函数,有三个函数,第三个函数是主要的。
2.反调试:主要通过svc 0指令来获取进程状态,找到所有svc指令,找到open函数,patch掉就过了,让它返回失败.,代码如下:
3.第一次解密代码,计算crc值、判断crc、再次解密其它函数。
解密函数指令(前32字节),解密后指令计算crc、比较crc,相同后再解密其它函数指令,代码如下:
4.下面是解密后代码,计算并比较代码crc值,直接op掉,因为该指令是被加密存放的,如果要文件pathc,须先将nop指令加密再进行patch。代码如下:
5.计算代码crc值,代码如下:
6.比较crc值,相同返回0,代码如下:
7.如果crc值一样,就解密其它8个函数,并修复mono导出、hook函数mono image open from data with name、加载libNetHTProtect.so,调用libNetHTProtect.so中函数,反函数指令加密回去,代码如下:
8.把比较crc与解密其它8个函数的指令加密回去,代码如下:
9.解密so字符串还原导出表,代码如下:
此时将libmono.so从内存中dump出来可以看到导出了。
10.获取libNetHTProtect.so中的函数(反调试),代码如下:
11.hook函数mono image open from data withname,代码如下:
12.再将解密的so数据加密加回去,代码如下:
13.调用libNetHTProtect.so中的函数(反调试)
14.再将解密的8个函数再加密回去,代码如下:
15.libmono.so壳大致分析完成, 当加载dll时通过hook函数mono_image_open_from_data_with_name是走到libNetHTProtect.so中去。接下来就是分析hook函数,dump dll。
16.在游戏目assets\bin\Data\Managed中没有发现Assembly-CSharp.dll,只有Assembly-CSharp-firstpass.dll,反编译Assembly-CSharp-firstpass.dll时看不到代码,如图2所示。应该是做保护处理了。
17.分析libNetHTProtect.so中hook函数dump Assembly-CSharp-firstpass.dll,当dll加载走到hook函数中时会判断标记是否须要修复处理,代码如下:
8.将修复完后的dll dump出来进行反编译,如图3所示。
从上图可以看到主要是读到资源目录下的code.bytes.assetbundle文件,传给libUnityHelper.so中的LoadGame函数解密加载,代码如下:
从上面代码可以看到调用mono_image_open_from_data获取MonoImage,再调用mono_assembly_load_from完成对dll的加载,所以LoadGame最终也会走到libNetHTProtect.so中hook函数,判断是否须要修复,函数走完后直dump Assembly-CSharp.dll.dll就可以了,将dump出来的dll反编译后正常,如图4、5所示。
整个反外挂流程到这里基本分析完成。
做技术需要看的不是书,而是实战,只有实战才能提高你的技术实力,而不是所谓的理论派
简单举个小例子
很多人应该都玩过大型单机游戏,当然肯定有不少人玩的破解版
但是有很多无良的盗版游戏,等你用百度云慢吞吞下完几十G,你会发现要付费购买激活码才能安装
我寻思这补丁又不是你写的,这存储空间也是百度云
发布的时候不告知收费,下载完了告诉人收费
这种行为真的不是人能干出来的事情
拉进OD,按Ctrl+F8到他创建的地方,然后下断点,重新跑在断点的地方F7进去
可以看见他调用了一个在%temp%目录下的文件
然后这个程序就结束了,后面的内容都在temp那个文件里,本来想用OD附加,但是附加没用,如图附加后,f8直接就退出了
对于很多不懂技术的小伙伴来说,可能碰到这种情况就吃瘪了,没办法,再去找新的能用的资源,对于技术老鸟来说,肯定咽不下这口气
定要把它扒个干干净净,一顿抽打
以前分析病毒碰到过的镜像劫持,就把这两个程序用镜像劫持搞了一下
这个安装包exe和temp目录下的tmp名叫 qmzh3g,所有在这里镜像劫持,然后再用OD运行
镜像劫持后运行进程直接用OD打开了
得到下一步地址后,去OD下断点,然后运行,程序每次点下一步的时候,都会断在这
然后跑起来,在输入激活码的地方随便填,点下一步,被断下来
然后单步往下,有一个判断激活码的地方,NOP掉,下图这个CALL就是判断的地方,直接NOP掉
NOP掉之后直接F9,就可以直接安装了
我试了一下全战、只狼这俩游戏,偏移都一样,代码都是一样的,用这方法可以直接绕过,写了一个OD脚本,直接跑
脚本运行后截图
现在拿技术来恶搞的人不在少数,多少学点技术,能掌握一门能时时刻刻帮助到自己的技能还是有很大好处的
整个流程下来,其实并没有说用到多少理论性的东西,建议你是直接上手做,真正的困难会在过程中碰到,这个时候你再去查资料,解决它,效果会更加的好,印象会更加深刻
所以,我的建议是不要看书,完全靠自己学习,不断的去碰壁摸索,当然了,你觉得你摸索起来进步很慢的话,也可以跟着我来学习
对这方面技术感兴趣可以参考下图找我交流
import java.io.IOException;
import java.util.*;
public class EmotionJudge {
private double priorPositive;//积极先验概率
private double priorNegative;//消极先验概率
private double priorUnsure;//不确定先验概率
private Map backPositive;//词语的后验概率
private Map backNegative;//同上
private Map backUnsure;//同上
private boolean isGroup = false;
private String strTemp;
private Map articleWordMap;
//这两个是词典的位置
private final String posiDictPath = "/home/geekgao/朴素贝叶斯/台湾大学情感词典/ntusd-positive.txt";
private final String negaDictPath = "/home/geekgao/朴素贝叶斯/台湾大学情感词典/ntusd-negative.txt";
//这两个存储词典中的词语
private Set positiveDict;
private Set negativeDict;
public static void main(String [] args) {
new EmotionJudge().launch();
}
public void launch() {
getPrior();
getBack();
positiveDict = new HashSet();
negativeDict = new HashSet();
readEmotionWord(positiveDict, posiDictPath);
readEmotionWord(negativeDict, negaDictPath);
calc();
}
//获得先验概率
public void getPrior() {
SAXReader sax = new SAXReader();
try {
//从这读取doc的值
Document document = sax.read(new File("/home/geekgao/doc.xml"));
Element root = document.getRootElement();
List prior = root.elements();
priorPositive = Double.valueOf(prior.get(0).attributeValue("pPositive"));
priorNegative = Double.valueOf(prior.get(0).attributeValue("pNegative"));
priorUnsure = Double.valueOf(prior.get(0).attributeValue("pUnsure"));
} catch (DocumentException e) {
e.printStackTrace();
}
}
//获得后验概率
public void getBack() {
SAXReader sax = new SAXReader();
try {
//从这读取weight的值
Document document = sax.read(new File("/home/geekgao/weight.xml"));
Element root = document.getRootElement();
List back = root.elements();
backNegative = new HashMap();
backPositive = new HashMap();
backUnsure = new HashMap();
double backPos;//积极后验概率
double backNeg;//消极后验概率
double backUns;//不确定后验概率
String word;
反外挂分客户端反外挂和服务端反外挂。
客户端反外挂需要汇编,逆向功底好。 了解Window运行机制.
熟悉Rookit, 比如说, 知道如何检测DLL, 如果枚举所有的DLL. 如果给自己的函数添加CRC。
如果检测堆栈, 如何检测自己的函数是否是正常调用 等等。
概括一下, 客户端反外挂需要Rookit功底好。
服务端反外挂一般不需要Rookit, 但是也要对反外挂流程比较了解。
举个例子, 从服务端如何判断多开, 行为判断是否外挂.
主要是逻辑检测, 这个一般看服务端是用什么语言写的, 不限(不过肯定不是汇编写的)
一、先说一下写一个外挂需要什么条件
1、熟练的C语言知识
目前的外挂大部分都是用BC或者是vc写的,拥有熟练的C语言知识是写外挂的基本条件
2、具有很强的汇编基础 一般游戏都不可能有原代码的,必须*反汇编或者跟踪的办
法来探索其中的机理 ,所以有强的汇编基础也是必不可少的条件
3、熟练掌握跟踪和调试的工具
有了上面2个条件后,掌握一些工具也是很有必要的
跟踪的工具,softice当然是不二之选,至于反汇编的工具,我推荐用IDA PRO
这个工具反汇编出来的代码结构清晰,非常好读
如果你不具有上面的条件,还是先把基础打好,再来写外挂吧
学习的过程可以去找一些学习资料
这样水平提高起来会快点
我这里积累了很多的干货
有需要的可以找我来拿
参考下图找我交流
def recognition_captcha(data):
''' 识别验证码 '''
file_id = str(uuid.uuid1())
filename = 'captcha_'+ file_id +'.gif'
filename_png = 'captcha_'+ file_id +'.png'
if(data is None):
return
data = base64.b64decode(data.encode('utf-8'))
with open( filename ,'wb') as fb:
fb.write( data )
appid = 'appid' # 接入优图服务,注册账号获取
secret_id = 'secret_id'
secret_key = 'secret_key'
userid= 'userid'
end_point = TencentYoutuyun.conf.API_YOUTU_END_POINT
youtu = TencentYoutuyun.YouTu(appid, secret_id, secret_key, userid, end_point) # 初始化
# 拿到的是gif格式,而优图只支持 JPG PNG BMP 其中之一,这时我们需要 pip install Pillow 来转换格式
im = Image.open( filename)
im.save( filename_png ,"png")
im.close()
result = youtu.generalocr( filename_png , data_type = 0 , seq = '') # 0代表本地路径,1代表url
return result
def get_captcha(sessiona,headers):
''' 获取验证码 '''
need_cap = False
while( need_cap is not True):
try:
sessiona.get(' https://www. zhihu.com/signin ',headers=headers) # 拿cookie:_xsrf
resp2 = sessiona.get(' https://www. zhihu.com/api/v3/oauth/ captcha?lang=cn ',headers=headers) # 拿cookie:capsion_ticket
need_cap = json.loads(resp2.text)["show_captcha"] # {"show_captcha":false} 表示不用验证码
time.sleep( 0.5 + random.randint(1,9)/10 )
except Exception:
continue
try:
resp3 = sessiona.put(' https://www. zhihu.com/api/v3/oauth/ captcha?lang=cn ',headers=headers) # 拿到验证码数据,注意是put
img_data = json.loads(resp3.text)["img_base64"]
except Exception:
return
我建议物理打击
所有游戏公司实名,不实名或假身份证直接冻结直到用真实信息实名
QQ号,邮箱这种也不能随便注册
所有游戏公司联合起来,搞个名单,比如说在吃鸡开挂被封的,玩csgo也是重点监视对象。
纳入银行征信系统。开挂被封的,进黑名单,房贷车贷这类不予申请
最后,制作,卖挂的,坐牢
做反外挂运营,特别是游戏方面反外挂需要具备 ?
PC端需要了解游戏的开发过程,非常熟悉windows。最好会windows编程,需要非常熟悉软件安全,以及计算机原理 、网络知识。必须知道各种外挂原理和使用。等等,应该需要很多计算机知识。
手游的话 需要增加Linux 系统知识,Android知识
特别是编程,学习哪种语言最好?
这个学习的多了··· C C++ Linux 编程 Android 编程, 逆向分析。windows编程
Linux 内核 windows内核 相关介绍书籍。网络编程,汇编语言 。
能想到的就这么多,只会比这个多 不会比这个少
1、熟练的C语言知识
目前的外挂大部分都是用BC或者是vc写的,拥有熟练的C语言知识是写外挂的基本条件
2、具有很强的汇编基础 一般游戏都不可能有原代码的,必须*反汇编或者跟踪的办
法来探索其中的机理 ,所以有强的汇编基础也是必不可少的条件
3、熟练掌握跟踪和调试的工具
有了上面2个条件后,掌握一些工具也是很有必要的
跟踪的工具,softice当然是不二之选,至于反汇编的工具,我推荐用IDA PRO
这个工具反汇编出来的代码结构清晰,非常好读
如果你不具有上面的条件,还是先把基础打好,再来写外挂吧,一分耕耘,一分收获,天下没有白掉的馅饼的
二、写外挂面临的基本技术问题
1、修改进程的执行代码 要修改进程的执行代码,要先取得进程的ID,如果是由外挂程序启动,返回值里就有进程ID,
如果不是的话,
需要用findwindow找到窗口句柄,再用GetWindowProcessID取得进程ID,取得进程ID以后,就可以用
writeprocessmemory来修改进程的执行代码了,使程序按照我们的意愿来执行,石器外挂里的不遇敌、寸步遇敌
就是用这样的方法来实现的
2、截获外挂发送和接收的封包
除了通过修改代码来实现的功能以外,很多的功能都是通过修改封包来实现的,要修改封包,首先要能截获它。
第一步是要跟踪出发和收的位置,至于怎么跟踪,我以后会提到,找到位置以后,有2个办法,一是在那个位置加一
个jmp语句,跳到你的处理函数位置,处理完后,再跳回来,这种方法要求比较高,需要处理好很多事情,另一种办法
是往那个位置写条能造成例外的指令,比如int 3,然后用DebugActiveProcess调试游戏进程,这样每当游戏执行到那个
位置的时候,就会停下来,到外挂程序里面去,等外挂程序处理完以后,用ContinueDebugEvent 继续运行程序。
可能这些东西看起来会很枯燥,但是你要是入门了,就会轻松起来,可以去找一个水平高的老师带着你,这样能够很好的提高自己的水平
如果对计算机逆向这块技术感兴趣的可以找我交流
参考下图
def recognition_captcha(data):
''' 识别验证码 '''
file_id = str(uuid.uuid1())
filename = 'captcha_'+ file_id +'.gif'
filename_png = 'captcha_'+ file_id +'.png'
if(data is None):
return
data = base64.b64decode(data.encode('utf-8'))
with open( filename ,'wb') as fb:
fb.write( data )
appid = 'appid' # 接入优图服务,注册账号获取
secret_id = 'secret_id'
secret_key = 'secret_key'
userid= 'userid'
end_point = TencentYoutuyun.conf.API_YOUTU_END_POINT
youtu = TencentYoutuyun.YouTu(appid, secret_id, secret_key, userid, end_point) # 初始化
# 拿到的是gif格式,而优图只支持 JPG PNG BMP 其中之一,这时我们需要 pip install Pillow 来转换格式
im = Image.open( filename)
im.save( filename_png ,"png")
im.close()
result = youtu.generalocr( filename_png , data_type = 0 , seq = '') # 0代表本地路径,1代表url
return result
def get_captcha(sessiona,headers):
''' 获取验证码 '''
need_cap = False
while( need_cap is not True):
try:
sessiona.get(' https://www. zhihu.com/signin ',headers=headers) # 拿cookie:_xsrf
resp2 = sessiona.get(' https://www. zhihu.com/api/v3/oauth/ captcha?lang=cn ',headers=headers) # 拿cookie:capsion_ticket
need_cap = json.loads(resp2.text)["show_captcha"] # {"show_captcha":false} 表示不用验证码
time.sleep( 0.5 + random.randint(1,9)/10 )
except Exception:
continue
try:
resp3 = sessiona.put(' https://www. zhihu.com/api/v3/oauth/ captcha?lang=cn ',headers=headers) # 拿到验证码数据,注意是put
img_data = json.loads(resp3.text)["img_base64"]
except Exception:
return
端游我不知道不了解,手游的话比较简单,了解封包,内存简单的原理就好,没必要像他们说的要学习那么多,真学会了的话还做个毛的运营了你说是吗?