Y1rannn 发表于 2022-4-5 14:51

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} 木有什么难度~

maomaochong 发表于 2022-4-5 15:03

{:301_998:}完全看不懂!!!!!!!!!!!

lsydy681021 发表于 2022-4-5 15:16

太专业了,慢慢学习。

tp206555 发表于 2022-4-5 22:58

太专业了,表示看不懂

sssssshen 发表于 2022-4-6 10:23

太强了,完全做不到100分的题

xajh2002 发表于 2022-4-8 18:08

太专业了,虽然看不懂,仍然要支持,学习中...
页: [1]
查看完整版本: BUUOJ DudeLocker/babyunic /gdssagh/[SCTF2019]music/sabataD Writeups