-
-
[原创]Android第三题思路,一二题解法
-
发表于: 2015-10-18 19:10 3293
-
先说说第三题,代码混淆太厉害,没做出来
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,找到:
通过两次动态调试发现v4是常量,而v10与输入有关,再次找到最近的v10被赋值的地方:
在这里下断点后,发现存在一个循环,每次v10都会增加一个值,而这个值是成等差数列增长。于是我直接输入0看v10的最后结果,与v4做个差就是最终答案
第二题、
比较在native层,IDA挂上动态调试,经过第一届MSC的洗礼,猜测应该有一个反调试,就是开一个线程不断获取Tracepid,于是直接在strstr返回处设置断点,保证返回0
然而动态调试到真正的加密算法才是这道题刚刚开始,大致将加密流程分成三块:
1. 进行简单的与常量进行异或、相加、相减,逆向十分容易不贴出代码了
2. 一个循环,每次输入4个数字,相互作用之后输出4个数字,输出的数字将作为下次循环的输入(算法挺恶心的,本来想自己手写一个看看能不能简化,结果和IDA直接F5出来的差不多,只能靠自己的理解了,将代码模块分析)。推导了一番感觉并没有直接的逆向算法,最后采用枚举的办法。对每一层循环,在已知输出的情况下,需要先计算出16个中间变量,再通过这16个中间变量逆向出四个输入。这里可以分成四组,每次逆向得到4个中间变量,首先枚举第一个中间变量,通过异或的性质可以推导出第二个中间变量的高位字节,再通过遍历表查询得到低位字节,以此类推得到四个中间变量的值。这16个中间变量是通过从4个输入的不同位置取下8bit进行一些变换后查表取得,所以逆向回四个输入比较简单。逆向代码如下,通过IDAPython执行
3. 第三部分就是将第二部分的四个输出又进行了一些相互作用,通过一番推理可以得到逆向算法如下:
从下往上执行逆向代码最终获得答案
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)
从下往上执行逆向代码最终获得答案
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
赞赏
他的文章
- [原创]基于IDA Python的Dex Dump 16705
- [原创]Android第三题思路,一二题解法 3294
- [求助]百度加固是否检测Xposed 11022
- [讨论][原创][求助]基于Xposed的不那么通用的脱壳机 20743
谁下载
看原图
赞赏
雪币:
留言: