BUU刷题记录
Buuctf刷题记录
¶红帽杯-XX
¶考点
xxtea、异或、换位
¶分析
整个过程就是取前四个输入作为密钥,先进行XXTEA加密,然后位置互换混淆,最后进行异或加密
¶取密钥
这里判断取出前四位,判断是否为数组内的元素,因为如果不是的话,最后V11=V14退出程序
取出地址中存储的字符,保证其不为0,下面那个循环是将取出的key末尾填充0
我们的key是int型,这里传参时强制转为char型
函数内部起始段是将我们传入的key转为int型,转换大小端序,因为原本是flag,转为int之后就变成了galf
然后xxtea加密
¶打乱位置
¶异或
这段的逻辑就是只要是3的倍数就取出来异或,index从1开始,所以0、1、2下标的字符都不会被加密,3、4、5进行一次加密,异或的值为下标为0的enc_flag,6、7、8则两次,异或的值为下标为0、1的加密后的字符,依次往后,直到21、22、23,此时异或前六位加密字符
¶脚本
xxtea
1 |
|
异或和位置互换
1 |
|
¶[安洵杯 2019]crackMe
¶考点
SM4、Base64变表加密、换位
¶分析
这里我和别人不一样,我运行不了程序,所以没办法动调,只能X查看交叉引用
进去定位到主加密函数
¶初始化密钥
对key查看交叉引用,可以进入这里,看一下对赋值后的字符串处理
通过FindCrypt可以知道是SM4加密,所以这一段就是初始化密钥了
¶SM4加密
回到encode函数
可以发现最后将加密后的字符串给到了final
¶Base64加密
对final查看交叉引用,发现对其进行了加密
这里解释一下一些东西
我们base64就是将三个字符也就是24位转为4个6位,做索引,这里使用移位直接将三个字符成为一个int型,也就是每个左移8位,而待会取出的时候右移六位即可取出,实现了8位与6位的转换,比较有意思
在红框函数中将传入的6位索引进行+24,也就是(index+24)%64,我们可以将base64表整体左移,就相当于index+24了
再对base64表查看交叉引用,发现了将大小写转换
¶换位
可以看到这里将最后用来对比的字符串每两个字符进行互换
¶脚本
1 |
|
得到59D095290DF2400614F48D276906874E
SM4解密
https://the-x.cn/cryptography/Sm4.aspx
¶[SWPU2019]ReverseMe
¶考点
异或、ZUC算法
¶分析
先异或SWPU_2019_CTF,再异或ZUC算法生成的数据
ZUC算法生成异或的值
unsigned int 的异或,通过动调也可以知道
¶脚本
1 | unsigned int data[8] = { |
¶[MRCTF2020]EasyCpp
¶考点
异或、替换,素因数分解
¶分析
一些关键的都已经标识出来了
¶读取输入
读取9次key,并且拼接起来
¶异或
这里面是和1异或
¶素因数分解
这里只要能整除i,就重新进入递归,参数为整除i后的数,如果i遍历完不符合,结束循环,然后拼接上空格
¶替换
将数字换成字母,空格换为=
¶比较
红框数组存储的是最后比较的字符串
¶脚本
这里我直接手动替换算出来的
1 | printf("%d", (293 * 8) ^ 1); |
md5即可
¶SCTF2019-Creakme
¶考点
AES-CBC加密、Base64加密、反调试、SMC
¶分析
¶反调试、SMC
一看到这种遍历段名称的操作,熟悉SMC自解密的应该知道这是敏感的操作,也就是解密操作
对于这种在输入开始前的反调试,采用attach to process
可以看到如果不是调试状态,就将数据强制转为函数指针
这里已经解密完并执行完程序了
对其交叉引用可以看到
¶AES-CBC、Base64加密
动调发现这就是加密函数
可以知道该函数就是初始化密钥
从这里的明文异或结合CBC可以知道是CBC模式
key和iv分别为sycloversyclover、sctfsctfsctfsctf
这里很多this指针,但是我们还是可以通过一些特征以及FindCrypt发现这是AES中的key的初始化
AES-CBC加密
进入该函数中,明显是base64加密
找到码表,发现没有被改过
¶比较
¶解密
¶SCTF2019-babyre
¶考点
base64解密、Maze、移位与异或、花指令
¶分析
花指令就不说了,全部都是一样的,去除即可
迷宫也没啥说的,注意这里是三维迷宫 ddwwxxssxaxwwaasasyywwdd
¶base64解密
可以看到这里先将我们的输入去table找索引,然后&0x3F取出最后的六位,按位与上v5左移6,这样就得到了8位的字符,加上=4的判断,类似于base64的解密操作
直接将最后的字符串加密即可c2N0Zl85MTAy
¶换位异或
加密流程:每四个输入存入int型的变量,然后进行xor_enc加密,将前四个字符加密后存放到第四个字符的后一个字符,依次往后。
之所以要这样进行移位是因为如果强制转为int型,由于小端序,存储的时候是12345678,这样int取出的时候就变成了4321
xor_enc加密流程:将第二第三第四个字符进行异或,分为四个字节去table找到对应的值,然后重新组合成int型,再经过一系列左移右移异或操作并返回,再将返回值与第一个字符异或,这样就得到了一个加密后的结果,这里要一直等到index<=29,也就是前四个字符不会加密
我们可以看到这里v10只有26,那么26、27、28、29下标的v10就赋值给了v11、v12、v13、v14
取出最后四个int型存储的十六个字节,存储到enc_flag数组,然后比较
假设int a=0x12345678,那么HIBYTE(a)=0x12,BYTE2(a)=0x34,BYTE1(a)=0x56
这样我们就知道了最后的四个int型的元素,往前推,29是怎么来的呢,是flag[25]enc(flag[26],flag[27],flag[28])得到的,所以flag[29]enc(flag[26],flag[27],flag[28])即可得到flag[25],前面的元素同理
¶脚本
因为涉及了ida的左右移位操作,而ida目录下defs.h有定义,所以可以直接引用
1 |
|
这样子就不会存在int型读取时小端序的问题