android客户端故障模拟总结

1) 资源类故障模拟方案

资源类故障,主要是指操作系统本身资源可能存在的故障,例如高负载状态、低可用状态等等,其目标是观察客户端在可用资源异常情况下的可用性,下面分为几大类进行介绍:

cpu高负载模拟

cpu高负载模拟,主要指通过各种方式提高cpu的使用率,以达到高负载场景的测试需要。

可选工具
  • stress
  • itest
  • solopi

在实现原理上,itest和solopi的实现,是基于函数循环计算的,属于计算密集型的模拟;而stress的实现较为多样,既有基于函数循环计算、不断切换线程、也有不断申请资源释放等方式;itest和solopi只能基于Android环境测试,stress则可以在linux平台使用。

在操作方式上,stress主要通过终端cli方式调用,而其余两种则通过安装apk,并在应用界面操作的方式执行。

由于stress基本涵盖了并扩展了其他工具的功能,这里重点介绍该工具。

stress基础说明:

#stress
`stress' imposes certain types of compute stress on your system

Usage: stress [OPTION [ARG]] ...
 -?, --help         show this help statement
     --version      show version statement
 -v, --verbose      be verbose
 -q, --quiet        be quiet
 -n, --dry-run      show what would have been done
 -t, --timeout N    timeout after N seconds
     --backoff N    wait factor of N microseconds before work starts
 -c, --cpu N        spawn N workers spinning on sqrt()
 -i, --io N         spawn N workers spinning on sync()
 -m, --vm N         spawn N workers spinning on malloc()/free()
     --vm-bytes B   malloc B bytes per vm worker (default is 256MB)
     --vm-stride B  touch a byte every B bytes (default is 4096)
     --vm-hang N    sleep N secs before free (default none, 0 is inf)
     --vm-keep      redirty memory instead of freeing and reallocating
 -d, --hdd N        spawn N workers spinning on write()/unlink()
     --hdd-bytes B  write B bytes per hdd worker (default is 1GB)

Example: stress --cpu 8 --io 4 --vm 2 --vm-bytes 128M --timeout 10s

Note: Numbers may be suffixed with s,m,h,d,y (time) or B,K,M,G (size).
-? 显示帮助信息

-v 显示版本号

-q 不显示运行信息

-n 显示已完成的指令情况

-t --timeout N 指定运行N秒后停止

--backoff N 等待N微妙后开始运行

-c 产生n个进程 每个进程都反复不停的计算随机数的平方根

-i 产生n个进程 每个进程反复调用sync(),sync()用于将内存上的内容写到硬盘上

-m --vm n 产生n个进程,每个进程不断调用内存分配malloc和内存释放free函数

--vm-bytes B 指定malloc时内存的字节数 (默认256MB)

--vm-hang N 指定在free钱的秒数

-d --hadd n 产生n个执行write和unlink函数的进程

-hadd-bytes B 指定写的字节数

--hadd-noclean 不unlink

时间单位可以为秒s,分m,小时h,天d,年y,文件大小单位可以为K,M,G

更加详细的命令说明可直接参考如下链接:stress工具使用指南和结果分析

低可用故障模拟

低可用故障,主要模拟低电或高温下cpu锁频的情况,该操作需权限较高,因此需要对设备进行root处理。

root后,可以通过直接修改配置文件的方式施行,但更建议通过安装专业的系统工具箱,例如镧系统工具,在图形化界面进行配置。

mem资源故障

高负载故障模拟

mem的高负载故障,同样可使用cpu的高负载故障工具模拟,下面介绍下其中的不同。

在内存申请上,这三者均是通过c的malloc函数请求分配,但在逻辑实现上,itest和solopi侧重于内存的一直占用,其判断逻辑会预先评估出系统还剩多少运存可供分配,在实际请求分配时,也不会超过这个限制进行请求,并且除非手动停止,内存不会主动释放;

而stress则需要预先查看设备剩余内存,再通过参数进行申请;此外,在使用方式上,默认的参数值,是一个循环请求-释放的方式,如果需要保持内存的持续占用,需要加上--vm-hang参数,该参数代表保持内存申请后多久才释放掉,单位是秒。

典型的stress申请内存占用的命令参考如下:

stress --vm 1 --vm-bytes 1G --vm-hang 50 --timeout 50s
低可用故障模拟

对mem的高负载故障强调系统mem资源被极限占用,而对低可用故障而言,则是只分配给应用固定的较低的使用值。

其故障模拟方式可以通过shell ulimit命令完成,首先建立一个shell进程,再执行ulimit -Sv memsize对该进程进行虚拟内存的限制,再通过该进程打开目标应用,就完成了对目标应用的内存限制。

io资源故障

io的高负载故障,主要测试高iowait的环境下,应用是否稳定。

其故障模拟方式可以通过stress模拟,典型的负载模拟指令参考如下:

stress-ng -i 1 --hdd 4 --timeout 600

-i参数指定系统启动几个进行执行io任务,任务内容为调用sync(),它表示通过系统调用 sync() 来模拟 I/O 的问题,刷新内存缓冲区的数据到磁盘中,以确保同步。

为保证产生足够的io压力(如果缓冲区内本来就没多少数据,那读写到磁盘中的数据也就不多,也就没法产生 I/O 压力),还需要在加一个-hhd参数,循环执行磁盘write/unlink的操作。

disk资源故障

对disk资源而言,故障类型主要是no space,即低或无可用空间,通常我们采用使用dd命令占满可用空间的方式模拟,但需要注意的是,android本身对可用空间是存在保护策略的,无法一次性完完全全的占满。

dd命令的使用方式如下:

dd if=/dev/zero of=/mnt/sdcard/bigfile

使用此命令在手机/mnt/sdcard/目录下生成一个超大文件,直至填满整个手机存储空间。

上面的这种方式兼容性较好,但因为通过io写入文件实际填充,故速度较慢;除了这种方式外,还有一些方式通过分配块并将其标记为未初始化来快速完成预分配,而无需对数据块进行任何IO操作,几乎可瞬间填充空间,但是各家rom和硬件支持度不一,需要实际尝试;实际运用中,可先尝试以下命令,无效后改用上面的dd方式。

需要注意的是,以下命令中的示例参数50G,并非被测设备磁盘余量,比磁盘全部空间大的任意数值均可。

命令如下:

1、fallocate -l 50G big_file

2、truncate -s 50G big_file    

3、dd of=bigfile bs=1 seek=50G count=0

网络资源故障

网络资源故障主要通过模拟异常的网络环境,例如弱网环境、丢包环境、高延迟、断网等等,这里推荐一个工具,实践中可较全面的模拟比网络环境,来自腾讯的Qnet。

其底层原理是vpn service,通过vpn代理转发数据并按规则模拟流量出入方式;其使用方式为,apk安装,ui界面中配置,较为便捷。

需要说明的是,该工具只适用于允许流量通行vpn的应用,如果在应用内做了vpn相关判断并不允许流量走vpn,则该方式不可行。

2) 程序类故障模拟方案

程序类故障主要指对客户端本身的逻辑、状态、操作等进行故障模拟,同样按照以下几大类进行介绍。

网络数据包fuzz

网络数据包fuzz主要指通过对客户端请求和服务端响应的拦截,并加以一定的随机替换规则进行替换,观察异常数据下客户端的可用性。

例如,我们可以将所有页面展示的数据,替换为随机长度、空值、异常字符等,观察页面展示是否符合需求。

目前有两种方式可以达到目的:

代理类拦截替换

代理类的拦截替换原理类似中间人攻击,通过代理层拦截数据包,并根据我们自定义的规则替换后重新发出/接收,此类代表性的工具有:

  • fiddler
  • anyproxy
  • BurpSuite
  • 。。。

以上工具均可以自定义脚本完成对数据包的规则性fuzz。

hook类拦截替换

hook类的拦截替换原理是通过对通用网络类库方法的劫持,替换函数的输入输出参数,从而达到变相替换数据包的目的。

此类代表性的工具有

  • taichi
  • xposed
  • frida
  • 。。。

其中,除frida的使用方式是pc-device外,其余两种均可以应用的形式工作。

需要说明的是,不论是代理类还是hook类,均有其缺陷性:

对代理类来说,android7以上的版本里,无法做到对https的拦截解析(如果应用只信任系统证书),解决办法是应用内将信任证书改为代理工具颁发的证书,或者通过root将代理工具颁发的证书转换并置为系统证书信任;或者android工程内配置信任文件;

对hook类工具而言,需要较高的权限执行,因此需要root环境,且项目使用的网络类库、版本不尽相同,导致兼容性问题较大。

关键函数fuzz

关键函数fuzz是指,在客户端运行过程中,根据实际需要,对关键业务的关键函数进行hook,并根据随机规则fuzz其输入或者输出值,从而验证客户端在业务逻辑异常情况下的可用性。

依旧可以使用hook工具taichi、xposed、frida进行hook操作。

权限随机开关

对客户端而言,权限也是比较重要的点,我们可以在客户端运行的过程里,通过adb命令来动态的授予或者移除对应用的权限,测试客户端的可用性,其命令如下:

授予权限:

adb shell pm grant packagename permission

移除权限:

adb shell pm revoke packagename permission

随机操作测试

随机操作测试主要通过monkey工具进行,通过指定packagename持续运行monkey,观察客户端在长时间随机操作下的可靠性。

Intent fuzz

Intent fuzz主要通过遍历应用获取到的Activity、BroadcastReceiver、Service、Instrumentation、ContentProvider,并通过Intent尝试启动所有可以获取到的组件,从而测试客户端是否存在不应有的安全漏洞。

推荐故障模拟工具IntentFuzzer,其使用方法为,安装apk,在ui化的界面上选择所选目标,并按照有参/无参的方式展开intent遍历。

你可能感兴趣的:(android客户端故障模拟总结)