设为首页收藏本站 今天是: 2022-05-18    "国际博物馆日"  了解博物馆,更好地发挥博物馆的社会功能

复仇者黑客组织

 找回密码
 立即注册

QQ登录

只需一步,快速开始

    查看: 607|回复: 10

    从零开始教你做辅助(一)

    [复制链接]

    该用户从未签到

    14

    主题

    14

    帖子

    80

    积分

    网站信息宣传员

    Rank: 7Rank: 7Rank: 7

    积分
    80
    发表于 2022-1-26 11:22:46 | 显示全部楼层 |阅读模式
    大家好,我是山里猴,上次发了篇经验分享的帖子后,有些朋友说能不能做一个从零开始的系列.
    承蒙大家厚爱,小弟受宠若惊,哈哈,从零开始系列来了.
    说到怎么做好一个辅助啊,这我非常有经验,辅助最重要的就是,对线期一定不要跟大哥抢钱,大哥上去送的时候一定要及时加血,并用自己伟岸的身躯给大哥挡伤害.
    !!!不对,这里是吾爱论坛啊,不好意思,走错片场了,下面回归正题.
    本期内容先讲下怎么从目标程序中获取怪物信息.
    这期内容的markdown我也会同步放到我的gayhub项目中的https://github.com/shanlihou/hack_warspear,的tutorial文件夹下面
    获取怪物信息

    0x01:工具及背景知识

    1.cheat engine

    ce查内存神器,还能调试
    2.IDA

    查看反汇编静态代码用的
    3.immunity debugger

    查看代码或者调试都很有用
    4.语言(c++,python,lua,汇编)

    c++:用来编写辅助程序
    python:用来在immunity debugger中编写插件
    lua:用来在ce中编写插件
    汇编:能看懂就行,不要求会写,逆向程序逻辑时候需要
    0x02:找到修改血量代码位置

    首先找到怪物的血量地址,如下图.
    TBC茶馆-复仇者黑客组织大家好,我是山里猴,前次发了篇履历分享的帖子后,有些朋友说能不能做一个从零开始的系列.承蒙大家厚爱,小弟复仇者黑客组织(1)
    如上图所示,按照上图位置右键"找出是什么改写了这个位置",并点击附加到进程.
    在附加到进程后攻击这个怪物.这时候会看到下图
    TBC茶馆-复仇者黑客组织大家好,我是山里猴,前次发了篇履历分享的帖子后,有些朋友说能不能做一个从零开始的系列.承蒙大家厚爱,小弟复仇者黑客组织(2)
    图中地址00570FFB就是修改怪物血量的代码位置
    0x03:找到调用堆栈

    还记得我们上次讲怎么用ce+lua吗.
    我们编写如下脚本
    代码位置:$(ROOT)/info/find_hp_base.lua
    1. function print_stack(ebp, deep) --打印堆栈的函数,返回值是堆栈调用过程
    2.     if deep == 0
    3.     then
    4.         return ""
    5.     end
    6.     local ebp_4 = readInteger(ebp + 4)
    7.     local str_ret = string.format("%x->", ebp_4)
    8.     local next_ebp = readInteger(ebp)
    9.     str_ret = str_ret .. print_stack(next_ebp, deep - 1)
    10.     return str_ret
    11. end
    12. function clear_debug() --清除所有已经添加的断点
    13.     local tbl = debug_getBreakpointList()
    14.     if tbl == nil
    15.     then
    16.         return
    17.     end
    18.     for i,v in ipairs(tbl) do
    19.         print(string.format("%4d 0x%X",i,v))
    20.         debug_removeBreakpoint(v)
    21.     end
    22. end
    23. function debugger_onBreakpoint() --默认断点函数
    24.     if EIP == 0x570FFB -- 这个位置是咱们刚刚获得的修改怪物血量的代码位置
    25.     then
    26.         local ret = print_stack(EBP, 10)
    27.         print(ret)
    28.     else
    29.         print("not found")
    30.     end
    31.     return 1
    32. end
    33. clear_debug()
    34. debug_setBreakpoint(0x570FFB)
    复制代码
    好,我们现在拿着如上代码在ce上执行.执行完后,就可以操作玩家打怪了.
    在玩家攻击后会看到如下图打印
    TBC茶馆-复仇者黑客组织大家好,我是山里猴,前次发了篇履历分享的帖子后,有些朋友说能不能做一个从零开始的系列.承蒙大家厚爱,小弟复仇者黑客组织(3)
    上图中红框框出来的这个打印就是一次扣血的调用过程,我们就拿着这个找基址
    70e76a->70fa54->747e0e->87c579->86052b->75b247ab->75b02aac->75b044db->75b041e0->8602c6->
    0x04:找到基址

    现在用immunity debugger打开我们的游戏并定位到位置0x570FFB
    TBC茶馆-复仇者黑客组织大家好,我是山里猴,前次发了篇履历分享的帖子后,有些朋友说能不能做一个从零开始的系列.承蒙大家厚爱,小弟复仇者黑客组织(4)
    我们从上图1位置(0x570FFB)可以看出血量应该是保存在esi+0xf4这个位置,那么我们现在就要找esi的值是怎么来的
    我们网上看图2位置(0x570ff2)esi是从eax赋值的,那么就要找eax怎么来的.
    在网上看图3位置有一个函数调用,一般汇编的函数如果有返回值的话是保存在eax的.所以我们要跟进去看是不是这个函数返回的.
    TBC茶馆-复仇者黑客组织大家好,我是山里猴,前次发了篇履历分享的帖子后,有些朋友说能不能做一个从零开始的系列.承蒙大家厚爱,小弟复仇者黑客组织(5)
    上图是进入函数0x715720后,的相关内容,我给大家翻译一下上面的内容,下面是翻译后的c++代码.
    ```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;
    }
    }
    1. 有一定c/c++语言功底的朋友不难看出,上面代码是一段对数据结构二叉树的查找过程.所以我们可以确定了,这款游戏的怪物信息是使用二叉树来存储的.  
    2. 把上图的eax想象成一个节点.那么eax+0x10这个位置存储的就可能是类似id的值,然后跟edx这个目标值来比较.  
    3. 如果当前id > edx 则从右节点继续找(eax + 0x04)
    4. 如果当前id < edx 则从左节点继续找(eax + 0x08)
    5. 如果相等就用eax = *(eax + 0x14)然后返回.
    6. 所以从上图汇编代码我们得到三个信息:  
    7. 1.a的确是返回值  
    8. 2.怪物信息存在一个二叉树里  
    9. 3.从第一行(MOV EAX,DWORD PTR DS:[ECX+38])看出,咱门下一个追踪目标就是这个ecx了
    10. 我们继续顺着上面汇编图的4,5,6会发现我们已经找到了基址(哈哈,很尴尬,前面的查看堆栈貌似没啥用啊,没关系,下次讲一定会把它用上的.因为我之前完成的时候已经过去很久了,写这篇文章时候是边做边写的.所以没想到没用上)  
    11. 从"MOV EAX,DWORD PTR DS:[9A45B0]" 中得到基址 0x9A45B0
    12. ## 0x05:测试基址是否正确
    13. 我们编写如下lua代码  
    14. 代码位置:$(ROOT)/info/print_tree.lua
    15. ```lua
    16. function handleNode(value, ptr, hp)
    17.     print(string.format('%x,%x,%d', value, ptr, hp))
    18. end
    19. function read_tree(node, func)--读取二叉树结构体的代码
    20.     if (node == 0 or node == nil)
    21.     then
    22.         return
    23.     end
    24.     local left = readInteger(node + 4)
    25.     local right = readInteger(node + 8)
    26.     local value = readInteger(node + 0x10)
    27.     local ptr = readInteger(node + 0x14)
    28.     local hp = readInteger(ptr + 0xf4) --这里存的就是血量了.对应上面汇编代码中的(esi + f4)
    29.     read_tree(left, func)
    30.     read_tree(right, func)
    31.     func(value, ptr, hp)
    32. end
    33. local g_base = readInteger(0x9a45b0)
    34. local tmp_ptr = readInteger(g_base + 0x10)
    35. tmp_ptr = readInteger(tmp_ptr + 0x38)
    36. local root = readInteger(tmp_ptr)
    37. read_tree(root, handleNode)
    复制代码
    把上面代码放在ce中执行就会看到打印如下
    TBC茶馆-复仇者黑客组织大家好,我是山里猴,前次发了篇履历分享的帖子后,有些朋友说能不能做一个从零开始的系列.承蒙大家厚爱,小弟复仇者黑客组织(6)
    上图中1已经把我自己的hp打印出来了.可以看出这个基址是没有问题的.
    0x06:写我们的辅助程序

    好了现在完事具备,只欠东风,下面就开始写我们的辅助程序.
    TBC茶馆-复仇者黑客组织大家好,我是山里猴,前次发了篇履历分享的帖子后,有些朋友说能不能做一个从零开始的系列.承蒙大家厚爱,小弟复仇者黑客组织(7)
    如图是用vs2019打开工程后的目录结构.
    图上标号1位置这个工程是辅助逻辑相关,比如查看怪物信息,攻击怪物,捡去物品等,这个最后生成了一个静态库
    图上标号2位置这个工程是注入后的主进程,最后编译为一个动态库.(实际上1和2可以合并一起,因为2在运行过程中调用gameData工程里的接口,所以把gameData静态链接进2)
    图上标号3位置这个工程是用来把上面编写的动态库注入到目标程序中用的.  
    下面我们就其中一些重要并在本章节用到的代码讲解一下
    1.注入过程

    代码位置:$(ROOT)/InjectDll/InjectDll.cpp
    ```c++
    warHandle = FindWindowA(GAME_CLASS_NAME, NULL);//根据窗口名字找到目标进程的窗口句柄
    if (warHandle == 0)
    return;
    1. printf("find handle\n");
    2. GetWindowThreadProcessId(warHandle, &pid); // 根据目标句柄获取目标主进程pid
    3. if (pid == 0)
    4. {
    5.     printf("get pid error\n");
    6.     return;
    7. }
    8. hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); // 获取目标进程句柄,并获取所有操作权限
    9. if (hProcess == NULL)
    10. {
    11.     printf("get hProcess error\n");
    12.     return;
    13. }
    14. addressDW = (LPDWORD)VirtualAllocEx(hProcess, NULL, 256, MEM_COMMIT, PAGE_READWRITE);
    15. //在目标进程内申请一段内存,主要用来存放即将被我们注入的动态库的全路径
    16. if (addressDW == NULL)
    17. {
    18.     printf("get hProcess error\n");
    19.     return;
    20. }
    21. WriteProcessMemory(hProcess, addressDW, dllPath, strlen(dllPath) + 1, &byWriteSize);
    22. //将动态库全路径保存到刚刚申请的内存里
    23. if (byWriteSize < strlen(dllPath))
    24. {
    25.     printf("write memmory failed!");
    26.     return;
    27. }
    28. threadHandle = CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibraryA, addressDW, NULL, NULL);
    29. //在目标进程内创建线程线程,线程会执行加载动态库的操作
    30. WaitForSingleObject(threadHandle, 0xFFFFFFFF);
    31. //等待刚刚加载动态库操作完成,好了,到此,我们的注入操作完成.
    32. CloseHandle(threadHandle);
    33. VirtualFreeEx(hProcess, addressDW, 256, MEM_COMMIT);
    34. CloseHandle(hProcess);
    复制代码
    1. ### 2.注入后的主函数
    2. 代码位置:$(ROOT)/GameData/HookGameMainThread.cpp
    3. ```c++
    4. LRESULT CALLBACK GameWndProc(int nCode, WPARAM wParam, LPARAM lParam)
    5. {
    6.     CWPSTRUCT* lpArg = (CWPSTRUCT*)lParam;
    7.     if (nCode == HC_ACTION)
    8.     {
    9.         if (lpArg->hwnd == getGameWndHandle() && lpArg->message == g_myMsgCode)
    10.         {
    11.             // 注入后的ui线程会给主线程发消息,消息被钩子在这里截获,截获后,根据消息类型执行相关操作
    12.             doAction((MsgAction)lpArg->wParam);
    13.             return 1;
    14.         }
    15.     }
    16.     return CallNextHookEx(g_hhkGame, nCode, wParam, lParam);
    17. }
    18. DWORD HookMainThread() //注入后的主函数其实会实例化一个ui窗口,然后再窗口主进程里执行这个函数
    19. {
    20.     log_debug("hook ok\n");
    21.     HWND hGame = getGameWndHandle(); // 获取主线程窗口句柄,这个要通过ce实现查找主线程句柄存放基址
    22.     DWORD ndThreadId = GetWindowThreadProcessId(hGame, NULL); // 根据主线程句柄获取主线程id
    23.     if (ndThreadId == NULL)
    24.     {
    25.         return 1;
    26.     }
    27.     g_hhkGame = SetWindowsHookExA(WH_CALLWNDPROC, GameWndProc, NULL, ndThreadId);
    28.     // 注册一个钩子函数到主线程中,钩子函数为上面的GameWndProc
    29.     return 1;
    30. }
    复制代码
    最终效果如下图所示:
    TBC茶馆-复仇者黑客组织大家好,我是山里猴,前次发了篇履历分享的帖子后,有些朋友说能不能做一个从零开始的系列.承蒙大家厚爱,小弟复仇者黑客组织(8)
    大家会看到,多了一个图标和我们目标进程一样,名字叫Dialog的窗口,这个就是注入后的UI线程.
    点击窗口中的test按钮,会给主线程发送一个MsgTest的消息,主线程中收到消息后会把怪物信息输出到e:\shlog\warspear.log里面(这个位置是写死的,大家可以在GameData/debug.h文件里修改)
    可以看到,日志输出和我们在ce里面看到的是一样的,到此,我们的获取怪物信息就ok了.
    大家有什么不明白,欢迎给我提issue.




    上一篇:理解ret2dlsolve和函数地址解析过程
    下一篇:某wasu mp4地址获取解密-复仇者黑客组织

    该用户从未签到

    1

    主题

    1052

    帖子

    530

    积分

    高级会员

    Rank: 4

    积分
    530
    发表于 2022-1-26 11:22:57 | 显示全部楼层
    开局就是地狱难度
    回复

    使用道具 举报

    该用户从未签到

    0

    主题

    1013

    帖子

    2

    积分

    新手上路

    Rank: 1

    积分
    2
    发表于 2022-1-26 11:23:33 | 显示全部楼层
    我傻傻的以为自己真的要学会做辅助了
    回复

    使用道具 举报

    该用户从未签到

    2

    主题

    983

    帖子

    794

    积分

    高级会员

    Rank: 4

    积分
    794
    发表于 2022-1-26 11:23:50 | 显示全部楼层
    楼主,我想请教一下,这个论坛的markdown是不是大标题有bug啊?需要用二级标题才能正常显示?
    回复

    使用道具 举报

    该用户从未签到

    0

    主题

    1074

    帖子

    2

    积分

    新手上路

    Rank: 1

    积分
    2
    发表于 2022-1-26 11:24:02 | 显示全部楼层
    纯python估计不行的,需要调用一些c++封装的接口,但是可以大部分逻辑用python
    回复

    使用道具 举报

    该用户从未签到

    1

    主题

    1052

    帖子

    530

    积分

    高级会员

    Rank: 4

    积分
    530
    发表于 2022-1-26 11:24:09 | 显示全部楼层
    好像显示没啥问题,",获取怪物信息"就是我的大标题
    回复

    使用道具 举报

    该用户从未签到

    4

    主题

    993

    帖子

    983

    积分

    高级会员

    Rank: 4

    积分
    983
    发表于 2022-1-26 11:25:07 | 显示全部楼层
    牛比呀!!!!
    回复

    使用道具 举报

    该用户从未签到

    1

    主题

    962

    帖子

    887

    积分

    高级会员

    Rank: 4

    积分
    887
    发表于 2022-1-26 11:26:03 | 显示全部楼层
    插点学习;哦
    回复

    使用道具 举报

    该用户从未签到

    2

    主题

    1053

    帖子

    722

    积分

    高级会员

    Rank: 4

    积分
    722
    发表于 2022-1-26 11:26:33 | 显示全部楼层
    谢谢大佬分享知识,受教
    回复

    使用道具 举报

    该用户从未签到

    1

    主题

    1052

    帖子

    530

    积分

    高级会员

    Rank: 4

    积分
    530
    发表于 2022-1-26 11:26:56 | 显示全部楼层
    你只以为我在第一层 其实我在地下十八层
    但是大佬确实牛逼
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    Loading...
    嗨!您好:
    欢迎来到 复仇者黑客组织。
    我的名字叫小光
    很高兴能够为您服务!
    如果已经注册【立即登录】
    还没有账号请立即注册
    关闭Powered by ©科大讯飞语音云
    快速回复 返回顶部 返回列表