CISCN逆向《babyre》
Posted Corax0o0
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CISCN逆向《babyre》相关的知识,希望对你有一定的参考价值。
虽然两天就解出来一道题,但是好歹是写了,还是写个wp记录一下吧。
题目babyre
baby都能做出来的re。。
解法
其实这道题我也头疼了很久。
因为下载下来是一个xml文件,我没做过类似的逆向题。
打开之后看到是一个xml文档,很乱,虽然捕捉到了类似于“welldone”这种关键的回显信息,但是对xml的整个框架是完全一头雾水。
但我注意到了在文件的开头
查到了这个snap好像是一个什么编译环境,我们可以把它下载下来
然后打开它
可以看到框框中的部分有一个secret的操作,然后在右边
是i和i-1 位的一个异或操作。
所以我们,首先要先把这个secret还原出来,通过自己人工把插入的位置都给解决好,解决。
k1=[102,10,13,6,28,74,3,1,3,7,85,0,4,75,20,92,92,8,28,25,81,83,7,28,76,88,9,0,29,73,0,86,4,87,87,82,84,85,4,85,87,30]
然后我们再写算法
得到flag
Flag:flag12307bbf-9e91-4e61-a900-dd26a6d0ea4c(不知道为什么少了个后括号,自己加上去了)
2021CISCN-逆向-galss复现及总结
一、apk文件逆向
没有接触过app开发,临时学习:
1.apk文件逆向工具:jadx 、jeb 、jd-gui
选择jadx的gui工具,反编译apk文件(代码阅读为请教tx,app开发需要补课)
在主活动中查看主要的代码,
大致逻辑为在主活动中通过checkflag()函数对用户的输入进行比较,一致则right,而loadlibrary("native-lib")则说明了checkflag函数在某个so文件中,可以在资源文件下找到:
只需要反编译so文件完成逆向既可以找到flag。
将.apk后缀更改为.zip,解压缩,在文件夹中可以拿到libnative-lib.so文件
拖入ida进行分析。
分析checkflag()函数
二、异或逆向
自下往上进行解密,第一个加密函数是对传入的值完成异或加密
提取出最后的结果
unsigned char result[] = { 0xA3, 0x1A, 0xE3, 0x69, 0x2F, 0xBB, 0x1A, 0x84, 0x65, 0xC2, 0xAD, 0xAD, 0x9E, 0x96, 0x05, 0x02, 0x1F, 0x8E, 0x36, 0x4F, 0xE1, 0xEB, 0xAF, 0xF0, 0xEA, 0xC4, 0xA8, 0x2D, 0x42, 0xC7, 0x6E, 0x3F, 0xB0, 0xD3, 0xCC, 0x78, 0xF9, 0x98, 0x3F };
复现一下异或加密过程
key=\'12345678\'
result[k]=result[k]^key[k%8]
for(i=0;i<len(result);i+=3){
result[i]=result[i]^result[i+2];
result[i+2]=result[i+2]^result[i+1]
result[i+1]=result[i+1]^result[i]^result[i+2]
}
此异或过程的逆向分析如下:
以前三位举例
new_r[0]=old_r[0]^old_r[2]
new_r[2]=old_r[2]^old_r[1]
new_r[1]=old_r[1]^old_r[0]^old_r[2]
//new是已知的,old是待求的
new_r[1]=old_r[1]^new_r[0]
=>
old_r[1]=new_r[1]^new_r[0]
new_r[2]=old_r[2]^old_r[1] //old_r[1]在上一步后为已知
=>
old_r[2]=old_r[1]^new_r[2]
new_r[0]=old_r[0]^old_r[2] //old_r[2]在上一步后为已知
=>
old_r[0]=new_r[0]^old_r[2]
解密脚本:
for i in range(0,39,3): res[i+1]=res[i+1]^res[i] res[i+2]=res[i+2]^res[i+1] res[i]=res[i]^res[i+2]
#应当注意异或运算的逆向过程,核心是把握对称性,其次要关注在多次的异或运算中后面的值是使用的新值还是旧值
三、RC4
后面两个函数,可以看出是RC4加密算法,
第一个为S表、T表的初始化,第二个函数为加密过程,注意RC4为对称加密,只需要按照伪代码的逻辑正着实现即可
res=[0xA3,0x1A,0xE3,0x69,0x2F,0xBB,0x1A,0x84,
0x65,0xC2,0xAD,0xAD,0x9E,0x96,0x05,0x02,
0x1F,0x8E,0x36,0x4F,0xE1,0xEB,0xAF,0xF0,
0xEA,0xC4,0xA8,0x2D,0x42,0xC7,0x6E,0x3F,
0xB0,0xD3,0xCC,0x78,0xF9,0x98,0x3F]
key=\'12345678\'
s=[0]*256
t=[0]*256
def rc4_init(): global s global t global key for i in range(0,256): s[i]=i t[i]=ord(key[i%8]) v9=0 for i in range(0,256): middle=s[i] v9=(v9+s[i]+t[i])%256 s[i]=s[v9] s[v9]=middle def rc4_encrpto(): v4=0 v3=0 v5=0 global s global res for i in range(0,38): v4=(v4+1)%256 v5=s[v4] v3=(v3+s[v4])%256 s[v4]=s[v3] s[v3]=s[v5] res[i]^=s[(v5+s[v4])%256]
参考:rc4:带你学加密丨RC4 (qq.com)
#注意识别RC4的加密特征,初始化的S表和T表(循环交换位置),初始化和加密都有个明显的swap()过程;另外注意对称加密的解密过程,算法一致
四、python写解题脚本的收获
res=[0xA3,0x1A,0xE3,0x69,0x2F,0xBB,0x1A,0x84, 0x65,0xC2,0xAD,0xAD,0x9E,0x96,0x05,0x02, 0x1F,0x8E,0x36,0x4F,0xE1,0xEB,0xAF,0xF0, 0xEA,0xC4,0xA8,0x2D,0x42,0xC7,0x6E,0x3F, 0xB0,0xD3,0xCC,0x78,0xF9,0x98,0x3F] key=\'12345678\' s=[0]*256 t=[0]*256 def rc4_init(): global s global t global key for i in range(0,256): s[i]=i t[i]=ord(key[i%8]) v9=0 for i in range(0,256): middle=s[i] v9=(v9+s[i]+t[i])%256 s[i]=s[v9] s[v9]=middle print(\'s:\',s) def rc4_encrpto(): v4=0 v3=0 v5=0 global s global res for i in range(0,38): v4=(v4+1)%256 v5=s[v4] v3=(v3+s[v4])%256 s[v4]=s[v3] s[v3]=s[v5] res[i]^=s[(v5+s[v4])%256] if __name__==\'__main__\': flag=\'\' for j in range(0,39): res[j]=res[j]^ord(key[j%8]) print(res) for i in range(0,39,3): res[i+1]=res[i+1]^res[i] res[i+2]=res[i+2]^res[i+1] res[i]=res[i]^res[i+2] print(\'old res:\',res) rc4_init() rc4_encrpto() for i in range(len(res)): flag+=chr(res[i]) print(\'now res:\',res) print(flag)
#注意使用global关键字来定义全局变量
#if __name__==\'__main__\':定义主函数
#格外注意python中的数据类型转换,key=\'12345678\',在运算中使用到的key[i]均是使用的字符所对应的ascall码,
ord()和chr()函数可以实现字符和对象ascall码之间的转换。
以上是关于CISCN逆向《babyre》的主要内容,如果未能解决你的问题,请参考以下文章