wis 发表于 2016-6-1 19:16

安卓逆向破解学习之“偷数据”

本帖最后由 wis 于 2016-6-1 19:21 编辑

移动端解密的教程略少,我来贡献一份~{:5_116:}
先解释下这里的“偷数据”是指通过对比原版app和别人逆向后的app,得到差异以及逆向分析思路。
这是一种很好的学习方法,通过对前人的逆向成品和原版的分析,在他没有给出逆向教程的前提下,我们也可以知道其逆向分析思路!
然后运用到新版本的app逆向中。
与其说是“偷数据”,不如说是“借鉴”{:5_188:}

0x1 流程
大致流程如下:
①分别反编译同版本的原版app和别人的逆向成品
②对比反编译后的文件,得到差异
③根据差异得到逆向分析思路,并运用到新版本中


0x2 工具
本文用到的工具如下:
AndroidKiller1.3.1,IDAProv6.8,Beyond Compare,010 Editor,ARM_ASM Converter
AndroidKiller:用于反编译和编译apk,反编译得到的smali、xml等格式文件也可以在其中直接修改
IDAPro:用于反汇编和分析so文件
Beyond Compare:用于对比apk反编译后的文件
010 Editor:由于so文件不能在AndroidKiller和IDA中直接修改,所以使用010 Editor进行修改
ARM_ASM Converter:转码用的。

0x3 反编译
反编译apk也很简单,分别拖进AndroidKiller中,等1,2分钟就行。







0x4 对比分析
把原版文件夹和逆向版文件夹拖进Beyond Compare。

这里有3个文件夹,由于所有反编译后的文件都存放于Project中,所以右键Project进行比较。




等几分钟后,就能知道两者的差异了。

如图,我们最主要关注的是smali和lib文件夹下文件的差异。

先看smali的:
打开其中一个smali看到差异


他在return v0 前添加了一句const/4 v0, 0x1,意思是令这个方法强制return true
他的逆向目的是改为vip版。关键词是"key_user_isvip"

其他smali的修改类似,都是强制return true,即强制修改为vip版。

关键词是"isvip"。

再看lib的:
他修改过的so文件是lib_jni_dict.so,我们看一下。

记下001198E0

然后把lib_jni_dict.so拖进IDA中分析。
我们不等IDA分析完全,直接ctrl+G,然后ctrl+F找到001198E0处或者附近的地址,看下数据。
(因为ctrl+F搜索001198E0无果,所以找附近的)


找到相应的位置后,按F5看到以下代码:
int __fastcall verifyContext(int a1, int a2)
{
int v2; // r6@1
int v3; // r4@1
int v4; // r0@3
int v5; // r7@3
int v6; // r0@3
int v7; // r8@3
int v8; // r0@3
int v9; // r0@3
int v10; // r0@3
int v11; // r0@3
int v12; // r6@3
int v13; // r0@3
int v14; // r0@3
int v15; // r0@3
int v16; // r0@3
int v17; // r6@3
int v18; // r0@3
int v19; // r0@3
int v20; // r0@3
int result; // r0@5

v2 = a2;
v3 = a1;
if ( !(*(int (**)(void))(*(_DWORD *)a1 + 24))() )
{
    _JNIEnv::CallObjectMethod(v3, 0, 0);
    v2 = 0;
}
v4 = (*(int (__fastcall **)(int, _DWORD))(*(_DWORD *)v3 + 24))(v3, "android/content/ContextWrapper");
v5 = v4;
v6 = (*(int (__fastcall **)(int, int, _DWORD, _DWORD))(*(_DWORD *)v3 + 132))(
         v3,
         v4,
         "getPackageManager",
         "()Landroid/content/pm/PackageManager;");
v7 = _JNIEnv::CallObjectMethod(v3, v2, v6);
v8 = (*(int (__fastcall **)(int, int, _DWORD, _DWORD))(*(_DWORD *)v3 + 132))(
         v3,
         v5,
         "getPackageName",
         "()Ljava/lang/String;");
_JNIEnv::CallObjectMethod(v3, v2, v8);
v9 = (*(int (__fastcall **)(int, int))(*(_DWORD *)v3 + 124))(v3, v7);
v10 = (*(int (__fastcall **)(_DWORD, _DWORD, _DWORD, _DWORD))(*(_DWORD *)v3 + 132))(
          v3,
          v9,
          "getPackageInfo",
          "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");
v11 = _JNIEnv::CallObjectMethod(v3, v7, v10);
v12 = v11;
v13 = (*(int (__fastcall **)(int, int))(*(_DWORD *)v3 + 124))(v3, v11);
v14 = (*(int (__fastcall **)(int, int, _DWORD, _DWORD))(*(_DWORD *)v3 + 376))(
          v3,
          v13,
          "signatures",
          "[Landroid/content/pm/Signature;");
v15 = (*(int (__fastcall **)(int, int, int))(*(_DWORD *)v3 + 380))(v3, v12, v14);
v16 = (*(int (__fastcall **)(int, int, _DWORD))(*(_DWORD *)v3 + 692))(v3, v15, 0);
v17 = v16;
v18 = (*(int (__fastcall **)(_DWORD, _DWORD))(*(_DWORD *)v3 + 124))(v3, v16);
v19 = (*(int (__fastcall **)(int, int, _DWORD, char))(*(_DWORD *)v3 + 132))(v3, v18, "hashCode", "()I");
v20 = _JNIEnv::CallIntMethod(v3, v17, v19);
if ( v20 == 1747956166 || v20 == -1666615029 )
    result = 820711;
else
    result = _JNIEnv::CallObjectMethod(v3, 0, 0);
return result;
}由getPackageInfo、signatures和hashCode这三个词,判断这是apk的签名验证。



这是他改动的地方,代码如下:
.text:001198CA               ADD   R2, PC          ; "hashCode"
.text:001198CC               ADD   R3, PC          ; "()I"
.text:001198CE               LDR   R5,
.text:001198D0               MOVS    R0, R4
.text:001198D2               BLX   R5
.text:001198D4               MOVS    R1, R6
.text:001198D6               MOVS    R2, R0
.text:001198D8               MOVS    R0, R4
.text:001198DA               BL      _ZN7_JNIEnv13CallIntMethodEP8_jobjectP10_jmethodIDz ; _JNIEnv::CallIntMethod(_jobject *,_jmethodID *,...)
.text:001198DE               LDR   R3, =0x682FB1C6
.text:001198E0               CMP   R0, R3         
.text:001198E2               BEQ   loc_1198FC
.text:001198E4               LDR   R3, =0x9CA9790B
.text:001198E6               CMP   R0, R3
.text:001198E8               BEQ   loc_1198FC
.text:001198EA               MOVS    R0, R4
.text:001198EC               MOVS    R1, #0
.text:001198EE               MOVS    R2, #0
.text:001198F0               BL      _ZN7_JNIEnv16CallObjectMethodEP8_jobjectP10_jmethodIDz ; _JNIEnv::CallObjectMethod(_jobject *,_jmethodID *,...)
.text:001198F4大意是先将R0和hashCode1(0x682FB1C6)进行比较,相等则跳到loc_1198FC
然后将R0和hashCode2(0x9CA9790B)进行比较,相等则跳到loc_1198FC
由于修改过的apk要进行重新签名,所以R0肯定和任一hashCode均不相等的了
我们要改为相等。
其中一个改法是改为CMP R0, R0,如此一来,绝对相等,然后跳到loc_1198FC了。
或者像他一样改,改为"不等则跳"也行。




0x5 修改&回编译
通过以上的对比分析,得知此app逆向的2个关键点:
一是在smali里搜索isvip,可以将app改为vip版
二是在so里搜索signature,目的是逆向签名验证(如果不逆向此处,修改过的app会闪退)。


然后一一进行修改即可。{:5_116:}


比如so里的签名验证,用010 Editor打开lib_jni_dict.so,ctrl+G搜索001198E0

如我想把CMP R0,R3改为CMP R0,R0怎么改?
如下图:




只需把此处的9842改为8042即可!~

END~
新手,求不喷~~{:5_121:}



wakichen 发表于 2016-6-1 19:21

完全没看懂啊,大神出个教程好了{:5_116:}

yueyongbing 发表于 2016-6-1 19:26

看到已晕..板凳已做

userxy 发表于 2016-6-1 19:34

看到头昏脑涨的。。

520Kelly 发表于 2016-6-1 19:45

没看懂为什么const/4 v0, 0x1就retn true

A00 发表于 2016-6-1 19:51

非常不错,期待更多这方面的教程

wis 发表于 2016-6-1 20:53

@Shark恒本文完全是原创的。
而本文用到的逆向版也是本人所逆向的
我用自己的逆向作品 来 描述一种新人学习安卓逆向逆向的方法而已。。。{:5_188:}
也就是对比学习法

Gming 发表于 2016-6-1 21:26

貌似很给力的样子!!...感谢分享

Shark恒 发表于 2016-6-1 21:28

wis 发表于 2016-6-1 20:53
@Shark恒本文完全是原创的。
而本文用到的逆向版也是本人所逆向的
我用自己的逆向作品 来 描述一种新人 ...
抱歉,我也是为了保护原作者的权益,并不是对你有什么偏见,请提供该文章首发地。这里面有一些文字是复制过来的,所以我认为你是转载。

wis 发表于 2016-6-1 21:39

Shark恒 发表于 2016-6-1 21:28
抱歉,我也是为了保护原作者的权益,并不是对你有什么偏见,请提供该文章首发地。这里面有一些文字是复制 ...

首发:https://www.52hb.com/thread-24150-1-1.html
文字全是手打的 {:5_188:}
没有一个文字是复制的啊{:5_189:}

当然,你要是觉得这种学习方法太弱了 也是没有办法的 毕竟是自学嘛!
页: [1] 2 3 4 5 6 7
查看完整版本: 安卓逆向逆向学习之“偷数据”