来自<Android软件安全与逆向分析>
一。配置安卓环境
1.安装JDK
http://www.oracle.com/technetwork/java/javase/downloads/index.html
DwonLoads->下载JDK
我下载的版本是
jdk-8u91-windows-x64.exe
一路安装好了之后,添加用户变量
JAVA_HOME 值为安装目录 I:\Android\jdk
并将I:\Android\jdk\bin添加到PATH中
CMD-> 输入java -version出现版本信息说明安装成功
2.安装Android SDK
http://developer.android.com/intl/zh-cn/sdk/index.html
我下载的是android-studio-bundle-143.2790544-windows.exe
安装好了之后添加路径到PATH
I:\Android\Android\sdk\platform-tools
I:\Android\Android\sdk\tools
打开CMD 输入emulator -version查看是否成功
打开I:\Android\Android\sdk\目录下的SDK Manager.exe
选择自己需要的版本下载
我选择了6.0、5.0和4.1
3.安装Android NDK
Android NDK是Google提供的开发Android原生程序的工具包。
http://developer.android.com/intl/zh-cn/tools/sdk/ndk/index.html
我下载的版本是
android-ndk-r11c-windows-x86_64.zip
解压到任意目录
新建变量 ANDROID_NDK I:\Android\android-ndk-r11c
并将ANDROID_NDK 加入PATH中
4.Eclipse
http://www.eclipse.org/downloads/
我安装的版本是eclipse-java-mars-2-win32-x86_64.zip
点击运行即可
5.安装CDT、ADT插件
如果Eclipse选择的是Eclipse IDE for Java Developers则需要安装
选择的是Eclipse for Mobile Developers则自带
CDT安装方式
1.启动Eclipse Help->Install New Software
输入网址Http://download.eclipse.org/tools/cdt/releases/juno 这个地方我没弄对
2.到Eclipse官网下载最新版CDT
http://www.eclipse.org/cdt/downloads.php
下载好离线包 直接Help->Install New Software -> Add -> Archive
全选 Next
ADT
http://developer.android.com/intl/zh-cn/tools/sdk/eclipse-adt.html
这个网址一直找不到下载页面
然后直接下载的
http://dl.google.com/android/ADT-23.0.7.zip
打开Eclipse Window -> Preferences 选择Android列表项
SDK Location处选择 Android SDK 的安装位置
NDK Location处选择 Android NDK 的安装位置
到此CDT 和 ADT 就完成了。
AVD Manager.exe创建一个虚拟设备 ,我选择4.1.2
二。创建一个安卓程序
新建安卓工程,这里遇到了问题就是最后一步点Finish没反应
是因为创建时选的2.2 , 选在4.0之上就没问题了
然后在activity_main.xml文件上设置登陆控件
一个用户名,一个密码,一个注册按钮就行
接着在strings.xml中写入常量字符串
最后在MainActivity.java中设置监听器
private EditText edit_userName; private EditText edit_sn; private Button btn_register; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); setTitle(R.string.unregister); //模拟程序未注册 edit_userName = (EditText) findViewById(R.id.edit_username); edit_sn = (EditText) findViewById(R.id.edit_passwd); btn_register = (Button) findViewById(R.id.buttonRG); //对于Button的点击事件的监听 btn_register.setOnClickListener(new OnClickListener() { public void onClick(View v) { if (!checkSN(edit_userName.getText().toString().trim(), edit_sn.getText().toString().trim())) { Toast.makeText(MainActivity.this, //弹出无效用户名或注册码提示 R.string.unsuccessed, Toast.LENGTH_SHORT).show(); } else { Toast.makeText(MainActivity.this, //弹出注册成功提示 R.string.successed, Toast.LENGTH_SHORT).show(); btn_register.setEnabled(false); setTitle(R.string.registered); //模拟程序已注册 } } }); }
private boolean checkSN(String userName,String sn) { try{ if((userName==null)||(userName.length()==0)) return false; if((sn==null)||(sn.length()==0)) return false; MessageDigest digest = MessageDigest.getInstance("MD5"); digest.reset(); digest.update(userName.getBytes()); byte[] bytes = digest.digest(); //采用MD5对用户名进行HASH String hexstr = toHexString(bytes, ""); //将计算结果转化成字符串 StringBuilder sb = new StringBuilder(); for(int i=0;i<hexstr.length();i+=2) { sb.append(hexstr.charAt(i)); } String userSN = sb.toString();//计算出的SN if(!userSN.equalsIgnoreCase(sn))//比较注册码是否正确 return false; } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return false; } return false; } private static String toHexString(byte[] bytes, String separator) { StringBuilder hexString = new StringBuilder(); for (byte b : bytes) { String hex = Integer.toHexString(0xFF & b); if(hex.length() == 1){ hexString.append(‘0‘); } hexString.append(hex).append(separator); } return hexString.toString(); }
简单的一个注册码验证,成功或失败弹出相应的字符串提示
三。破解该注册程序
这里我们使用ApkTool 反编译 生成Smali格式的反汇编 代码
阅读Smali文件的代码来理解程序运行机制,找到突破口进行修改
使用ApkTool重新编译生成apk文件并签名,最后运行测试
http://ibotpeaches.github.io/Apktool/
解压,添加环境变量
我使用的是
apktool_2.0.0rc4.jar
apktool-install-windows-r05-ibot.tar.bz2
解压出来的一共三个文件放在一个目录下,添加环境变量,方便cmd命令直接使用
将apktool_2.0.0rc4.jar 名称 修改成apktool.jar
反编译命令 apktool d crackmemz02.apk
在反编译的时候也遇到很多问题,这里罗列一下搜索结果
1.使用apktool工具遇到could not decode arsc file的解决办法
解决方案:下载最新版本的apktool.jar
2.Input file was not found or was not readable.
3.Destination directory (C:\Users\user\a) already exists. Use -f switch if you want to overwrite it.
4.Exception in thread "main" brut.androlib.AndrolibException: Could not decode ars c fil..........
解决方案:
2和3是因为apktool升级到2.0以上时,使用方式已经替换,格式为:apktool d [-s] -f <apkPath> -o <folderPath>,参数具体的意思可以直接打apktool回车(windows)查看帮助
1和4是因为apktool版本过低导致,请升级到最新版本,地址:https://bitbucket.org/iBotPeaches/apktool/downloads
反编译出来的一个文件夹就是整个工程了
我们在res\valuse\strings.xml 中找到
<string name="unsuccessed">无效用户名或注册码</string>
在res\valuse\public.xml中找到unsuccessed的ID为0x7f050004
<public type="string" name="unsuccessed" id="0x7f050004" />
我们在smali搜索该Id
发现MainActivity$1.smali文件有调用该处
.line 43
const v1, 0x7f050004
如果不合法则不跳转 提示不成功 .line 40 # invokes: Lcom/example/crackmemz021/MainActivity;->checkSN(Ljava/lang/String;Ljava/lang/String;)Z invoke-static {v0, v1, v2}, Lcom/example/crackmemz021/MainActivity;->access$2(Lcom/example/crackmemz021/MainActivity;Ljava/lang/String;Ljava/lang/String;)Z #检查注册码是否合法 move-result v0 .line 41 if-nez v0, :cond_0 #如果结果不为0 ,就跳转到cond_0标号处 .line 42 iget-object v0, p0, Lcom/example/crackmemz021/MainActivity$1;->this$0:Lcom/example/crackmemz021/MainActivity; .line 43 const v1, 0x7f050004 #unsuccessed字符串 .line 42 invoke-static {v0, v1, v3}, Landroid/widget/Toast;->makeText(Landroid/content/Context;II)Landroid/widget/Toast; 成功则跳转至cond_0,显示成功 .line 45 :cond_0 iget-object v0, p0, Lcom/example/crackmemz021/MainActivity$1;->this$0:Lcom/example/crackmemz021/MainActivity; .line 46 const v1, 0x7f050005 #successed 字符串 代表成功 .line 45 invoke-static {v0, v1, v3}, Landroid/widget/Toast;->makeText(Landroid/content/Context;II)Landroid/widget/Toast; move-result-object v0 .line 46 invoke-virtual {v0}, Landroid/widget/Toast;->show()V .line 47 iget-object v0, p0, Lcom/example/crackmemz021/MainActivity$1;->this$0:Lcom/example/crackmemz021/MainActivity; # getter for: Lcom/example/crackmemz021/MainActivity;->btn_register:Landroid/widget/Button; invoke-static {v0}, Lcom/example/crackmemz021/MainActivity;->access$3(Lcom/example/crackmemz021/MainActivity;)Landroid/widget/Button; move-result-object v0 invoke-virtual {v0, v3}, Landroid/widget/Button;->setEnabled(Z)V #设置注册按钮不可用 .line 48 iget-object v0, p0, Lcom/example/crackmemz021/MainActivity$1;->this$0:Lcom/example/crackmemz021/MainActivity; const v1, 0x7f050003 #registered字符串 模拟注册成功 invoke-virtual {v0, v1}, Lcom/example/crackmemz021/MainActivity;->setTitle(I)V goto :goto_0
只需将if-nez 改成if-eqz就行,这样程序就修改成功
我们在用apktool重新编译
apktool b crackmemz02
在该目录的dist目录下有重新生成的apk了 , 这个时候的apk是没有签名的
需要使用signapk.jar工具对apk文件进行签名
signapk crackmemz.apk
签名后生成signed.apk
安装测试
打开虚拟设备
adb install signed.apk
到这里我们就完成了,第一次的安卓破解
反编译工具: http://pan.baidu.com/s/1c1XNiBA 密码 fyn7
安卓环境搭建工具: http://pan.baidu.com/s/1bIslFS 密码 dmmj
安卓代码 : http://pan.baidu.com/s/1mi6cIhE Apk.zip为反编译后的工程