本期内容先讲下怎么从目标程序中获取怪物信息.
这期内容的 markdown 包括代码还有文件都在文中末尾的链接里

获取怪物信息
0x01:工具及背景知识
1.cheat engine
ce查内存神器,还能调试
2.IDA
查看反汇编静态代码用的
3.immunity debugger
查看代码或者调试都很有用
4.语言(c++,python,lua,汇编)
c++:用来编写辅助程序
python:用来在immunity debugger中编写插件
lua:用来在ce中编写插件
汇编:能看懂就行,不要求会写,逆向程序逻辑时候需要

0x02:找到修改血量代码位置
首先找到怪物的血量地址,如下图.

如上图所示,按照上图位置右键"找出是什么改写了这个位置",并点击附加到进程.
在附加到进程后攻击这个怪物.这时候会看到下图

图中地址00570FFB就是修改怪物血量的代码位置
0x03:找到调用堆栈
还记得我们上次讲怎么用ce+lua吗.
我们编写如下脚本
代码位置:$(ROOT)/info/find_hp_base.lua

function print_stack(ebp, deep) --打印堆栈的函数,返回值是堆栈调用过程 if deep == 0 then return "" end local ebp_4 = readInteger(ebp + 4)     local str_ret = string.format("%x->", ebp_4)     local next_ebp = readInteger(ebp)     str_ret = str_ret .. print_stack(next_ebp, deep - 1)     return str_ret end function clear_debug() --清除所有已经添加的断点 local tbl = debug_getBreakpointList()     if tbl == nil then return end for i,v in ipairs(tbl) do print(string.format("%4d 0x%X",i,v))         debug_removeBreakpoint(v)     end end function debugger_onBreakpoint() --默认断点函数 if EIP == 0x570FFB -- 这个位置是咱们刚刚获得的修改怪物血量的代码位置 then local ret = print_stack(EBP, 10)         print(ret)     else print("not found")     end return 1 end  clear_debug() debug_setBreakpoint(0x570FFB)

好,我们现在拿着如上代码在ce上执行.执行完后,就可以操作玩家打怪了.
在玩家攻击后会看到如下图打印

上图中红框框出来的这个打印就是一次扣血的调用过程,我们就拿着这个找基址

70e76a->70fa54->747e0e->87c579->86052b->75b247ab->75b02aac->75b044db->75b041e0->8602c6->
0x04:找到基址

现在用immunity debugger打开我们的游戏并定位到位置0x570FFB

我们从上图1位置(0x570FFB)可以看出血量应该是保存在esi+0xf4这个位置,那么我们现在就要找esi的值是怎么来的
我们网上看图2位置(0x570ff2)esi是从eax赋值的,那么就要找eax怎么来的.
在网上看图3位置有一个函数调用,一般汇编的函数如果有返回值的话是保存在eax的.所以我们要跟进去看是不是这个函数返回的.

上图是进入函数0x715720后,的相关内容,我给大家翻译一下上面的内容,下面是翻译后的c++代码.

eax = (ecx + 0x30); eax = (eax); edx = (ebp + 0x8); while (1): {     ecx = (eax + 0x10);// MOV ECX,DWORD PTR DS:[EAX+10] if (ecx > edx){//CMP ECX,EDX;    JBE SHORT warspear.0071573C         eax = (eax + 0x4);     continue; } else if (exc < edx){//JNB SHORT warspear.0071574B     eax = (eax + 0x8);     continue; } else{     eax = *(eax + 0x14);     break; } }
有一定c/c++语言功底的朋友不难看出,上面代码是一段对数据结构二叉树的查找过程.所以我们可以确定了,这款游戏的怪物信息是使用二叉树来存储的.   把上图的eax想象成一个节点.那么eax+0x10这个位置存储的就可能是类似id的值,然后跟edx这个目标值来比较.   如果当前id > edx 则从右节点继续找(eax + 0x04) 如果当前id < edx 则从左节点继续找(eax + 0x08) 如果相等就用eax = *(eax + 0x14)然后返回.  所以从上图汇编代码我们得到三个信息:   1.a的确是返回值   2.怪物信息存在一个二叉树里   3.从第一行(MOV EAX,DWORD PTR DS:[ECX+38])看出,咱门下一个追踪目标就是这个ecx了  我们继续顺着上面汇编图的4,5,6会发现我们已经找到了基址(哈哈,很尴尬,前面的查看堆栈貌似没啥用啊,没关系,下次讲一定会把它用上的.因为我之前完成的时候已经过去很久了,写这篇文章时候是边做边写的.所以没想到没用上)   从"MOV EAX,DWORD PTR DS:[9A45B0]" 中得到基址 0x9A45B0  ## 0x05:测试基址是否正确  我们编写如下lua代码   代码位置:$(ROOT)/info/print_tree.lua  ```lua function handleNode(value, ptr, hp) print(string.format('%x,%x,%d', value, ptr, hp)) end function read_tree(node, func)--读取二叉树结构体的代码 if (node == 0 or node == nil)     then return end local left = readInteger(node + 4)     local right = readInteger(node + 8)     local value = readInteger(node + 0x10)     local ptr = readInteger(node + 0x14)     local hp = readInteger(ptr + 0xf4) --这里存的就是血量了.对应上面汇编代码中的(esi + f4)     read_tree(left, func)     read_tree(right, func)     func(value, ptr, hp) end local g_base = readInteger(0x9a45b0) local tmp_ptr = readInteger(g_base + 0x10) tmp_ptr = readInteger(tmp_ptr + 0x38) local root = readInteger(tmp_ptr) read_tree(root, handleNode)

把上面代码放在ce中执行就会看到打印如下

上图中1已经把我自己的hp打印出来了.可以看出这个基址是没有问题的.
0x06:写我们的辅助程序
好了现在完事具备,只欠东风,下面就开始写我们的辅助程序.
如图是用vs2019打开工程后的目录结构.

图上标号1位置这个工程是辅助逻辑相关,比如查看怪物信息,攻击怪物,捡去物品等,这个最后生成了一个静态库
图上标号2位置这个工程是注入后的主进程,最后编译为一个动态库.(实际上1和2可以合并一起,因为2在运行过程中调用gameData工程里的接口,所以把gameData静态链接进2)
图上标号3位置这个工程是用来把上面编写的动态库注入到目标程序中用的.
下面我们就其中一些重要并在本章节用到的代码讲解一下
1.注入过程
代码位置:$(ROOT)/InjectDll/InjectDll.cpp

warHandle = FindWindowA(GAME_CLASS_NAME, NULL);//根据窗口名字找到目标进程的窗口句柄 if (warHandle == 0) return; printf("find handle\n"); GetWindowThreadProcessId(warHandle, &pid); // 根据目标句柄获取目标主进程pid if (pid == 0) { printf("get pid error\n"); return; } hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); // 获取目标进程句柄,并获取所有操作权限 if (hProcess == NULL) { printf("get hProcess error\n"); return; } addressDW = (LPDWORD)VirtualAllocEx(hProcess, NULL, 256, MEM_COMMIT, PAGE_READWRITE); //在目标进程内申请一段内存,主要用来存放即将被我们注入的动态库的全路径 if (addressDW == NULL) { printf("get hProcess error\n"); return; } WriteProcessMemory(hProcess, addressDW, dllPath, strlen(dllPath) + 1, &byWriteSize); //将动态库全路径保存到刚刚申请的内存里 if (byWriteSize < strlen(dllPath)) { printf("write memmory failed!"); return; } threadHandle = CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibraryA, addressDW, NULL, NULL); //在目标进程内创建线程线程,线程会执行加载动态库的操作 WaitForSingleObject(threadHandle, 0xFFFFFFFF); //等待刚刚加载动态库操作完成,好了,到此,我们的注入操作完成. CloseHandle(threadHandle); VirtualFreeEx(hProcess, addressDW, 256, MEM_COMMIT); CloseHandle(hProcess); ### 2.注入后的主函数 代码位置:$(ROOT)/GameData/HookGameMainThread.cpp ```c++ LRESULT CALLBACK GameWndProc(int nCode, WPARAM wParam, LPARAM lParam) { CWPSTRUCT* lpArg = (CWPSTRUCT*)lParam; if (nCode == HC_ACTION) { if (lpArg->hwnd == getGameWndHandle() && lpArg->message == g_myMsgCode) { // 注入后的ui线程会给主线程发消息,消息被钩子在这里截获,截获后,根据消息类型执行相关操作 doAction((MsgAction)lpArg->wParam); return 1; } } return CallNextHookEx(g_hhkGame, nCode, wParam, lParam); } DWORD HookMainThread() //注入后的主函数其实会实例化一个ui窗口,然后再窗口主进程里执行这个函数 { log_debug("hook ok\n"); HWND hGame = getGameWndHandle(); // 获取主线程窗口句柄,这个要通过ce实现查找主线程句柄存放基址 DWORD ndThreadId = GetWindowThreadProcessId(hGame, NULL); // 根据主线程句柄获取主线程id if (ndThreadId == NULL) { return 1; } g_hhkGame = SetWindowsHookExA(WH_CALLWNDPROC, GameWndProc, NULL, ndThreadId); // 注册一个钩子函数到主线程中,钩子函数为上面的GameWndProc return 1; }

最终效果如下图所示:

大家会看到,多了一个图标和我们目标进程一样,名字叫Dialog的窗口,这个就是注入后的UI线程.
点击窗口中的test按钮,会给主线程发送一个MsgTest的消息,主线程中收到消息后会把怪物信息输出到e:\shlog\warspear.log里面(这个位置是写死的,大家可以在GameData/debug.h文件里修改)
可以看到,日志输出和我们在ce里面看到的是一样的,到此,我们的获取怪物信息就ok了.
大家有什么不明白,欢迎给我提issue.

本篇文章的markdown在下方链接中,欢迎下载并交流沟通

https://www.dslt.tech/article-49-1.html

版权声明:本文由 shanlihou 原创,欢迎分享本文,转载请保留出处

从零教新手开始学做游戏辅助系列(一)相关推荐

  1. 我在日本学做游戏期间的所见所闻与所想

    "想去日本学做游戏",我当初只有这么一个懵懵懂懂的想法.或许有些朋友的情况与我类似,从小接触游戏,自然而然有了投身游戏行业的想法.国内现在还没有成熟的游戏开发教育体系,而邻国日本作 ...

  2. Construct2 ——— 零基础也能自己做游戏

    Construct2 --- 零基础也能自己做游戏 Construct2是一款跨平台的二维游戏开发引擎,他不需要你有任何的编码基础,通过定义部件和事件而完成游戏的制作.简单直观,迅速的让你拥有自己的小 ...

  3. 零基础机器学习做游戏辅助第一课--神经网络与Keras介绍

    本课程前言: 本课程的目的很明确,教会大家使用机器学习中的神经网络去做游戏辅助.不用担心自己数学不好,英语不好能不能学会,我在课程中以最通俗易懂的方法给你讲解.只要下定决心去学,就一定可以学会. 本课 ...

  4. S27赛季即将来袭 教你用Java做游戏王者荣耀

    咳咳,冒昧问一下大家,S26赛季大家达到了什么段位了?有没有什么大神带带我这个永恒小钻石. 废话少说,有人带吗? 废话再少说,带得动吗? 废话没了,开始我们今天的课程,今天给大家讲解了一个王者荣耀游戏 ...

  5. html5(熊与蘑菇)一步一步学做游戏 第一回:游戏分析

    该游戏教程主要参考了老外Jason Croucher的博客 http://jacebook.co.uk/blog/2010/09/11/html5-writing-a-game/ 游戏代码也下载自他的 ...

  6. 零基础新手小白学编程必会的100个代码

    前言 我记得刚开始接触编程的时候,觉得太难了. 也很好奇,写代码的那些人也太厉害了吧?全是英文的,他们的英文水平一定很好吧? 他们是怎么记住这么多代码格式的?而且错了一个标点符号,整个程序都会有影响. ...

  7. Construct2 ——— 零基础也能自己做游戏

    construct2是一个很方便的游戏制作软件,可以专门制作一些比较简单的二维小游戏, 首先,我们要添加一些图层,可以点那个加号添加 回到背景层,双击可以添加一些游戏角色,这里提供一些游戏素材. 之后 ...

  8. 一步一步学做游戏 第二回:让蘑菇随鼠标动起来

    上回分析了游戏,在这一回我们将让蘑菇跟随鼠标动起来~ 达到这个效果: http://www.html5china.com/html5games/mogu/index1.html 一.写html代码 X ...

  9. 一步一步学做游戏 第五回:熊碰撞蘑菇处理

    第五回主要讲熊碰到 蘑菇 之后向上反弹的效果 预期达到的效果: http://www.html5china.com/html5games/mogu/index4.html 一.由于碰撞的地方比较多,所 ...

  10. 零基础机器学习做游戏辅助第十三课--原神自动钓鱼(三)labelimg的使用

    一.什么是labelimg labelimg是一款开源的图像标注工具,标签可用于分类和目标检测,它是用python写的,并使用Qt作为其图形界面,简单好用(虽然是英文版的).其注释以 PASCAL V ...

最新文章

  1. 台式计算机无线设置,台式电脑怎么设置无线网络?
  2. 计算机一级必考知识点,计算机一级word操作知识点
  3. 用jQuery作为JS对象从选项中添加选项的最佳方法是什么?
  4. ABAP--如何快速从BSEG读取数据
  5. QML和C++混合编程--(三)
  6. *PAT_B_1030_Java(22分)_C++(25分)
  7. 白板机器学习笔记 P22-P27 PCA降维
  8. 用jframe给MySQL输入数据_如何从JTextField输入Info到sql数据库?
  9. mat分析dump分析_使用Eclipse Memory Analyzer Tool(MAT)分析线上故障(一)
  10. 1015 德才论 (25 分)—PAT (Basic Level) Practice (中文)
  11. iOS 时间校准解决方案
  12. GitHub添加SSH-key的步骤
  13. vscode中如何修改vetur配置_vscode vetur插件配置不换行
  14. h.265/HEVC 和 h.264/AVC 比较,在技术上的改进和优势
  15. 已知两个向量的坐标求夹角的大小_两个向量的夹角怎么算
  16. 追求技术之美:云计算开发者的自我修养
  17. vue element-ui 项目使用双色主题(白天,黑夜模式)
  18. 创建 Time Machine 时间机器的备份至 openmediavault 5(OMV 5) NAS 的 SMB/CIFS 共享文件夹
  19. oracle如何实现自增?----用序列sequence的方法来实现
  20. CodeVS4416 FFF 团卧底的后宫

热门文章

  1. 图贴图软件 ——— Snipaste
  2. 推荐支持 azw3 、epub 和 mobi 格式的阅读器:FBReader
  3. A very hard mathematic problem HDU - 4282(二分)
  4. Linux 计算器程序
  5. 基于java网上购物系统论文,基于Java的网上购物系统的设计与实现_毕业设计(论文).doc...
  6. MAC-终端命令大全
  7. c++如何侦测鼠标点击?
  8. CSS font-family 各字体一览表
  9. DBImport v3.0 中文版发布:支持各大数据库数据互导(IT人员必备工具)
  10. BMC bioinformatics research