目录

10-2:IDA找敌人数组相关函数思路(有符号so)

目录

如果没看上一篇,建议去看看:安卓单机游戏绘制教程10-1:认识数组

https://i0.hdslb.com/bfs/article/71bf2cd56882a2e97f8b3477c9256f8b09f361d3.png

先补充上一篇文章的一个细节:

https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/3b38d70d4cfc4f3c46ff594b21ebd903be908f66.png@942w_329h_progressive-20220130104556764.png

这里随便run-as了一个debuggable=true的app包名,是为了能在gg中看到我们的hello程序,如果直接运行hello可执行文件,gg的进程列表是看不到的。

https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/db75225feabec8d8b64ee7d3c7165cd639554cbc-20220130104426516.png

解压T游戏的安装包找到so文件,直接拖进IDA,这一步可以参考我前面录制的IDA找单机老旧手游矩阵思路

要找数组的基址偏移,首先找到数组出现的位置,先猜猜数组可能出现到的函数,有以下思路(个人经验,仅供参考): \1. “AI”表示人机,搜索带有AI的函数 \2. 找单个敌人的行为相关函数,例如fire,damage,move等

分辨哪里用到了数组,并不难,找while循环和for循环就行了,多留意观察循环中哪个变量有变化(以及变了多少),哪个变量无变化,以及循环的终止条件;我们最后写代码的时候,也是要通过while或者for循环去遍历所有敌人,循环的条件到时候也可以“照抄”。

找到数组出现的函数之后,接下来找调用栈(函数之间的调用关系),这样就可以通过观察参数变化,找到参数的来源,就可以分析出数组的基址、偏移。找调用栈思路:对着函数名按X,如果按X找不到,打断点看R14寄存器(具体请等下期教程)。

比如,GmSimInitAITANKs和GmSimAiUpdate这两个函数,

https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/ccf1158bf2c5d61c25089a6424dcdeaaca1d6e6e.png@942w_477h_progressive-20220130104551735.pngGmSimInitAITANKs

https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/9855d638460eb5b1a4d4cae9c0a8a2c248b50799.png@942w_500h_progressive.pngGmSimAiUpdate

如上图所示,我们可以猜测724就是敌人结构体的长度。

https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/0b2941fdb3e04ccee1ef6426b798793308cdca74.png@942w_479h_progressive-20220130104544262.pngAIMoveAndFireAITANK

像AIMoveAndFireAITANK这种比较复杂的可以先大概看一眼,根据刚才的推测,724可能是结构体长度,这里和724相乘的a2不被循环影响,a2显然是敌人在数组中的下标,所以可以对着这个函数名按X,一定有地方有for或者while循环且在循环体当中调用了AIMoveAndFireAITANK函数。

https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/30130c7095e1908716b15357b6d9728d015222b5.png@942w_470h_progressive-20220130104539191.png

对着函数名按一下X,果然,是GmSimAiUpdate调用了这个函数,数组在GmSimAiUpdate函数中被遍历,AIMoveAndFireAITANK的参数2是循环到的次数(可以直接理解成敌人的序号)

https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/02db465212d3c374a43c60fa2625cc1caeaab796.png

然后找单个敌人的行为相关函数再演示一次,比如move,可以发现GmSimMoveTANKs这个函数里面就已经有循环了,

https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/3ed4640fa4007b1d784bedd69ddb86f6f1c3f119.png@942w_654h_progressive.pngGmSimMoveTANKs

不具体演示了,总之就是,找行为动作相关函数,然后按X,找引用调用它的函数,调用它的函数内部很可能就有for或while循环

https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/8a6fcf4b31ba5df2266f04d75b9b066dd949a8ee.png@942w_435h_progressive.png

比如GmSimIsFriendlyFire,

https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/f0789cb7d857568fd6b6cf7e2072b5d2e6d8d133.png@942w_411h_progressive-20220130104523927.pngGmSimIsFriendlyFire

按X,就能找到GmSimCheckProjectileCollisionWithAllTANKs这个函数,并且可以看到一个很清晰的循环。

https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/09da5724b83010766cc1ef3a9d121953ec83e8b9.png@942w_642h_progressive.png

https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/02db465212d3c374a43c60fa2625cc1caeaab796.png

对于本游戏,也可以通过数量下手,搜索count、get num of···,这样可以找到GmSimGetNumOfDeadAiTANKs这个函数(搜索“AI”也能看到它),

https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/7f5fc933cfdaa293e4fb4c7329ddd0f34893a3d0.png@942w_590h_progressive.pngGmSimGetNumOfDeadAiTANKs

根据函数名称可以猜测这个函数作用是统计已经死亡的人机坦克数量,返回v3,v3最初是0,v2最初是参数1,每一次循环,v2都会自增724,也就是说,while循环过程中,v2是每个人机坦克的结构体地址,而参数一就是整个数组的起始地址,每个敌人结构体可以通过偏移72这个byte类型数值来判断是否为死亡的人机。所以这里用来判断敌人是否死亡的偏移也得到了,后续可以用来过滤死掉的敌人。

后续文章会通过GmSimGetNumOfDeadAiTANKs这个函数进行“溯源”(因为它看起来最清晰,代码只是在很单纯的遍历,从这个函数的名字就能看出它只是负责统计坦克数量),得到数组的基址偏移。

https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/4adb9255ada5b97061e610b682b8636764fe50ed-20220130104427730.png

本系列教程作者B站账号:赶码人