周末打了一下红帽杯,Reverse比较简单,解了XX、easyRE以及childRE,简略写了 下writeup
XX
程序首先校验前四个字符是否在”qwertyuiopasdfghjklzxcvbnm1234567890”这个字符集
1 | v17 = xxtea((__int64)Code, v3, (unsigned __int8 *)&v30, &Size); |
之后进行xxtea加密,密钥为前四个字符,明文为输入的19个字符+0x00000013,密文为6*32bits,24个字符
接下来是一个一一映射的关系,改变密文顺序,最后是一个比较简单的异或算法,结果与常量进行比较
1 | *(_QWORD *)&v30 = 0xC0953A7C6B40BCCEi64; |
直接还原出xxtea密文,爆破密钥,复杂度为36**4
1 | #include <stdbool.h> |
flag{CXX_and_++tea}
easyRE
main函数解出了一个提示还有彩蛋
1 | ➜ hmb ./easyRE |
根据提示最后发现了
1 | unsigned __int64 sub_400D35() |
尝试解一下
1 | byte_6CC0A0 = [0x40,0x35,0x20,0x56,0x5d,0x18,0x22,0x45,0x17,0x2f,0x24,0x6e,0x62,0x3c,0x27,0x54,0x48,0x6c,0x24,0x6e,0x72,0x3c,0x32,0x45,0x5b] |
flag{Act1ve_Defen5e_Test}
childRE
前面是一个一一映射关系,改变输入字符串顺序,先不管
之后对输入字符串反修饰C++ 符号名
1 | UnDecorateSymbolName(v5, outputString, 0x100u, 0); |
限定输入长度为31,输出长度为62,之后是一个简单的比较算法
1 | do |
先还原出c++函数名
1 | src ='1234567890-=!@#$%^&*()_+qwertyuiop[]QWERTYUIOP{}asdfghjkl;\x27ASDFGHJKL:"ZXCVBNM<>?zxcvbnm,./' |
得到原函数名
private: char * __thiscall R0Pxx::My_Aut0_PWN(unsigned char *)
根据c++规范手撸修饰后的符号,得到
?My_Aut0_PWN@R0Pxx@@AAEPADPAE@Z
前面说过有一个一一映射的关系,懒得逆了,输入
1234567890abcdefghijklmnopqrstu
得到输出
fg8hi94jk0lma52nobpqc6rsdtue731
直接将结果映射回去得到真正的输入,md5得到flag
1 | s1 = 'fg8hi94jk0lma52nobpqc6rsdtue731' |
flag{63b148e750fed3a33419168ac58083f5}
Calc
这道题是赛后才搞出来的,cpp、stl太恶心(还是太菜了
主要都是动态调试调出来的,程序逻辑大概就是输入三个整数然后计算
1 | v24 = (char *)x[0]; |
上面这一段是校验 输入的三个整数 x、y、z 中 x<z && y<x
接下来就是 加、减、乘、幂运算了,连蒙带猜理清了一些逻辑关系
1 | v40 = mul(&v146, v135, x); // v40 = 3*x |
这一部分计算了 (x+y)*3 - 3xyy - 3xx*y
下面还有一部分计算了 (z+4)3 - 12*(z2) - z*48 - 22
最终校验两部分是否相等
化简可以得到一个丢番图方程
x3+y3-z**3 == 42
参考https://en.wikipedia.org/wiki/Sums_of_three_cubes
得到结果
1 | x == 80435758145817515 |
flag{MD5(“804357581458175151260212329733563180538738812075974”).tolower()}
get flag flag{951e27be2b2f10b7fa22a6dc8f4682bd}