Andriod 破解之道(一)

# 前言

在Root前提下,我们可以使用Hooker方式绑定so库,通过逆向方式篡改数值,从而达到所谓破解目的。然而,目前无论是软件加固方式,或是数据处理能力后台化,还是客户端数据真实性验证,都有了一定积累和发展,让此“懒技术”不再是破解修改的万金油。再者,阅读汇编指令,函数指针替换,压栈出栈等技术需要一定技术沉淀,不利于开发同学上手。

两年前,也是因为懒,很懒,非常懒,堆积了足够的动力,写了一个基于人工模拟方式,对一个特定规则的游戏进行暴力破解。我们都知道,人工模拟方式,绕过了大量防破解技术,只要还是人机交互模式,并且满足一定的游戏规则,基本是无法防御的。

以下是一段技术应用视频,以便大家对文章有个初步认识:

大家能够看到,这段一分钟的视频,在50秒的时候就刷爆了游戏分数上限,足见此技术能力并不亚于传统的Hooker篡改内存地址方式。

技术实现原理

因涉及到安全方面的考量,本文主要围绕技术实现原理和关键技术点进行阐述。

技术要求:

  1. 支持多分辨率
  2. 支持多点触摸
  3. 支持输入速率动态变更
  4. 处理能力峰值需要达到30fps

实现方式分三步:

  1. 劫持屏幕
  2. 分析数据
  3. 模拟输出

1.劫持屏幕

先说说劫持屏幕,做过截屏功能的同学应该清楚,Root了之后能访问设备“dev/graphic”文件夹,里面有fb0, fb1, fb2三个screen buffer文件。这里用到的是fb0文件。

抛出一个问题,当前主流屏幕分辨率都在1920*1080区间,一张图片的缓存能去到2M左右,要达到30fps的性能指标,光是屏幕数据的读写耗时,就满足不了要求。怎么做呢?

一般在做图像处理的时候都会想到parallel programming。然而,这里的图片是时间相关的,不适宜采用多线程任务派发。

懒人一番思量后,发现一条捷径,共享内存读取,请看以下代码。

mapbase = mmap(0, **mapsize, PROT_READ, MAP_SHARED, fd, offset);

这行代码广泛存在于各个截屏代码片段中,精髓在于PROT_READ 和 MAP_SHARED上。先科普一下mmap参数中这两个参数吧。

prot : 映射区域的保护方式。可以为以下几种方式的组合:

  • PROT_EXEC 映射区域可被执行
  • PROT_READ 映射区域可被读取
  • PROT_WRITE 映射区域可被写入
  • PROT_NONE 映射区域不能存取

flags : 影响映射区域的各种特性。在调用mmap()时必须要指定MAP_SHARED 或MAP_PRIVATE。

  • MAP_FIXED 如果参数start所指的地址无法成功建立映射时,则放弃映射,不对地址做修正。通常不鼓励用此旗标。
  • MAP_SHARED 对映射区域的写入数据会复制回文件内,而且允许其他映射该文件的进程共享。
  • MAP_PRIVATE 对映射区域的写入操作会产生一个映射文件的复制,即私人的“写入时复制”(copy on write)对此区域作的任何修改都不会写回原来的文件内容。
  • MAP_ANONYMOUS建立匿名映射。此时会忽略参数fd,不涉及文件,而且映射区域无法和其他进程共享。
  • MAP_DENYWRITE只允许对映射区域的写入操作,其他对文件直接写入的操作将会被拒绝。
  • MAP_LOCKED 将映射区域锁定住,这表示该区域不会被置换(swap)。

因为我们不需要写屏,所以prot只需要采用PORT_READ;而我们期望避免屏幕数据的多次创建,flags就需要用到MAP_SHARED,这样文件句柄fd指向的内存块数据就会实时变更,无需多次创建,拷贝,释放数据。

2.分析数据

截取到屏幕数据就好办了,对每一帧进行数据处理,这里完全就是算法问题了。懒人都用搓算法,大概的思路就是:7*7宫格,对于所有相连的两个同色item做了横向映射表和纵向映射表,然后轮寻处理5连,4连和3连。里面还有一些涉及到实现细节的映射表重置与预判,因为不是本文重点,就带过了。

void Handle_X_Combination() {

    LOGE("Handle_X_Combination");

    gen_Horizontal_Matrix(6);

    get_Horizontal_X_Match();

    gen_Vertical_Matrix(0, 6);

    get_Vertical_X_Match();
}

下面是程序运行时的Log信息片段,以供大家参考。

3. 模拟输出

算法会输出当前屏幕的一个模拟手势操作队列,最精彩的当然放到最后,也是此工程的技术点,怎么模拟输出手势的问题。

Android所给予的截屏和模拟操作分别为 adb screenshot 和 adb shell sendevent (根据android版本,有些机型用的是input event,记得没错的话~)
所有需要adb处理的指令,都不能采用高并发方式调用,要不然要么机器重启,要么指令堵塞。所以adb这条路不通。
怎么办呢?

懒人又一番思量后,linux系统大都采用文件buffer,直接将指令写文件吧。其实adb也是写文件,不过adb做了一层转译,这里涉及到设备层指令代码,不同机型定义的指令代码不尽相同。

要完成此任务,首先要弄清楚几件事情:

  1. 一个点击事件的构成是怎样的
  2. 一个滑动事件的构成多了什么
  3. 事件的指令代码分别代表什么

万能的adb给了我一些思路,adb shell getevent,会打印出当前event的指令。再科普一下,event有很多,包括compass_sensor,light_sensor,pressure_sensor,accelerometer_sensor等等。
我们这里监听的是,touchscreen_sensor。

有了上面的指导信息,要构建一个模拟操作函数就很容易了。操作屏幕打印出想要的模拟的手势,然后写下来就好了。一共会有这么几个模拟操作函数需要创建:


void simulate_long_press_start_event(int touch, int fromX, int fromY);
void simulate_long_press_hold_event(int touch, int fromX, int fromY);
void simulate_long_press_end_event(int touch);
void simulate_press_event(int touch, int fromX, int fromY);
void simulate_move_event(int touch, int fromX, int fromY, int toX, int toY);

下面给出一个我写好的范例出来,大家可以依葫芦画瓢,把剩下的写好。

void simulate_press_event(int touch, int fromX, int fromY) {

    pthread_mutex_lock(&global.writeEventLock);

    LOGE("simulate_press_event");

    INPUT_EVENT event;

    // 0. Multi-Touch
    // 此项目非必要,因为没有用到多点触摸,是另一个项目使用到了
    event.type = 0x3;
    event.code = 0x2f;
    event.value = touch;
    write(global.fd_event, &event, sizeof(event));

    // 1. ABS_MT_TRACKING_ID:
    // 理论上必要,因为Android事件输入是批量处理的,需要用到输入id,
    // 但是这里偷懒使用了同步锁,并且没有多点触摸需求,所以不会有Tracking_ID串扰问题,也就不需要记数了
    event.type = 0x3;
    event.code = 0x39;
    event.value = global.event_id > 60000 ? 10 : global.event_id++;
    write(global.fd_event, &event, sizeof(event));

    // 2. At screen coordinates:
    // 触摸点x,y坐标
    event.type = 0x3;
    event.code = 0x35;
    event.value = fromX;
    write(global.fd_event, &event, sizeof(event));
    event.type = 0x3;
    event.code = 0x36;
    event.value = fromY;
    write(global.fd_event, &event, sizeof(event));

    // 4. Sync
    // 数据同步到设备
    event.type = 0x0;
    event.code = 0x0;
    event.value = 0x0;
    write(global.fd_event, &event, sizeof(event));

    event.type = 0x3;
    event.code = 0x39;
    event.value = 0xffffffff;
    write(global.fd_event, &event, sizeof(event));

    // 4. Pure event separator:
    // 结束符
    event.type = 0x0;
    event.code = 0x0;
    event.value = 0x0;
    write(global.fd_event, &event, sizeof(event));

    pthread_mutex_unlock(&global.writeEventLock);
}

建议大家在动手写模拟输入模块之前,先仔细研读Android input事件机制,对于个人程序修为大有裨益。有时间我会单独写一个技术文档供大家参考,目前就此带过了。

调试

因为我是个懒人,能偷懒的地方都会花时间深研。以下,是个人针对本项目调试的一些懒技巧,以供各位参考。

下面是在Debug模式下生成的8张连续图片。能看到每个小宫格的右上方都打印出了当前识别的颜色。如果当前宫格需要被移动,则采用双色绘制表明移动的方向,上下双色表示需要上下移动,左右双色表示需要左右移动。

此外,调测程序的时候必不可少的就是单步回归了,以下是设计的Dummy模式,以验证Bug修复效果。

int loadImageData(const LPSTR device, GGLSurface *gr_framebuffer,
        Var_ScreenInfo vi, Fix_ScreenInfo fi, ssize_t* mapsize) {
#ifdef TEST_DUMMY
    return test_dummy("/mnt/sdcard/screenss.bmp", &gr_framebuffer, &vi, &fi);
#else
    return get_framebuffer(device, &gr_framebuffer, &vi, &fi, &mapsize);
#endif
}

至此,主要关键技术已经简述完毕,谢谢大家。

# 后记

大家如果仔细看了这篇文章,会发现视频中的游戏版本,和截屏图片的版本是不一致的。视频是我在13年的时候录的,截屏是因为KPI考核要求写文章,临时又生成一遍的,所以会有版本差异。做这个技术的初衷就是因为懒,才想到虐爆Android的。从开始到第一个demo出来,大概花了一周的时间,因为思路都比较清晰,后续的优化反而花了一个多月,包括防破解这块(总不能出个破解然后被人爆菊吧,太侮辱智商了)还是需要仔细走读一下底层实现。其中也请教了当时公司安全部的哥们,知道了更多关于软件实现机制,也深知安全的重要性,所以这段代码一直只存留在我的代码实验室,以前不会,现在不会,以后也不会开源发布,所以请各位海涵了。有兴趣的同学可以通过自己的努力实现一遍,对个人技术的提高会有很大帮助。

这篇技术文档的确只覆盖了一些关键技术节点,还有较多和当前程序不相关的技术并没有被涵盖,例如底层加固技术,动态底层Binary Dex加载技术(在Art下需要有一定的修改,懒,没有去深挖了),so库混淆,屏幕同步,模拟输入同步等,往后有时间再行一一简述吧。

时间: 2024-11-08 18:49:21

Andriod 破解之道(一)的相关文章

Java的破解和反破解之道

破解 java字节码能够很容易被反编译大家都晓得啦, 今天下午我为了得到一个心仪已久的jbuilder opentools(昨天1.0 Released,新鲜出炉!但只能用14天,这怎么行~@@#!@#!#@!@#%%^@,少说也要140天嘛!),于是我不惜放下其他工作,研究了一把该软件加密方法的破解和反破解,结合以前的一些经验,作文一篇与大家共飨,并不是鼓励大家...破解之道:如今市面上的java obfuscator很多(可以从google分类中列出)比较著名的有4thpass的产品(呵呵,

Android 破解之道 (二)

前言 在这篇文章,我们来讨论一下基于Android系统多缓存文件方式截屏的一些事.< 破解之道(一)>开篇介绍了基于Root环境截屏的技术,使用这种方式获取屏幕数据是快捷而便捷的.然而,大家先不要开心太早,此中却有两个系统级问题,很少有文章涉猎讨论,在此向大家详细解说一下. SurfaceFlinger 简述 下面这张截屏图片包含了较多信息,大家在往下阅读前,请稍微思考一下. 从截屏中读取的信息大概归纳如下,欢迎大家友情补充: 系统应该是分屏刷新的,能看到切分了三块区域 系统应该有个一刷新完成

混合云或许是破解之道

互联网的冲击从金融.制造.连锁型企业等向所有的行业蔓延."积极进行互联网变革是找死,等着互联网冲击来是等死",如何才能不死?传统企业需要回答这个问题,传统企业的信息化部门更需要回答这个问题,因为互联网对传统行业的冲击最先体现在这个部门,苏宁云商云技术开发中心总监金龙说,完成互联网转型难度并不亚于创业本身. 前不久,由浪潮集团主办.广东省网商协会协办的2014年互联网应用技术峰会(IATS)2014在广州举行.网易.搜狐.奇虎等互联网企业的技术负责人:互联网转型较为成功的传统企业,如苏宁

实达交换机密码破解之道

一,网络环境: 公司使用实达的3500系列(具体型号是3548)交换机,在交换机上面连接了一台华为2621路由器,通过电信的光纤上网.由于忘记密码,因此要试图破解它的密码. 二,准备工作: 由于整个工作需要断网,毕竟涉及到重新启动交换机等操作,所以选择时间在工作下班后的晚上23点.另外由于破解密码这类操作都必须使用CONSOLE控制台线来设置,所以地点只能是中心机房.笔者找到了实达3548设备的所有相关工具,包括安装说明与CONSOLE控制线等. 三,实战破解密码: 根据笔者以往经验实达所有设备

云计算安全:专家谈云中的密码破解之道

对于那些在短期内需要一些计算容量,但又不想在固定资产方面长期投资的企业来说,随需提供的云计算是一种非常神奇的工具.由于相同的原因,云计算对于黑客来说也非常有用-- 很多黑客活动都牵涉到口令.密钥破解,以及其它形式的暴力解破,所有这些活动需要的都是昂贵和高度并行的计算. 对于黑客来说,随需的计算资源有两个主要来源:由消费者PC构成的僵尸网络和服务商提供的基础设施即服务(IaaS).每种形式都可以提供暴力计算所需的随需计算能力.僵尸网络的可靠性较差,并且采用异型设备,"提供服务"所需的时间

大数据的五大误区及其破解之道

&http://www.aliyun.com/zixun/aggregation/37954.html">nbsp;     有些人认为,"大数据"这一词汇不过是企业营销时的大肆炒作.但即使是那些接受大数据概念的人,也需要消除某些大数据误区. 全球领先的信息技术研究和咨询公司Gartner指出,大肆宣传大数据概念,使企业在选择适当的行动方案时,受到更多困扰,但对消除一些仍存在的误区却毫无帮助. 例如,80%的数据是非结构化的,这是错误的:又如高级分析功能只是更复

智慧交通难题破解之道在公共服务创新

随着物联网和大数据等技术的成熟普及,智慧城市正在加快融入每个人的生活.住建部统计,我国已有广州.深圳和天津等一线.二线400多个城市宣布建设智慧城市,覆盖东.中.西部地区,其中,"智能交通"是被普遍看好的细分领域. 智能交通行业是目前智慧城市建设投资最大.覆盖范围最广的领域,交通运输部相关规划中提出,到2020年,智慧交通领域总产值规模将超过千亿元.今年年初,北京市十四届人大五次会议举行的"建设和谐宜居之都"新闻发布会透露,北京今年将建成并投用缓解交通拥堵信息系统,

多维防护:虚拟化安全挑战的破解之道

在"云"大行其道的时代,虚拟化正在成为企业IT基础架构管理的标配.然而,凡事有一利必有一弊,云计算与虚拟化并非完美无缺的技术,虚拟化的"另一面",是新的安全威胁.如今网络上的恶意代码数量呈现几何倍数的增长,平均1秒钟就会有一个新的网络安全威胁产生,每5分钟就会发生一起网络入侵行为,高级威胁随时都可能感染数据中心平台.根据市场调研机构Gartner报告显示,虚拟化数据中心面临比传统数据中心更大的安全挑战! 虚拟化给安全带来重重挑战 挑战一:防病毒系统资源消耗严重 传统

阿里技术协会(ATA)11月系列精选文集

JAVA核心技术 1.面向GC的Java编程 2.JVM飙高排查脚本-结构分析 3.理解Java NIO 4.杜绝假死,Tomcat容器做到自我保护,设置最大连接数 5.Groovy与Java集成常见的坑 6.java 深拷贝探讨 分布式计算 1.jstorm 介绍 2.Spark的调度策略详解 3.生活中的Paxos,原来你我都在使用--对Paxos生活化的解读(一) 4.生活中的Paxos,原来你我都在使用--对Paxos生活化的解读(二) 5.消息中间件MetaQ高性能原因分析 大数据 1