-
-
[原创]Android第三题思路,一二题解法
-
发表于: 2015-10-18 19:10 3406
-
先说说第三题,代码混淆太厉害,没做出来
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)
从下往上执行逆向代码最终获得答案
[培训]传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!
赞赏
他的文章
- [原创]基于IDA Python的Dex Dump 16901
- [原创]Android第三题思路,一二题解法 3407
- [求助]百度加固是否检测Xposed 11197
- [讨论][原创][求助]基于Xposed的不那么通用的脱壳机 20940
谁下载
赞赏
雪币:
留言: