2019 *CTF
赛后复现, 学习学习!
yy
题目:yy
这题真是调和猜出来的0.0…..
根据调试和猜测, 从yylex()函数中的yysec[]数组可以猜出合法字符为。
yyaccept = [] |
猜测为:*CTF{0123456789_abcdefghijklmnopqrstuvwxyz}
继续调试可发现, 程序会根据输入字符从box[]中取出对应的字符替换buffer中的字符, 而“_”
则是调用aes_cbc_encrypt进行加密, 并更新buffer。最终和cmp进行对比:
switch ( (unsigned int)&savedregs ) |
则解密脚本如下:
from Crypto.Cipher import AES |
由于append中有可转化字符, 所以打印出来后手动除去hhhhh……..
最终flag如下:
*CTF{yy_funct10n_1s_h4rd_and_n0_n33d_to_r3v3rs3}
fanoGo
题目:fanoGo
本题一路连猜带蒙。。。
根据输出Say something:
找到主要函数…….看不懂, 开始调试:
输入后会经过fano___Fano__Decode
函数进行解码(为什么是解码名字说的很清楚hhh), 解码后长度为0x15A, 由该语句确认:
if ( e._type == (runtime__type_0 *)0x15A ) |
后进入runtime_eqstring()函数进行对比, 汇编代码如下0.0:
.text:0000000000456B83 cmp rbx, 40h |
而调试着可以发现对比对象就是这串:
"If you cannot read all your books...fondle them---peer into them, let them fall open where they w" |
尝试搜索Encode函数, 还真有hhhhhh, patch上去, 将上面那串进行编码就得到我们的输入。
脚本:
from pwn import * |
由于是后面做的, 端口已经关了, 所以只能本地打了hhhhhh
Matr1x
题目:Matr1x
题目一打开, 通过start找到main函数。
.text:00002620 start proc near ; DATA XREF: LOAD:00000018↑o |
去花指令和冗余代码
…..一堆花指令和冗余代码。那就去掉咯。
其中, 除去全局变量的代码如果之间在全局变量赋值处patch会出问题, 来自Apeng大佬的指导:
问题出在pie的重定位上了, 由于程序原本开启了pie, 对全局变量引用的时候地址是会变的, 所以elf运行的时候会把所有这些全局变量的引用都patch成重定位之后的。而他查找的方式肯定不是根据语句来查, 可能是有个表, 所以所有这些全局变量都会被patch。所以只需要把mov eax, 0xxx这句话patch到其他地方就行了
所以稍微修改了一下, 最终如下:
bg = 0x00002620 |
之后就可以F5, 但是由于IDA是软件分析, 所以那些函数得一个个F5…..
之后再手动去掉冗余代码, 就可以很愉快的分析了:
printf(format); |
算法
for ( i = 0; i < v8 / 2; ++i ) |
这个循环将输入每两位一组转成十六进制数:例如输入1234会转成0x12, 0x34
主要操作为sub_39C7(v9);
int __cdecl sub_39C7(char *s) |
根据case可以知道我们输入的范围:10~15, 20~25, 30~35
随便进去一个看一下(这里也有一些冗余代码我手动去掉了, , 便于分析):
int sub_6D47() |
应该是个轮换。
再根据经验不难推出, 这应该是一个3阶魔方:一共6个面, 每个面有9个元素, 共有3*6=18种操作
判断函数sub_4638():
int sub_4638() |
可以分析出, 该判断为每个魔方的:
sum(center + middle)==cmp[2 * i]
sum(center + coner)==cmp[2 * i + 1]
而得到flag的循环:
for ( i = 0; i < 6; ++i ) |
穷举求解
由上述分析, 由于corner[4*6], middle[4*6], center[6], 数据量小, 可以通过穷举的方法求解:
提取
mul_cube = [[0xB849CD19, 0x55E00017, 0x844966B, 0x80C181EC, 0x686C0B3C, 0x55400592, 0xCD42168A, 0x4039E81, 0xD9DE549F],[0x2034677D, 0x144ABD, 0x49100D00, 0xE003A0E0, 0x80F0006D, 0x8307ADD6, 0x4CF60781, 0xA0352643, 0xC580C3DE],[0xEA8C4E24, 0x68603008, 0x687FBFFF, 0x19DE4BF9, 0x271A1179, 0x99791C4D, 0x29CBFFC, 0x2B82801E, 0x3C0307FB],[0xDAE61CD6, 0x8F7B1BF0, 0xC56CEF1D, 0xD6493A96, 0x1808018, 0xF48001B9, 0x3712519, 0x9294F318, 0x6DE20384],[0xF3750B04, 0x256A122A, 0x257290B, 0xC4582056, 0x204E8BC0, 0x79C7ADE7, 0xC4C20203, 0x5B961570, 0x66034856],[0x78329E3A, 0x1D07C00, 0x4AC240E6, 0x854CFBBE, 0xABFEC404, 0x5BD80037, 0xE94CBCD8, 0x1, 0xC4CA280D]] |
组合求值
用cmp来center的确定值以及对应corner, middle的取值
import itertools |
排列组合, 穷举求解
用可见字符进行过滤
center = [0xdf7502ce, 0x9967f311, 0xdc9e8f3c, 0xfe32ed8f, 0x19382448, 0xfb5a012f] |
得到:
------------------- |
根据词义不难猜出flag为:
*CTF{7h1S_Cu63_is_m4g1c}
Obfuscating Macros II
题目:[Obfuscating Macros II](https://raw.githubusercontent.com/Alikas0/CTF/master/challenges/StarCTF-2019/Obfuscating Macros II.zip)
根据题目混淆宏emmmmmm不懂
运行下程序
./obfuscating_macros_II.out |
IDA打开找到main函数:
v21 = __readfsqword(0x28u); |
程序流程
根据调试:
首先判断输出长度是否为16:
if ( v3 != 16 ) |
接着进入encrypto函数进行加密, 加密后判断:
if ( v16 != 0xA1E8895EB916B732LL || v17 != 0x50A2DCC51ED6C4A2LL ) |
重点就是在encrypto函数咯。
加密函数
进去以后发现根本看不懂….调试大法好!
首先是将输入切成两段, 长度为8:
接着在栈里面看哪里对这两块地方进行了操作, 这里我输入了11111111AAAAAAAA:
得到:
首先来到了v16 = 0, 判断v16 <= 0x3FF, 那么回到这里就是一个循环咯:
接着第一段取反
v8 = ~v7; |
接着
if(v7&1) |
为真则
v8^=*v5 |
这里看到v8 指向了v6, v5 指向了v7
接下来就是
v6 = v8 |
再接着根据调试不难发现, 接下来就是对整一个128位字符进行循环左移1位.
因为一开始if(v7&1)
为真, 这次我们输00000000AAAAAAAA:
得到v8^=*v5
此时v5变成了指向~v7, 而之后就都一样了。
不难写出加密算法:
def Andf(str): |
则解密脚本为:
def Andf(str): |
得到flag:
*CTF{fUnfl@tCf9}
验证
./obfuscating_macros_II.out |