BUUOJ DudeLocker/babyunic /gdssagh/[SCTF2019]music/sabataD Writeups
ahh, 因为感觉一道题发一个帖子有点太占用大家空间了, 通过回复判断其实即使我打上CTF这个标签,来看的也不一定是真想看的, 所以以后wp都五道题一发了这五道题略水, 但是都是99-100分的题
---
## DudeLocker
Win32程序, 给了一个PE和一个应该是被加密了的doc
!(https://tianyu.xin/usr/uploads/2022/04/3552325705.png)
全是WinAPI, MSDN先备好
!(https://tianyu.xin/usr/uploads/2022/04/3768358630.png)
关注一下预处理, 16是Desktop, Filename是~\Desktop\Briefcase,如果打开失败就说你显然不是Re, 否则进else关闭文件句柄
到第42行获取卷序列号, 要求必须是0x7DAB1D35, 下面申请堆就不关注了, 直接关注1940
!(https://tianyu.xin/usr/uploads/2022/04/3358284832.png)
a3就是上面的十六进制, a1是一个明文表, 注意端序, 应该是0x35, 0x1D, 0xAB, 0x7D
!(https://tianyu.xin/usr/uploads/2022/04/3386254320.png)
直接解一下`thosefilesreallytiedthefoldertogether`
!(https://tianyu.xin/usr/uploads/2022/04/2159871605.png)
1080长这样, WinCrypt, 看上去1180比较重要因为和上面的字符串有关
!(https://tianyu.xin/usr/uploads/2022/04/78388549.png)
!(https://tianyu.xin/usr/uploads/2022/04/3944898832.png)
把上面的SHA1掉
!(https://tianyu.xin/usr/uploads/2022/04/2065242541.png)
6610则是AES256, 用哈希值产生一个秘钥, 一层层返回到main的hKey里
!(https://tianyu.xin/usr/uploads/2022/04/2290780357.png)
关注1300
!(https://tianyu.xin/usr/uploads/2022/04/3836823246.png)
4030F4是\\*, 后面接一起把filename下的所有文件都加密之应该是
!(https://tianyu.xin/usr/uploads/2022/04/2555006911.png)
!(https://tianyu.xin/usr/uploads/2022/04/2968305921.png)
8003都能背下来了, MD5
把传进来的第四个参数Hash之后SetKey, 具体Set的是一个IV,之后没再做别的了, 回main关注1500
!(https://tianyu.xin/usr/uploads/2022/04/1316169875.png)
a1是key, 这瞎猜都能猜到了吧..
就是以一个明文SHA1为秘钥生成根, 用CryptoAPI生成一个AES-256的秘钥, IV是文件名的MD5
因为本身用Python模仿CryptoAPI生成秘钥挺麻烦的, 分析通了就做到这儿了.
---
## babyunic
看名字就看得出来是Unicorn题, 有两个so和一个func, 猜测是OPCODE
!(https://tianyu.xin/usr/uploads/2022/04/561782806.png)
把un.so给babyunic, babyunic负责主逻辑, 这是baby的main, 读入到v5之后扔CBA里, 最后和明文对比, 拿出来不亏
```c
unsigned char ida_chars[] =
{
0xFF, 0xFF, 0xFF, 0x94, 0xFF, 0xFF, 0xFF, 0x38, 0x00, 0x00,
0x01, 0x26, 0xFF, 0xFF, 0xFF, 0x28, 0xFF, 0xFF, 0xFC, 0x10,
0x00, 0x00, 0x02, 0x94, 0xFF, 0xFF, 0xFC, 0x9E, 0x00, 0x00,
0x06, 0xEA, 0x00, 0x00, 0x00, 0xDC, 0x00, 0x00, 0x00, 0x06,
0xFF, 0xFF, 0xFF, 0x0C, 0xFF, 0xFF, 0xFD, 0xF6, 0xFF, 0xFF,
0xFA, 0x82, 0xFF, 0xFF, 0xFC, 0xD0, 0x00, 0x00, 0x01, 0x82,
0x00, 0x00, 0x03, 0xDE, 0x00, 0x00, 0x01, 0x4E, 0x00, 0x00,
0x02, 0xB2, 0xFF, 0xFF, 0xF8, 0xD8, 0x00, 0x00, 0x01, 0x74,
0xFF, 0xFF, 0xFA, 0xA6, 0xFF, 0xFF, 0xF9, 0xD4, 0x00, 0x00,
0x01, 0xC2, 0xFF, 0xFF, 0xF9, 0x7C, 0x00, 0x00, 0x03, 0x5A,
0x00, 0x00, 0x01, 0x46, 0xFF, 0xFF, 0xFF, 0x3C, 0xFF, 0xFF,
0xFA, 0x14, 0x00, 0x00, 0x01, 0xCE, 0x00, 0x00, 0x07, 0xDC,
0xFF, 0xFF, 0xFD, 0x48, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00,
0x08, 0x5E, 0xFF, 0xFF, 0xFD, 0xB0, 0xFF, 0xFF, 0xFF, 0xBC,
0x00, 0x00, 0x03, 0x6E, 0xFF, 0xFF, 0xFF, 0x4E, 0xFF, 0xFF,
0xF8, 0x36, 0x00, 0x00, 0x05, 0xC0, 0x00, 0x00, 0x06, 0xAE,
0x00, 0x00, 0x06, 0x94, 0x00, 0x00, 0x00, 0x22
};
```
!(https://tianyu.xin/usr/uploads/2022/04/3219148752.png)
这儿看起来得学一波uc
```c
UNICORN_EXPORT
uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **uc);
```
第一个是架构, 第二个是模式
```c
typedef enum uc_arch {
UC_ARCH_ARM = 1, // ARM architecture (including Thumb, Thumb-2)
UC_ARCH_ARM64, // ARM-64, also called AArch64
UC_ARCH_MIPS, // Mips architecture
UC_ARCH_X86, // X86 architecture (including x86 & x86-64)
UC_ARCH_PPC, // PowerPC architecture (currently unsupported)
UC_ARCH_SPARC, // Sparc architecture
UC_ARCH_M68K, // M68K architecture
UC_ARCH_MAX,
} uc_arch;
typedef enum uc_mode {
UC_MODE_LITTLE_ENDIAN = 0, // little-endian mode (default mode)
UC_MODE_BIG_ENDIAN = 1 << 30, // big-endian mode
// arm / arm64
UC_MODE_ARM = 0, // ARM mode
UC_MODE_THUMB = 1 << 4, // THUMB mode (including Thumb-2)
UC_MODE_MCLASS = 1 << 5, // ARM's Cortex-M series (currently unsupported)
UC_MODE_V8 = 1 << 6, // ARMv8 A32 encodings for ARM (currently unsupported)
// mips
UC_MODE_MICRO = 1 << 4, // MicroMips mode (currently unsupported)
UC_MODE_MIPS3 = 1 << 5, // Mips III ISA (currently unsupported)
UC_MODE_MIPS32R6 = 1 << 6, // Mips32r6 ISA (currently unsupported)
UC_MODE_MIPS32 = 1 << 2, // Mips32 ISA
UC_MODE_MIPS64 = 1 << 3, // Mips64 ISA
// x86 / x64
UC_MODE_16 = 1 << 1, // 16-bit mode
UC_MODE_32 = 1 << 2, // 32-bit mode
UC_MODE_64 = 1 << 3, // 64-bit mode
// ppc
UC_MODE_PPC32 = 1 << 2, // 32-bit mode (currently unsupported)
UC_MODE_PPC64 = 1 << 3, // 64-bit mode (currently unsupported)
UC_MODE_QPX = 1 << 4, // Quad Processing eXtensions mode (currently unsupported)
// sparc
UC_MODE_SPARC32 = 1 << 2, // 32-bit mode
UC_MODE_SPARC64 = 1 << 3, // 64-bit mode
UC_MODE_V9 = 1 << 4, // SparcV9 mode (currently unsupported)
// m68k
} uc_mode;
```
MIPS+MIPS32+BIGENDIAN
!(https://tianyu.xin/usr/uploads/2022/04/2925820625.png)
基本能看出来吧, 通过a1算a2, a2一共41个, 41*4应该是正好和对比数据一样大, 这样我们z3跑一下就行了, IDA真乃神器也
代码太长了就不贴了, 除了s.add以外基本上啥也没有, 就是传统z3题, 哦, 记得那些0xFFFFF打头的一看就是补码, 要转一下
{Un1c0rn_Engin3_Is_@_P0wer7ul_TO0ls!}
---
## gdssagh
!(https://tianyu.xin/usr/uploads/2022/04/954833540.png)
!(https://tianyu.xin/usr/uploads/2022/04/1618969280.png)
我直接? 我还以为是加壳, 但是这怎么直接.. 退出了? 我疑惑了一下并进行动调发现仍然是直接退出.
中间巨大的数据里面都是可见字符, 是Base64..
413H-CC1A4H, python提一下
```python
>>> with open('./gdssagh', "rb") as f:
... b = f.read()
... import base64
... b = base64.b64decode(b)
... ff = open("./out", "wb")
... ff.write(b)
... ff.close()
```
<img src="E:\ctf\wp\gdssagh.assets\image-20220401111016042.png" alt="image-20220401111016042" style="zoom:150%;" />
err, 竟然是个PNG, 这他妈的不会是个隐写把.. 直接zsteg一把梭试试
!(https://tianyu.xin/usr/uploads/2022/04/480121402.png)
!(https://tianyu.xin/usr/uploads/2022/04/1150059706.png)
这俩比较像, 但是正常人肯定都看看PE..
!(https://tianyu.xin/usr/uploads/2022/04/784062516.png)
就它了, 导出
!(https://tianyu.xin/usr/uploads/2022/04/3839288335.png)
这他妈是Misc, 不是逆向, 狗看了都摇头
---
## music
!(https://tianyu.xin/usr/uploads/2022/04/1192865627.png)
逛一圈关注到了这个yes和no
!(https://tianyu.xin/usr/uploads/2022/04/2974793905.png)
这个g(a)要是1
!(https://tianyu.xin/usr/uploads/2022/04/1088598798.png)
!(https://tianyu.xin/usr/uploads/2022/04/2905873134.png)
和Resource里的资源相等, 回去看看a哪里来的
!(https://tianyu.xin/usr/uploads/2022/04/1428897830.png)
000就是input
!(https://tianyu.xin/usr/uploads/2022/04/3991377192.png)
b定位到了这儿
!(https://tianyu.xin/usr/uploads/2022/04/1790220386.png)
!(https://tianyu.xin/usr/uploads/2022/04/3860418003.png)
c.a有两个参数, 一个是输入的字符串, 另一个是经过this.a变换的this.d, this.d来自于上面这个get, 是一个db
!(https://tianyu.xin/usr/uploads/2022/04/2883083511.png)
把get经过md5之后传进来, c.a的两个参数来源都有了, 回头看看c.a怎么加密
看上去像个RC4, 应该是魔改过的. 整个流程已经很清楚了: 用md5(db.iwantofind)做秘钥, 输入做明文, 加密之后hex, 然后和resource里的明文做对比
`out = (char)((flagenc ^ S[(S + S % 256) % 256]) + k);`
注意rc4的最后一轮是改过的
flag{IT_IS_A_NICE_SONG}
---
## sabataD
64位ELF. 丢IDA
!(https://tianyu.xin/usr/uploads/2022/03/3714156166.png)
有个0xE的signal, 去看看是哪个
!(https://tianyu.xin/usr/uploads/2022/03/1992250740.png)
后面跟着一个0x14秒Alarm, handler是退出, 我们整个过程不能超过20秒, 扬了
去看B7A
!(https://tianyu.xin/usr/uploads/2022/03/4270527663.png)
首先是这个位置, 把读入按模3剩余类操作, 先扔AEA里, 0放s1, 1放s2, 2放pattern, 151-154这四位转int放v7
!(https://tianyu.xin/usr/uploads/2022/03/3000976554.png)
要满足这两个,
!(https://tianyu.xin/usr/uploads/2022/03/2250350362.png)
s1要满足这个, 看看glob, err大概是个处理文件名的函数, 可以猜测就是打开homectf下的flag, 读v7次到v15里, 然后print出来, 进入下一个循环, 直到s1是"terminate"
!(https://tianyu.xin/usr/uploads/2022/03/3002075064.png)
AEA这样的, 字母就丢B3E里, 是个ROT13
```python
s1 = "Fetch from file with index"
s2 = "watevr-admin"
s3 = "/home/ctf/flag.*"
inp = ""
def ROT13(ch) :
num = ord(ch)
if num >= 0x61 and num <= 0x7a :
num -= 0x61
num += 13
num %= 26
num += 0x61
elif num >= 0x41 and num <= 0x5a :
num -= 0x41
num += 13
num %= 26
num += 0x41
return chr(num)
for i in range(len(s1)) :
inp += ROT13(s1)
if i >= len(s2) :
inp += '_'
else :
inp += ROT13(s2)
if i >= len(s3) :
inp += '_'
else :
inp += ROT13(s3)
inp += (150-len(inp)) * "_" + "1234"
print(len(inp), inp.encode(encoding="utf-8"))
```
随便构造了一个, 跑通倒是通了, 但是我们想访问的是flag, 他不让, 给我的感觉就是我们要找一个方法绕过strcmp然后通过glob来访问flag.txt
!(https://tianyu.xin/usr/uploads/2022/03/4172507251.png)
支持匹配啊, 那试试
!(https://tianyu.xin/usr/uploads/2022/03/4103920640.png)
flag{f3b5b172-a26b-464d-b7ee-7599d75a111c} 木有什么难度~ {:301_998:}完全看不懂!!!!!!!!!!! 太专业了,慢慢学习。 太专业了,表示看不懂 太强了,完全做不到100分的题 太专业了,虽然看不懂,仍然要支持,学习中...
页:
[1]