首页
社区
课程
招聘
[原创]Android第三题思路,一二题解法
2015-10-18 19:10 3218

[原创]Android第三题思路,一二题解法

2015-10-18 19:10
3218
先说说第三题,代码混淆太厉害,没做出来
check的jni函数地址偏移为0x19c38,如图一

获取偏移的方式为:通过Xposed注入,然后利用jni获取Method结构体,打印出code off即可

动态调试的过程中遇到两个signal:
unknown signal #255
Segmentation violation signal
第一个signal通过挂起该线程即可
第二个signal通过set ip跳过
流程太长,单步跟踪也找不到头绪。。。。

一二题之后再写

补充一二题解法:
第一题、
关键在Check.check函数,jeb打开无法正常显示,只能直接看smali,一打开才发现居然有上万行代码,直接吓哭,必须要动态调试才行,参考:
http://bbs.pediy.com/showthread.php?t=189610
当然直接动态调试也没有太大效果,毕竟有上万行,必须先找到关键代码:
先搜索关键词return,找到:
:goto_0
return v4

再搜索关键词goto_0,找到:
cmp-long v4, v4, v10
if-nez v4, :cond_3
const/4 v4, 0x1
goto/16 :goto_0

通过两次动态调试发现v4是常量,而v10与输入有关,再次找到最近的v10被赋值的地方:
move-wide/from16 v10, v20

在这里下断点后,发现存在一个循环,每次v10都会增加一个值,而这个值是成等差数列增长。于是我直接输入0看v10的最后结果,与v4做个差就是最终答案

第二题、
比较在native层,IDA挂上动态调试,经过第一届MSC的洗礼,猜测应该有一个反调试,就是开一个线程不断获取Tracepid,于是直接在strstr返回处设置断点,保证返回0
然而动态调试到真正的加密算法才是这道题刚刚开始,大致将加密流程分成三块:
1.        进行简单的与常量进行异或、相加、相减,逆向十分容易不贴出代码了
2.        一个循环,每次输入4个数字,相互作用之后输出4个数字,输出的数字将作为下次循环的输入(算法挺恶心的,本来想自己手写一个看看能不能简化,结果和IDA直接F5出来的差不多,只能靠自己的理解了,将代码模块分析)。推导了一番感觉并没有直接的逆向算法,最后采用枚举的办法。对每一层循环,在已知输出的情况下,需要先计算出16个中间变量,再通过这16个中间变量逆向出四个输入。这里可以分成四组,每次逆向得到4个中间变量,首先枚举第一个中间变量,通过异或的性质可以推导出第二个中间变量的高位字节,再通过遍历表查询得到低位字节,以此类推得到四个中间变量的值。这16个中间变量是通过从4个输入的不同位置取下8bit进行一些变换后查表取得,所以逆向回四个输入比较简单。逆向代码如下,通过IDAPython执行
__author__ = 'CwT'

from idaapi import *
from idautils import *
from idc import *

global a1, a2, a3, a4

def getDword(addr):
    return Dword(addr)

def getByte(addr):
    return Byte(addr)

def getWord(addr):
    return Word(addr)

def getindex(a, address):
    for i in range(0x100):
        if getWord(address + i * 2) == a:
            return i * 2
    return -1

def getv76(X, addr, inputa):
    global a1, a2, a3, a4
    a1 = 0
    a2 = 0
    a3 = 0
    a4 = 0
    index = 0
    X ^= getDword(inputa)
    found = False
    for index in range(0x100):
        x1 = (X >> 24) & 0xff
        x2 = (X >> 16) & 0xff
        x3 = (X >> 8) & 0xff
        x4 = X & 0xff
        if found == True:
            break
        a1c1 = getWord(addr+index*2)
        a1 = (a1c1 >> 8) & 0xff
        c1 = a1c1 & 0xff
        x1 ^= a1
        x2 ^= c1
        x3 ^= c1
        x4 ^= (a1 ^ c1)
        a2 = x2 ^ x3 ^ x4
        for i in range(0x100):
            if found is True:
                break
            get = getWord(addr+i*2)
            if ((get >> 8) & 0xff) == a2:
                c2 = get & 0xff
                x1 ^= (a2 ^ c2)
                x2 ^= a2
                x3 ^= c2
                x4 ^= c2
                a3 = x1 ^ x2
                x3 ^= a3
                if x1 ^ x3 == x4:
                    for j in range(0x100):
                        if found is True:
                            break
                        one = getWord(addr+j*2)
                        if ((one >> 8) & 0xff) == a3:
                            c3 = one & 0xff
                            c4 = x1 ^ c3
                            a4 = x4 ^ c3
                            a1 = (a1 << 8) + c1
                            a2 = (a2 << 8) + c2
                            a3 = (a3 << 8) + c3
                            a4 = (a4 << 8) + c4
                            if getindex(a4, addr) >= 0:
                                found = True
                                print "found it"
                                print "a1 =", hex(getindex(a1, addr))
                                print "a2 =", hex(getindex(a2, addr))
                                print "a3 =", hex(getindex(a3, addr))
                                print "a4 =", hex(getindex(a4, addr))
                                a1 = getindex(a1, addr)
                                a2 = getindex(a2, addr)
                                a3 = getindex(a3, addr)
                                a4 = getindex(a4, addr)
    if found is not True:
        print "not found"

inputa = 0x5F1EEF20
addr = 0x5CD2E758
def jiemi():
    global a1, a2, a3, a4
    v77 = 0x6e624e2a
    v44 = 0x67b2033d
    v75 = 0xae3a6dcbL
    v76 = 0x806f96c3L
    for i in range(9):
        v76_tmp = 0
        v77_tmp = 0
        v75_tmp = 0
        v44_tmp = 0
        getv76(v76, addr, inputa- 12 - 16 * i)   # v76
        v76_tmp |= (a1 << 23)
        v75_tmp |= (a2 << 15)
        v44_tmp |= (a3 << 7)
        v77_tmp |= (a4 >> 1)
        getv76(v75, addr, inputa- 8 - 16 * i)    # v75
        v75_tmp |= (a1 << 23)
        v44_tmp |= (a2 << 15)
        v77_tmp |= (a3 << 7)
        v76_tmp |= (a4 >> 1)
        getv76(v44, addr, inputa- 4 - 16 * i)    # v44
        v44_tmp |= (a1 << 23)
        v77_tmp |= (a2 << 15)
        v76_tmp |= (a3 << 7)
        v75_tmp |= (a4 >> 1)
        getv76(v77, addr, inputa - 16 * i)      # v77
        v77_tmp  |= (a1 << 23)
        v76_tmp  |= (a2 << 15)
        v75_tmp  |= (a3 << 7)
        v44_tmp  |= (a4 >> 1)
        v76 = v76_tmp & 0xffffffff
        v77 = v77_tmp & 0xffffffff
        v75 = v75_tmp & 0xffffffff
        v44 = v44_tmp & 0xffffffff
        print "round ", i
        print "v77 =", hex(v77)
        print "v44 =", hex(v44)
        print "v75 =", hex(v75)
        print "v76 =", hex(v76)

jiemi()

3.        第三部分就是将第二部分的四个输出又进行了一些相互作用,通过一番推理可以得到逆向算法如下:
res = [0x5CDA772F, 0xA3C63E39, 0xB6F0F3ED, 0x515A9986,]
addr = 0x5CCF2758
inputa = [0x915a0cca, 0x47f11117, 0x335a63f2, 0xcef2a5a1,]
v44 = 0
v75 = 0
v76 = 0
v77 = 0
ans = res[3] ^ inputa[3]
a = (ans >> 24) & 0xff 
b = (ans >> 16) & 0xff
c = (ans >> 8) & 0xff
d = ans & 0xff
v44 |= (getByteindex(d, addr) & 0xff)
v75 |= ((getindex(c, addr) & 0x1fe) << 7)
v76 |= ((getindex(b, addr) & 0x1fe) << 15)
v77 |= ((getindex(a, addr) & 0x1fe) << 23)

ans = res[2] ^ inputa[2]
a = (ans >> 24) & 0xff 
b = (ans >> 16) & 0xff
c = (ans >> 8) & 0xff
d = ans & 0xff
v75 |= (getByteindex(d, addr) & 0xff)
v76 |= ((getindex(c, addr) & 0x1fe) << 7)
v77 |= ((getindex(b, addr) & 0x1fe) << 15)
v44 |= ((getindex(a, addr) & 0x1fe) << 23)

ans = res[1] ^ inputa[1]
a = (ans >> 24) & 0xff 
b = (ans >> 16) & 0xff
c = (ans >> 8) & 0xff
d = ans & 0xff
v76 |= (getByteindex(d, addr) & 0xff)
v77 |= ((getindex(c, addr) & 0x1fe) << 7)
v44 |= ((getindex(b, addr) & 0x1fe) << 15)
v75 |= ((getindex(a, addr) & 0x1fe) << 23)

ans = res[0] ^ inputa[0]
a = (ans >> 24) & 0xff 
b = (ans >> 16) & 0xff
c = (ans >> 8) & 0xff
d = ans & 0xff
v77 |= (getByteindex(d, addr) & 0xff)
v44 |= ((getindex(c, addr) & 0x1fe) << 7)
v75 |= ((getindex(b, addr) & 0x1fe) << 15)
v76 |= ((getindex(a, addr) & 0x1fe) << 23)

print "anser: ", "v77: ", hex(v77)
print "anser: ", "v44: ", hex(v44)
print "anser: ", "v75: ", hex(v75)
print "anser: ", "v76: ", hex(v76)


从下往上执行逆向代码最终获得答案

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

上传的附件:
收藏
点赞0
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回