下载到豌豆荚,历史迭代版本都有
最新版比较难,所以在古早版本里从简单开始,从友好开始
天涯论坛看起来就是个贴吧
看到帖子就想下载,收藏,收藏在我的下载里面
今天就研究怎么找到下载的帖子加密的数据和研究加密的代码
首先运行adb中frida server
天涯社区包存放位置
aosp:/data/data # cd cn.tianya.light
aosp:/data/data/cn.tianya.light # ls
app_bugly app_textures cache pangle_com.byted.pangle
app_crashrecord app_tt_pangle_bykv_file code_cache shared_prefs
app_e_qq_com_dex_37f3f88ff312fff57329035c00e2d04b app_turingdfp databases
app_e_qq_com_plugin_37f3f88ff312fff57329035c00e2d04b app_turingfd files
app_e_qq_com_setting_37f3f88ff312fff57329035c00e2d04b app_webview lib
目的明确,找到离线下载数据存放的位置
方法一:导出整个databases,在navicat查看
方法二:再离线下载一个看文件最后更改的时间,确定是存在files还是databases
此处略查找过程,确定在databases里
aosp:/data/data/cn.tianya.light # cd databases
aosp:/data/data/cn.tianya.light/databases # ls
bugly_db_ downloads.db-journal
bugly_db_-journal pangle_com.byted.pangle_bd_embed_tea_agent.db
cache.db pangle_com.byted.pangle_bd_embed_tea_agent.db-journal
cache.db-journal pangle_com.byted.pangle_downloader.db
data.db pangle_com.byted.pangle_downloader.db-journal
data.db-journal pangle_com.byted.pangle_npth_log.db
download_info.db pangle_com.byted.pangle_npth_log.db-journal
download_info.db-journal pangle_com.byted.pangle_ttopensdk.db
downloads.db pangle_com.byted.pangle_ttopensdk.db-journal
一通随便分析,在offline.db
那下一步把他导出来’
至于怎么导呢。不知道
好像不支持arm,看不了的样子
文件里已经给了,请放心享用~
怎么查看加密算法呢???
用jadx查看(因为搜索和检索很好用)
在androidmanifest.xml里找
肯定不太现实
不论是创建字段还是访问字段里的数据,都需要用到notedata,不妨搜索关键词找到代码呢~~
问题来了,
downloaddata里被加密的是notedata
download里被加密的是attachdata
到底搜什么比较好找呢
当然是两个都搜
哪个少找哪个
反正加密算法肯定都是一个路子
PS:记得忽略大小写取消啊~会少一点点哟
你看,这边能有个put encryptbytes,hook这个函数就差不多能知道
但是呢,做过sqlite的小朋友很清楚,int columnIndex = query.getColumnIndex这个东东在获取索引值,已经在搞事情了
查看第一个query.getColumnIndex
Cursor query = context.getContentResolver().query(CacheContentHelper.getNoteContentUri(context), null, "CATEGORYID=? AND NOTEID=? AND PAGEINDEX=?", new String[]{str, String.valueOf(i2), String.valueOf(i3)}, null);
if (query != null) {
if (query.moveToFirst()) {
query.getInt(query.getColumnIndex(ContentProviderUtil.DEFAULT_ORDER));
int columnIndex = query.getColumnIndex("NOTEDATA");
if (!query.isNull(columnIndex) && (uncompress = CompressEncrypt.uncompress(EncryptUtil.encryptBytes(query.getBlob(columnIndex)))) != null) {
noteContentList = (NoteContentList) JSONUtil.parseString(uncompress);
query.close();
query = null;
}
}
noteContentList = null;
query.close();
query = null;
}
if (query != null && !query.isClosed()) {
query.close();
}
if (!query.isNull(columnIndex) && (uncompress = CompressEncrypt.uncompress(EncryptUtil.encryptBytes(query.getBlob(columnIndex)))) != null) {
query.getBlob(columnIndex)?
读取blob流,输出到页面,说白了就是读取加密字段
通过索引值,获取加密数据
把query.getBlob(columnIndex)传入encryptbytes方法中
encrypt加密,decrypt解密,为什么数据库中加密字段还要encrypt呢
先放着不管先,改成DEcrypt,就是这么拽
通过decrypt操作完后返回给uncompress操作
先看uncompress操作
别问为什么不先看decrypt,问就是程序分析的惯性思维,找到离明文最近的方法
就去hook 这个uncompress
笑死,不会写,没人教我写hook代码,自己也是蓝狗一条
我们换个东东,用GDA4看看
拜托,有这个工具,去写java层的代码,有啥子一一诶~
还记得frida server嘛,怎么在模拟器里启起来应该不用说的吧
对应目录 ./frida哦
什么GDA4不会hook?
笑死,我也不会,但我摸索出来了
点一下右边的APK入口就能看到方法函数了
找一下uncompress,然后右键firda->hook方法
(what?你不知道为什么是这个)
(冷漠)
(都是一边不就知道打开离线下载的文件会触发哪个函数了~)
一打开hook,就自动打开天涯论坛,
打开离线下载,哗啦啦啦hook显示一堆东西
根据分析,hook函数,由密文变成明文,说明,这个方法非常的至关重要
public static String uncompress(byte[] p0){
try{
return new String(CompressEncrypt.unzip(p0));
}catch(java.lang.Exception e1){
p0.printStackTrace();
return null;
}
}
明文<-uncompress<-unzip<-
input:bArr
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bArr);
new:新建
bArr强行转化为byteArraayInputStream
下面又把参数传递给gZIPInputStream
Java运用gZIP进行压缩和解压缩
public static byte[] unzip(byte[] bArr) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bArr);
GZIPInputStream gZIPInputStream = new GZIPInputStream(byteArrayInputStream);
byte[] bArr2 = new byte[1024];
while (true) {
int read = gZIPInputStream.read(bArr2);
if (read >= 0) {
byteArrayOutputStream.write(bArr2, 0, read);
} else {
gZIPInputStream.close();
byteArrayInputStream.close();
byte[] byteArray = byteArrayOutputStream.toByteArray();
byteArrayOutputStream.close();
return byteArray;
}
}
查看DEcrypt
try-catch操作很多,异常情况才看第二个return
重要的只有一行
return EncryptJni.encryptData(bArr);
/* renamed from: encryptBytes */
public static byte[] DEcryptBytes(byte[] bArr) {
if (bArr == null || bArr.length == 0) {
return bArr;
}
try {
return EncryptJni.encryptData(bArr);
} catch (Throwable th) {
th.printStackTrace();
return ByteUtils.deOrderBytes(bArr);
}
}
所以去看看encryptData方法对bArr是什么个操作
/* loaded from: classes.dex */
public class EncryptJni {
static final String TIANYA_TEXT = "tianya";
static {
try {
System.loadLibrary(TIANYA_TEXT);
} catch (Throwable th) {
th.printStackTrace();
}
}
/* JADX INFO: Access modifiers changed from: package-private */
public static native byte[] encryptData(byte[] bArr);
static native String getLoginkey();
竟然什么都没有,说明代码不在Java层,在C语言层
打开zip解压缩过的天涯论坛下lib文件夹
在哪里看native代码在哪里呢?
上面有system loadlibrary为的是将lib加载到系统中
参数是TIANYA_TEXT,真实数据是tianya
那么要去搜索哪个关键词了呢?
lib+tianya+.so=libtianya.so
有知情人士透露:armeabi-v7a
这个elf文件用32位IDA去check
通常搜都是搜java,涉及到开发的知识,写一遍就知道了,或者听高人一言也能少走十年弯路
很神奇的事encrypt和decrypt是一样的代码,换而言之,对称加密
汇编转C:view+open subview+F5
没有意义的灰色内容右键hide cast
jbyteArray __fastcall Java_cn_tianya_jni_EncryptJni_encryptData(JNIEnv *env, jobject thiz, jbyteArray bytes)
{
jsize v5; // r6
jbyte *v6; // r4
v5 = (*env)->GetArrayLength(env, bytes);
v6 = malloc(v5);
(*env)->GetByteArrayRegion(env, bytes, 0, v5, v6);
j_EncryptData(v6, v5);
(*env)->SetByteArrayRegion(env, bytes, 0, v5, v6);
free(v6);
return bytes;
}
JNIEnv *env:java和C的翻译官,无所谓
jobject thiz,:不重要
jbyteArray bytes:input
v5+v6:申请空间给传入的加密数据
GetByteArrayRegion:把申请的空间填入
关键在 j_EncryptData(v6, v5)
ps:v6为input,v5为length
双击进入
void __fastcall j_EncryptData(unsigned __int8 *s, int len)
{
EncryptData(s, len);
}
没有内容,双击EncryptData(s, len)
void __fastcall EncryptData(unsigned __int8 *s, int len)
{
j_j_ReOrderData(s, len);
}
没有内容,双击j_j_ReOrderData(s, len)
void __fastcall j_j_ReOrderData(unsigned __int8 *s, int len)
{
j_ReOrderData(s, len);
}
没有内容,双击j_ReOrderData(s, len)
unsigned __int8 *__fastcall j_ReOrderData(unsigned __int8 *data, int len)
{
return ReOrderData(data, len);
}
没有内容,双击 ReOrderData(data, len)
unsigned __int8 *__fastcall ReOrderData(unsigned __int8 *data, int len)
{
int v2; // r6
int v3; // [sp+7h] [bp-21h]
char v4; // [sp+Bh] [bp-1Dh]
v2 = 0;
v4 = 33;
v3 = -2127046473;
while ( v2 < len )
{
data[v2] ^= *(&v3 + v2 % 5);
v2 += v2 % 5 + 1;
}
return data;
}
循环异或操作,v3,v4改成16进制,右键hexadecimal
v4 = 0x21;
v3 = 0x8137D8B7;
方法:读取数据库加密数据,把数据给C语言异或解密
将解密数据给uncompress+unzip
数据库解密告一段落,开启下一个例子
just_hook.apk
拖入GDA和jadx和雷电