反编译APK成功后,在outdir目录下会生成一系列目录与文件。

smali:程序所有的反汇编代码;

res:程序中所有的资源文件;

如何寻找突破口是分析程序的关键。错误提示一般是指引关键代码的风向标,错误提示附近一般是核心验证代码,我们需要阅读这些代码来理解软件的注册流程。

错误提示是安卓中的字符串资源:

1:硬编码到源码中;

2:引用自“res\values"目录下的string.xml文件。

apk文件在打包时,string.xml文件中的字符串被加密存储在resources.arsc文件保存到APK程序包中,APK被反编译之后这个文件也被解密出来。

eg:编写一个安卓程序:

功能:计算用户名与注册码是否匹配。

计算方法:使用MD5算法计算这个用户名字符串的hash,将计算所得的结果转换为长度为32位的十六进制字符串,然后取字符串的所有奇数位重新组合生成新的字符串。此字符串就是最终的注册码。将它与传入的字符串相比较,如果想等,即正确。运行结果如下图:

开始分析:

当程序运行错误时:会弹出,无效的用户名或注册码,以此线索来寻找关键代码。打开"res\values\string.xml"文件:

<?xml version="1.0" encoding="UTF-8"?>

-<resources>

<string name="app_name">Crackme0201</string>

<string name="menu_settings">Settings</string>

<string name="title_activity_main">Crackme0201</string>

<string name="info">Android程序破解演示实例</string>

<string name="username">用户名:</string>

<string name="sn">注册码:</string>

<string name="register">注 册</string>

<string name="hint_username">请输入用户名</string>

<string name="hint_sn">请输入16位的注册码</string>

<string name="unregister">程序未注册</string>

<string name="registered">程序已注册</string>

<string name="unsuccessed">无效用户名或注册码</string>

<string name="successed">恭喜您!注册成功</string>

</resources>

string.xml中的字符串资源在"gen/<packagename>/R.java"文件中的string类中被标识,每一个字符串都有唯一的Int类型索引值,apktool反编译之后,所有索引值在public.xml文件中。

<?xml version="1.0" encoding="UTF-8"?>

-<resources>

<public id="0x7f020001" name="ic_launcher" type="drawable"/>

<public id="0x7f020000" name="ic_action_search" type="drawable"/>

<public id="0x7f030000" name="activity_main" type="layout"/>

<public id="0x7f040000" name="padding_small" type="dimen"/>

<public id="0x7f040001" name="padding_medium" type="dimen"/>

<public id="0x7f040002" name="padding_large" type="dimen"/>

<public id="0x7f050000" name="app_name" type="string"/>

<public id="0x7f050001" name="menu_settings" type="string"/>

<public id="0x7f050002" name="title_activity_main" type="string"/>

<public id="0x7f050003" name="info" type="string"/>

<public id="0x7f050004" name="username" type="string"/>

<public id="0x7f050005" name="sn" type="string"/>

<public id="0x7f050006" name="register" type="string"/>

<public id="0x7f050007" name="hint_username" type="string"/>

<public id="0x7f050008" name="hint_sn" type="string"/>

<public id="0x7f050009" name="unregister" type="string"/>

<public id="0x7f05000a" name="registered" type="string"/>

<public id="0x7f05000b" name="unsuccessed" type="string"/>

<public id="0x7f05000c" name="successed" type="string"/>

<public id="0x7f060000" name="AppTheme" type="style"/>

<public id="0x7f070000" name="activity_main" type="menu"/>

<public id="0x7f080000" name="textView1" type="id"/>

<public id="0x7f080001" name="edit_username" type="id"/>

<public id="0x7f080002" name="edit_sn" type="id"/>

<public id="0x7f080003" name="button_register" type="id"/>

<public id="0x7f080004" name="menu_settings" type="id"/>

</resources>

可知:unsuccessed的值为0x7f05000b;

接下来在smali目录中搜索含有内容为0X7F05000b的文件:【注:在文件下面的组织里面的--文件夹和搜索选项中--搜索---始终搜索文件名和内容】即可搜索。(有点问题,有时候搜不出来。正在钻研中。)

最后发现:只有MainActivity$1.smali文件一处被调用。

.class Lcom/droider/crackme0201/MainActivity$1;
.super Ljava/lang/Object;
.source "MainActivity.java" # interfaces
.implements Landroid/view/View$OnClickListener; # annotations
.annotation system Ldalvik/annotation/EnclosingMethod;
value = Lcom/droider/crackme0201/MainActivity;->onCreate(Landroid/os/Bundle;)V
.end annotation .annotation system Ldalvik/annotation/InnerClass;
accessFlags = 0x0
name = null
.end annotation # instance fields
.field final synthetic this$0:Lcom/droider/crackme0201/MainActivity; # direct methods
.method constructor <init>(Lcom/droider/crackme0201/MainActivity;)V
.locals 0
.parameter .prologue
.line 1
iput-object p1, p0, Lcom/droider/crackme0201/MainActivity$1;->this$0:Lcom/droider/crackme0201/MainActivity; .line 29
invoke-direct {p0}, Ljava/lang/Object;-><init>()V return-void
.end method # virtual methods
.method public onClick(Landroid/view/View;)V
.locals 4
.parameter "v" .prologue
const/4 v3, 0x0 .line 32
iget-object v0, p0, Lcom/droider/crackme0201/MainActivity$1;->this$0:Lcom/droider/crackme0201/MainActivity; iget-object v1, p0, Lcom/droider/crackme0201/MainActivity$1;->this$0:Lcom/droider/crackme0201/MainActivity; #getter for: Lcom/droider/crackme0201/MainActivity;->edit_userName:Landroid/widget/EditText;
invoke-static {v1}, Lcom/droider/crackme0201/MainActivity;->access$0(Lcom/droider/crackme0201/MainActivity;)Landroid/widget/EditText; move-result-object v1 invoke-virtual {v1}, Landroid/widget/EditText;->getText()Landroid/text/Editable; move-result-object v1 invoke-interface {v1}, Landroid/text/Editable;->toString()Ljava/lang/String; move-result-object v1 invoke-virtual {v1}, Ljava/lang/String;->trim()Ljava/lang/String; move-result-object v1 .line 33
iget-object v2, p0, Lcom/droider/crackme0201/MainActivity$1;->this$0:Lcom/droider/crackme0201/MainActivity; #getter for: Lcom/droider/crackme0201/MainActivity;->edit_sn:Landroid/widget/EditText;
invoke-static {v2}, Lcom/droider/crackme0201/MainActivity;->access$1(Lcom/droider/crackme0201/MainActivity;)Landroid/widget/EditText; move-result-object v2 invoke-virtual {v2}, Landroid/widget/EditText;->getText()Landroid/text/Editable; move-result-object v2 invoke-interface {v2}, Landroid/text/Editable;->toString()Ljava/lang/String; move-result-object v2 invoke-virtual {v2}, Ljava/lang/String;->trim()Ljava/lang/String; move-result-object v2 .line 32
#calls: Lcom/droider/crackme0201/MainActivity;->checkSN(Ljava/lang/String;Ljava/lang/String;)Z
invoke-static {v0, v1, v2}, Lcom/droider/crackme0201/MainActivity;->access$2(Lcom/droider/crackme0201/MainActivity;Ljava/lang/String;Ljava/lang/String;)Z move-result v0 .line 33
if-nez v0, :cond_0 #如果结果不为0,则跳转到cond_0处。 .line 34
iget-object v0, p0, Lcom/droider/crackme0201/MainActivity$1;->this$0:Lcom/droider/crackme0201/MainActivity; .line 35
const v1, 0x7f05000b .line 34
invoke-static {v0, v1, v3}, Landroid/widget/Toast;->makeText(Landroid/content/Context;II)Landroid/widget/Toast; move-result-object v0 .line 35
invoke-virtual {v0}, Landroid/widget/Toast;->show()V .line 42
:goto_0
return-void .line 37
:cond_0
iget-object v0, p0, Lcom/droider/crackme0201/MainActivity$1;->this$0:Lcom/droider/crackme0201/MainActivity;
#使用iget-object指令获取MainActivity实例的引用。
.line 38
const v1, 0x7f05000c .line 37
invoke-static {v0, v1, v3}, Landroid/widget/Toast;->makeText(Landroid/content/Context;II)Landroid/widget/Toast; move-result-object v0 .line 38
invoke-virtual {v0}, Landroid/widget/Toast;->show()V .line 39
iget-object v0, p0, Lcom/droider/crackme0201/MainActivity$1;->this$0:Lcom/droider/crackme0201/MainActivity; #getter for: Lcom/droider/crackme0201/MainActivity;->btn_register:Landroid/widget/Button;
invoke-static {v0}, Lcom/droider/crackme0201/MainActivity;->access$3(Lcom/droider/crackme0201/MainActivity;)Landroid/widget/Button; move-result-object v0 invoke-virtual {v0, v3}, Landroid/widget/Button;->setEnabled(Z)V .line 40
iget-object v0, p0, Lcom/droider/crackme0201/MainActivity$1;->this$0:Lcom/droider/crackme0201/MainActivity; const v1, 0x7f05000a invoke-virtual {v0, v1}, Lcom/droider/crackme0201/MainActivity;->setTitle(I)V goto :goto_0
.end method

 修改Smali文件代码:

if-nez v0, :cond_0   #如果结果不为0,则跳转到cond_0处。修改为:
if-eqz v0, :cond_0   #如果结果为0或等于0,则跳转到cond_0处。

然后对修改后的文件进行重新编译打包成apk文件。

在cmd中输入:apktool b outdir

编译生成的apk没有签名,还不能安装测试。接下里需要用signapk.jar工具对apk文件进行签名。(见后文)

安装测试:

由于AVD太慢,所以在手机设备上运行;转换成手机模式:window---OpenPerspective---DDOS,双击即可。
在命令行下:adb install signed.apk

安装完后,随便输入注册码,就会出现:恭喜您,注册成功字样!

破解第一个程序----分析APK文件的更多相关文章

  1. 分析Android程序之破解第一个程序

    破解Android程序通常的方法是将apk文件利用ApkTool反编译,生成Smali格式的反汇编代码,然后阅读Smali文件的代码来理解程序的运行机制,找到程序的突破口进行修改,最后使用ApkToo ...

  2. 从”茄子快传”看应用程序怎样获取手机已安装程序的apk文件

    "茄子快传"是联想开发的一款近距离文件共享软件.它通过wifi-direct(速度飞快,不须要联网)或者普通的网络(速度慢)在不同手机间传递文件. 不知为何.它就火了起来,火的也飞 ...

  3. 只需三步--轻松反编译Android Apk文件

    安卓程序是通过java语言进行编写的,可以很容易进行反编译.很多apk文件被反编译后再二次打包,就成了自己的产品,很是流氓.下面我们来看看如何进行apk的反编译,以及常用的防反编译手段. 一.反编译A ...

  4. Android系统加载Apk文件的时机和流程分析(1)--Android 4.4.4 r1的源码

    本文博客地址:https://blog.csdn.net/QQ1084283172/article/details/80982869 Android系统在启动时安装应用程序的过程,这些应用程序安装好之 ...

  5. Python:使用Kivy将python程序打包为apk文件

    1.概述 Kivy是一套Python下的跨平台开源应用开发框架,官网,我们可以用 它来将Python程序打包为安卓的apk安装文件.以下是在windows环境中使用. 安装和配置的过程中会下载很多东西 ...

  6. 构建-13 Analyzer APK文件分析

    官方文档 使用APK Analyzer分析您的构建  [Analyze your build with APK Analyzer] Android Studio包含一个APK分析器,可在构建过程完成后 ...

  7. 使用GDB 追踪依赖poco的so程序,core dump文件分析.

    前言 在windows 下 系统核心态程序蓝屏,会产生dump文件. 用户级程序在设置后,程序崩溃也会产生dump文件.以方便开发者用windbg进行分析. so,linux 系统也有一套这样的东东- ...

  8. android 开发 程序中下载安装APK文件 问题汇总 解析程序包时出现问题

    1 若把APK文件保存到应用程序的files目录下,则一定注意保存时使用 FileOutputStream os = openFileOutput(fileName, MODE_WORLD_READA ...

  9. mac下破解apk文件以及apktool的相关使用

    Android apktool是一个用来处理APK文件的工具,可以对APK进行反编译生成程序的源代码和图片.XML配置.语言资源等文件,也可以添加新的功能到APK文件中.用该工具来汉化Android软 ...

随机推荐

  1. poj1459 最大流Dinic

    比较简单. #include<stdio.h> #include<string.h> #include<queue> #define maxn 110 #defin ...

  2. phpexcel使用说明2

      转自:http://serisboy.iteye.com/blog/1928139 首先到phpexcel官网上下载最新的phpexcel类,下周解压缩一个classes文件夹,里面包含了PHPE ...

  3. HZOJ Permutation

    输出原序列有45分…… 字典序最小可以和拓扑序联系起来. 根据原来的题意不是很可做,于是对原序列求逆,令q[p[i]]=i; 那么就成功将题意转化:相邻元素值的差大于等于k时可以交换,使序列字典序最小 ...

  4. 原生js扫雷代码

    思路要点: 1. 随机地雷放到一个二维数组中: 2. 每一个格子要统计周围有几颗雷: 3. 每一个格子是否处于打开状态,用于判断是否赢得游戏: 4. 如果点击到周围没有雷的地方,把周围的打开: 具体的 ...

  5. Vue知识点——vue数据深拷贝方法

    背景 在vue页面传递数据的过程中,传递数据的引用地址并不会改变,所以当我们改变一些数据时,数据源 也会随之改变.可是有很多情景,我们改变传递的数据,并不需要源数据值发生变化,这时我们就需要对数据进行 ...

  6. Spring集成Hessian1

    Hessian是一个轻量级的远程调用工具,采用的是Binary RPC协议,很适合于发送二进制数据,基于HTTP具有防火墙穿透能力.Hessian一般是通过Web应用来提供服务,因此非常类似于平时我们 ...

  7. 使用epoll实现简单的服务器

    1. 头文件 #ifndef __TCP_SERVER_H__ #define __TCP_SERVER_H__ #include <unistd.h> #include <stdi ...

  8. CH1401 兔子与兔子

    #include<bits/stdc++.h> using namespace std; ,p=; typedef unsigned long long ULL;//自然溢出 ULL f[ ...

  9. 一文告诉你Adam、AdamW、Amsgrad区别和联系 重点

    **序言:**Adam自2014年出现之后,一直是受人追捧的参数训练神器,但最近越来越多的文章指出:Adam存在很多问题,效果甚至没有简单的SGD + Momentum好.因此,出现了很多改进的版本, ...

  10. input标签前台实现文件上传

    值得注意的是:当一个表单里面包含这个上传元素的时候,表单的enctype必须指定为multipart/form-data,method必须指定为post,浏览器才会认识并正确执行.但是还有一点,浏览器 ...