GoogleCTF2023 Writeup

GoogleCTF2023 Writeup

Misc

  • NPC

Crypto

  • LEAST COMMON GENOMINATOR?

Web

  • UNDER-CONSTRUCTION

NPC

A friend handed me this map and told me that it will lead me to the flag.
It is confusing me and I don’t know how to read it, can you help me out?

Attachment


使用Graphviz工具将hint.dot转换为图片,得到下图

dot -Tjpg  hint.dot -o hint.jpg
hint.jpg

分析代码:

  • USACONST.TXT中随机选择N个单词生成密码,使用passphrase.encrypt(secret, password)对flag加密

  • 对于password中的每个字母,创建一个带有唯一ID的节点,并添加到图中

  • 按照password的顺序,对密码中相邻的两个字符创建一条边

  • 向图中随机添加int(len(password) ** 1.3)条边

  • 随机打乱图中节点和边的顺序

  • 随机交换一些节点的起点和终点,由于random() % 2只有在random函数返回值为0时才为False,我们假定图中每条边的起点和终点都被交换了一遍

  • 将节点和边的信息写入到hint.dot文件中

我是思路是:

  1. 遍历words_list中的单词,从每个节点出发,使用DFS判断是否可以在图中找到,这样过滤后得到30个单词,即密码一定由该30个单词中的某几个单词组成

  2. 枚举密码中所用的单词个数N

  3. 使用组合数从这30个单词选择N个单词

  4. 判断所选的N个单词组成的字符集和hint.dot中的字符集是否一致

  5. 对N个单词进行全排列,并尝试解密 (为了提高效率,这里还用到了多进程)

当N=5时,得到passwordstandardwatersigngivenchosenflag.

代码
import concurrent.futures
import itertools
import re
from collections import Counterfrom pyrage import passphrasefrom encrypt import get_word_listclass Node:def __init__(self, letter):self.letter = letterself.adjacent = []def __str__(self) -> str:return f"{self.letter} -> {[x.letter for x in self.adjacent]}"__repr__ = __str__def build_nodes():pattern = r"\s+(\d+)\s+\[label=(\w+)\];"pattern2 = r"\s+(\d+)\s+--\s+(\d+);$"nodes = dict()with open("hint.dot", "r") as f:for line in f:if "label" in linematch = re.match(pattern, line)node_id = match.group(1)letter = match.group(2)nodes[node_id] = Node(letter)elif "--" in line:match = re.match(pattern2, line)start = match.group(1)end = match.group(2)# nodes[start].adjacent.append(nodes[end])nodes[end].adjacent.append(nodes[start])return nodesvisited = set()def dfs(node, index, word):if index == len(word):return Trueif node.letter != word[index]:return Falsevisited.add(node)for adj in node.adjacent:if adj not in visited:if dfs(adj, index + 1, word):return Truevisited.remove(node)return Falsedef check(password):with open("secret.age", "rb") as f:enc = f.read()try:print("[FLAG] is ", passphrase.decrypt(enc, password))print("Password is ", password)except Exception as e:passdef filter_words(nodes):ans = set()for word in get_word_list():visited.clear()for node in nodes.values():if dfs(node, 0, word):ans.add(word)breakprint("ans:", len(ans), ans)return ansdef main():nodes = build_nodes()letters = sorted([node.letter for node in nodes.values()])ans = filter_words(nodes)for num in range(1, len(ans) + 1):print(f"Num is {num}")for comb in itertools.combinations(ans, num):  # 组合if sorted("".join(comb)) == letters:passwords = ["".join(perm) for perm in itertools.permutations(comb, len(comb))]with concurrent.futures.ProcessPoolExecutor(max_workers=8) as executor:executor.map(check, passwords)if __name__ == "__main__":main()

flag: CTF{S3vEn_bR1dg35_0f_K0eN1g5BeRg}

参考:

  • concurrent.futures — 启动并行任务 – Python 3.11.4 文档

LEAST COMMON GENOMINATOR?

Someone used this program to send me an encrypted message but I can’t read it! It uses something called an LCG, do you know what it is? I dumped the first six consecutive values generated from it but what do I do with it?!

Attachment


generate.py
from secret import config
from Crypto.PublicKey import RSA
from Crypto.Util.number import bytes_to_long, isPrimeclass LCG:lcg_m = config.mlcg_c = config.clcg_n = config.ndef __init__(self, lcg_s):self.state = lcg_sdef next(self):self.state = (self.state * self.lcg_m + self.lcg_c) % self.lcg_nreturn self.stateif __name__ == '__main__':assert 4096 % config.it == 0assert config.it == 8assert 4096 % config.bits == 0assert config.bits == 512# Find prime value of specified bits a specified amount of timesseed = 211286818345627549183608678726370412218029639873054513839005340650674982169404937862395980568550063504804783328450267566224937880641772833325018028629959635lcg = LCG(seed)primes_arr = []dump = Trueitems = 0dump_file = open("dump.txt", "w")primes_n = 1while True:for i in range(config.it):while True:prime_candidate = lcg.next()if dump:dump_file.write(str(prime_candidate) + '\n')items += 1if items == 6:dump = Falsedump_file.close()if not isPrime(prime_candidate):continueelif prime_candidate.bit_length() != config.bits:continueelse:primes_n *= prime_candidateprimes_arr.append(prime_candidate)break# Check bit lengthif primes_n.bit_length() > 4096:print("bit length", primes_n.bit_length())primes_arr.clear()primes_n = 1continueelse:break# Create public key 'n'n = 1for j in primes_arr:n *= jprint("[+] Public Key: ", n)print("[+] size: ", n.bit_length(), "bits")# Calculate totient 'Phi(n)'phi = 1for k in primes_arr:phi *= (k - 1)# Calculate private key 'd'd = pow(config.e, -1, phi)# Generate Flagassert config.flag.startswith(b"CTF{")assert config.flag.endswith(b"}")enc_flag = bytes_to_long(config.flag)assert enc_flag < n# Encrypt Flag_enc = pow(enc_flag, config.e, n)with open ("flag.txt", "wb") as flag_file:flag_file.write(_enc.to_bytes(n.bit_length(), "little"))# Export RSA Keyrsa = RSA.construct((n, config.e))with open ("public.pem", "w") as pub_file:pub_file.write(rsa.exportKey().decode())

分析可知:

  • flag是使用RSA加密的,已知公🔑 文件,即n,e

  • 使用LCG线性同余生成器生成素数

  • 已知LCG的种子和前6个连续生成的数字

  • config.it = 8

  • config.bits = 256

LCG是伪随机数生成器和流密码的一种,递推公式是 𝑋𝑛+1=(𝑎𝑋𝑛+𝑐) 𝑚𝑜𝑑 𝑚

已知初值和随后LCG连续生成的6个值,未知增量、乘数和模数.

我们可以通过攻击得到这三个值,然后模拟原算法通过LCG得到8个素数后,进一步计算n的欧拉函数并求逆元得到d,解密即可.

题解:
import math
from functools import reduceimport gmpy2from Crypto.PublicKey import RSA
from Crypto.Util.number import bytes_to_long, isPrime, long_to_bytesdump_file = open("dump.txt")
output_values = [int(x) for x in dump_file.readlines()]  # 已知的 LCG 输出值def crack_unknown_increment(states, modulus, multiplier):"""已知:a,m,s0,s1求c"""increment = (states[1] - states[0] * multiplier) % modulusreturn modulus, multiplier, incrementdef crack_unknown_multiplier(states, modulus):"""已知:m,s0,s1,s2求a"""multiplier = ((states[2] - states[1]) * gmpy2.invert(states[1] - states[0], modulus) % modulus)  # 注意这里求逆元return crack_unknown_increment(states, modulus, multiplier)def crack_unknown_modulus(states):"""已知:s0-s6求a,c,m"""diffs = [s1 - s0 for s0, s1 in zip(states, states[1:])]zeroes = [t2 * t0 - t1 * t1 for t0, t1, t2 in zip(diffs, diffs[1:], diffs[2:])]modulus = abs(reduce(math.gcd, zeroes))return crack_unknown_multiplier(states, modulus)class LCG:def __init__(self, lcg_m, lcg_c, lcg_n, lcg_s):self.state = lcg_sself.lcg_m = lcg_mself.lcg_c = lcg_cself.lcg_n = lcg_ndef next(self):self.state = (self.state * self.lcg_m + self.lcg_c) % self.lcg_nreturn self.statem, a, c = crack_unknown_modulus(output_values)
seed = 211286818345627549183608678726370412218029639873054513839005340650674982169404937862395980568550063504804783328450267566224937880641772833325018028629959635
lcg = LCG(a, c, m, seed)
print(a, c, m)
primes_n = 1
primes_arr = []
for i in range(8):while True:prime_candidate = lcg.next()if not isPrime(prime_candidate):continueelif prime_candidate.bit_length() != 512:continueelse:primes_n *= prime_candidateprimes_arr.append(prime_candidate)breakprint(list(primes_arr))phi = 1
for k in primes_arr:phi *= k - 1key = RSA.importKey(open("public.pem", "r").read())
n = key.n
e = key.e
d = gmpy2.invert(e, phi)enc = open("flag.txt", "rb").read()flag = pow(int.from_bytes(enc, "little"), d, n)
print(long_to_bytes(flag))

flag: CTF{C0nGr@tz_RiV35t_5h4MiR_nD_Ad13MaN_W0ulD_b_h@pPy}

参考:

  • 攻击线性同余生成器(LCG) | 码农网
  • LCG(线性同余生成器)_lcg线性同余_WustHandy的博客-CSDN博客

UNDER-CONSTRUCTION

We were building a web app but the new CEO wants it remade in php.

Attachment
https://under-construction-web.2023.ctfcompetition.com
https://under-construction-php-web.2023.ctfcompetition.com


题目提供了Flask和PHP两个站点,用户可以在Flask站点进行注册,注册的账号可以同时用于登录Flask和PHP两个站点.

分析代码:

Flask会将HTTP请求原始查询参数转发到PHP应用程序中完成用户注册.

# File: /flask/authorized_routes.py
@authorized.route('/signup', methods=['POST'])
def signup_post():raw_request = request.get_data()...requests.post(f"http://{PHP_HOST}:1337/account_migrator.php", headers={"token": TOKEN, "content-type": request.headers.get("content-type")}, data=raw_request)return redirect(url_for('authorized.login'))

只有gold级别的用户,在PHP站点登录后才可以看到FLAG

# File: /php/index.php
function getResponse()
{...$response = "Login successful. Welcome " . htmlspecialchars($username) . ".";if ($tier === "gold") {$response .= " " . getenv("FLAG");}return $response;
}

Flask会对查询参数进行校验,防止创建高权限的用户.

# File: /flask/authorized_routes.py
@authorized.route('/signup', methods=['POST'])
def signup_post():...tier = models.Tier(request.form.get('tier'))if(tier == models.Tier.GOLD):flash('GOLD tier only allowed for the CEO')return redirect(url_for('authorized.signup'))...

HTTP查询参数中存在重复的key时,在Flask和PHP有不同的行为,flask会取第一个值,而PHP会取最后一个值.

因此我们可以构造如下命令,以此绕过Flask对查询参数的校验,并在PHP中注册高权限用户.

curl

curl -X POST https://under-construction-web.2023.ctfcompetition.com/signup -d "username=admin&password=admin&tier=blue&tier=gold"

然后用上述的用户名和密码去PHP站点登录即可.

flag: CTF{ff79e2741f21abd77dc48f17bab64c3d}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/384531.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

软件更新的双刃剑:从”微软蓝屏”事件看网络安全的挑战与对策

引言 原文链接 近日&#xff0c;一场由微软视窗系统软件更新引发的全球性"微软蓝屏"事件震惊了整个科技界。这次事件源于美国电脑安全技术公司"众击"提供的一个带有"缺陷"的软件更新&#xff0c;如同一颗隐形炸弹在全球范围内引爆&#xff0c;…

17.5【C语言】static的补充说明

static &#xff08;静态的) 作用&#xff1a;修饰局部变量&#xff0c;修饰全局变量&#xff0c;修饰函数 对比两段代码 #include <stdio.h> void test() {int a 5;a;printf("%d ", a); } int main() {int i 0;for(i0; i<5; i){test();}return 0; } …

高并发内存池——链表设计

自由链表类的设计 由于申请的空间块经过对齐之后大小至少为8&#xff0c;因此可以考虑在未被使用的内存块中取前8字节存储下一个空间的地址 FreeList类初步声明 class FreeList { private:void* _freelistnullptr; //自由链表头指针size_t _size0; //自由链表的长度size_t …

【Django】anaconda环境变量配置及配置python虚拟环境

文章目录 配置环境变量配置python虚拟环境查看conda源并配置国内源在虚拟环境中安装django 配置环境变量 control sysdm.cpl,,3笔者anaconda安装目录为C:\ProgramData\anaconda3 那么需要加入path中的有如下三个 C:\ProgramData\anaconda3 C:\ProgramData\anaconda3\Scripts C:…

最新风车IM即时聊天源码及完整视频教程2024年7月版

堡塔面板 试验性Centos/Ubuntu/Debian安装命令 独立运行环境&#xff08;py3.7&#xff09; 可能存在少量兼容性问题 不断优化中 curl -sSO http://io.bt.sy/install/install_panel.sh && bash install_panel.sh 1.宝塔环境如下: Nginx 1.20 Tomcat 8 MySQL 8.0 R…

Java 开发环境配置

1. 下载 JDK 直接在oracle 官网下载 https://www.oracle.com/java/technologies/downloads或者使用博主已经从oracle下载的 jdk21&#xff1a;https://download.csdn.net/download/u011171506/89585231jdk8&#xff1a;https://download.csdn.net/download/u011171506/8958523…

快醒醒,别睡了!...讲《数据分析pandas库》了—/—<4>

一、废话不多说&#xff0c;直接开讲 1、DataFrame的索引和切片 1.1 选择列 当想要获取 df 中某列数据时&#xff0c;只需要在 df 后面的方括号中指明要选择的列即可。如果是 一列&#xff0c;则只需要传入一个列名;如果是同时选择多列&#xff0c;则传入多个列名即可&#xf…

SAPUI5基础知识20 - 对话框和碎片(Dialogs and Fragments)

1. 背景 在 SAPUI5 中&#xff0c;Fragments 是一种轻量级的 UI 组件&#xff0c;类似于视图&#xff08;Views&#xff09;&#xff0c;但它们没有自己的控制器&#xff08;Controller&#xff09;。Fragments 通常用于定义可以在多个视图中重用的 UI 片段&#xff0c;从而提…

集成千兆网口(Gigabit Ethernet Port)的作用主要是提供高速的有线网络连接,其工作原理涉及以下几个关键点:

传输速率&#xff1a; 千兆网口支持的最高传输速率达到1 Gbps&#xff08;即每秒10亿位&#xff09;&#xff0c;是传统百兆网口&#xff08;100 Mbps&#xff09;的十倍速度。这使得它能够处理更大量、更高质量的数据传输。 数据传输效率&#xff1a; 千兆网口能显著提高局域…

C#如何引用dll动态链接库文件的注释

1、dll动态库文件项目生成属性中要勾选“XML文档文件” 注意&#xff1a;XML文件的名字切勿修改。 2、添加引用时XML文件要与DLL文件在同一个目录下。 3、如果要是添加引用的时候XML不在相同目录下&#xff0c;之后又将XML文件复制到相同的目录下&#xff0c;需要删除引用&am…

【机器学习】Python、NumPy和向量化的基础知识以及三者结合的用法和示例

引言 在机器学习中&#xff0c;NumPy是一个非常重要的库&#xff0c;特别是在进行向量化操作时。向量化是一种优化技术&#xff0c;可以显著提高数组计算的效率&#xff0c;特别是在处理大型数据集时。NumPy提供了丰富的数组运算功能&#xff0c;使得向量化操作变得简单高效 文…

驾驭代码的无形疆界:动态内存管理揭秘

目录 1.:为什么要有动态内存分配 2.malloc和free 2.1:malloc 2.2:free 3.calloc和realloc 3.1:calloc 3.1.1:代码1(malloc) 3.1.2:代码2(calloc) 3.2:realloc 3.2.1:原地扩容 3.2.2:异地扩容 3.2.3:代码1(原地扩容) 3.2.3:代码2(异地扩容) 4:常见的动态内存的错误…

掀桌子了!原来是咱们的大屏设计太酷,吓着前端开发老铁了

掀桌子了&#xff01;原来是咱们的大屏设计太酷&#xff0c;吓着前端开发老铁了 艾斯视觉观点认为&#xff1a;在软件开发的世界里&#xff0c;有时候创意和设计的火花会擦得特别亮&#xff0c;以至于让技术实现的伙伴们感到既兴奋又紧张。这不&#xff0c;我们的设计团队刚刚…

Vue的安装配置

1.安装node js Node.js — 在任何地方运行 JavaScript (nodejs.org) 2.测试nodejs是否安装成功 node -v npm -v3.通过npm 安装 vue npm install -g vue/cli4.测试vue是否安装成功 vue --version5.打开PyCharm&#xff0c;创建项目&#xff1a;flask-web vue create flask…

【H.264】H.264详解(二)—— H264视频码流解析示例源码

文章目录 一、前言二、示例源码【1】目录结构【2】Makefile源码【3】h264parser.c源码【4】编译运行【5】源码下载地址 声明&#xff1a;此篇示例源码非原创&#xff0c;原作者雷霄骅。雷霄骅&#xff0c;中国传媒大学通信与信息系统专业博士生&#xff0c;在此向雷霄骅雷神致敬…

MySQL客户端命令一节将.sql文件导入MySQL

MySql客户端命令 直接输入SQL语句 使用MySQL客户端连接到服务器之后&#xff0c;可以发送SQL语句到服务器执行&#xff0c;并且以&#xff1b;和\g, \G作为结束不同的结束方式显示内容有所不同** TIPS: ;和\g结尾以表格的形式显示结果\G以行的形式显示结果 在连接到服务器之后…

FineBI连接MySQL5.7

一、在FineBI系统管理中&#xff0c;点击【新建数据库连接】 选择MySQL数据库 配置数据库连接&#xff0c;如下&#xff0c;其中数据库名称就是需要连接的目标数据库

5.CSS学习(浮动)

浮动&#xff08;float&#xff09; 是一种传统的网页布局方式&#xff0c;通过浮动&#xff0c;可以使元素脱离文档流的控制&#xff0c;使其横向排列。 其编写在CSS样式中。 float:none(默认值) 元素不浮动。 float:left 设置的元素在其包含…

Web3 职场新手指南:从技能到素养,求职者如何脱颖而出?

随着 2024 年步入下半年&#xff0c;Web3 行业正在经历一系列技术革新。通过改进的跨链交互机制和兼容性&#xff0c;逐步消除市场碎片化的问题。技术的进步为开发者和用户都打开了新的前景。然而&#xff0c;复杂的技术和快速变化的市场环境也让许多新人望而却步。求职者如何找…

Unity 之 【Android Unity 共享纹理】之 Android 共享图片给 Unity 显示

Unity 之 【Android Unity 共享纹理】之 Android 共享图片给 Unity 显示 目录 Unity 之 【Android Unity 共享纹理】之 Android 共享图片给 Unity 显示 一、简单介绍 二、共享纹理 1、共享纹理的原理 2、共享纹理涉及到的关键知识点 3、什么可以实现共享 不能实现共享…