DRKCTF-复现
我们开展的DRKCTF!
没打,而且好难,所以跟着wp把它复现出来
CRYPTO
密码_sinin
1 | from Crypto.Util.number import * |
这个是LCG线性同余随机数生成器
原理是攻击线性同余生成器(LCG) (zer0yu.github.io)
过程:
- 求m
- 求a
- 求b
- 求seed
这里由于是间隔一个来给X,所以求到$a^2$之后不好求a,太大了,所以要以$a^2$作为新的a,$(a+1)b$作为新的b
求到后就可以穷举2的16次方爆flag
1 | import math |
还有第二种方法
Grobner基求解多项式多个根,但是不会,给个D神的链接QAQ
EzDES
一开始没想到QAQ
DES 弱密钥 - lightless blog看看佬的blog
有四个弱密钥是绝对不能使用的:
1
2
3
4 \x01\x01\x01\x01\x01\x01\x01\x01
\xFE\xFE\xFE\xFE\xFE\xFE\xFE\xFE
\xE0\xE0\xE0\xE0\xF1\xF1\xF1\xF1
\x1F\x1F\x1F\x1F\x0E\x0E\x0E\x0E如果不考虑校验位的密钥,下面几个也是属于弱密钥的:
1
2
3
4 \x00\x00\x00\x00\x00\x00\x00\x00
\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF
\xE1\xE1\xE1\xE1\xF0\xF0\xF0\xF0
\x1E\x1E\x1E\x1E\x0F\x0F\x0F\x0F如果使用弱密钥,PC1 计算的结果会导致轮密钥全部为 0,全部为 1 或全部 01 交替。
因为所有的轮密钥都是一样的,并且 DES 是 Feistel 网络的结构,这就导致加密函数是自反相 (self-inverting) 的,结果就是加密一次看起来没什么问题,但是如果再加密一次就得到了明文。
部分弱密钥
部分弱密钥是指只会在计算过程中产生两个不同的子密钥,每一个在加密的过程中使用 8 次。这就意味着这对密钥 K1 和 K2 有如下性质:
6 个常见的部分弱密钥对
- 0x011F011F010E010E and 0x1F011F010E010E01
- 0x01E001E001F101F1 and 0xE001E001F101F101
- 0x01FE01FE01FE01FE and 0xFE01FE01FE01FE01
- 0x1FE01FE00EF10EF1 and 0xE01FE01FF10EF10E
- 0x1FFE1FFE0EFE0EFE and 0xFE1FFE1FFE0EFE0E
- 0xE0FEE0FEF1FEF1FE and 0xFEE0FEE0FEF1FEF1
OpenSSL 中对弱密钥的检查
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 119 static const DES_cblock weak_keys[NUM_WEAK_KEY]={
120 /* weak keys */
121 {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01},
122 {0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE},
123 {0x1F,0x1F,0x1F,0x1F,0x0E,0x0E,0x0E,0x0E},
124 {0xE0,0xE0,0xE0,0xE0,0xF1,0xF1,0xF1,0xF1},
125 /* semi-weak keys */
126 {0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE},
127 {0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01},
128 {0x1F,0xE0,0x1F,0xE0,0x0E,0xF1,0x0E,0xF1},
129 {0xE0,0x1F,0xE0,0x1F,0xF1,0x0E,0xF1,0x0E},
130 {0x01,0xE0,0x01,0xE0,0x01,0xF1,0x01,0xF1},
131 {0xE0,0x01,0xE0,0x01,0xF1,0x01,0xF1,0x01},
132 {0x1F,0xFE,0x1F,0xFE,0x0E,0xFE,0x0E,0xFE},
133 {0xFE,0x1F,0xFE,0x1F,0xFE,0x0E,0xFE,0x0E},
134 {0x01,0x1F,0x01,0x1F,0x01,0x0E,0x01,0x0E},
135 {0x1F,0x01,0x1F,0x01,0x0E,0x01,0x0E,0x01},
136 {0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1,0xFE},
137 {0xFE,0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1}};有弱密钥的加密算法
- DES
- RC4
- IDEA
- Blowfish
摘抄完QAQ,再根据提示
二次加密得到明文
1 | from Crypto.Cipher import DES |
MidRSA
这道题没写完
1 | from Crypto.Util.number import * |
第一部分
这里有两个c,知道n是m<<300,只要找到模数n,就找到了m,构造$c_i=m^{e_i} \mod n$改写成${c_i}^{e_j}={{m^{e_i}}^{e_j}} ={c_j}^{e_i}\mod n$这样两数之差就是kn,再来一个kn,求gcd即可
第二部分
这里重看一下共模攻击和CRT:
中国剩余定理(CRT)及其扩展(EXCRT)详解 - ailanxier - 博客园 (cnblogs.com)
这里要想到三个e对应三个方程,不能简单当成gcd(e1,e2,e3)
把它当成两次共模攻击
1 | # from prism import * |
REVERSE
elec_go
佬出的题,第一次见
根据
Electron编写的exe 逆向思路 - 『脱壳破解区』 - 吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn
1 | npm install asar -g |
打开js源代码,有一个base64,解密之后发现是aes,但是不知道key,直接写一个
1 | dialog.showMessageBox({ |
重新打包,拿到key的值,在线解密
flower_tea
在这里说一下出题思路吧QAQ
这个题本来是想考一下去花指令的,没想到有佬直接调出来了,tql
花指令基本都很萌新QAQ,对栈做操作或者call,ret。
想了一下,可能反调试比花出的还好一点。毕竟x64的和x86有一点不一样。
感觉还有可以改进的地方:
隐藏交叉引用-用多级指针来隐藏交叉引用
真tea中jmp修正为jz和jnz,这样能起到一些混淆的作用
防止附加调试-在scanf之后再次判断调试状态,修改hook
但是都不会QAQ,还是要好好学,下面抄的官方wp
观察main函数:
主函数的大概是这样。
如果要调试,要先把第一个函数nop掉(实际上并不用)
这里先看encode函数,点开后是爆红的,所以先解花指令
这个是一个简单的jmp花指令,把后面的jmp nop掉,然后可以看到第一部分。
这时最上面还是有标红
在汇编界面看看哪里还有花
这里有一个奇怪的call:
逻辑是:call完之后把ret的值+0xC然后返回
把这一部分按u解除,在加0xC后的位置再反编译
所以ret之后就会到pop的位置
把中间这一段全部nop,然后把整个函数u,然后c,再浏览一下函数,中间有一个怪jmp,删掉
然后再p,得到解完花的函数
1 | __int64 __fastcall encode(__int64 a1, __int64 a2) |
这个的特征很明显是xxtea,并且没有魔改,网上直接搜脚本
exp:(需要用clang)
(网上的脚本https://www.cnblogs.com/zpchcbd/p/15974293.html)
1 | #include <stdio.h> |
得到假flag:
1 | DRKCTF{Sorry.There_is_no_more_flower_tea.Please_try_again!!} |
很明显,这个不是真flag,这说明:
动态调试的时候和正常的时候运行的逻辑不一样
第一时间会想到这个可能是smc或者hook
所以先查看encode的交叉引用。
于是找到这个函数:
可以看到上层函数
修改了encode中的前几个字节用ret的方法返回到sub_140012A0中
这里的第一个是反调试,在x64下,调试标志位在PEB表偏移0x2的位置,通过获取gs寄存器找到peb表的位置:
readsqword(0x62)得到调试标志位并判断当前进程是否在调试
block是单纯地得到对应的两个函数地址
get_virtual_protect中,通过异或把virtualprotect函数名隐藏并通过搜索它在kernel32.dll中位置返回函数地址
通过上面的分析,可以得出我们需要查看sub_140012A0的内容,这里才是真正的加密函数
打开,还是花QAQ
汇编中,可以看到函数后段全是一个指令+一个jmp
由于汇编不是很好看,改成流程图看奇怪的地方。
可以猜测:如果一个地方有一块代码,并且有连续jmp,这里可能是人工加的花
那么就先看一下那个很远的环和上面一排没有入口的块
1
这里能看到push和pop,所以从push进入花,从pop离开花,可以看出可以这样还原
2
这里有一个call,尝试跟着call走,它下一步修改了返回地址,减去5A
即:140001460
转换一下这里的指令
所以把call nop了就好
3
nop之后
然后全部u,c,p还原函数
这里又可以看到上面的一个奇怪return,看汇编可以发现还是一个花
直接把call到retn去掉(除了shl)
这是一个变体tea,尝试化简这个函数
写脚本直接解
exp:
1 |
|
Debug
die看不出来壳,但是ida可以,所以用x64dbg到脱完壳的地方,
不过得先调试,结果用ida调试直接寄在tls的call rax里面,用x64dbg一点事都没有,百思不得其解,最后发现
tls里面有个反调试,在解壳之前,所以得先跳过,dbg里面自带的插件直接秒了,所以dbg就没事QAQ
这个感觉很不错,要是有办法在ida里面用就好了
记录一下用工具修复iat表的过程:
x64dbg 插件 scylla
去反调试,然后把smc搞出来,直接解
1 | from prism import * |
一起做杯下午茶吧
不会QAQ
Osint
羡慕群友每一天
直接开搜
发现不是中间圆心的位置好像不一样
找另一个
1 | DRKCTF{美国-弗罗里达州-迈阿密-Skyviews} |
1 | DRKCTF{美国-佛罗⾥达州-迈阿密-Skyviews} |
1 | DRKCTF{美国-佛罗里达州-迈阿密-Skyviews} |
1 | DRKCTF{美国-佛罗里达州-迈阿密州-Skyviews} |
1 | DRKCTF{美国-佛罗里达州-迈阿密市-Skyviews} |
第五个是对的
Misc
DNA -5
提示:遥遥领先
抽象的题,没看wp之前我绝对想不到QAQ
1 | ACGCTAATACCATCAACTCCATAACTCCCCACCTAAATCCAATAACCAGCTAAATCCAATAACCACTACCCCTCCATAAGAGAATAACCACTCATCCCCCTAATAAGAATAAACCTCCCCCAC |
根据wp,由遥遥领先想到5G,又因为-5,所以可以想到要少5个G
1 | ACCTAATACCATCAACTCCATAACTCCCCACCTAAATCCAATAACCACTAAATCCAATAACCACTACCCCTCCATAAAAATAACCACTCATCCCCCTAATAAAATAAACCTCCCCCAC |
看这个可以先试试DNA解密
不行
结果是摩斯
1 | WIPXGU7bSZ_SZ_1G5_N0IH3 u7d u |
然后解atbash
1 | DRKCTF{HA_HA_1T5_M0RS3} |