From(书旗小说签名验证 【使用DDMS】):https://www.cnblogs.com/LuLuLuHao/p/12874468.html
签名验证一般步骤:
- 1. 先检查是否有壳,如果有壳,先脱壳
- 2. 若不加壳,则 apk 重新签名,不做任何修改,然后安装,看能不能打开 app
书旗小说.apk 过签名校验
1.根据启动过程
:https://www.bilibili.com/video/BV1vE411c7Zj?p=62
2、
( log插桩方法 ):https://www.bilibili.com/video/BV1vE411c7Zj?p=63
:、
视频是通过搜索签名三兄弟,定位到 smali,然后 log 插桩,ddms 看 log 输出,分析过程。
3、根据 ddms 中 log 信息判断
1. 把书旗小说.apk(下载地址:https://www.wandoujia.com/apps/288203/history_v175 )通过AndroidKiller重新签名,然后安装,安装闪回。
2. 打开 ddms 看看有什么信息 发现了一个 killProcess 方法
( 默认按时间顺序列出,底部是最新的 log )
3. 打开 jadx-gui 分析代码,搜索 "" 根据 ddms 信息 发现它调用了 com.shuqi.app.ShuqiApplication 包里的方法 我们跳进去
4. 他的逻辑很清楚。
5. 让这个 handleToken 方法返回 true 即可 我们打开 Androidkiller 修改 smali
6 .apk 完美运行
4、搜索
一个 APK 只有一个 Application。,Application对象 执行 onCreate方法时APP就开始运行
反调试或签名验一般都在进行中 (),每个 Apk 运行时需要一个,所以直接搜索 。
点击进入 ,然后找到onCreate 并查看方法,可以看到 一个checkSigAsync 方法,
点击进入checkSigAsync 方法,可以看到是签名验证。
2022.03.18 新版书旗小说
2022.03.18 最新版本的书旗小说 签名验证不再 java 层,但放进去 so 层,
jadx 反编译 书旗小说apk ,然后搜索 signature ,
Android 文档:https://developer.android.google.cn/reference/android/content/pm/Signature?hl=en
浦发银行 apk 过签名校验
哔哩哔哩(浦发银行.apk签名校验【】和 ):
最新版本有壳。。。所以下载旧版本。 apk
浦发银行apk 下载地址(8.0 版本 ):https://www.wandoujia.com/apps/31675/history_v83
这个签名是在 so 层。。。
1. 查壳
下载好 8.0 版本的 apk,首先使用 AndroidKiller 检查是否有壳
可以看到 8.0 版本的 apk 没有加壳。
2. 根据 入口点 或者 入口页面
加载和执行。
图示:
定位到入口点 smali 代码,找到 onCreate 函数,分析时,函数可以转换为java 分析代码
提示:AndroidKiller调用 jd-jui 查看 java 代码出现 "找不到对应的APK源码" 时,说明 jd-jui 无法把 smali 代码转换成 java 此时需要更改代码,例如:jadx-gui、Jeb 等
转换成 java 分析代码( 这里使用jadx-gui 转换 )
这里什么也看不见( 其实 YTSafe 就是要找的 关键点),打开 ddms 或者 monitor 看下 log 输出,
查看 对应的 java 代码(静态注册)
可见是在 libyt_safe.so 库中的验证
到此,java 层分析结束后,以下是使用 IDA 分析这个 so 库了。。。
使用 IDA Pro 分析 so
使用 IDA Pro 打开提取物 libyt_safe.so 文件。
拿到一个 so 库后,先分析 so 的 "",
因为 init_array 比 JNI_onLoad 执行时间较早,先看 init_array 没有坑。。
Ctrl s 打开 窗口,选择init_array 点击进入init_array 对应代码位置
发现 init_array 里面没有什么函数,然后搜索 JNI_onLoad ,发现没有JNI_onLoad 搜索这个函数 开头函数(即 静态注册函数),发现有许多静态注册函数
可以看到 有个函数带 init ,点进去看看。 ---> ARM 汇编代码 ---> F5 反编译 ,查看伪代码
双击 init_lib 可以看到函数,跳转到函数对应的位置 init_lib 函数调用了 check_app 函数
查看 check_app 代码,发现有个 get_sign 函数,字面意思理解就是 得到签名,
直接把这个函数去掉,或者 nop 掉,不调用这个签名函数。
修改 so 文件,并保存( 34' 45'' )。也可以使用 winhex 打开并修改对应位置。 35' 25''
修改后,替换原来的 so 文件,安装还是闪退,看下 check_app 代码 逻辑,是在 while 循环里面 ,
可以 使用 IDA 动态调试 so ,然后打断点进行分析,
int __fastcall check_app(int a1, int a2)
{
int v2; // r5
int v3; // r4
int v4; // r0
int v5; // r0
int v6; // r5
int v7; // r6
unsigned __int8 *v8; // r5
char *v9; // r5
char *v10; // r6
int i; // r3
char v12; // r3
int v13; // r5
int v14; // r6
int v15; // r3
int v17; // [sp+Ch] [bp-44h]
int v18; // [sp+10h] [bp-40h]
unsigned __int8 *v19; // [sp+14h] [bp-3Ch]
int v20; // [sp+18h] [bp-38h]
_BYTE *v21; // [sp+1Ch] [bp-34h]
int v22; // [sp+20h] [bp-30h]
int v23; // [sp+24h] [bp-2Ch]
int v24; // [sp+28h] [bp-28h]
unsigned __int8 *v25; // [sp+30h] [bp-20h]
v2 = a2;
v3 = a1;
v4 = (*(int (**)(void))(*(_DWORD *)a1 + 668))();
v5 = get_sign(v3, v2, v4);
v6 = cert_encode(v3, v5);
v7 = message_digest(v3, "MD5", v6);
v22 = message_digest(v3, "SHA1", v6);
v20 = (*(int (__fastcall **)(int, int))(*(_DWORD *)v3 + 684))(v3, v22);
v23 = j_malloc(v20);
(*(void (__fastcall **)(int, int, _DWORD, int, int))(*(_DWORD *)v3 + 800))(v3, v22, 0, v20, v23);
v8 = (unsigned __int8 *)(*(int (__fastcall **)(int, int, _DWORD))(*(_DWORD *)v3 + 736))(v3, v7, 0);
v24 = (*(int (__fastcall **)(int, int))(*(_DWORD *)v3 + 684))(v3, v7);
inv_mix_key(v8, v24);
v25 = (unsigned __int8 *)get_key(v8, v24);
(*(void (__fastcall **)(int, int, unsigned __int8 *, _DWORD))(*(_DWORD *)v3 + 768))(v3, v7, v8, 0);
v18 = 0;
while ( !CHECK_APP )
{
if ( v18 >= ENC_COUNT )
j_exit(0);
v9 = &enc_sha1[65 * v18];
v17 = j_strlen(v9) / 2;
v19 = (unsigned __int8 *)j_malloc(v17);
v10 = (char *)j_malloc(3);
v10[2] = 0;
for ( i = (int)v19; ; i = (int)(v21 + 1) )
{
v21 = (_BYTE *)i;
if ( i - (signed int)v19 >= v17 )
break;
*v10 = *v9;
v12 = v9[1];
v9 += 2;
v10[1] = v12;
*v21 = hex2dec(v10);
}
j_free(v10);
v13 = invCipherAll(v19, v17, v25, v24);
j_free(v19);
while ( !*(_BYTE *)(v13 + v17 - 1) )
--v17;
v14 = j_malloc(v17);
j_memcpy();
v15 = 0;
if ( v17 == v20 )
{
while ( 1 )
{
if ( v15 >= v20 )
{
LOBYTE(v15) = 1;
goto LABEL_16;
}
if ( *(unsigned __int8 *)(v14 + v15) != *(unsigned __int8 *)(v23 + v15) )
break;
++v15;
}
LOBYTE(v15) = 0;
}
LABEL_16:
CHECK_APP = v15;
++v18;
}
j___android_log_print(6, "YT_SAFE", &unk_695E);
return (*(int (__fastcall **)(int, int, int, _DWORD))(*(_DWORD *)v3 + 768))(v3, v22, v23, 0);
}
在看下 get_sign 函数
点击
函数进入,可以看到和签名相关的函数
方法 2( 搜索字符串 ):
在打开的 Strings window中搜索 getPackageManager、getPackageInfo、signatures。这里以搜索 getPackageManager 为例:
查看 getPackageManager 的调用:
可以看到只在 get_sign 里面调用了 getPackageManager,所以可以判定 get_sign 是关键函数。。。
或者 直接把 check_app 给去掉 。 40' 30''
按教程 上搞到这没搞出来,换思路在搞。。。so 分析流程,ida 修改 so 文件
方法 2:
删除 smali 代码中的
发现 apk 可以打开显示界面
这里不在截图。。。