我查查 6.6 去校验分析
其实我是不用这个软件的,不过受烈火之托,就看了看这个校验,据说在.so文件中。
首先呢,用VTS打开apk文件,经过初步分析,判断是否被修改全部根据下面这个位于com/wochacha/datacenter/DataProvider中的函数的返回值
.method private native init()I .end method
这是个native函数,所以确实是在.so文件中的。 经过搜索,发现libe.so文件中Java_com_wochacha_datacenter_DataProvider_init函数,果断IDA打开libe.so。
EXPORT Java_com_wochacha_datacenter_DataProvider_init Java_com_wochacha_datacenter_DataProvider_init PUSH {R4,LR} BL _Z9checkSignP7_JNIEnvP8_jobject ; checkSign(_JNIEnv *,_jobject *) POP {R4,PC} ; End of function Java_com_wochacha_datacenter_DataProvider_init
这个函数直接跳转到checkSign(_JNIEnv *,_jobject *)函数,这个函数名敢再直白一点吗?
稍微看了一下,这个checkSign函数,就只是先是检查了一下com/wochacha/util/WccConstant的DEBUG常量,然后计算并对比了一下apk签名的MD5,并没有什么特殊操作。
本着一切从简的原则,能不改.so就不改.so。
于是回到DataProvider.smali,搜索了一下init()I这个函数只在这一个地方被调用了,于是干脆把调用函数以及判断返回结果的代码全部注释掉,让他直接把1写入initResult:Z。
修改之后代码如下:
#.line 108 #invoke-direct {p0}, Lcom/wochacha/datacenter/DataProvider;->init()I #move-result v0 #.line 109 #if-nez v0, :cond_29 #.line 110 #const/4 v0, 0x0 #iput-boolean v0, p0, Lcom/wochacha/datacenter/DataProvider;->initResult:Z #.line 113 #:goto_28 #return-void #.line 112 #:cond_29 iput-boolean v1, p0, Lcom/wochacha/datacenter/DataProvider;->initResult:Z return-void #goto :goto_28
重新编译,测试一下,本来以为没什么问题了,可惜后来发现不管扫什么条形码都说没有收录。
果然没这么简单,搜索PackageManager,发现libgcbarcode_j.so里面居然有,嗯,很可疑,IDA之。
找到Gc_func_ab函数,果然有校验,不过貌似只是对比了一下包名和软件名,不过管它呢,虽然我不需要改动这些,但是既然见到了校验怎么能不去掉呢。
所有的几个对比失败了都会跳转到这里。
MOV R0, #0 LDMFD SP!, {R3-R11,PC}
#0改成#1即可。
只好继续找了,我又尝试搜索了几个常见的关键词,都没有什么收获。那就只好从问题入手分析了。
首先找到显示条形码没有收录的界面的函数是com/wochacha/compare/CommodityCompareResultActivity的showInValidInfo(Ljava/lang/String;)V。
会调用这个函数是因为barcodeErrorType:Ljava/lang/String;是255,这个变量的值是从Lcom/wochacha/datacenter/BarcodeInfo;->ErrorType:Ljava/lang/String;得到的,而唯一修改ErrorType的函数就是BarcodeInfo中的setErrorType(Ljava/lang/String;)V。
经过搜索,又回到了DataProvider.smali。分析发现这个错误代码来自一个json数据,而这个json是从网络获取的。此时我有点绝望,但仔细分析构建url的代码后,发现url中的barcode参数实际上是加了密的,并且还有一个参数是b_en就是用来加密的,把它也传给服务器说明也可以用它来解密。这时思路顿时清晰了,下面来看看加密过程吧。
这里必须要插一句,看了这个url的参数我算是体会到这款软件是有多么流氓了,完全没有考虑用户隐私,就一个查询条形码的请求,参数中居然包括了UDID(就是你的IMEI),MAC地址,连接方式(wifi或者3G), 最恐怖的是,如果定位信息可用的话还会把GPS的经纬度坐标也发给服务器。
回到barcode加密,实际调用的是Lcom/wochacha/datacenter/DataProvider;->convertData([BII)Ljava/lang/String;函数。看到函数的原型我笑了。
.method private native convertData([BII)Ljava/lang/String; .end method
果然又是native啊(喂喂不是naive啊看清楚你想什么呢)。搜索显示这个函数也在libe.so,可是这个文件很小,总共也只有不到十个函数,如果有这个函数我之前怎么会没看到呢?再次打开IDA,果然函数列表中没有这个函数,看上去应该是IDA的bug。
看了半天convertData,实际上关键部分不在这里,而是在wcc_encode函数,这个函数之前我也有看到,但是没有找到任何地方会调用这个函数(都怪IDA),于是也没注意。
这回仔细看一下,函数开头读取了内存中的一个值,和1比较,之后会有两种不同的encode算法,这两种算法绝大部分都一样,只是其中一个算法在某一步读取内存时多加了个0xC的偏移。
再看了看,之前比较的那个值貌似就是checkSign函数最后保存的。于是我修改了几个指令让checkSign函数所有情况都会返回并且保存1。
测试一下,居然还是不行!才想起来最开始的修改直接把调用init()I的代码注释掉了,导致checkSign函数根本没运行,从而也无法将1保存到内存中。
这次把最开始的修改恢复成原始的样子,打包,测试。
终于没问题了,剩下的去广告之类的工作就交给烈火吧。
写这篇文章也算是让自己记住这次教训,本来很容易的一件事,绕了一大圈最后还是回到原地解决。
近期评论