i春秋作家:HAI_

原文来自:https://bbs.ichunqiu.com/thread-41371-1-1.html

说明

拿到一个CreakeMe,写一个分析思路。CreakMe主要是对.so文件内容进行分析,当然很多学习Android逆向的在分析到smali代码的时候就已经停止脚步了。在接触到.so文件的时候才是开始进一步的逆向学习,当然这里就要学习ARM汇编了。关于ARM汇编在网上有很多的资料,这里就不再赘述。

导航

请使用:HAI手册

0×01 分析逻辑

1.初始界面

2.输入数字

3.输入字符

4.总结

尝试使用App得出这些结论。
1.我们需要一个key。
2.这个key是数字。

0×02 java层逻辑分析

逆向拿到smali代码。
工具:Android Killer。

1.逻辑分析

找到入口MainActivity。

我们看到这里有一段代码:

这段代码的作用就是调用so文件库。我们猜测这个App很有可能把关键key写在了so文件里。

我们从onClick方法定位到关键点。

这里是判断正误的地方,这里看到如果v0和v2的值不相等的话就跳转。并且这里v2的值是1。

我们向上看。

这里有一个调用方法。

在这里我们看到这个是Native层的方法。并且这个方法会返回一个int数据,这里猜测可能会是0或者1。在这里还有一个就是传入的是一个int型数据,根据我们之前的测试,知道这里就是我们从输入框输入的内容。

2.逻辑图猜测

监听事件——输入key——key方法判断——返回0或1

1为正确,0为错误。

但是我们依然没有找到Key的是指内容。

0×02 Native层分析

so逆向
使用工具:ida

1. key方法分析

找到关键的Key函数。

这里可以看到ARM汇编比smali难的可不是一个度两个度。

为了提升能力,我们还是一句一句的分析。如果是学习的话,请不要依赖F5。

PUSH            {R7,LR}

把R7寄存器和LR入栈。

R7的含义就是指向前一个保存的栈帧和链接寄存器在栈上的地址。

这里可能会对LR的作用不知道,简单的说一下,LR的作用一个是保存子程序的返回地址。还有一个是当异常发生时,LR中保存的值等于异常发生时PC的值减4。LR相当于是一个备份。

MOV             R7, SP

这里的含义就是标志着caller栈帧的结束及callee的栈帧的开始。相当于是参数准备就绪,我们可以开始执行程序了。

SUB             SP, SP, #0x20

这里是给子程序开辟空间。

以上三步结束的时候ARM开始调用部分就结束了。

MOV             R3, R2

R2的值给R3。

MOV             R12, R1

R1的值给R12

MOV             LR, R0

R0=LR。

STR             R0, [SP,#0x28+var_10]
STR             R1, [SP,#0x28+var_14]
STR             R2, [SP,#0x28+var_18]

这三句一起看,意思就是把R0,R1,R2放入栈中。位置分别是,18,14,10。

LDR             R0, [SP,#0x28+var_18]

把栈上10位置的内容拿下来给R0寄存器,我们栈上10的位置是R2。相当于是R0=R2。

MOVS            R1, #0x80

R1赋值为80,这里movs和mov的区别在于movs会更改N,Z,C标志。N=0代表整数或者0,N=1代表是整数。此时R1>30,所以N为0。Z表示运算结果。R1不为0则z=1;C标志位一般不会通过加减改变。

STR             R0, [SP,#0x28+var_1C]

把R0的内容放在栈C。

MOV             R0, R1  ; int

R1的值给R0。

STR             R3, [SP,#0x28+var_20]

R3的值原本为R2,这里把这个值放在栈8。

STR.W           R12, [SP,#0x28+var_24]

把R12的值放入栈4中。
这里的.W 是wide。指定汇编器必须为这条指令选择一个32位的编码模式。如果办不到,汇编器报错。

STR.W           LR, [SP,#0x28+var_28]

LR存入栈0中

BLX             j__Z2uri

跳转到 j__Z2uri。这里的注释是ur(int),说明这个函数原型是ur(int)

 LDR             R1, [SP,#0x28+var_1C]

这里把栈c里的内容放到R1中。这个时候其实我们拿到是我们输入的key。

CMP             R1, R0

然后用我们的key        和R0进行比较,这里的R0是最后ur的返回结果。

BNE             loc_4490

不一样跳转loc_4490

B               loc_448A

否则跳转到loc_448A

这里我们就知道了关键方法就是ur(int)这个了。

最后我们来看一下流程图。

2.ur(int)方法分析

说真的。。。分析这个是真的累,不过进步起来还是非常快的。

2.1 第一段分析

PUSH            {R7,LR}
MOV             R7, SP
SUB             SP, SP, #0x28

这三行之前说过,相当于ARM在准备阶段。

MOV             R1, R0
STR             R0, [SP,#0x30+var_C]
LDR             R0, [SP,#0x30+var_C]
STR             R0, [SP,#0x30+var_10]

这一小部分完成之后的效果就是,R1=R0,栈24的部分存为R0,并且给R0重新复制为栈20

LDR             R0, [SP,#0x30+var_C]

把R0从栈24拿出来

STR             R0, [SP,#0x30+var_14]

然后把R0的值给栈2C的位置。

这里我们先来看一下流程图。

如果之前自己分析过循环的话就知道这个肯定是一个循环逻辑。而且再循环里还嵌套了循环和if语句。

MOVS            R0, #2

把立即数2赋值给R0。

 STR             R0, [SP,#0x30+var_18]

把2这个立即数给栈18位置。

STR             R1, [SP,#0x30+var_1C]

我们的R1原本是R0的值,现在把R1的值给栈14位置。

B               loc_42E2

无条件跳转到loc_42E2。

目前位置,总结一下,相当于写了

i=2
sp[5]=128

来看loc_42E2部分。

LDR             R0, [SP,#0x30+var_18]

从栈18中拿到立即数#2。并且给R0。

MULS            R0, R0

将两个理解书相乘。现在状态R0=R0*R0,R0=4;

LDR             R1, [SP,#0x30+var_14]

从栈1C中拿出数据,这里的数据之前存的是R0的数据,R0则是128。这里有一个小疑问,为什么这里不从栈14出拿数据。

CMP             R0, R1

比较R0和R1

BGT             loc_433E

如果大于则跳转loc_433E

B               loc_42EE

否则跳转到loc_42EE

这个时候我们来再看看流程图。

主要看框起来的内容,这里有一个分支结束了,证明这一个部分结束了。
而另外一边则会返回loc_42E2,这说明什么情况,这个就是典型的for循环。
如果之后有需要就对所有可能出现的状态逻辑图进行一个梳理。

我们这里先来分析一下 loc_42EE部分。

LDR             R0, [SP,#0x30+var_14]

从栈1c处拿到数据。此时栈1c出存的数据是128。16进制显示为80

LDR             R1, [SP,#0x30+var_18]

从栈18处拿到数据,此时栈18存储的内容是2。

BL              sub_13FCC

跳转到sub_13FCC,并且保存下一条的地址,可以使用mov PC,LR返回原处。

我们先来看sub_13FCC这个子程序。

CMP             R1, #0

R1和立即数0进行比较。我们来确定一下R1的数值。

BEQ             loc_13FBA

如果相等则跳转loc_13FBA

PUSH.W          {R0,R1,LR}

把R0,R1,LR入栈

BL              sub_13F0C

跳转sub_13F0C,保存LR。

之后还有很长一串,这里有兴趣的可以继续分析下去。这里直接说明结果就是对128进行取余操作。

128%i

我们还是回到之前的ur方法处继续分析。

CMP             R1, #0

比较我们取余的结果。

STR             R0, [SP,#0x30+var_20]

把R0的值放入栈10,R0的值是128

BNE             loc_4334

如果不相等,则跳转至loc_4334。

B               loc_42FE

否则跳转loc_42FE

如果是跳转到loc_4334。

直接进入第二次循环。

如果是跳转到loc_42FE,则进行深一层次的判断。

2.2 小结

总的来说这个CreakMe是这样子的

for(int i;i*i<128)
{
        if(128%i==0)
        {
                while()
                {
                }        
        }
}
if()
{ }
return ...

整体逻辑结构就是这个了。如果在这个时候进行动态分析的话,也可以很轻松的解决。

经过一些分析,发现这个CreakMe是在进行一个欧拉函数的计算。

就是在计算一个数的和这个数互质的个数。

这里也可以确定到128就是其中内嵌的一个欧拉函数。

那我们很简单自己写一个欧拉函数的计算方法就可以了。

0×03 注册机编写

所谓的注册机,就是根据一定的逻辑来推算出正确结果。

这里我们需要写一个程序来完成欧拉函数的计算。

int oula(int number)
{
    int res=number;
    int a=number;
    for(int i=2;i*i<=a;i++)
    {
        if(a%i==0){
            res=res/i*(i-1);
            while(a%i==0) a/=i;
        }
    }
    if(a>1) res=res/a*(a-1);
    return res;
}

最后128的欧拉函数结果是64。

输入之后

以上

i春秋推出优享会员制,开通会员可以免费畅享多类课程、实验、CTF赛题等付费内容,并可享有包括会员日专属福利、就业推荐等多种特权福利,更多活动详情可点击:https://bbs.ichunqiu.com/thread-40795-1-1.html了解哦~

so静态分析进阶练习——一个CreakeMe的分析思路的更多相关文章

  1. 框架源码系列四:手写Spring-配置(为什么要提供配置的方法、选择什么样的配置方式、配置方式的工作过程是怎样的、分步骤一个一个的去分析和设计)

    一.为什么要提供配置的方法 经过前面的手写Spring IOC.手写Spring DI.手写Spring AOP,我们知道要创建一个bean对象,需要用户先定义好bean,然后注册到bean工厂才能创 ...

  2. enode框架step by step之框架要实现的目标的分析思路剖析1

    enode框架step by step之框架要实现的目标的分析思路剖析1 enode框架系列step by step文章系列索引: 分享一个基于DDD以及事件驱动架构(EDA)的应用开发框架enode ...

  3. 多线程_java多线程环境下栈信息分析思路

    导读:Java多线程开发给程序带来好处的同时,由于多线程程序导致的问题也越来越多,而且对问题的查找和分析解决对于菜鸟程序原来是是件头疼的事.下面我就项目中使用多线程开发程序过程中遇到的问题做详细的分析 ...

  4. Android闪屏问题的分析思路

    http://www.devba.com/index.php/archives/6157.html  Android闪屏问题的分析思路 作者:孤风一剑   发布:2015-01-22 12:35   ...

  5. 实用教程!SPSSAU验证性因子分析思路总结

    验证性因子分析,是用于测量因子与测量项(量表题项)之间的对应关系是否与研究者预测保持一致的一种研究方法.尽管因子分析适合任何学科使用,但以社会科学居多. 目前有很多软件都可以非常便利地实现验证性因子分 ...

  6. Java应用性能瓶颈分析思路

    1 问题描述 因产品架构的复杂性,可能会导致性能问题的因素有很多.根据部署架构,大致的可以分为应用端瓶颈.数据库端瓶颈.环境瓶颈三大类.可以根据瓶颈的不同部位,选择相应的跟踪工具进行跟踪分析. 应用层 ...

  7. 【性能测试】常见的性能问题分析思路(二)案例&技巧

    上一篇介绍了性能问题分析的诊断的基本过程,还没看过的可以先看下[性能测试]常见的性能问题分析思路-道与术,精炼总结下来就是,当遇到性能问题的时候,首先分析现场,然后根据现象去查找对应的可能原因,在通过 ...

  8. 【jvm】09-full gc分析思路

    [jvm]09-full gc分析思路 欢迎关注b站账号/公众号[六边形战士夏宁],一个要把各项指标拉满的男人.该文章已在github目录收录. 屏幕前的大帅比和大漂亮如果有帮助到你的话请顺手点个赞. ...

  9. CPU利用率异常的分析思路和方法交流探讨

    CPU利用率异常的分析思路和方法交流探讨在生产运行当中,经常会遇到CPU利用率异常或者不符合预期的情况,此时,往往暗示着系统性能问题.那么究竟是核心应用的问题?是监控工具的问题?还是系统.硬件.网络层 ...

随机推荐

  1. 在delphi中XLSReadWriteII.组件的应用实例(2)

    第三方组件:XLSReadWriteII.v.5.20.67_XE3 实例源码如下:   unit Unit1; interface uses Winapi.Windows, Winapi.Messa ...

  2. 2、python的变量

    1.什么是变量 变量>顾名思义变化的量,量是一种表示一种状态的方式,而且可以变 2.为什么要用变量 程序的执行是一直处于一种变化状态的,我们可以用变量表示表示程序进行中的状态,并将它记录下来 3 ...

  3. SpringJDBC :jdbcTemplate在连接是出现 org/springframeworkbc/core/JdbcTemplate : Unsupported major.minor version 52.0 异常解决

    原因是这个在jdk9版本才能使用,需更新jdk版本. 更新jdk9之后在idear的配置: 第一步:File---->Project Structure---->Project 第二步: ...

  4. Windows 10同步时间的方法

    今天在安装了Windows 10 1809(October 2018 update)之后发现时间不能同步,以前并没有出现这种情况. 1) 打开控制面板,找到时钟域地区 2) 选择日期和时间 3) 选择 ...

  5. 《CSAPP》虚拟存储器

    虚拟存储器与物理存储器 虚拟存储器(VM)被组织为一个由存放在磁盘上的N个连续的字节大小的单元组成的数组.每一个字节都有一个唯一的虚拟地址,这个唯一的虚拟地址作为数组的索引.磁盘上的数组内容被缓存在主 ...

  6. python list初始化技巧

    一维列表 # 初始化递增的list,与L = [i for i in range(10)] 效果相同 L = range(10) # print(L) # [0,1,2,3,4,5,6,7,8,9] ...

  7. 100-days: eleven

    Title: Facebook's live streaming(网络直播) is criticized(批评) after mosque(清真寺) shooting(枪击). live adj.现场 ...

  8. 【转载】我为什么弃用OpenStack转向VMware vsphere

    我为什么弃用OpenStack转向VMware Vsphere,一切皆为简单.高效.因为我们在工作过程中涉及到大量的测试工作,每天都有成百个虚拟机的创建和销毁工作. 工作任务非常繁重,我们的持续集成平 ...

  9. [leetcode]56. Merge Intervals归并区间

    Given a collection of intervals, merge all overlapping intervals. Example 1: Input: [[1,3],[2,6],[8, ...

  10. Django contenttypes 应用

    Django contenttypes 应用 什么是Django ContentTypes? Django ContentTypes是由Django框架提供的一个核心功能,它对当前项目中所有基于Dja ...