吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 14193|回复: 138
收起左侧

[原创] 从零开始教你做辅助--拾取篇(三 完结篇)

    [复制链接]
shanlihou 发表于 2021-3-13 17:46
大家好,我是山里猴.
哈哈,好久不见不知道还有人记得我吗,最近是真的忙,距离上一次更新估计有一两个月了.
这次更新也是这个系列最后一篇,主要是本系列后面更新重复内容会逐渐增多,新的可以和大家分享的内容就不多了.
我本人主要是做开发的,所以在做逆向的过程中,比较喜欢通过自己做一些插件等方式来提升逆向的效率.
其实最初选调试器的时候也用过OD,但是OD编写扩展相对其他调试器缺乏官方支持,后来也编译过x64Dbg,不过当时使用过程中有bug,可能是我编译问题.
后来发现immunity debugger这个调试器原生支持python,相信大家都听说过"人生苦短,我用python",python这语言开发效率确实高,很适合用来做插件
再后来发现CheatEngine 这个神器不止能查找内存,修改内存,也有调试功能.
而且我看论坛之前好像对于CheatEngine + lua方式,还有immunity debugger这方面的帖子也不多,所以就做了这个系列.

自己做辅助的过程也让自己又提升不少,为了分析方便,最近又学了下IDA pro的插件开发,做了个根据调用堆栈辅助分析基址的插件,之后把这个也分享下.
这是这个IDA Pro插件工程地址,用c++开发的 https://github.com/shanlihou/ida_get_base
用起来就如下图这样,下图显示的就是我用来查拾取函数参数基址时候的效果
ida_plugin.png

下面是前两篇的导航
从零开始教你做辅助一
从零开始教你做辅助二
---------------------------------------------- 废话分割线 -----------------------------------------------------

物品拾取

0x01 找到函数调用地址

上期我们在找攻击的调用函数地址时候其实已经找到了这个函数 76A670
这个函数里面有一个switch case 在case 10006的时候会走到拾取逻辑,最终走到769b30这个函数中  

open_monster_bag  

汇编代码就如上图,咱们就在调用的时候加个断点,来看下esi和edi究竟是什么,其实esi可以根据之前的攻击函数才出来,应该是玩家实体,毕竟这里应该调用的是玩家类的成员函数,所以ecx相当于this这个指针.  

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 == 0x76a7a5
    then
        print(string.format("enter in 0x76a7a5, esi:0x%X, edi:0x%X", ESI, EDI))
    else
        print(2)
    end
    return 1
end

clear_debug()
print(1)
debug_setBreakpoint(0x76a7a5)

打印这两个值得代码其实如上,前面已经展示很多遍了,其实这种逻辑比较简单的,大家加断点,在断下来之后直接查看寄存器,也可以,只不过我个人不太喜欢让游戏停下来,因为大部分游戏,停下来之后再运行可能要重新走下登录流程,很麻烦.
最后打印出如下
enter in 0x76a7a5, esi:0xEF4F4C8, edi:0xD623270
这个esi经过我和玩家实体指针对比,确实是玩家没错.这个edi并不是之前的怪物实体指针,需要在确认下具体是什么.
这个貌似没什么捷径,只能一层一层往上找,网上看到下图位置,看到edi是从函数的入参传进来的,现在只能继续逆流而上查找入参是从哪里来的.

modify_edi_1  

0x02: 分析参数来源

然后我们用老方法,获取调用过程如下.

76a5c6->5c72b5->7af2f9->7e8c79->5c77df->7bf179->747b18->8699b2->87b817->4be438->

modify_edi_4
从上层传入的第一个参数也是edi,再找这个edi的来源
modify_edi_2
可以看到,edi来自ecx+8
modify_edi_3
这里一顿操作,发现eax来自esi
modify_edi_5
esi又来自ecx
modify_edi_6
ecx又来自ebx
modify_edi_7
好了,这里真相了,ebx来自eax, eax又来自基址9A45B0,这个基址仔细一看跟当初的怪物列表最终的基址一模一样,应该出自同一个全局变量之类的.  

废了老大功夫,找到这个edi,我把它这个逻辑写到咱们的辅助程序里,试了下,结果直接异常退出了,这时候我把获取到的参数和ce里面获取到的比较了一下,发现这么深的一个变量只是用来临时存储用的.
只能从头来过了,其实还是重复上面的操作,下面还是直接贴个结果吧,主要还是让大家了解向上追踪的一个方法.

0x03: 编写打开怪物掉落列表的窗口的代码

void EntityBase::searchDead()
{
    try
    {

        DWORD tmp_ptr = *(DWORD*)(BASE_MONSTER_LIST_ROOT);
        log_debug("before get ptr :%p\n", tmp_ptr);
        tmp_ptr = *(DWORD*)(tmp_ptr + 0x10);
        log_debug("before get ptr :%p\n", tmp_ptr);
        tmp_ptr = *(DWORD*)(tmp_ptr + 0x3c);
        log_debug("before get ptr :%p\n", tmp_ptr);
        tmp_ptr = *(DWORD*)(tmp_ptr + 0x38c);
        log_debug("before get ptr :%p\n", tmp_ptr);
        tmp_ptr = *(DWORD*)(tmp_ptr + 0xecc);
        DWORD tmp2 = tmp_ptr;

        //下面这些是根据咱们第一次向上追踪写出来的一个获取参数的逻辑
        //log_debug("before get ptr :%p\n", tmp_ptr);
        //tmp_ptr = *(DWORD*)(tmp_ptr + 0x78);
        //log_debug("before get ptr :%p\n", tmp_ptr);
        //tmp_ptr = *(DWORD*)(tmp_ptr + 0x0);
        //log_debug("before get ptr :%p\n", tmp_ptr);
        //tmp_ptr = *(DWORD*)(tmp_ptr + 0x8);
        //log_debug("after get tmp %p\n", tmp_ptr);

        //如下是tmp2是咱们在第一次失败后第二次追踪后写出来的
        tmp2 = *(DWORD*)(tmp2 + 0x48);
        tmp2 = *(DWORD*)(tmp2 + 0x44);
        tmp2 = *(DWORD*)(tmp2 + 0x0);
        DWORD node = tmp2;
        DWORD next_node = *(DWORD*)(node + 0x4);
        while (next_node) { //这边应该是获取了列表里最后一个节点,但是这个列表存了什么暂时还不清楚
            node = next_node;
            DWORD next_node = *(DWORD*)(node + 0x4);
        }
        tmp2 = *(DWORD*)(node + 0x14);
        if (tmp2 == 0)
        {
            log_debug("search but tmp_ptr:0\n");
            return;
        }

        DWORD selfPtr = this->basePtr;
        log_debug("will searchDead tmp2 %p %p\n", selfPtr, tmp2);
        DWORD searchDropCall = SEARCH_DEAD_DROP;
        __asm
        {
            mov eax, tmp2
            push eax //怪物的地址
            mov ecx, selfPtr //自己的地址
            mov eax, searchDropCall
            CALL eax
        }
    }
    catch (...)
    {
    }
}

上面的代码流程中吧第一次找的地址tmp_ptr这个也包含了进来,失败了就给注释掉了,tmp2才是咱们要的
编译运行后就能正确的打开掉落列表了

drop_list  

0x04: 寻找拾取的代码地址(就是点击如上下一页)

为了找到拾取代码的地址,只能用老方法,通过send函数调用堆栈来找,这里跟上一章碰到的问题也一样,send函数只是从消息队列中取出消息来发送,要想找到拾取代码位置,还是需要找到插入消息队列的函数地址.

分析后发现如下三个插入到消息队列的操作,调用堆栈如下,在看这三个堆栈都经过这个6f0e25地址.
并且这个地址只会经过一次,所以到这里已经得到拾取函数的地址了,就是这个地址6F00B0.  

eax:0x8
50dd22->7a714e->7a44ca->6eea24->6f0110->6f0e25->7e8b65->7a7222->7af33c->7a73e0->7bf0a7->747b18->8699b2->87b817->4be438->860521->76b647ab->76b42aac->
eax:0x14
50dd1c->7a714e->6eeb25->6f0110->6f0e25->7e8b65->7a7222->7af33c->7a73e0->7bf0a7->747b18->8699b2->87b817->4be438->860521->76b647ab->76b42aac->76b444db->
eax:0x14
50dd1c->7a714e->6eeeb8->6f0fa2->7e8e48->6f0110->6f0e25->7e8b65->7a7222->7af33c->7a73e0->7bf0a7->747b18->8699b2->87b817->4be438->860521->76b647ab->  

0x05: 分析拾取代码的调用参数

现在函数已经有了,下面就是传参了,首先在6f0e20这里下断,观察发现,入参eax一直为0,剩下的就是ecx的获取了.
根据上面已经获取的堆栈分析后,得到如下获取ecx值得过程.  

        DWORD a = 0x9A5798;
        a = *(DWORD*)(a + 0xc);
        a = *(DWORD*)(a + 0x0);
        a = *(DWORD*)(a + 0x7c);
        a = *(DWORD*)(a + 0x40);
        a += 0x550c;
        a = *(DWORD*)(a + 0x1A98);
        a = *(DWORD*)(a + 0x18);
        __asm
        {
            mov ecx, 0x0 
            push ecx
            mov ecx, a
            mov eax, 0x6f00b0
            CALL eax
        }

可惜编写了如上代码后,发现这个最终获取到的a并不是我们想要的,看来这个值是在另一个流程里赋值进去的.
现在再用ce对如上获取到a这个内存地址查是谁改写了这个值,得到如下这个地址,可以看到这里把值放进了1a98,那应该就是这个地址了.

007BECA1 - 8B EC  - mov ebp,esp
007BECA3 - 8B 45 08  - mov eax,[ebp+08]
007BECA6 - 89 81 981A0000  - mov [ecx+00001A98],eax <<
007BECAC - 5D - pop ebp
007BECAD - C2 0400 - ret 0004

EAX=0A1F0AF8
EBX=00000003
ECX=00CD0614
EDX=000000DA
ESI=0A1F0AF8
EDI=0EDE24F0
ESP=0019F85C
EBP=0019F85C
EIP=007BECAC

再对如上地址加断点获取到如下堆栈.  

7a74f8->7af2f9->7a73e0->7ae053->7af2a3->7e8c79->6f0c50->7bf179->747b18->8699b2->87b817->4be438->  

最终我们根据堆栈分析出了如下这个调用过程

        DWORD a = 0x9A5798;
        a = *(DWORD*)(a + 0xc);
        a = *(DWORD*)(a + 0x0);
        a = *(DWORD*)(a + 0x7c);
        a = *(DWORD*)(a + 0x40);
        a += 0x550c;
        a = *(DWORD*)(a + 0x10); 
        a = *(DWORD*)(a + 0x8); 
        a += 8; 
        a = *(DWORD*)(a + 0x8); 
        a = *(DWORD*)(a + 20); 
        a = *(DWORD*)(a + 0x18); 

        __asm
        {
            mov ecx, 0x0 
            push ecx
            mov ecx, a
            mov eax, 0x6f00b0
            CALL eax
        }

用了如上代码后,大功告成

免费评分

参与人数 71威望 +1 吾爱币 +79 热心值 +64 收起 理由
time2s + 1 + 1 我很赞同!
ss721521 + 1 + 1 热心回复!
lksdo886 + 1 + 1 不明觉厉
又飘小雪 + 1 + 1 谢谢@Thanks!
mgm1111 + 1 谢谢@Thanks!
低空飞行i + 1 + 1 我很赞同!
kid2468 + 1 + 1 谢谢@Thanks!
Hmily + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
1287417511 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
啊饭kun + 1 谢谢@Thanks!
wuai164 + 1 用心讨论,共获提升!
Q1ngyun + 1 + 1 谢谢@Thanks!
heartfilia + 1 + 1 热心回复!
玉金 + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
无知是原罪 + 1 + 1 热心回复!
wth0411 + 1 + 1 我很赞同!
jw987123jw + 1 + 1 用心讨论,共获提升!
lifan123 + 1 我很赞同!
喜欢猫的吉良 + 1 + 1 谢谢@Thanks!
zjun777 + 1 + 1 用心讨论,共获提升!
chenxi666+ + 1 我很赞同!
daye303322 + 1 我很赞同!
sub + 1 我很赞同!
良辰美景 + 2 + 1 谢谢@Thanks!
子不语 + 1 + 1 谢谢@Thanks!
kjian + 1 + 1 不明觉厉
吾恋兮不知 + 1 + 1 谢谢@Thanks!
Lgx1911853 + 1 + 1 我很赞同!
Haoxuexi + 1 + 1 谢谢@Thanks!
a110三色堇 + 1 热心回复!
听雨夜声 + 1 + 1 谢谢@Thanks!
baiyangshu + 1 用心讨论,共获提升!
爷爷的扫堂腿 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
jyu15 + 1 + 1 我很赞同!
tgdq5 + 1 谢谢@Thanks!
DarklyBoy + 1 谢谢@Thanks!学习了
CWJYBB + 1 + 1 我很赞同!
xiaoss + 1 + 1 用心讨论,共获提升!
zrf1980 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
慕容语嫣 + 1 + 1 热心回复!
wy350 + 1 已经处理,感谢您对吾爱破解论坛的支持!
kxandsht + 1 + 1 我很赞同!
浪漫思域 + 1 + 1 我很赞同!
LittleMonster + 1 + 1 萌新来给大佬打call了。现在分享技术的这么详细的真不多
keA + 1 + 1 我很赞同!
烈焰乌龙茶 + 1 + 1 我很赞同!
大大大李子儿 + 1 我很赞同!
zengyi2020 + 1 我很赞同!
微風 + 1 + 1 谢谢@Thanks!
HUACANYA + 1 + 1 我很赞同!
紫风飘零 + 1 + 1 热心回复!
kirinoooo + 1 + 1 太牛了,虽然看不懂
大根君爱打牌 + 1 + 1 热心回复!
roxulo + 1 谢谢分享
moyi161 + 1 用心讨论,共获提升!
yanxsyuo + 1 我很赞同!
hett123456 + 1 鼓励转贴优秀软件安全工具和文档!
m178407583 + 1 + 1 我很赞同!
debug_cat + 1 + 1 前来给大佬打call
铭久 + 1 + 1 谢谢@Thanks!
七夜狼 + 1 + 1 热心回复!
Ge丶二蛋 + 1 + 1 我很赞同!
zbaby523 + 1 + 1 谢谢@Thanks!
sunnylds7 + 1 + 1 热心回复!
a12583657 + 1 + 1 热心回复!
lyl610abc + 1 我很赞同!
九天临兵帝 + 1 + 1 谢谢@Thanks!
明鸭 + 1 + 1 我很赞同!
zhanghua123466 + 1 + 1 我很赞同!
wenkQ + 1 + 1 用心讨论,共获提升!
lsy832 + 1 + 1 我就喜欢这种帖子

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

scghjl 发表于 2021-3-13 22:10
完全看不懂啊,大佬,我想学习写辅助,主要是能够遍历角色周围地上的物品,就传奇那类的游戏,不知道要学习哪方面的知识,望指点一下,谢谢了
 楼主| shanlihou 发表于 2021-3-14 11:58
scghjl 发表于 2021-3-13 22:10
完全看不懂啊,大佬,我想学习写辅助,主要是能够遍历角色周围地上的物品,就传奇那类的游戏,不知道要学习 ...

写辅助推荐用c++吧,也有人用易语言
遍历物品要找到基址,需要cheatengine先分析下
lyl610abc 发表于 2021-3-13 17:47
lsy832 发表于 2021-3-13 17:50
我就喜欢这样的帖子
wylksy 发表于 2021-3-13 17:56
先感谢下
x1188 发表于 2021-3-13 18:50
学习一下,谢谢了
liyingqiu123 发表于 2021-3-13 19:00
学习一下6666666666
vbhvhgh 发表于 2021-3-13 19:07
大佬 厉害  赶紧学习
Mdr 发表于 2021-3-13 19:12
不错楼主,支持下
yoyoma211 发表于 2021-3-13 20:48
不明觉厉,进来跟高手学习了
debug_cat 发表于 2021-3-13 20:56
萌新来给大佬打call了。现在分享技术的这么详细的真不多。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-15 14:00

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表