FZNCTF Writeup

FZNCTF Writeup
卿欢颜Crypto
sign
解密
打开得到这一串密文,一眼Base64了;
flag{w@rm_up_m@n_wh@t_c@n_i_s@y}
babyRSA
[CTF Crypto RSA合集(新生赛难度)_swpuctf 2021 新生赛]crypto1-CSDN博客
可以看看这个博客,关于RSA;
1 | import gmpy2 |
两c两e,一个n;直接调用博客里面的代码了,修改数据即可;
1 | from gmpy2 import * |
运行即可得到flagFZNCTF{D0_U_kn0w_c0mm0n_m0du1u5_4tt4ck?}
Reverse
诸神的三试炼
1 | // local variable allocation has failed, the output may be wrong! |
全是字符,有点多,动调一下;
跟进得到第一段flag;
第二段;
得到一个假的第三段;
shift+f12看到一个,按任意键退出,跟进看看,目前我们还没到这里;
一个随机种子的异或,跟进提取密文,直接写脚本就行;
1 |
|
三段连起来加上头就是flag;FZNCTF{G00d!!!_N0w_y0U_c@n_Use_IDA!!!}
LZM爱恋日记
下载得到这么个东西,.exe文件是c++写的,放入IDA里面依托,太冗杂了,没找到;直接运行.exe看看;
迷宫题?这个还不是正常的键位…强行爆破10000次了;
1 | eeeessssseeessA |
上面txt文件;
1 | import time |
这是之前用过的脚本;可恶的出题人,爆破这么久给我说是错误的flag???
醉了…看看另外一个;C#写的,用dnspy打开看看
可以找到这么个玩意,逐字节异或;写解密脚本;
1 |
|
少了个头,懒得纠结了,手动添加;FNZCTF{1zm_find_h1s_9ir17riend}
lzm出逃日记
嗯…少复制了几个密文,导致解密的时候一直差几位明文…4*8=24?我也不知道自己怎么算的;
这个位置有个显而易见的SMC自异或;动调修改一下;重新反编译可以得到如下的伪代码:
1 | unsigned int sub_401550() |
这里就只有一个简单的异或…多复制点,4*8=24我真没招了;
这里有个异或,密钥也给了;
没招了...FZNCTF{Th@nk_y0u_f0r_h3lp1ng_1zm}
GoTea
Go语言,就一个反调试,也是脑子抽了,没做出来;
四个函数,Input、Debug、TEAdecrypt、main;实则就只有一个反调试,过了就行…TM以为这个是TEA加密;
在调试的地方下断点找到在哪调试的,直接nop掉(这也行?我还准备进去看看怎么绕过呢)…
然后回到TEAdecrypt函数的返回点,查看:
这里看出来v23是解密的块,v23是从v1来的,跟进查看:FZNCTF{R3ver5e_G0g0Go_H4v3_4_G00D_D4y}
babyvm
Frida
爆破条件:
- 单字节比较–>如果明文和密文之间是通过数组一位一位的比较的就可以使用此方法,我们可以通过不断的变换明文每一个位置的字符,直至加密后的明文和密文相匹配,证明我们得到了这个位置的正确明文,循环上述操作直至得到所有明文;通过此思想可以判断,多字节比较也是可行的,将多字节作为一个整体就行,不过,鉴于可见字符集是100位,如果当两位字节为一组的时候爆破时间和难度就成指数级上升了,单字节需要爆破100位,双字节就需要爆破100^2位,以此类推,所以当解密块的字节大于4字节时,不考虑爆破;
- 可以同过输入明文并且微调明文的字符对比加密后的密文可以知道密文是不是单字节加密的,如果每个明文间不是独立加密也不可用Frida爆破;
爆破理论:
- 由于是通过数组来比较明文和密文的,所以相关数组必然会有一个索引自增的位置,我们就可以通过数组的自增知道这个位置爆破的字符是等于明文的;
- 如果此时爆破的字符不等于明文,必然会有一个条件判断,使得程序跳转到错误指令的地方,我们可以通过此条件的变化知道此时爆破的字符不等于明文,于是尝试下一个字符的爆破;
爆破方法:
- 基于条件断点的理论,等同于在程序的固定位置增加函数,因此我们可以在索引自增的地方增加一个函数,功能为:输出此时爆破的字符,即明文;并且尝试下一位明文的爆破;
- 在程序进入错误函数的条件的位置增加一个函数,功能为输出下一位爆破字符,并且再次判断是否触发函数的判断条件;
BUUCTF-[MRCTF2020]Xor
frida学习了,试试之前没有得到的题,直接修改脚本,自增的地方地址为10E0,判断错误的地方为10FF,退出的地址为4B7E(地址110E处调用的函数);flag长度为0x1B;光速套用脚本修改即可;
1 | //Frida脚本 |
1 | #python脚本 |
**MRCTF{@_R3@1ly_E2_R3verse!!3verse!}**修改头即可;
babyvm
鉴于需要动调,需要先绕过一下反调试,30行开始调试的检测,63行才检测完调试开始正常的主函数,因此直接从29行的函数执行完时跳到63行正常主函数即可;
将这里的跳转函数指令修改即可,记得保存;
这是两次不同输入对比的密文,可以看出来这里只有第一位密文不一样,所以推断是单字节加密;各位可以再试试,鉴于是复现并且之前已经试过,故不再尝试;
跟踪输出”Correct!“可以很容易的找到加密过程;
这里可以动调发现algn_7FF674005664这个东西是传入的明文flag,但是在加密函数外交叉引用str会发现找不到引用,原因是因为”数组越界访问(不知道叫这个名字合不合适,但是个人是这样理解的)“;在这里可以看到明文的地址应该是7FF674005664,但是真正查看明文的时候会发现,明文的地址是7FF674005670,查看附近的汇编看看,可以发现它将5665h作为了基地址,然后使用rdi+rax的变化来访问数据,究其原因理解是:”数据段在内存中是连续的,假设我们定义两个数组a[10]和b[10],在正常情况下,我们应该是无法访问和编译a[11]的,但鉴于数据段内存的连续性,我们可以通过a[11]来间接访问b[0],a[11]是从a的地址之后的第11个数据,但恰好a首地址往后推的第11个数据的地址就是b[0]的地址,此时我们访问到了b[0],但是我们想要引用b的话,程序自然无法找到在哪,因为对于程序来说,它本身是没有调用b这个数组的,但它确实使用到了b这个数组的数据“;
回到加密逻辑,显然IDA反编译得到的伪代码很难看,所以这里在单字节加密的前提下,考虑爆破;向下查看一下明文和密文的比较逻辑;
随便看看伪代码,就可以去对照着汇编寻找我们爆破需要的东西(地址)了;v25是程序是否退出的条件,也就是明文和密文比较成功与否的标志;
大致了解后,我们就可以去套用Frida脚本了;
脚本一
1 | //Frida脚本 |
1 | #python脚本 |
脚本二
在前面绕过动调的基础上,将程序结束跳回main函数,实现死循环,避免程序退出,方便持续爆破;
main函数的最后,这里有防止栈溢出的检测,也就是call指令这里,所以需要给这个地方修改一下,从lea这个指令开始,打开Assemble复制指令,从xor这个指令接着打开Assemble覆盖,重复直至retn;最后就算修改完成了;
试过了,不该报错了;按照上面修完就可以了;
1 | //Frida脚本 |
1 | #python脚本 |
1 | #checkflag脚本 |
感觉原理都差不多,解毕 FNZCTF{1t_is_an_e4sy_vm}
Misc
Misc-有趣的emoji
进去第一个压缩包密码,看文件名得到压缩包密码FZNCTF,跟进得到txt文件和一个asc文件,以及一个压缩包;
???对这句话RSA加密???,当时比赛理解的是对这串英文字符进行RSA加密…最后发现RSA加密的私钥每次分解出来的私钥对是随机的啊…这怎么处理?
我以为这串是私钥…没看出来PGP是一种加密;后面比完赛了才知道,才疏学浅了;直接给这串丢到CyberChef上了;
前十二个字符就是压缩包密码“wcBMA2Uwnbca”
比赛前一天才聊到emoji是Base100加密…结果困在压缩包密码了…
FZNCTF{M1sc_15_s0_f45cin4ting!}










































