d3CTF2023
d3CTF2023
AntCTF x D^3CTF 2023 题目复现
d3sky
32位打开,加了TLS反调试
利用除零异常将密钥改为YunZh1JunAlkaid
然后进行rc4加密
主函数的逻辑比较简单的虚拟机
以v9为偏移然后读取三个字符后进行rc4加密
将加密后的数据作为操作码进行执行
然后再加密打乱Sbox
首先提取出指令码进行解密
1 | arr = [0x009E, 0x0028, 0x00F5, 0x0075, 0x0073, 0x0073, 0x0030, 0x007E, 0x0048, 0x0048, 0x00F2, 0x002F, 0x003D, 0x00EC, |
看出指令码非常的有规律
虽然这个虚拟机只有与非运算,但是众所周知,与非门是一种通用的逻辑门,因为任何布尔运算都可以用与非来实现
A ^ B = !A * B + A * !B = !(AA) * B + A * !(B*B) = !( !( !(AA) * B ) * !( A * !(B*B) ) )
然后动调获取密文
写脚本
1 | from z3 import * |
flag{A_Sin91e_InS7rUcti0N_ViRTua1_M4chin3~}
d3rc4
64位
只是rc4加密,直接动调提取异或的keystream
然而解密后是假flag
1 | fake = [0xDB, 0xB6, 0x2A, 0x04, 0xC7, 0xB9, 0x68, 0xE0, 0xBD, 0x3E, 0x04, 0x6F, 0xD3, 0x38, 0x10, 0x6B, 0x4A, 0xE5, |
c0ngratul@t1ons_but_i_am_n0t_f1ag
调试以及查看函数表可知
在main函数之前有init函数,负责对key以及输出的初始化
在main函数之后,还有fini对输入做进一步的校验
大概分析了一下他fork调用的流程
总的来说,利用管道对key进行修改。打开一个子进程然后修改key
子进程又打开子进程。
因为有wait函数,当前进程会等待其子进程结束后再继续运行
利用gdb进行调试
首先在fork出下断
这里会进行创建子进程,因此如果想要跟踪子进程,就得将gdb的跟踪模式从主进程切换到子进程
1 | set follow-fork-mode child |
切换到子进程后在校验处下断
对应ida里面的
提取rdx里面的值,写脚本
1 | flag = [0xF7, 0x5F, 0xE7, 0xB0, 0x9A, 0xB4, 0xE0, 0xE7, 0x9E, 0x05, 0xFE, 0xD8, 0x35, 0x5C, 0x72, 0xE0, 0x86, 0xDE, |
getting_primes_with_pipes_is_awesome
d3recover
附件是两个文件ver1无符号而ver2有符号
利用bindiff恢复符号
找到可疑的函数
看起来很复杂但是很多都是对函数异常时的处理,只要关注其调用的python函数即可
简单化简一下逻辑
1 | for(int i = 0; i < 32; i++) { |
然后就是猜了,看了别的师傅的wp,可以通过调试来调试出最后做比较的字符
但是我找不到。
留意到有一串疑似经过base64加密的字符串
长度也对的上,将其base64解码后再解密
1 |
|
flag{y0U_RE_Ma5t3r_0f_R3vocery!}
d3syscall
ida64
点开函数,发现全是自己定义的Linux系统调用
找到注册的函数下断,然后将生成的my_module文件丢进ida
my_module中定义了每个系统调用号对应的函数,发现是个虚拟机
最后写脚本
1 | import z3 |
1 |
|
d3ctf{cef9b994-2547-4844-ac0d-a097b75806a0}
d3hell
To be continue……