美文网首页
Android CrackMe[1]

Android CrackMe[1]

作者: N8_xEnn7nA1 | 来源:发表于2018-07-10 22:03 被阅读0次

    运行APK,如图:


    image.png

    一个很典型的CrackMe。拖到JEB看一下,如图:


    image.png

    关键函数就是Native函数check(),只要它返回0就是正确的。

    用IDA打开so库,可以看到,存在JNI_OnLoad函数,可判断它用的是动态注册的方式:


    image.png
    image.png

    可以看到,该函数的代码很长,而且可读性非常差,即便通过F5插件转换成C代码也是如此,所以我并没有截全。我猜代码段应该是混淆或者加密过了。因为正常来说,JNI_OnLoad函数是比较很简单的,要做的事情无非就是注册JNI函数,和一些初始化动作而已。因此下面就来尝试用IDA对该so库进行动态调试,运气好的话该APK只是做了防止静态分析的工作,呵呵。

    IDA attch了进行后,再找到JNI_OnLoad函数处,可以看到汇编指令就比较正常了:


    image.png

    利用F5插件切换到C代码视图,然后通过更改关键变量类型,比如JavaVM,JNIEnv等,就能识别出常见的那几个函数了,如图:

    image.png

    可见,dword_75473014处就是注册函数相关的结构体,点过去,如图:


    image.png

    可以看到4个地址,从上到下,依次是:

    1.Java层对应的函数名字符串首地址 --> "check"
    2.Java层对应的函数的函数签名:"(Ljava/lang/String;Ljava/lang/String;)Z"
    3.C层对应函数的首地址

    双击C层对应函数的首地址,该函数如下图(已修改了函数名和部分变量名):

    这里要特别提一下,IDA原本识别出函数名为:_arm_aeabi_3。。是不是很有迷惑性,而且在C层还有一个名为check的函数,如果没有分析JNI_OnLoad函数,而直接去分析那个check函数的话,不好意思,这个check函数根本没用到,完全是出题人骗人的小把戏。

    这里将该函数改名为:real_check,然后在里面下一个断点,在name编辑框中输入abcd,在pass编辑框中输入dcba123456,然后点击check,可以看到程序断下来了:


    image.png

    如上图,调用了_arm_aeabi_5()这个函数对输入的密码进行某种加密,并存放到newBuf缓冲区中,这里先不暂且不去分析_arm_aeabi_5()函数的实现,而是直接在内存中观察newBuf缓冲区在执行该函数后的内容,单步步过,查看newBuf的内存,如图:


    image.png

    可以看到,_arm_aeabi_5() 这个函数其实就是将输入的密码原样显示在内存中。
    因为16进制的字符为0-9和A-F,所以这个函数里是有某种判断的,也就是输入的字母的要求是:大写字母不能大于F,小写字母不能大于f。

    【注:如果一开始输入的是大于F或者f的字母,则_arm_aeabi_5()函数会直接返回,newBuf并不会存放正确的数据。如果是这种情况下,那就得分析一下_arm_aeabi_5()函数的实现才行...但是我测试的时候运气比较好,输入的字母里没有大于F或大于f的数值,因此就不用去看这个函数的实现了】

    继续单步往下分析,到如下代码处:


    image.png

    如上图,newBuf2是一个新的缓冲区地址,for循环之前,该缓冲区里的内容是输入的name,这里是"abcd",经过一个for循环,再与src连接后,newBuf2的内容变成了"abcdgeek201508261314",即:

    newBuf2 = name + "geek201508261314";

    再往下一点看,如图:


    image.png

    这里就是最后校验的地方,如何校验呢?
    就是比较newBuf2和newBuf的内容是否一致。我们已经知道了newBuf2的构成,那么在回头看一下newBuf相关的处理,如图:


    image.png

    可以看到,对newBuf处理很简单。这里写了个Python脚本来计算密码,代码如下:

    #!/usr/bin/env python3
    # -*- coding:utf-8 -*-
    
    name = input("Please input name: ")
    
    verifyRet = name + "geek201508261314"
    
    
    verifyRetList = list(verifyRet)
    tmpList = []
    
    for i in range(len(verifyRetList)):
        verifyRetList[i] = (ord(verifyRetList[i]) ^ 0x22) + 120
        tmpList.append("%2x" % verifyRetList[i])
    
    # password = "".join(tmpList)
    # print("pass=(" + password + ")")
    
    print("pass=" + tmpList.__str__())
    

    测试name为"abcd"的情况,如下:


    image.png

    相关文件下载地址:
    链接:https://pan.baidu.com/s/14ZNHAKPY0Av5WRjIRo0KGw 密码:j6r8

    相关文章

      网友评论

          本文标题:Android CrackMe[1]

          本文链接:https://www.haomeiwen.com/subject/klbqpftx.html