移动端测试 - 如何快速的开发一款测试小工具

最近在测试一些需求时感觉额外的费力,例如快速构建非重复性请求+统计结果。通过手动操作应用的方式触发请求,不但需要修改代码,还得配置相应的测试环境。使用抓包软件修改请求又需要重新计算签名,否则会导致校验失败。综上种种,需要开发一款定制的工具来辅助进行测试。

项目是以Android客户端的请求为基础,所以设计的思路是用java写一个简单的GUI并处理数据,这样更方便修改请求。native层负责签名,最后将项目打包成jar直接使用。

主要步骤如下(本文环境均在macOS Mojave系统):

1、Intellij IDEA通过GUI Form创建图形界面
2、Java层处理数据
3、C实现加密算法并编译成动态库
4、项目打成jar包
5、jar包调用动态库
6、Obfuscator-LLVM(ollvm)混淆

一、开发简单的GUI交互界面

页面布局极为简单,这里用Intellij IDEA通过GUI Form创建图形界面的方式实现。

1、创建新的GUI Form

项目中File -> New -> GUI Form

2、绘制布局

在右侧点击控件,然后再点击想要放置的位置,就可以添加控件了,控件的属性可以在左侧的窗口中设置,例如preferredSize等等。

3、跳转到绑定的class

选中一个控件,使用快捷键 fn + F4 跳转到Form绑定的class类。

4、初始化界面

选中panel,快捷键⌘N键Generate,点击上图中的Form main(),即可创建main() 并且初始化界面。

5、运行

Run一下Main()就可以看到我们创建的GUI了。接下来就是设置各种监听事件和逻辑处理。

二、处理数据

1、Java工程导入JSONObject

处理服务端返回的数据时需要用到json库的相关方法,因此需要导入库。

这里直接从Git下载https://github.com/stleary/JSON-java,在工程中新建package -> org.json,然后把所有文件拷贝org.json目录下,就可以使用了。

2、Java调用CURL命令

原始数据的采集是curl格式,偷点懒代码中也是直接调用curl命令。

开始的时候,直接把整个curl命令字符串传了进去,但是总是不能顺利执行。后面查了下资料,需要把curl命令切割成数组,再执行才能成功。

# 错误的演示
String curl = "curl xxxxx";
Process process = Runtime.getRuntime().exec(curl);

# 正确的演示
String[] cmd = {"curl", "-H", "Host: www.xxx.com"};
Process process = Runtime.getRuntime().exec(cmd);

3、巧用正则表达式处理数据

上面说到要把原始的curl命令拆成数组,这里就需要正则上场了。

仔细观察curl命令,发现可以按照空格来切割字符串。唯一需要注意的是单引号内的空格需要保留,以免破坏某些诸如设备信息等数据的格式。这里有个取巧的方法,既然需要按照空格拆分又不能拆分单引号里面的内容,那么可以把单引号之外的空格全部替换为某个字符,然后按照这个特定字符再切割curl命令就可以了。

匹配单引号之外的所有空格

# 伪代码
 regex = " (?=([^']*['][^']*['])*[^']*$)";
 command.replaceAll(regex, "awsomeReg");
 String[] curl = command.split("awsomeReg");

三、Java调用动态库

1、调用动态库

在Java中调用动态库也很单,使用System.load(file name)或者System.loadLibrary(lib-name)。但是这两种方法都不够灵活,后面还会再讲到。

2、编译动态库文件

加密算法是在Android native实现的,动态库也是基于arm的,所以不能直接在mac上使用,需要手动重新编译一下。得益于mac系统的便利性,省去了很多环境配置的麻烦。

首先生成.h文件,接下来可以用gcc来进行编译,编译成功后会生成libxxx.jnilib文件,这个就是我们能够通过java直接调用的动态库了。

但是这样编译的话第一次会报缺少jni_md.h的错误。不过不用担心,这个问题很好解决,把对应的.h文件拷贝到jdk的include目录就好了。

四、Intellij Idea将Java项目打成jar包

总体上只需要四步就能完成打包了:

1、菜单:File->project stucture
2、在弹窗最左侧选中Artifacts->"+",选jar,选择from modules with dependencies,然后会有配置窗口出现,配置完成后,勾选Build on make >ok保存
3、然后菜单:Build->make project
4、最后在项目目录下去找输出的jar包(路径在你添加Artifacts的时候设置的路径)

五、jar包调用动态库

这里有很多坑,运行jar的时候会发现,无法直接加载Jar包中的动态库。

这与JVM的一个系统变量有关,可以通过打印System.getProperty("java.library.path")查看。我们在任意一个目录执行jar文件的时候,系统实际上是找不到这个libxxx.jnilib(so,dll等等)动态库文件的。为了方便,我们又不可能同时提供一个jar文件和一个动态库,这样太傻了。

回过头来看System.load(String filename)这个方法,它是从本地文件系统中以指定的文件名加载代码文件,并且文件名参数必须是完整的路径名。所以我们可以在执行jar的时候,通过流的形式写出动态库到本地,然后再加载调用。

    static {
        try {
            InputStream in = Your.class.getClassLoader().getResourceAsStream("libxxx.jnilib");
            File ffile = new File("");
            String filePath = null;
            filePath = ffile.getAbsolutePath() + File.separator
                    + "libxxx.jnilib";
            File jnilib = new File(filePath);
            FileOutputStream out = new FileOutputStream(jnilib);
            int i;
            byte[] buf = new byte[1024];
            try {
                while ((i = in.read(buf)) != -1) {
                    out.write(buf, 0, i);
                }
            } finally {
                in.close();
                out.close();
            }
            System.load(jnilib.getAbsolutePath());
            jnilib.deleteOnExit();
        } catch (Throwable e) {
            try {
            } catch (Throwable ee) {
                throw ee;
            }
        }
    }

这样,我们只需要一个jar文件,就可以搞定所有事情了。运行一下jar包,在json中把version改为0.1,然后提交。可以成功的看到服务端的返回数据,说明修改的请求已经通过服务端的校验。

通过这个小测试工具,可以脱离客户端做一些实时的网络请求;也可以针对特定的接口做边界值的验证;还可以做一些安全和渗透测试等等。

对于批量甚至是组合的请求,虽然GUI不能满足,但是利用工程本身却非常容易实现。例如我需要测试一个推荐策略(100页不能有重复内容),那么至少得刷上百次带翻页接口,手动完成该任务并记录结果显然不太现实。但是利用工程就容易的多,修改请求分页数据的参数,再记录返回值并对比有无重复就可以了。

所以从这里我们看出,最关键的地方不在于数据怎么组织,而是如何进行校验,也就是所谓的sign值。Java由于其容易被反编译,现在的应用已经几乎没有再把签名算法放在java层了,都统一交给了native层去做。但是需要注意的是,native代码如果不进行混淆加密,也是非常容易被反编译的。接下来就聊聊native代码的保护。

六、Obfuscator-LLVM(ollvm)混淆

我们都知道java代码容易被反编译,为了让反编译后的代码难以读懂,通常采用混淆的方式。但即使这样,一些关键的代码也难以隐藏。例如之前分析的某app协议,通过反编译工具能够清晰的看到被还原的代码。

同样的,native代码也可以被反编译。如下图所示,虽然易读性要差一些,但关键的逻辑方法都能看到,甚至加密的key也能读到。懂一点点汇编语言就能摸清程序的执行流程,会动态调式的更加毫无阻拦。由此可见native代码的安全性也不容忽视。

Obfuscator-LLVM就是这样一个项目,它旨在提供一套开源的针对LLVM的代码混淆工具,以增加对逆向工程的难度。虽然官方的版本只更新到4.0版本 LLVM-4.0,但是一些大神在此基础上做了更新和移植。这里我们采用一个移植好的版本https://github.com/heroims/obfuscator,该作者fork原版后又加入了llvm5.0,6.0,7.0以及swift-llvm5.0的版本,并扩展了一些功能。这些已经足够满足当前项目的需要了。

七、macOS配置ollvm环境

介绍完ollvm,接下来就讲下如何在macOS配置ollvm环境。

1、下载LLVM

直接下载整理好的移植版本,我选则了llvm-8.0的版本。https://github.com/heroims/obfuscator/tree/llvm-8.0

2、编译

解压缩zip后,进入目录新建一个build目录,然后按照下面的命令编译。

mkdir build
cd build
#如果不想跑测试用例加上-DLLVM_INCLUDE_TESTS=OFF 
cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_CREATE_XCODE_TOOLCHAIN=ON ../obfuscator/
make -j7
3、使用

原版ollvm中提供了3种混淆方式,分别是:

-mllvm -fla:控制流扁平化
-mllvm -sub:指令替换
-mllvm -bcf:虚假控制流程

大神移植的时候又扩展了一个字符串混淆方式,-mllvm -sobf 字符串加密,可以丰富我们的使用场景。

直接使用编译的二进制文件

build/bin/clang test.c -o test -mllvm -sub -mllvm -fla -mllvm -bcf

也可以重新编译

/build/bin/clang  -shared -fPIC you.c you2.c -o libxxx.so -mllvm -sub -mllvm -sobf -mllvm -fla -mllvm -bcf

最后我们看下效果,混淆前:程序的流程非常清晰明了。

混淆后:流程加入了大量干扰的模块,并且字符串也是加密的,极大的提高了静态分析的难度。

至此,这个小工具就算完成了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,688评论 1 330
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,559评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,749评论 0 226
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,581评论 0 191
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,741评论 3 271
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,684评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,122评论 2 292
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,847评论 0 182
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,441评论 0 228
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,939评论 2 232
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,333评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,783评论 2 236
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,275评论 3 220
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,830评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,444评论 0 180
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,553评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,618评论 2 249