标签:
1 //原签名信息 2 private static final String SIGNATURE = "478yYkKAQF+KST8y4ATKvHkYibo="; 3 private static final int VALID = 0; 4 private static final int INVALID = 1; 5 6 public static int checkAppSignature(Context context) { 7 try { 8 PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(),PackageManager.GET_SIGNATURES); 9 10 for (Signature signature : packageInfo.signatures) { 11 byte[] signatureBytes = signature.toByteArray(); 12 MessageDigest md = MessageDigest.getInstance("SHA"); 13 md.update(signature.toByteArray()); 14 15 final String currentSignature = Base64.encodeToString(md.digest(), Base64.DEFAULT); 16 17 Log.d("REMOVE_ME", "Include this string as a value for SIGNATURE:" + currentSignature); 18 19 //compare signatures 20 if (SIGNATURE.equals(currentSignature)){ 21 return VALID; 22 }; 23 } 24 } catch (Exception e) { 25 //assumes an issue in checking signature., but we let the caller decide on what to do. 26 27 } 28 return INVALID; 29 }
最近遇到一个进行了签名校验的apk,它是在客户端获取签名信息然后在服务器端进行签名比对的,而且签名的获取是在native代码中实现的。这种签名校验的破解思路一般是在sd卡中保存一个原apk包,修改apk路径,让程序获取原apk的签名信息。修改办法一般有三种,下面一一介绍。
1 private static String getApkPath(String pkgName) { 2 PackageManager pm = mContext.getPackageManager(); 3 ApplicationInfo pi = null; 4 try { 5 pi = pm.getApplicationInfo(pkgName,PackageManager.GET_UNINSTALLED_PACKAGES); 6 if(pi != null) 7 return pi.sourceDir; 8 else 9 return null; 10 } catch (NameNotFoundException e) { 11 e.printStackTrace(); 12 return null; 13 } 14 }
sourceDir保存了apk的完整路径:
1 void uncrypt_test() 2 { 3 //采用MINIZIP进行文件解压缩 4 unzFile uf=NULL; 5 unzFile data[1200]; 6 unz_global_info64 gi; 7 unz_file_info64 FileInfo; 8 9 //打开zip文件 10 uf = unzOpen64("D:\\myfile.zip"); 11 int result=unzGetGlobalInfo64(uf, &gi); 12 if (result != UNZ_OK) 13 throw "文件错误"; 14 15 //循环解压缩文件 16 for(int i=0;i<gi.number_entry;++i) 17 { 18 if (unzGetCurrentFileInfo64(uf, &FileInfo, 0, 0,NULL,0,NULL,0)!= UNZ_OK) 19 throw "文件错误"; 20 21 if(!(FileInfo.external_fa & FILE_ATTRIBUTE_DIRECTORY)) //文件,否则为目录 22 //打开文件 23 //result=unzOpenCurrentFile(uf);/* 无密码 */ 24 result=unzOpenCurrentFilePassword(uf,"123"); /* 有密码 */ 25 26 //读取内容 27 int size= unzReadCurrentFile(uf,data,sizeof(data)); 28 29 //关闭当前文件 30 unzCloseCurrentFile(uf); 31 32 //出错 33 if(i < gi.number_entry - 1 && unzGoToNextFile(uf) != UNZ_OK) 34 throw "error"; 35 } 36 37 //关闭流 38 unzClose(uf); 39 }
从上述代码可知,解压过程中,apk路径以参数形式传入unzOpen64函数。所以我们需要hook这个函数。但是如何知道libAppVerify.so何时被加载呢?我们知道系统通过dvmLoadNativeCode函数从指定的路径加载so,如果对系统函数dvmLoadNativeCode进行hook,当它加载libAppVerify.so的时候,再hook unzOpen64函数,修改apk路径,不就行了?
dvmLoadNativeCode函数原型:
bool dvmLoadNativeCode(constchar* pathName, Object* classLoader, char** detail)
这里我们使用cydia substrate这个hook框架,关键代码如下:
1 const-string/jumbo v0, "substrate" 2 invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V 3 const-string/jumbo v0, "substrate-dvm" 4 invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V 5 const-string/jumbo v0, "HookVerify.cy" 6 invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V
由于需要在签名校验代码运行之前加载这些so,所以我们在Lcom/cgbchina/xpt/EMPView类的构造函数中添加上述代码,如下图所示:
标签:
原文地址:http://www.cnblogs.com/goodhacker/p/4842215.html