|
| |
普通会员
|
工具:IDA6.6,不会发图,只能用文字描述了。
研究过《遇见》登录的同学可能都知道,只要修改过APK,在登录时都会提示软件盗版。 经研究登录时safecode字段有问题,可能是验证了签名。在libiaroundnet.so中Java_net_iaround_utils_NativeLibUtil_aaa实现。 步骤1:下载 http://gdown.baidu.com/data/wisegame...yujian_570.apk 将yujian_570.apk改名为yujian_570.zip,将lib目录下的lib\armeabi\libiaroundnet.so提取出来拖入IDA中。 步骤2: 拖进来后发现SHA1Input,SHA1Output这样带有SHA1的函数,断定SO中用到了SHA1加密算法。 步骤3: 查看Java_net_iaround_utils_NativeLibUtil_aaa函数按F5出来C的伪代码,此时代码还不易读懂,不如像“v9 = (*(int (**)(void))(v8 + 124))()”,这样的代码。但是看到这个我们是不是应该想到C++里面的内存的寻址?,成员变量的首地址=对象的首地址+成员变量在类中的偏移. 假如 Struct node { int,x,y; }; node a;如果A的首地址是0x00000000,那么a.x的地址是0x00000000,a.y的地址是0x00000004; 由C伪代码我们不难得出:v8是JNIEnv *类型,查看jni.h并计算我们不难发现v8 + 124是GetObjectClass函数指针,同理我们可以计算出其他类似的调用。 步骤4: 有了步骤三的基础,我们可以想到一个简便的方法就是导入jni.h,从而确定JNIEnv类的结构,借助IDA直接识别函数。下载jni.h(虫大大书上修改JNI.H的方法貌似不好使,我自己改了个):http://pan.baidu.com/s/1sj3EaTn,然后File->Load File->parse C header file... 选择下载好的jni.h确定。然后在structures页面里按下insert键 ->add standard structure->滑到最下方选择"JNIEnv_",然后确定。 步骤5: 返回伪代码界面,鼠标点击Java_net_iaround_utils_NativeLibUtil_aaa的第一个参数,右键->convert to struct*->选择jnienv_*,这时,伪代码中不明函数的调用已经出来。 刚刚的(*(int (**)(void))(v8 + 124))()已经变成 ((int (*)(void))v8->GetObjectClass)(); 这时只要仔细阅读伪代码就知道该函数做了啥,逆向的C代码为:
代码:
JNIEXPORT jstring JNICALL Java_net_iaround_utils_NativeLibUtil_aaa (JNIEnv *env, jobject ob, jobject paramContext, jobject paramPackageInfo, jstring paramString1, jstring paramString2) { SHA1Context context; jstring ret=0; JNIEnv* p_env=env; char cifferbuf[128]={0}; char buf[64]={0}; jclass obClass=env->GetObjectClass(ob); char *pString="()Ljava/lang/String;"; jmethodID reusltID=p_env->GetMethodID(obClass,"getPackageName","()Ljava/lang/String;"); jobject retObject=p_env->CallObjectMethod(paramContext,reusltID); jboolean boolean=0; const char *str=p_env->GetStringUTFChars((jstring)retObject,&boolean); bool cmpResult=strcmp("net.iaround",str); if(cmpResult==0) { ret=p_env->NewStringUTF("123456"); } else { char destBuffer[128]={0}; const char* s1=p_env->GetStringUTFChars(paramString1,&boolean); const char *s2=p_env->GetStringUTFChars(paramString2,&boolean); __android_log_print(4, "logfromc", "%s",s1); __android_log_print(4, "logfromc", "%s",s2); int len1=strlen(s1); int len2=strlen(s2); memcpy(destBuffer,s1,len1); memcpy(destBuffer+len1,s2,len2); jclass packageInfo= p_env->GetObjectClass(paramPackageInfo); ret=(jstring)packageInfo; if(packageInfo) { jfieldID signatures=p_env->GetFieldID(packageInfo,"signatures","[Landroid/content/pm/Signature;"); ret=(jstring)signatures; if(signatures) { jobjectArray sigarray=(jobjectArray)p_env->GetObjectField(paramPackageInfo,signatures); if(sigarray) { jsize sigLength=p_env->GetArrayLength(sigarray); if(sigLength>0) { jobject ob=p_env->GetObjectArrayElement(sigarray,0); if(ob) { jclass jc=p_env->GetObjectClass(ob); if(jc) { jmethodID id=p_env->GetMethodID(jc,"toCharsString","()Ljava/lang/String;"); if(id) { jstring sigString =(jstring)p_env->CallObjectMethod(ob,id); const char* sigStr=p_env->GetStringUTFChars(sigString,&boolean); int passLen=strlen(destBuffer); memcpy(cifferbuf,sigStr+16,32); //__android_log_print(4, "logfromc", "%s",sigStr+16); //memcpy(cifferbuf,"a00302010202044e549d3a300d06092a",32); memcpy(cifferbuf+32,destBuffer,passLen); __android_log_print(4, "logfromc", "cifferString:%s",cifferbuf); SHA1Reset(&context); int cifferlen=strlen(cifferbuf); SHA1Input(&context,cifferbuf,cifferlen); //memset(&v51, 48, 0x29u); memset(buf,0,sizeof(buf)); if(SHA1Result(&context)) { sprintf(buf, "%08X%08X%08X%08X%08X", context.Message_Digest[0],context.Message_Digest[1], context.Message_Digest[2],context.Message_Digest[3],context.Message_Digest[4]); } else { __android_log_print(4, "logfromc", "ERROR-- could not compute message digest\n"); } ret=p_env->NewStringUTF(buf); } } } } } } } } return ret; } 一句话概括就是:将签名中取出32位+paramString1+paramString2后用SHA1加密 如果中途出错,直接返回“123456”。。。 这时可以得出该APK包是利用了签名加密后到服务器验证的。服务器计算出safecode和收到的safecode不一样时,反馈软件盗版。。 此贴只供学习,如做其它用途,后果自负。 | ||
|
最佳答案 - 作者: 杨剑超 |
在哪删帖,我要删帖!!!!!!!!!!!!!!!!!!!!! |
普通会员
|
在哪删帖,我要删帖!!!!!!!!!!!!!!!!!!!!!
| ||
|
普通会员
|
点一下编辑就行了 哈哈 被警告了吧
| ||
|
普通会员
|
| ||
|
普通会员
|
| ||
|
初级会员
|
写的很不错啊。、
| ||
|
普通会员
|
PS:我KX不够,不能和你悄悄话 | ||
|
普通会员
|
MARK
| ||
|
初级会员
|
这么好的技术文章,就不要删除了
| ||
|
普通会员
|
学习了 感谢分享!!
| ||
|
初级会员
|
不错哦 继续加油
| ||
|
初级会员
|
赞一个 长知识了~
| ||
|
初级会员
|
这个也就是通过c++部分再回调java的
| ||
|
初级会员
|
貌似IDA6.6 自动导入了jni.h这个文件了
| ||
|
普通会员
|
| ||
|
添加到书签 |
|
|
相似的主题 | ||||
主题 | 主题作者 | 论坛 | 回复 | 最后发表 |
如果没有遇见“你” | lijingli | 7)看雪十周年专版 | 26 | 2014-06-06 03:35:10 |
调试逆向 【求助】【求助】调试中 遇见一个函数zwqueryobject | fwoi | 『软件调试逆向』 | 19 | 2008-11-07 09:27:13 |
【求助】脱壳中遇见的问题 | xinghong | 『求助问答』 | 1 | 2008-09-08 11:16:58 |
【原创破解驱动PC/SC遇见麻烦!! | www | 『求助问答』 | 0 | 2008-07-27 11:52:58 |
【求助】脱ASPack 2.12 -> Alexey Solodovnikov遇见的问题 | 糖醋鱼 | 『求助问答』 | 3 | 2008-01-31 12:14:44 |