首页
社区
课程
招聘
[原创]kanxuectf2019 第二题
2019-3-22 10:34 8454

[原创]kanxuectf2019 第二题

2019-3-22 10:34
8454
没啥好说的,首先解压apk包,反编译(dex2jar)看看class.dex中有什么东东。
可以看到,调用了eq函数进行比较,如果返回结果为true,则对输入密码进行填充(不足24位时),然后调用aes进行解密。所以关键就在于eq这个native函数的逆向。
由于我不会调试android,所以只能直接硬看。。。
首先一进去,看到有个datadiv_decode函数,有名称的函数肯定先看啊
一看就是在解密数据,写个ida脚本解密下,看看到底是什么
哦吼,有点意思,其中就有eq函数的名称
然后再看看JNI_OnLoad函数,可以看到一个偏移地址off_4010,off_4014,先跟过去看看。
几个变量的地址和一个函数,那么这个函数就很可疑了,直接逆向它。
第一步:数据去“-”号
第二步:数据翻转,并按照8-4-4-12的格式进行保存
第三步:这里其实需要自己去分析下,其实0x23AE,0x2377是两个数组的基地址,由于他们的计算过程是采用add得来的,所以ida并没有将其识别为偏移。如果看懂了这个,其实就能知道,这就是一个简单的置换。
第四步:这里有个函数sub_D20,我刚开始也没太看懂,由于没法调试也不能看结果去猜这个函数时什么意思。后面,再看其汇编代码的时候IDA的识别出现了问题
我们看如下汇编代码
在调用sub_c78前,压栈的参数为R0,R1,LR,但执行完函数返回后弹栈时顺序变成了R1,R2,LR。也就是说执行完函数后,会将R0(ori)->R1, R1(ori)->R2,R0保存函数的返回结果,然后R1 = R1 - R3 = R1 - (R2*R0) = R1 - (R1(ori) * R0) = R0(ori) - (R1(ori)*R0)。
然后我们在看看当sub_D20调用完后,是怎么一个赋值的过程。
可以看到是以R1为下标索引去取值,然后存放到申请好的堆中,R0(ori)为当前要存放的地址与堆地址的偏移,R1(ori)为输入串的长度len。也就是关键就在于执行完sub_c78后函数的返回值R0是什么。
下面我们看看sub_c78函数都干了什么
有点复杂,我用了一种做数学题常用的方法来推测函数的功能,即特殊值法。我们可以看分支
 else if ( a2 & (a2 - 1) )
 {
        v2 = __clz(a2) - __clz(a1);
        v3 = a2 << v2;
        v4 = 1 << v2;
        v5 = 0;
        while ( 1 )
        {
          if ( a1 >= v3 )
          {
            a1 -= v3;
            v5 |= v4;
如果要想满足进入该分支的条件,那么a2&(a2-1)!=0,这是一种什么情况呢?其实仔细想想就能发现,只有当a2的二进制表示中只有一个1时,不满足该条件。也就是说当a2为2的次方时,该等式不成立。那么我们看看当a2为2的次方时,程序的逻辑是什么
美滋滋,就一句话。翻译一下就是R0/R1。ok!那么我们就能明白了当R1(len)为2的次方时,R0 = R0(ori) - (R1(ori)*(R0(ori)/R1(ori))。循环赋值!
第五步:不多说了,变异版base64
base64_charset = '!:#$%&()+-*/`~_[]{}?<>,.@^abcdefghijklmnopqrstuvwxyz0123456789\\\';'
print base64_charset,len(base64_charset)
print ''.join([chr(x) for x in data7])
check_str = ''
for i in range(len(data7)):
  if i%4 == 0:
    check_str += chr(data7[i]^0x7)
  elif i%4 == 2:
    check_str += chr(data7[i]^0xf)
  else:
    check_str += chr(data7[i])
得到的即为falg(吐槽下,我一直以为程序输出的flag{Android4-9    }什么的为flag。。。)
exp:
import os
import base64
#import idaapi

addr = 0x4020

data1 =[0x93, 0x90, 0x95, 0xC3, 0x9C, 0x95, 0x9C, 0xC6, 0x88, 0x92, 
  0x97, 0x94, 0x92, 0x88, 0x96, 0x93, 0x91, 0x92, 0x88, 0x9C, 
  0x96, 0x96, 0x94, 0x88, 0xC6, 0x9D, 0x97, 0xC1, 0xC3, 0x9D, 
  0xC7, 0x9C, 0x9D, 0xC0, 0x9C, 0x9D, 0xA5]

data2 = [0x84, 0x9F, 0x86, 0x81, 0x80, 0x83, 0x8D, 0x8C, 0x8E, 0x88, 
  0x8F, 0x8A, 0xC5, 0xDB, 0xFA, 0xFE, 0xF8, 0xDE, 0xD8, 0x9A, 
  0x99, 0x9B, 0x89, 0x8B, 0xE5, 0xFB, 0xC4, 0xC7, 0xC6, 0xC1, 
  0xC0, 0xC3, 0xC2, 0xCD, 0xCC, 0xCF, 0xCE, 0xC9, 0xC8, 0xCB, 
  0xCA, 0xD5, 0xD4, 0xD7, 0xD6, 0xD1, 0xD0, 0xD3, 0xD2, 0xDD, 
  0xDC, 0xDF, 0x95, 0x94, 0x97, 0x96, 0x91, 0x90, 0x93, 0x92, 
  0x9D, 0x9C, 0xF9, 0x82, 0x9E, 0xA5, 0x00, 0x00, 0x00, 0x00,  
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

data3 = [0xE5, 0xEA, 0xE0, 0xF6, 0xEB, 0xED, 0xE0, 0xAB, 0xF7, 0xF1, 
  0xF4, 0xF4, 0xEB, 0xF6, 0xF0, 0xAB, 0xF2, 0xB3, 0xAB, 0xE5, 
  0xF4, 0xF4, 0xAB, 0xC5, 0xF4, 0xF4, 0xC7, 0xEB, 0xE9, 0xF4, 
  0xED, 0xE5, 0xF0, 0xC5, 0xE7, 0xF0, 0xED, 0xF2, 0xED, 0xF0, 
  0xFD, 0x84
]

data4 = [0x99,0x8d,0xfc]

data5 = [0x4a,0x2e,0x8,0x3,0x14,0x3,0x4d,0xe,0x3,0xc,0x5,0x4d,0x31,0x16,0x10,0xb,0xc,0x5,
  0x59,0x4b,0x38,0x62]

data6 = [0xD7, 0xDF, 0x02, 0xD4, 0xFE, 0x6F, 0x53, 0x3C, 0x25, 0x6C, 
  0x99, 0x97, 0x06, 0x56, 0x8F, 0xDE, 0x40, 0x11, 0x64, 0x07, 
  0x36, 0x15, 0x70, 0xCA, 0x18, 0x17, 0x7D, 0x6A, 0xDB, 0x13, 
  0x30, 0x37, 0x29, 0x60, 0xE1, 0x23, 0x28, 0x8A, 0x50, 0x8C, 
  0xAC, 0x2F, 0x88, 0x20, 0x27, 0x0F, 0x7C, 0x52, 0xA2, 0xAB, 
  0xFC, 0xA1, 0xCC, 0x21, 0x14, 0x1F, 0xC2, 0xB2, 0x8B, 0x2C, 
  0xB0, 0x3A, 0x66, 0x46, 0x3D, 0xBB, 0x42, 0xA5, 0x0C, 0x75, 
  0x22, 0xD8, 0xC3, 0x76, 0x1E, 0x83, 0x74, 0xF0, 0xF6, 0x1C, 
  0x26, 0xD1, 0x4F, 0x0B, 0xFF, 0x4C, 0x4D, 0xC1, 0x87, 0x03, 
  0x5A, 0xEE, 0xA4, 0x5D, 0x9E, 0xF4, 0xC8, 0x0D, 0x62, 0x63, 
  0x3E, 0x44, 0x7B, 0xA3, 0x68, 0x32, 0x1B, 0xAA, 0x2D, 0x05, 
  0xF3, 0xF7, 0x16, 0x61, 0x94, 0xE0, 0xD0, 0xD3, 0x98, 0x69, 
  0x78, 0xE9, 0x0A, 0x65, 0x91, 0x8E, 0x35, 0x85, 0x7A, 0x51, 
  0x86, 0x10, 0x3F, 0x7F, 0x82, 0xDD, 0xB5, 0x1A, 0x95, 0xE7, 
  0x43, 0xFD, 0x9B, 0x24, 0x45, 0xEF, 0x92, 0x5C, 0xE4, 0x96, 
  0xA9, 0x9C, 0x55, 0x89, 0x9A, 0xEA, 0xF9, 0x90, 0x5F, 0xB8, 
  0x04, 0x84, 0xCF, 0x67, 0x93, 0x00, 0xA6, 0x39, 0xA8, 0x4E, 
  0x59, 0x31, 0x6B, 0xAD, 0x5E, 0x5B, 0x77, 0xB1, 0x54, 0xDC, 
  0x38, 0x41, 0xB6, 0x47, 0x9F, 0x73, 0xBA, 0xF8, 0xAE, 0xC4, 
  0xBE, 0x34, 0x01, 0x4B, 0x2A, 0x8D, 0xBD, 0xC5, 0xC6, 0xE8, 
  0xAF, 0xC9, 0xF5, 0xCB, 0xFB, 0xCD, 0x79, 0xCE, 0x12, 0x71, 
  0xD2, 0xFA, 0x09, 0xD5, 0xBC, 0x58, 0x19, 0x80, 0xDA, 0x49, 
  0x1D, 0xE6, 0x2E, 0xE3, 0x7E, 0xB7, 0x3B, 0xB3, 0xA0, 0xB9, 
  0xE5, 0x57, 0x6E, 0xD9, 0x08, 0xEB, 0xC7, 0xED, 0x81, 0xF1, 
  0xF2, 0xBF, 0xC0, 0xA7, 0x4A, 0xD6, 0x2B, 0xB4, 0x72, 0x9D, 
  0x0E, 0x6D, 0xEC, 0x48, 0xE2, 0x33]

data7 = [0x20, 0x7B, 0x39, 0x2A, 0x38, 0x67, 0x61, 0x2A, 0x6C, 0x21, 
  0x54, 0x6E, 0x3F, 0x40, 0x23, 0x66, 0x6A, 0x27, 0x6A, 0x24, 
  0x5C, 0x67, 0x3B, 0x3B]


base64_charset = ''


def sb64encode(origin_bytes):
    base64_bytes = ['{:0>8}'.format(str(bin(b)).replace('0b', '')) for b in origin_bytes]
    resp = ''
    #base64_bytes = origin_bytes
    nums = len(base64_bytes) // 3
    remain = len(base64_bytes) % 3

    integral_part = base64_bytes[0:3 * nums]
    while integral_part:
        tmp_unit = ''.join(integral_part[0:3])
        tmp_unit = [int(tmp_unit[x: x + 6], 2) for x in [0, 6, 12, 18]]
        resp += ''.join([base64_charset[i] for i in tmp_unit])
        integral_part = integral_part[3:]

    if remain:
        remain_part = ''.join(base64_bytes[3 * nums:]) + (3 - remain) * '0' * 8
        tmp_unit = [int(remain_part[x: x + 6], 2) for x in [0, 6, 12, 18]][:remain + 1]
        resp += ''.join([base64_charset[i] for i in tmp_unit]) + (3 - remain) * '='

    return resp


def sb64decode(base64_str):
    base64_bytes = ['{:0>6}'.format(str(bin(base64_charset.index(s))).replace('0b', '')) for s in base64_str if s != '=']
    resp = bytearray()
    nums = len(base64_bytes) // 4
    remain = len(base64_bytes) % 4
    integral_part = base64_bytes[0:4 * nums]

    while integral_part:
        tmp_unit = ''.join(integral_part[0:4])
        tmp_unit = [int(tmp_unit[x: x + 8], 2) for x in [0, 8, 16]]
        for i in tmp_unit:
            resp.append(i)
        integral_part = integral_part[4:]

    if remain:
        remain_part = ''.join(base64_bytes[nums * 4:])
        tmp_unit = [int(remain_part[i * 8:(i + 1) * 8], 2) for i in range(remain - 1)]
        for i in tmp_unit:
            resp.append(i)

    return resp



def sdecode(data,x,l):
  res = ''
  for i in range(l):
      byte = data[i] ^ x
      res += chr(byte)
  return res

print sdecode(data1,0xa5,37)
print sdecode(data2,0xa5,66)
print sdecode(data3,0x84,42)
print sdecode(data4,0xfc,3)
print sdecode(data5,0x62,len(data5))

m_str = '650f909c-7217-3647-9331-c82df8b98e98'.split('-')
m_str = ''.join(m_str)
print m_str
tmp = ''
v9 = len(m_str) - 1
v10 = 0xFFFFFFF8
v11 = 0

while v9!=-1:
  if ( (v11 | (v10 >> 2)) > 3 ):
    tmp += m_str[v9]
  else:
    tmp += '-'
    tmp += m_str[v9]
  v11 += 0x40000000
  v11 %= 0x100000000
  v10 += 1
  v10 %= 0x100000000
  v9 -= 1
print tmp


al_mode = [0x64,0x62,0x65,0x61,0x66,0x63]
num_mode = [0x32,0x34,0x30,0x39,0x37,0x31,0x35,0x38,0x33,0x36]
m_str = tmp
tmp = ''
for i in range(len(m_str)):
  if m_str[i] >= '0' and m_str[i] <='9':
    tmp += chr(num_mode[int(m_str[i])])
  elif m_str[i] >= 'a' and m_str[i] <= 'f':
    tmp += chr(al_mode[ord(m_str[i])-0x61])
  else:
    tmp += m_str[i]
print tmp

m_str = tmp
tmp = ''
for i in range(0x100):
  tmp += m_str[i%len(m_str)]
print tmp

m_str = tmp
tmp = []
for i in range(0x100):
  tmp.append(ord(m_str[i]))
#print tmp

v19 = (tmp[0] - 41)
data6[0] = data6[v19]
data6[v19] = 0xD7
v20 = 1
while v20 != 256:
  v21 = data6[v20]
  v19 = (v19 + tmp[v20] + v21) % 256
  data6[v20] = data6[v19]
  data6[v19] = v21
  v20 += 1
#print data6

base64_charset = '!:#$%&()+-*/`~_[]{}?<>,.@^abcdefghijklmnopqrstuvwxyz0123456789\\\';'
print base64_charset,len(base64_charset)
print ''.join([chr(x) for x in data7])
check_str = ''
for i in range(len(data7)):
  if i%4 == 0:
    check_str += chr(data7[i]^0x7)
  elif i%4 == 2:
    check_str += chr(data7[i]^0xf)
  else:
    check_str += chr(data7[i])
  
#check_str = check_str[:len(check_str)-2] + ';' + check_str[len(check_str)-1:]
print check_str
check_str = sb64decode(check_str)
i = 0
j = 0
ans = ''
for x in check_str:
  i = (i+1)%256
  tmp = data6[i]
  j = (j+tmp)%256
  data6[i] = data6[j]
  data6[j] = tmp
  y = data6[(data6[i]+data6[j])%256]
  x ^= y
  ans += chr(x)
print ans
'''
tmp = ''
for i in range(len(m_str))[::-1]:
  tmp += m_str[i]
  if i % 8 ==0 and i!=0:
    tmp += '-'
print tmp
#650f909c-7217-3647-9331-c82df8b98e98
'''




[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
点赞1
打赏
分享
最新回复 (1)
雪    币: 303
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
嘀学生卡 2021-10-19 20:37
2
0
ida脚本咋写
游客
登录 | 注册 方可回帖
返回