实验吧 这个FLAG有点怪 By Assassin

首先感慨一下,感觉自己还是太菜了,这个是2014sctf的RE200,实际是400分的安卓题目,现在做出来其实也是在大佬的提示下完成的,怎么说只能说是分析调出来了,并不算是自己做的,本题过程也很复杂(真心膜拜比赛期间可以做出来的大牛了)下面进入正题,我尽可能讲的清楚一些,在此期间也会借鉴一下大佬的东西
首先肯定是安卓模拟器看一看软件到底是干啥的,大概就是输入一个东西,返回一个值。然后我们将安卓apk文件拖到jeb下看一下,很快找到关键的代码

这里写图片描述

然后我们看到关键的判断函数在func函数中,但是!这个函数是私有的,然后想到了在so文件中被调用,然后我们就准备用IDA去反汇编so文件了,而且我们发现so文件只有一个,还好还好…

这里写图片描述

查找导出函数Java_com_syc_kitkat_func,但是发现这个函数并不存在!然后看了大佬的提示,so文件申明注册函数,可以在JNI_Onload中注册。dex文件加载so文件时,首先会在导出函数中查找JNI_Onload函数,JNI_Onload的默认情况下,不需要我们去声明与定义,但是我们可以重写JNI_Onload,来注册func函数。
然后我们找到JNI_Onload这个函数
这里写图片描述

点进去我们似乎发现了func函数,还有知道了字符串的处理真正位置在_cxa_begin_match中的,然后我们去看一看吧
分析一下知道这个gun_arm_fini_29函数是用来读取输入的字符串的
这里写图片描述

中间有很多东西,是关于调用线程和检测程序的,总的来说就是一种简单的对抗gdb调试的思路吧!(猜的)
这里写图片描述

然后继续看,我们刚刚输入的字符串进行了一个抑或加密,加密是以如下方式text[i]=text[i]^(i+1)进行的,比较好懂
这里写图片描述

然后我们继续看如下语句
这里写图片描述

这几个变量m_y,tempSt,tempabc貌似都没有定义啊!然后我们如果看sctf题解会发现存在一个提示

    反调试,代码在.init段

我们查看.init段,发现定义了个函数,_cxa_chk_fail函数,首先看一下

这里写图片描述

我们发现穿件了一个线程来着,进一步打开看一下!
这里写图片描述

查看发现原来这些变量是一个类似全局变量的东西,在这里对m_y和tempabc进行了初始定义!但是这里看貌似存在两个结果啊如下

m_y tempabc
6   syc
9   xctf

但是我们在后面尝试中发现只用到了第一种情况!(至今不知道是为什么…这个很奇怪,应该是和线程调用有关,但是我不太明白)
然后我们继续回到 _cxa_begin_match函数,首先调用了一个函数是imp_Unwind_k

这里写图片描述

进去看一下,关键代码如下
这里写图片描述

代码不难,分析一下功能就是,我们把输入的串向右移动了6位,然后将这个值赋值到了tempSt这个串中,然后我们是不是tempSt这个串的来历也清楚了!!!

继续回到_cxa_begin_match函数,然后进入了gun_armfini_33函数,我们看看它干了什么

这里写图片描述

关键代码如下
这里写图片描述

理解起来不复杂,总之就是对不同类字符进行处理,然后继续会进入验证函数imp_Unwind_j
这里写图片描述

注意这个v15是我们之前转换后的字符串了,结果进去以后发现类似方程组的东西,然后我们可以得到一个字符串!
这里写图片描述

小心分析求解后,发现它是验证改变后的也就是tempSt这个串的前十一位是不是GoodCracK3R
鼓舞人心!!!并且我们还需要注意一个细节,在_cxa_begin_match函数中的s现在存储的是经过gun_armfini_33函数转换过得串!
我们还是回到_cxa_begin_match函数,然后我们分析,将11位以后的值赋值给dest串(为什么呢,我们重点看一下变量的定义!)
这里写图片描述

并且这里我们给seed赋值,他的位置正好是加密后串(s串的第9、10、11位,也就是K3R)这个seed后面有用!之后进入gun_armfini_21函数,首先是进入gun_armfini_23函数,这里利用了seed值对v8生成了一个256长度的int数组!
这里写图片描述

我用python实现了一下这个数组的功能

def make(str,lens):
    a=[]
    for i in range(256):
        a.append(i)
    pos=0
    pos_temp=0
    for i in range(256):
        temp = a[i]
        pos_temp=(ord(str[pos])+a[i]+pos_temp)&0xff
        a[i]=a[pos_temp]
        a[pos_temp]=temp
        pos=((pos+1)%lens)&0xff
    return a
#make('K3R',3)

然后我们这个v8数组后面还会用到。之后进入gun_armfini_36函数,这个函数主要就是对11位之后的字符串进行了处理

这里写图片描述

然后我们还是回到_cxa_begin_match函数!接近尾声了!
这里写图片描述

我们看到是用sprintf函数对v18进行赋值(用11位以后,加密过的字符)然后进入gun_arm_ldiv0函数去匹配!
这里写图片描述

经过gun_Unwind函数简单加密了一下,就是简单的-2加密
这里写图片描述

最后我们看看它在做什么?11位之后的内容,进过加密,以16进制形式输出,需要匹配成串a8e5588f7e3f758

但是等等!a8e5588f7e3f758是15位的,也就是说一定有一位是0x01这种形式的,11位(那个GoodCracK3R)后面存在8位字符,事实上后八位加密后情况可能是如下

[[0x0a,0x8e,0x55,0x88,0xf7,0xe3,0xf7,0x58],
[0xa8,0x0e,0x55,0x88,0xf7,0xe3,0xf7,0x58],
[0xa8,0xe5,0x05,0x88,0xf7,0xe3,0xf7,0x58],
[0xa8,0xe5,0x58,0x08,0xf7,0xe3,0xf7,0x58],
[0xa8,0xe5,0x58,0x8f,0x07,0xe3,0xf7,0x58],
[0xa8,0xe5,0x58,0x8f,0x7e,0x03,0xf7,0x58],
[0xa8,0xe5,0x58,0x8f,0x7e,0x3f,0x07,0x58],
[0xa8,0xe5,0x58,0x8f,0x7e,0x3f,0x75,0x08]]

我们实验最后正确的是这个(这也是比较坑的地方….)

[0xa8,0xe5,0x58,0x8f,0x7e,0x03,0xf7,0x58]

然后根据上面的分析,我们就可以得到gun_armfini_33加密以后后八位的字符串是啥了!
我也用python生成了一下程序如下

def make(str,lens):
    a=[]
    for i in range(256):
        a.append(i)
    pos=0
    pos_temp=0
    for i in range(256):
        temp = a[i]
        pos_temp=(ord(str[pos])+a[i]+pos_temp)&0xff
        a[i]=a[pos_temp]
        a[pos_temp]=temp
        pos=((pos+1)%lens)&0xff
    return a
#make('K3R',3)

def hehe():
    a=make('K3R',3)
    value=[0xa8,0xe5,0x58,0x8f,0x7e,0x03,0xf7,0x58]
    temp1=0
    temp2=0
    temp3=0
    flag=''
    print a
    for i in value:
        temp1=(temp1+1)&0xff
        temp2=a[temp1]
        temp3=(temp3+temp2)&0xff
        a[temp1]=a[temp3]
        a[temp3]=temp2
        flag+=chr(i^a[(a[temp1]+temp2)&0xff])
    print flag
hehe()

最后得到gun_armfini_33加密后输入字符串为

GoodCracK3R;{0jN|B6

之后是不是就简单了!只需要逆向一下gun_armfini_33函数,再移位回去再抑或一下就得到答案了!解密程序如下

ppp="GoodCracK3R;{0jN|B6"
key = 'syc'
flag=[]
for i in ppp:
    flag.append(ord(i))
print flag
for j in range(len(flag)):
    if flag[j]>=ord('a') and flag[j]<=ord('z'):
        flag[j]=(flag[j]-97+26-ord(key[j%3])+97)%26+97
    elif flag[j]>=ord('A') and flag[j]<=ord('Z'):
        flag[j]=(flag[j]-65+26-ord(key[j%3])+97)%26+65

newflag=''
for i in range(6,6+len(flag)):
    newflag+=chr(flag[i%len(flag)]^(i-5))
print newflag
#xctf{hgJ7Q=|8a\wV;A~}}Wc}

至此成功解出答案!

写的可能稍微有一些些乱,但是这题目真心的好题目,又不太懂的地方还请大神斧正,也请各位包含。题目很复杂,所以一定一定要有耐心!嗯!加油












发布了188 篇原创文章 · 获赞 48 · 访问量 30万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章