《新人投稿》追书神器破解手记
0x00作为一个web转移动端二进制方向的炒鸡萌新,android包括java以前都没有接触过,看了两周《android软件安全与逆向分析》感觉光看书也不知道到底学到了什么就打算找个目标练练手。追书神器是我用了很多年的一款看小说软件,资源很全,android和ios上都有,但是在某次更新以后就不能免费看书了。论坛里有很多关于它的破解资源,但是却没找到讲述如何破解其android版本的相关资料,可能是因为这个软件破解比较简单的原因,不过挺适合我这种新手练手的。
0x01
既然是想破解正版源的书那么先抓个包看看免费和收费的区别吧。抓包工具是burpsuit,免费的章节直接就能看到正文的内容
而收费章节会得到正文经过某种加密后的密文
这个软件每天签到会给点追书券,攒够看一章的券购买一下试试
可以看到发送请求的时候带上了token和bookId,返回一个key值,这个key就是解密前面密文的密钥了。那么从这个流程上来看,在客户端这边下手是不行的了,最核心的key是在网站后台查询token相关信息后给的。用web的手段大致浏览了下这个网站发现了后台一些组件的登陆入口也就没有继续了,毕竟搞这个软件还是想练练android破解的技术。
0x02
既然不能免费看正版源那么让我免费看看盗版源总行吧。记得某次更新前所有的书都能看盗版源,之后就只有一些没什么人看的书可以了,不过官方依然保留了所有书的接口。web选手做这种事第一反应还是抓包看看,找两本书,一本叫《蛊真人》,挺火的小说,在看书的页面里没有换源的选项,抓到的包如下:
另外找了个没什么人看的小说《极品家丁后传》:
经过对比两个包发现了一个名叫_le的参数返回值有所区别,于是找了些其它的书实验发现凡是能够看盗版的该参数值都返回true,而只能看正版的则相反。确定了这一点后就要去程序里修改使用到这个参数的相关代码了,不过在这之前有一件事要做,就是去掉签名校验。这个软件在libtest.so里对整个包有个签名的校验,其校验核心函数是isZhuishuSignKey,代码如下
signed int __fastcall isZhuishuSignKey(JNIEnv *a1, int a2)
{
JNIEnv *v2; // r4@1
int v3; // r5@1
int v4; // r0@1
int v5; // r7@1
int v6; // r0@1
int v7; // r0@1
int v8; // r6@1
int v9; // r0@1
int v10; // ST0C_4@1
int v11; // r0@1
int v12; // r5@1
int v13; // r0@1
int v14; // r5@1
int v15; // r0@1
int v16; // r0@1
int v17; // r0@1
int v18; // r0@1
int v19; // r5@1
int v20; // r0@1
int v21; // r0@1
int v22; // r0@1
signed int result; // r0@2
v2 = a1;
v3 = a2;
v4 = ((int (*)(void))(*a1)->GetObjectClass)();
v5 = v4;
v6 = ((int (__fastcall *)(JNIEnv *, int, const char *, const char *))(*v2)->GetMethodID)(
v2,
v4,
"getPackageManager",
"()Landroid/content/pm/PackageManager;");
v7 = ((int (__fastcall *)(JNIEnv *, int, int))(*v2)->CallObjectMethod)(v2, v3, v6);
v8 = v7;
v9 = ((int (__fastcall *)(JNIEnv *, int))(*v2)->GetObjectClass)(v2, v7);
v10 = ((int (__fastcall *)(JNIEnv *, int, const char *, const char *))(*v2)->GetMethodID)(
v2,
v9,
"getPackageInfo",
"(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");
v11 = ((int (__fastcall *)(_DWORD, _DWORD, const char *, const char *))(*v2)->GetMethodID)(
v2,
v5,
"getPackageName",
"()Ljava/lang/String;");
v12 = ((int (__fastcall *)(JNIEnv *, int, int))(*v2)->CallObjectMethod)(v2, v3, v11);
((void (__fastcall *)(JNIEnv *, int, _DWORD))(*v2)->GetStringUTFChars)(v2, v12, 0);
v13 = ((int (__fastcall *)(JNIEnv *, int, int, int))(*v2)->CallObjectMethod)(v2, v8, v10, v12);
v14 = v13;
v15 = ((int (__fastcall *)(JNIEnv *, int))(*v2)->GetObjectClass)(v2, v13);
v16 = ((int (__fastcall *)(JNIEnv *, int, const char *, const char *))(*v2)->GetFieldID)(
v2,
v15,
"signatures",
"[Landroid/content/pm/Signature;");
v17 = ((int (__fastcall *)(JNIEnv *, int, int))(*v2)->GetObjectField)(v2, v14, v16);
v18 = ((int (__fastcall *)(JNIEnv *, int, _DWORD))(*v2)->GetObjectArrayElement)(v2, v17, 0);
v19 = v18;
v20 = ((int (__fastcall *)(_DWORD, _DWORD))(*v2)->GetObjectClass)(v2, v18);
v21 = ((int (__fastcall *)(_DWORD, _DWORD, const char *, const char *))(*v2)->GetMethodID)(v2, v20, "hashCode", "()I");
v22 = ((int (__fastcall *)(JNIEnv *, int, int))(*v2)->CallIntMethod)(v2, v19, v21);
if ( v22 == 1902783089 )
result = 1;
else
result = (unsigned int)(v22 - 722848853) <= 0;
return result;
}
这个校验过程并不复杂,我们甚至不需要关心它是怎么校验的, 只需要把最后的return result;替换成return true;就行了。用ida自带的patch功能或者找个16进制编辑器修改对应指令的机器码就行。改好了libtest.so后,我们就能自由地修改apk了。用jeb打开该apk,全局搜索字符串'_le',发现有两个与其相关的方法名字,一个是is_le,另一个是set_le,看了下数量也不是很多,就懒得一个一个看了,编辑相关的smali文件,把所有的名叫is_le的方法返回值都改为true,然后用androidcracktool重新打包签名生成新的apk文件,这次破解也就结束了,安装上看看效果:
打开《蛊真人》已经可以选取别的源了。
0x03
这个软件破起来确实没什么难度,不过还可以有更进一步的发挥,比如说解锁随机看书,解锁男生区女生区限制,去掉广告和一些无用的功能等。不过这些东西个人没什么需求,也就没有动力去弄了,先就这样吧。作为一个萌新来52还没正经发过什么帖子,主要是想记录下人生第一次破解软件,望大佬们勿笑。 哦哦,看了这个帖子,我只想说我只能当一粒沙子.. 哥们我发现你丢了个字burpsuite不是burpsuit哈哈 支持支持 你只写了大纲,没有写过程{:301_998:} 感谢分享 支持!学习 了! OmJJWang 发表于 2017-4-17 14:45
你只写了大纲,没有写过程
呃,具体改的话就是搜索字符找到方法然后改改返回值,感觉太low了就没写了 支持支持,感谢分享 技术贴啊~! 村支持了。