無標題文檔

Android 的 apk 包的反编译和破解初步

_注:此信息仅仅是作为技术研究使用,请勿用作非法用途。同时本团队的应用已经针对破
解有了对应的措施,并保留追求责任的权利。_

前些日子看到公司的应用被破解同时在论坛里流出,所以了解了下 Android 相应的应用破解原理以及过程。

首先,下载相应解开 apk 的工具包:

https://code.google.com/p/android-apktool/

下载完了以后得到个 jar 包,我们运行

java -jar apktool.jar

就可以得到它的用法。我这边直接解压缩相应的 apk 包:

java -jar apktool.jar decode origin-v1.0.apk

解压完毕以后,在本地目录就可以看到多出来个文件夹,里面包含了 apk 的原始资源等数据。

https://friable.rocks/_/2013_11_28/1385608157@640.png

其中,最重要的就是 smali 目录,它对应的是原始 Android 项目的 src 目录,也就是 Java 源文件。不过 smali 有点类似「Java 的汇编」,详细有关 smali 的信息可以在这里得到:

https://code.google.com/p/smali/

下面,比如我们已经知道原来应用注册的位置,例如 Activity 的入口,那么我们就从这里开始切入。

https://friable.rocks/_/2013_11_28/1385608119.png

我们很容易得就能得到相应的激活注册模块的方法在哪里,例如下面的 parseActive 方法就是判断 JSONObject 是否包含了注册信息。

.method public static parseActive(Lorg/json/JSONObject;)Lcn/dxy/android/medicinehelper/api/model/Active;

从大体的阅读源码来看,这个方法主要的功能就是解析服务器返回的 JSON 信息,然后根据返回判断是否注册。那么,我的思路就是修改方法,无论服务器返回什么都返回已经注册。

https://friable.rocks/_/2013_11_28/1385608183.png

看程序代码段中,有段为

.line 35
const-string v3, "active"

invoke-static {p0, v3, v4}, Lcn/dxy/sso/util/AppUtil;->getJsonBooleanValue(Lorg/json/JSONObject;Ljava/lang/String;Z)Z

move-result v1

.line 36
.local v1, active:Z
if-nez v1, :cond_0

.line 37
invoke-static {p0}, Lcn/dxy/sso/entity/ErrorType;->constructErrorBody(Lorg/json/JSONObject;)Lcn/dxy/sso/entity/ErrorType;

move-result-object v2

其中,有个语句 if-nez v1, :cond_0 很关键,因为这个语句下面就是错误信息了(v1 的值是 JSONOBject 过来的 activte 字段的内容)。那么可以判断,这个 if 就是主要判断语句,写成伪代码也就是

if (!active) {
    showError();
    return;
}

// Activited

所以我将这个判断的内容始终改成 true,查询 smali 的语法,简单的修改如下

if-eqz v1, :cond_0

也就是做了个相反的判断,虽然这样子正常的激活码就无法注册,但根据逻辑只要输入格式对应的激活码都可以激活了。

修改完成了以后我们需要重新打包成 apk 文件,这里还是要用到上述的 apktool 工具,做个相反的操作即可:

java -jar apktool.jar build <origin-v1.0-dir> new-v1.0.apk

注意,这时通过 apktool 生成的 apk 文件是没有经过签名的,直接 adb install 是无法
安装的,会报 INSTALL_PARSE_FAILED_NO_CERTIFICATES 错误。

因此,我们需要将其前面以后再安装,这里有 Google 相应的文档阐述如何签名 apk 包:


https://developer.android.com/tools/publishing/app-signing.html

当然使用了自定义前面的 apk 包以后您就无法安装和升级官方的 apk 包了。

https://friable.rocks/_/2013_11_28/1385608067@640.png

完成上述步骤了以后,我们安装打开已经经过修改的应用,发现随便输入任何激活码就可以完成本地激活了。

- eof -

Volley 使用笔记

Google I/O 2013 上就讲到了 Volley。当时并没还有在意这个类库,直到看了某项目的源代码后,发现这个东西值得推荐。

Volley 这个库的官方介绍是:

Volley is a library that makes networking for Android apps
easier and most importantly, faster.

不是很严谨的讲,Volley 就是个包含了很多封装功能的网络请求工具类。使用这个工具类有个优势就是可以节省很多在请求以及缓存方面的开发时间。

优势

[相比其他网络载入类库](https://github.com/nostra13/Android-Universal-Image-Loader
),Volley 的优势官方主要提到如下几点:

  1. 队列网络请求,并自动合理安排何时去请求。
  2. 提供了默认的磁盘和内存等缓存(Disk Caching & Memory Caching)选项。
  3. Volley 可以做到高度自定义,它能做到的不仅仅是缓存图片等资源。
  4. Volley 相比其他的类库更方便调试和跟踪。

基本使用

引入 Volley 很简单。使用 git 下载代码到本地

git clone https://android.googlesource.com/platform/frameworks/volley

然后引入到项目中就可以使用了。

Volley 简单的来讲主要由两个类控制:

  1. Request Queue
  2. Request

Volley 的「Hello,World」示例代码:

// 实例化 Request Queue
RequestQueue queue = Volley.newRequestQueue(context);

// 实例化 Request
String url = "<remote url>";
JsonObjectRequest jsonObjRequest =
    new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {

        @Override
        public void onResponse(JSONObject response) {
            // ...
        }
    }, new Response.ErrorListener() {

        @Override
        public void onErrorResponse(VolleyError error) {
            // ...

        }
    });

然后剩下要做的事情就是把这个 Request 扔到 Queue 里面即可:

queue.add(jsonObjRequest);

缓存图片资源

缓存图片资源 Volley 提供了个自定义的 NetworkImageView 继承自 ImageView 。它的优势就是载入远程图片几乎可以用「傻瓜」形容,例如:

mNetworkImageView.setImageUrl(imageUrl, new ImageLoader());

其中 ImageLoader 最重要的一个参数就是 ImageLoader.ImageCache 它控制是否需要请求网络获取数据。因此,我们可以将这个 Class 配合 LruCache 以及 DiskLruCache 用来内存和磁盘缓存。

主要方法

@Override
public Bitmap getBitmap(String url) {
    Bitmap data = mLruCache.get(url);
    if (data == null) {
        try {
            data = mDiskLruCache.get(key);
            if (data != null) {
                mLruCache.put(key, data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    } 

    return data;
}

这样子,就可以很清晰得把内存缓存和磁盘缓存之间的关系建立和链接起来了。

资源&参考

- eof -

使用命令行截取 Android 设备的界面

在进行 Android 开发的时候有时候需要截图,通常我的土办法就是打开 DDMS 然后再截取,这样有点不好就是效率不高每次都需要刷新然后手工去保存。

搜索了下,发现 Linux 下已经有现成的解决方案。原理就是使用使用 Android 自带的命令行 screencap 然后通过 adb 传输过来。

整条 Shell 命令其实很简单

adb shell screencap -p | sed 's/\r$//' > outputs.png

但发现在我的 Mac 无法运行。检查了以后发现是 GNU sed 和 BSD sed 命令间有不兼容的情况。我的解决方案就是使用 brew 安装 gsed(有更好的解决方案的同学欢迎指出)。

brew install gnu-sed

然后简单得修改下上面的 Shell 脚本:

adb shell screencap -p | gsed 's/\r$//' > ~/Desktop/`date +%Y%m%d%H%M%S.png`

这样子每次运行这个脚本就能把 Android 设备的截图放到桌面了,并自动命名。

UPDATE .1

原博客的作者也给出了在 Mac 下的解决方案,他是使用 Perl :

adb shell screencap -p | perl -pe 's/\x0D\x0A/\x0A/g' > screen.png

这样子对于没有安装 brew 的同学是个好消息。

-- EOF --

我的照片

嗨!我叫「明城」,八零后、码农、宁波佬,现居杭州。除了这里,同时也欢迎您关注我的 GitHubTwitterInstagram 等。

这个 Blog 原先的名字叫 Gracecode.com 、现在叫 「無標題文檔」 。 要知道作为码农取名是件很难的事情,所以不想在取名这事情上太费心思。

作为八零后,自认为还仅存点点可能不怎么被理解的幽默感,以及对平淡生活的追求和向往。 为了避免不必要的麻烦,声明本站所输出的内容以及观点仅代表个人,不代表自己所服务公司或组织的任何立场。

如果您想联系我,可以发我邮件 `echo bWluZ2NoZW5nQG91dGxvb2suY29tCg== | base64 -d`

分类

搜索

文章