篇幅较长
这么可爱 还不抱走?
如果只需要图,请拉倒最底下或去隔壁→点我进去。
这么可爱 还不抱走?
图片换原
提醒一下
前言
说真的我不怎么会玩这类游戏。更别说想要提取图片了。
不过有一天隔壁调教群某位萌(da)新(lao)让我去提取这个玩意。
她说:大佬大佬,你能不能提取联动图片。
我说:我一点不会反汇编安卓这个玩意,何况游戏。而且爆破这么好玩吗。
她又说:你看,大佬,难道不想来一发吗?
……
……
诶,真香。
然后我抱着作死的心态提取联动图。拆包、拖进IDA、分析一条龙服务。
看着函数控制流程控制图我就差点右键扔进回收站......(눈‸눈)
而且加密后的文件才不到900KB,想都不用想都知道这图片的质量了。(눈‸눈)
算了机智点,干脆换个方法......
Dump!!!!!!!!
今天大佬给我发了一张图。
好吧好吧,真的惹不起真大佬。(毕竟真正的大佬能叫别的大佬帮他做事情)
之前不知道怎么回事,静态反汇编已经是不可能搞出图源了,这次换个办法——动态调试。
问题来了,怎么调试......由于本人第一次接触安卓的调试,而且在这之前没有任何编译和调试安卓的操作。
(我就是个只会C\C++的渣渣)
查找了一下方法,之前Emulator也无法检测出调试进程,这次干脆不用adb shell am start -D -n com.jumpw.mobile300/com.jumpw.mobile300.Tombird
加载调试进程了,干脆直接运行程序然IDA直接加载SO文件动态调试。
对于之前,我们得先进行以下步骤调试:
首先你得有一台已经ROOT的手机。
打开USB调试,这不用说了吧:
打开CMD:
adb push d:/IDA_Pro_v7.0_Portable/dbgsrv/android_server /data/local/tmp/android_server
把调试服务放在安卓的目录下,第一个路径是IDA的dbgsrv目录的一个文件,第二个这个路径是可以随便放的。
adb shell
su
一定要有root权限,如果是第一次输入su获取权限注意需要授权。授权对象为com.android.shell。
在magisk下输入su后会有授权提示。
chmod 777 /data/local/tmp/android_server
给android_server可执行权限
/data/local/tmp/android_server
执行
IDA Android 32-bit remote debug server(ST) v1.22. Hex-Rays (c) 2004-2017
Listening on 0.0.0.0:23946...
如果出现这个输出,说明你成功运行了调试服务。
再开一个CMD:
adb forward tcp:23946 tcp:23946
设置端口转发,调试手机上的某个进程要有协议支持通信,让远程调试端IDA可以连接到被调试端 。
好了,这样就可以动态调试了吗?
并不是,在此之前你好得先找到解密函数在哪里,我也以为十分容易,但是却是个技术活,并不是一下子就能发现的。
而且为什么要用IDA呢?IDA提供了十分丰富的功能,特别是那简单粗暴的F5,而且2017年版本以解析优化更好了。
不说了,IDA YES!
打开IDA,载入需要调试的SO文件,由于这个游戏是基于Cocos2D制作,从拆包可以看到,我们需要调试的文件也应该是叫libgame.so的文件。
加载后(我这个是保存为idb格式后再次加载的,加载速度会变得很快)。我们第一步也无非寻找加密函数。
从网上的资料来看,大多数Cocos2d游戏资源的加密使用官方加解密Xxtea算法,而且我随便打开一个文件都有这样的加密头,也可能是Xxtea算法的签名值。
然而打开string视图,搜索“MP:”,居然啥也没有!猜测应该是做过优化,据我了解大多数优化变成了ASCII值一个一个对比。
查找资料发现,解密图片和资源无非从几个地方下手,第一个是IOCCImage::initWithImageData
,但是我注意到很多资源文件是mpk格式,其实就是一个压缩格式,可以在读该文件的CCFileUtils::getFileData
函数上下手。
然后我尝试搜索CCFileUtils::getFileData
,居然也没有,所以我怀疑从这里隐藏掉了函数从而把解密函数隐藏起来。
提示
CCFileUtils::getFileData
函数时候,是可以查找到的,当2019年3月时再次第二次尝试反汇编发现该函数不见了,疑似被隐藏。
没办法,只能在其他地方寻找突破口,所以先从IOCCImage::initWithImageData
函数入手。在旁边的Functions Windows下方的搜索框入输该函数回车搜索,双击进去查看函数。
事情变得十分有趣了,不难发现函数多出了一块东西,仔细一看是处理文件头部SIGN,看起来并不是直接与字符比较而是与其ASCII值一个一个比较。但沿着函数看下去解密函数并不在这里。
所以我断定解密算法在该函数的调用前面。
里面有个叫IOCCImage::initWithImageFileThreadSafey
引起了我的注意,按照官方的文档来看,可以从这里找到那些被优化掉的函数,毕竟还得调用他们,我进去一看。
感觉这里不对劲,再跟官方的源代码比较。(在gayhub上拿到的,应该也改了不少)
bool Image: :initWithImageFileThreadSafe(const char * fullpath) {
bool bRet = false;
unsigned long dataLen = 0;#
if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) FileUtilsAndroid * fileUitls = (FileUtilsAndroid * ) FileUtils: :getInstance();
unsigned char * pBuffer = fileUitls - >
getFileDataForAsync(fullpath, "rb", & dataLen);#
else unsigned char * pBuffer = FileUtils: :getInstance() - >
getFileData(fullpath, "rb", & dataLen);#endif
if (pBuffer != NULL & amp; & amp; dataLen & gt; 0) {
bRet = initWithImageData(pBuffer, dataLen);
}
CC_SAFE_DELETE_ARRAY(pBuffer);
return bRet;
}
呵,确认无误了sub_CBB222B8
这个函数肯定对应着我之前要寻找的函数CCFileUtils::getFileData
,点进去一看,哟,还设置多了一个跳转,这优化NB!
提醒
更让人感觉惊讶的是,这优化简直就是可怕。居然zipFile::getFileData
也优化掉了。可以哪我之前反汇编的对比一下。
这个是我2019年1月时候第一次反汇编的代码:
现在:
wdf??????(说真的那时候第一次反汇编这个玩意感觉自己打的注释就是渣渣)
其实不难发现和之前在IOCCImage::initWithImageData
上函数处理文件头部SIGN几乎一模一样,下面又是熟悉的do-while循环解密。
但是也不难发现,前面的sub_6B11B0(&v34, "2c596277db0fad6d6997bc80bf76a89f", (int)&v33)
是什么最新操作?
而且也影响下面的解密,当我点进去跟踪时候,wdf,简直就是吔屎啦你的神仙操作,一层又一层......
话说回来这根本不是Xxtea算法的操作了,是神仙算法优化!!嘤嘤嘤,欺负萌新!!
竟然找到了加密函数,看起来得拿出Dump大法了。
动态调试之Dump大法:
第一次调试时候,在IDA中Debugger选项中选择弹出Select a debugger页面,在选项中选择Remote ARMLinux/Android debugger后确定。
确认后再回到在IDA中Debugger选项中选择弹出Debug spplication setup:armliunx页面,在Application、Input file选择对应要调试的SO文件,Directory选择调试的SO文件下对应的目录。Hostname填写127.0.0.1,Port填写我们之前转发的端口23946,点击确定。
如果出现如以下错误框可以不用理,因为下一步就是附加进程了。
打开,鬼特么用什么adb shell am start -D -n com.jumpw.mobile300/com.jumpw.mobile300.Tombird
启动调试程序。什么他娘的精锐,老子打的就是精锐。
在IDA中Debugger选项中选择弹出Attach to precess页面,在选项中选择找到其对应的包名后确定。
确定后可能会出现一下情况。
Is the loaded file "/data/app/com.jumpw.mobile300-j1YqvtWhz4GOrbU056iQ=/lib/arm/game.s the same as the input file "J:\Downloads\300mobile_jump_Release_20190411\libameabi7a\libgame.so"?
看起来其实就是模块路径不同导致的错误,其实点击Same即可。
你还可能出现这种问题。
Do you really want IDA to access this path (possibly a remote server)
也是路径问题,确定即可。
确认无问题后,调试器会在主线程断下,点击调试即可。
在旁边的modules寻找你要调试的模块。
双击进去后,你可以看到该文件IDA解析出来的函数。
所以查找函数可以从这里查找。
当时我为了方便懒得还要下载某软件解压mpk文件,所以我在IOCCImage::initWithImageData
下了一个断点,想快速dump图片出来。
但是……居然在游戏界面无论怎么滑动,就没见调试器断下……
然后我就开始怀疑人生……我尝试在另外一个函数IOCCImage::initWithImageFileThreadSafe
下个断点,毕竟该函数会调用到,IOCCImage::initWithImageData
。
果然是能断下,但是我发现并没有调用IOCCImage::initWithImageData
,而是调用了某个函数缓存在了内存???
回想一下有什么不对,后面我盯上了之前寻找到的解密函数CCFileUtils::getFileData
,找到加密函数的入口,因为很多加载资源都是从这个函数处理,顺便在读取文件这边下一个断点。
可以,从这里能看到加载的文件。由于我发现该游戏是不断读取其中的加密文件,我就想到了一个办法……
先在进入英雄详细界面前,快速下断点,然后立马点击进入英雄详细界面。
蛤!断下来了
然后把鼠标放在一个文件名变量上,浮现出来的正是我们想要的文件名。
不难发现,后面还对其解密文件进行了解压。可以,简直就是CPU杀手。
uncompress是Liunx系统特有的解压函数,调用方法如下。
int uncompress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen);
注意函数的第二个参数 destLen 是传址调用。
当调用函数时,destLen 表示 dest 缓冲区的大小, dest 缓冲区要足以容下解压后的数据。
在进行解压缩时,需要提前知道被压缩的数据解压出来会有多大。这就要求在进行压缩之前,保存原始数据的大小(也就是解压后的数据的大小)。
当函数退出后, destLen 是解压出来的数据的实际大小。
所以真正的数据保存到了第一个参数下。
其大小保存到了第二个参数,不难读出大小为0x180010。
得了,竟然知道了数据的地址和大小,怎么讨论如何Dump出来。
不难发现,其数据开始地址对应R7寄存器,其大小对应变量v32,结尾就是r7+0x180010。所以Dump指令指令就这样写
static main(void)
{
auto fp, begin, end, dexbyte;
fp = fopen("D:\\60.pkm", "wb");
begin = r7;
end = r7 + 0x180010;
for ( dexbyte = begin; dexbyte < end; dexbyte ++ )
fputc(Byte(dexbyte), fp);
}
运行脚本。
打开Dunp出来的文件,成功打开!
我特么舔爆。
发现一个有趣的事情,当函数执行完后跳到了这里:
怎么回事,跳到这里了??函数呢??
v4 = (char *)(*(int (**)(void))(*(_DWORD *)v3 + 16))();
这一坨是什么玩意?????有点意思。
后来我回到汇编窗口才发现原来是保存了一个全局变量,读取后使用JNI函数方法调用函数。
解决办法
选中v3变量,然后按一下y键,输入:JNIEnv*,确定即可。
突然翻车
昨天17日更新得时候,有贴吧大佬(其实也是个肝帝),突然当着广大吧友的面子谄害广大吧友的身体。对就是这样。
awsl!!!!
隔天后......
出现了一堆问题......
??????
跟踪不到调用函数地址???怎么回事??
这个是IOCCImage::initWithImageFileThreadSafe
的入口函数,居然变成这样了,还出现了奇葩玩意。
这个是之前的,当时我怀疑SO文件被更新了,但是仔细一看汇编代码并不是。还是使用了blx实现跳转。
不知道是IDA的锅还是系统ROM的锅,在IDA进行动态调试的时候无法分析跳转到函数的地址,但是退出动态调试是可以看到的。
因为IOCCImage::initWithImageFileThreadSafe
几乎不被调用,自然根本没办法跟踪,所以我们换一个办法。
之前我们知道,虽然优化了函数,但是我们还可以从其他公开的函数中去跟踪到这个函数。
所以这次我从IocctextureETC::IoadFromFile
这个地方入手。从官方的文档来看,也是一个频繁调用的文件入口,这个函数也会调用到CCFileUtils::getFileData
进行资源的解密和加载。
找到改函数后按下F5……果不其然……
尝试对齐下断点时候错误说资源没有加载……是怎么回事……
看来只能进入汇编窗口跟踪了……
我尝试跟踪到CCFileUtils::getFileData
这个函数时候,居然这个函数被IDA识别出为instruction(指令),而不是regular functione(正规函数)。
这就很MMP了,这样你连F5都基本用不了……一按就报错。这也似乎能解释为什么F5下跟踪不到这个函数地址了……
得了,接下来只需要在调用CCFileUtils::getFileData
函数这个地方下个断点后F8执行后,发现数据保存在R0寄存器上面。
但是由于文件大小已经无法获取,毕竟我也懒得去找调用uncompress
的地方了,只能随意Dump大小,毕竟程序读取时候会读取到文件头为止,并不在意其大小,能读取完整图片即可。
完成!!
后续
今天回家后,想试试看是什么原因导致的汇编错误,就打开了IDA重新测试。
问题出现了,死都无法附加调试器。
按照之前的经验来讲,我觉得这个错误大多数是手机的调试服务问题,然后我一眼看了一下CMD,发现......
不对啊我记得我用的是2017年版本的,难道是????
重新把调试服务PUSH到系统中.......重新写上权限并运行。
还真是......
顺利读取。
我还真的发现是IDA版本不对,学校那个版本过于老旧,连一些工能都不能正常使用。
好吧还真是IDA的锅。
顺便吐槽一下
本来还想提取之前的一个宣传图的,但是......
emmmmm
算了能一点就是一点。
这个游戏真是良心还带阿尔法通道。省得我抠图的力气了。
PS打开图片,先显示带有通道的图片。在图层位置找到通道,右键点击红色层选择“复制通道”,会在下方生成一个红色通道。
点击选中红副本,再点击下方的选择圆,把红副本通道的内容选中。
ctrl+shift+I 反选内容,回到原本图层,按Delete,完美!
P站原图:
总结
可以说虽然提取图要在打开相应的节目程序才能Dump图片出来,但是对于这种加密是最好最快的办法了。
当然你要掏空他的身体也不是不行——写出解密程序。
这个比我上次折磨某NetHTProtect的加壳还简单了,最主要还是有很多意想不到的的操作(如调用函数优化等等)让你百思不得其解。
在这之前我也大量的百度和谷歌才慢慢摸索出方法(这就是大佬为什么叫你百度了)。
当然,大量的经验积累才是真正的重要。
重点:废话不多说放图片吧。
图片
洛天依:
洛天依-鹊桥仙【P站】(这个图P站就有,从游戏提取出的比这个还差2333):
洛天依-汤依炮弹:
P站原图:
乐正绫:
乐正绫-碟念花:
墨清弦:
墨清弦-虞美人:
洛天依SP:
洛天依SP唤醒:
言和:
言和-雨霖铃:
乐正龙牙:
乐正龙牙-水龙呤:
徵羽摩柯:
徵羽摩柯-风栖息梧:
神之荣耀:
算了直接舔吧。
下载
原图以及高清质量的版本:
更新日记
- 2019年5月2日11:53:44
今天继续怀着作死的心态打开了IDE,不到1小时还是退出了。
继续换位思考。
更新了乐正绫的图片。
- 2019年5月11日00:20:42
今天继续怀着作死的心态打开了IDE,但是我还是找到了方法。
顺利一发Dump读取出了解密后的源文件。
- 2019年5月19日06:11:23
回到学校后,不知道是什么玄学原因。
在今天反汇编时似乎在动态调试时因为IDA对函数的分析错误,导致有全局变量保存函数地址无法一键F5反汇编出C原地址,不得不重进行动态调试拿到地址。
成功提取了新的图片。
最后才发现原来是IDA版本号不同造成的。
- 2019年6月7日00:03:03
由于前不久刷机不慎滚回系统后导致数据全部丢失,刚刚才解包完成。
本来我要洗澡的啊嘤嘤嘤......
- 2019年6月13日08:21:35
关于MMDS无法获取进程信息
之前提到当我把手机连接到电脑时候,在MMDS看不到任何进程,最后好像就出现了一个magisk的进程。
导致无法使用adb shell am start -D -n com.jumpw.mobile300/com.jumpw.mobile300.Tombird
后把调试进程继续运行。
后来发现DDMS工具获取的进程信息的前提是这个应用为可调试状态。
所以得利用mprop工具修改全部进程为Debug状态。
adb push mprop /data/local/tmp/mprop
adb shell
su
chmod 777 /data/local/tmp/mprop
/data/local/tmp/mprop
cd /data/local/tmp/
./mprop ro.debuggable 1
stop;start
注意输入最后一条命令时候会重新全部进程,注意备份数据!
工具下载地址:mprop
- 2019年7月5日19:21:43
现在T爹大大已经在P站更新原图,图片比提取的清晰,决定部分图片换源。
感谢Luminous提供的图床。
- 2019年7月11日15:00:00
高三了,然后......我妈把我的电脑给物理搬走了........
啧......然后拿出了我尘封多年的电脑,11年买的了2333
不过只能挂载Ubuntu而已,可以想象在Windows下有多卡了。
但是.......Ubuntu怎么运行IDA,这让我想到了Wine容器,完美运行2333
不过......唯一问题是......在Wine里面模拟出的环境......不用想执行效率有多慢了......
导致Dump一个图片花费了20分钟......我的天啊.......
要图的小伙伴们只能等了(哭唧唧)
- 2019年7月11日16:32:55
更新最新图片,现在我差点去世......
- 2019年9月30日22:00:41
我去怎么还来qwq,好吧更新了。
注意
*联动图画师TID,版权由上海禾念持有
*图片仅供个人交流使用,禁止用于任何商业用途
*图片使用遵守以上两条使用无需询问,无需注明本站出处
*文章转载遵需注明本站出处