HGAME 2026

HGAME 2026

Aristore

Week 1

其实就只打了week1的misc(

Misc

打好基础

Challenge

😛 ENJOY HGAME!

1
🐲👝🐱👁👠👮👌👞👂🐬🐽🐡👎👮🐪🐿🐾👞🐨👕🐫👤👏👟👍👉🐲👑👍👀👔👭🐩👮🐾👏🐮👑🐨🐩🐠👯👡🐮👍🐨👒🐘🐨🐮👔👍🐸🐥🐡👇🐶👝👏👱🐺👀👌🐢🐦🐦👟👂👮👝🐡🐳🐰👒👄👡🐶👤👀👴🐯🐭🐛👱👎👫🐭🐢🐫👨👭👬👌👲👧🐘🐮👊👕👊👦🐥👎👈👟🐴👈🐭🐶👭🐥🐡🐽👓🐨👝👛🐡👕🐫🐡🐽👯👱👌👁👡🐫🐲🐡🐲🐟🐶👪🐭👳👌👖👲👡👈👯🐘👇🐫🐡👈🐰👕👡🐩👎👁🐳👒👡👣👨👞👞🐫👠👈🐽🐲👤🐩👎👂🐤👟🐬👤🐴👣👛👃👳🐽🐢👃👀🐨👧🐠👎🐹👓👢🐼🐳👁🐱👚🐳👭🐨👔👍🐠👥🐸🐱🐣🐸👖🐰👓🐬👄🐳👱👐👉🐢👝🐠🐤👯👀👎👥🐤👔🐨👊👊👃🐽👱🐪👱👚👍🐵🐶👎🐻👛🐤👂🐳🐾🐟🐨👢👍👥🐼👟👕👙👣🐡👣👭🐿👦🐩👂👬🐞🐢👋🐠👙🐶🐤👥👋🐲👱🐩👕🐝🐺🐯👴👍🐡🐦🐰👍🐨👋👔👤🐚🐻👐🐽👟🐴🐷👎🐴👫👀👤🐦👡🐥👡🐵🐸🐺👫👛👮👲🐬👯👌👔👙👉🐷🐺👁👅🐪👒👈👕👅🐯🐩🐝👰👚👌👂🐵🐽

Solution

Base100 -> Base92 -> Base91 -> Ascii85 -> Base64 -> Base62 -> Base58 -> Base45 -> Base32

FLAG

1
hgame{L4y_a_sO11d_f0unDaTi0n}

shiori不想找女友

Challenge

Tremse正在帮Shiori找女友,但是他现在找不到Shiori了!但是他留下了他的头像,你可以帮我找找他在哪里吗🙏

Solution

查看 exif 发现 User Comment 藏有信息

1
{"block": 1, "start_x": 10, "start_y": 10, "step_x": 7, "step_y": 7, "column_num": 450}

放大图片发现图片有整齐排列的点,猜测上面的提示是指从 shiori.png(10, 10) 坐标开始,以 x 方向步长 7、y 方向步长 7 的间隔拾取像素,共 450 列,编写脚本提取像素组成新的图片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
from PIL import Image
import math

def extract_pixels(input_file, output_file, rules):
try:
# 打开源图像
src_img = Image.open(input_file)
src_img = src_img.convert("RGB") # 确保是RGB模式
width, height = src_img.size

# 获取规则参数
block = rules.get("block", 1)
start_x = rules.get("start_x", 0)
start_y = rules.get("start_y", 0)
step_x = rules.get("step_x", 1)
step_y = rules.get("step_y", 1)
out_cols = rules.get("column_num", 100)

extracted_pixels = []

# 遍历源图像提取像素
# 假设按行优先顺序扫描 (先X后Y)
# 注意:这里采用了两层循环遍历整个图,按照步长提取
for y in range(start_y, height, step_y):
for x in range(start_x, width, step_x):
# 检查边界
if x + block <= width and y + block <= height:
# 获取像素 (这里处理 block=1 的情况,直接取点)
# 如果 block > 1,通常需要决定如何处理块(取平均值或左上角),这里默认取左上角像素
pixel = src_img.getpixel((x, y))
extracted_pixels.append(pixel)

# 计算输出图像的高度
total_pixels = len(extracted_pixels)
if total_pixels == 0:
print("未提取到任何像素,请检查规则和图像尺寸。")
return

out_rows = math.ceil(total_pixels / out_cols)

# 创建新的空白图像
out_img = Image.new("RGB", (out_cols, out_rows), (0, 0, 0))

# 填充像素
for i, pixel in enumerate(extracted_pixels):
x = i % out_cols
y = i // out_cols
out_img.putpixel((x, y), pixel)

# 保存输出图像
out_img.save(output_file)
print(f"成功提取 {total_pixels} 个像素,已保存至 {output_file}")
print(f"输出尺寸: {out_cols} x {out_rows}")

except FileNotFoundError:
print(f"错误: 找不到文件 {input_file}")
except Exception as e:
print(f"发生错误: {e}")

# 定义规则
params = {
"block": 1,
"start_x": 10,
"start_y": 10,
"step_x": 7,
"step_y": 7,
"column_num": 450
}

# 运行提取
if __name__ == "__main__":
extract_pixels("shiori.png", "output.png", params)

得到提示 This_is_a_key_for_u,这是压缩包的密码

解压后的图片存在 LSB 隐写,在 StegSolve 找一个比较好看出来的 Plane (比如 Green Plane 0)识图转文字即可

FLAG

1
hgame{bec0use_lilies_are_7he_b1st}

[REDACTED]

Challenge

兔兔说她对一份机密文件进行了“完美的”脱敏处理。还好你在发送之前检查了一下。

提交说明: 附件中包含四段敏感字符串,格式为 [1-4]:.+。用下划线字符 _ 连接去掉序号的四段字符串,包裹 hgame{} 后提交。例如,若四段敏感字符串分别为 1:Example2:Redacted3:Secret4:Strings_!,则提交的 flag 为 hgame{Example_Redacted_Secret_Strings_!}

Solution

1:PAR4D0X

HGAME2026-1

2:AllCl3arToPr0ceed

HGAME2026-2

HGAME2026-3

3:Sh4m1R

HGAME2026-4

至此浮于表面的答案都找到了,还没仔细研究过这个 PDF 文件本身

先使用 pdfid 初步扫描文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
┌──(kali㉿kali)-[~/Desktop]
└─$ pdfid manual.pdf
PDFiD 0.2.10 manual.pdf
PDF Header: %PDF-1.7
obj 110
endobj 110
stream 23
endstream 23
xref 2
trailer 2
startxref 2
/Page 3 <----------
/Encrypt 0
/ObjStm 0
/JS 0
/JavaScript 0
/AA 0
/OpenAction 0
/AcroForm 0
/JBIG2Decode 0
/RichMedia 0
/Launch 0
/EmbeddedFile 0
/XFA 0
/Colors > 2^24 0

PDF 就只有 2 页,但 pdfid 扫出来 3 页,这咋看都不对劲,可能是通过修改 PDF 目录结构隐藏了一页

用 pdf-parser 进一步分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
┌──(kali㉿kali)-[~/Desktop]
└─$ pdf-parser manual.pdf
This program has not been tested with this version of Python (3.13.3)
Should you encounter problems, please use Python version 3.12.2
PDF Comment '%PDF-1.7\n'

PDF Comment '%\xc2\xb5\xc2\xb6\n\n'

obj 1 0
Type: /Page
Referencing: 59 0 R, 101 0 R, 2 0 R

<<
/Type /Page
/Parent 59 0 R
/Resources 101 0 R
/MediaBox [0 0 521.2913 737.2913]
/Tabs /S
/StructParents 0
/Contents 2 0 R
>>

...

obj 59 0
Type: /Pages
Referencing: 101 0 R, 1 0 R, 7 0 R, 34 0 R

<<
/Type /Pages
/Resources 101 0 R
/Kids [1 0 R 7 0 R 34 0 R]
/Count 3
>>

...

obj 59 0
Type: /Pages
Referencing: 101 0 R, 7 0 R, 34 0 R

<<
/Type /Pages
/Resources 101 0 R
/Kids [7 0 R 34 0 R]
/Count 2
>>

...

通过检查输出中的页树根节点(/Pages,即 Object 59),发现了文件被篡改的痕迹:

  1. 原始定义(Object 1, 7, 34):

    1
    2
    3
    4
    obj 59 0
    Type: /Pages
    Kids [1 0 R 7 0 R 34 0 R] <----------
    Count 3
  2. 增量更新(Object 7, 34):

    1
    2
    3
    4
    obj 59 0
    Type: /Pages
    Kids [7 0 R 34 0 R] <----------
    Count 2

Object 1 就是被隐藏的第一页,定位到隐藏页 Object 1

1
2
3
4
5
6
7
8
9
10
11
12
13
obj 1 0
Type: /Page
Referencing: 59 0 R, 101 0 R, 2 0 R

<<
/Type /Page
/Parent 59 0 R
/Resources 101 0 R
/MediaBox [0 0 521.2913 737.2913]
/Tabs /S
/StructParents 0
/Contents 2 0 R <----------
>>

它指向 Object 2 作为其内容流,提取并解压 Object 2 的数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
┌──(kali㉿kali)-[~/Desktop]
└─$ pdf-parser -o 2 -f manual.pdf
This program has not been tested with this version of Python (3.13.3)
Should you encounter problems, please use Python version 3.12.2
obj 2 0
Type:
Referencing:
Contains stream

<<
/Length 145
/Filter /FlateDecode
>>

b'0.1 w\n/Artifact BMC\nq 0 0.028 521.263 737.263 re\nW* n\nEMC\n/P<</MCID 0>>BDC\nq 0 0 0 rg\nBT\n200.8 367.841 Td /F1 12 Tf<010203040506070809070A0B070C0D0E090B09>Tj\nET\nQ\nEMC\nQ '
  • -o 2: 指定对象 ID 2
  • -f: 自动处理过滤器

从输出得到了一段 PostScript 绘图指令,其中包含一段可疑的内容:/F1 12 Tf <010203040506070809070A0B070C0D0E090B09> Tj

这里的 <010203040506070809070A0B070C0D0E090B09> 是字体的 Character ID 索引,这段文字使用了自定义的字体映射

现在需要找到字体 F1 的映射表来还原真实文本

1
2
3
4
5
6
7
8
9
10
11
12
13
obj 1 0
Type: /Page
Referencing: 59 0 R, 101 0 R, 2 0 R

<<
/Type /Page
/Parent 59 0 R
/Resources 101 0 R <----------
/MediaBox [0 0 521.2913 737.2913]
/Tabs /S
/StructParents 0
/Contents 2 0 R
>>

先找到 Object 1 资源由 Object 101 定义,接着查看 Object 101 的定义

1
2
3
4
5
6
7
8
9
10
11
12
obj 101 0
Type:
Referencing: 100 0 R, 50 0 R

<<
/Font 100 0 R <----------
/XObject
<<
/Im50 50 0 R
>>
/ProcSet [/PDF/Text/ImageC/ImageI/ImageB]
>>

找到字体映射关系存储在 Object 100 中,接着查看 Object 100 的定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
obj 100 0
Type:
Referencing: 64 0 R, 79 0 R, 84 0 R, 89 0 R, 74 0 R, 69 0 R, 94 0 R, 99 0 R

<<
/F1 64 0 R <----------
/F2 79 0 R
/F3 84 0 R
/F4 89 0 R
/F5 74 0 R
/F6 69 0 R
/F7 94 0 R
/F8 99 0 R
>>

找到 /F1 指向 64 0 R,接着查看 Object 64 的定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
obj 64 0
Type: /Font
Referencing: 62 0 R, 63 0 R

<<
/Type /Font
/Subtype /TrueType
/BaseFont /BAAAAA+CMUTypewriter-Light
/FirstChar 0
/LastChar 18
/Widths [0 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525]
/FontDescriptor 62 0 R
/ToUnicode 63 0 R <----------
>>

这表明 Object 63 存储了从 CID 到 Unicode 的映射表,提取映射表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
┌──(kali㉿kali)-[~/Desktop]
└─$ pdf-parser -o 63 -f manual.pdf
This program has not been tested with this version of Python (3.13.3)
Should you encounter problems, please use Python version 3.12.2
obj 63 0
Type:
Referencing:
Contains stream

<<
/Length 304
/Filter /FlateDecode
>>

b'/CIDInit/ProcSet findresource begin\n12 dict begin\nbegincmap\n/CIDSystemInfo<<\n/Registry (Adobe)\n/Ordering (UCS)\n/Supplement 0\n>> def\n/CMapName/Adobe-Identity-UCS def\n/CMapType 2 def\n1 begincodespacerange\n<00> <FF>\nendcodespacerange\n18 beginbfchar\n<01> <0034>\n<02> <003A>\n<03> <0044>\n<04> <0030>\n<05> <0063>\n<06> <0052>\n<07> <0033>\n<08> <0071>\n<09> <0075>\n<0A> <0073>\n<0B> <0074>\n<0C> <0072>\n<0D> <005F>\n<0E> <0054>\n<0F> <0031>\n<10> <0050>\n<11> <0041>\n<12> <0058>\nendbfchar\nendcmap\nCMapName currentdict /CMap defineresource pop\nend\nend\n'

得到映射表内容 Object 63

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<01> <0034>
<02> <003A>
<03> <0044>
<04> <0030>
<05> <0063>
<06> <0052>
<07> <0033>
<08> <0071>
<09> <0075>
<0A> <0073>
<0B> <0074>
<0C> <0072>
<0D> <005F>
<0E> <0054>
<0F> <0031>
<10> <0050>
<11> <0041>
<12> <0058>

最后将 Object 2 中的十六进制串逐字节对照 Object 63 的映射表进行替换即可得到 4:D0cR3qu3st3r_Tutu

也可以直接用 foremost 提取

HGAME2026-5

最后拼起来即可得到 flag

1
hgame{PAR4D0X_AllCl3arToPr0ceed_Sh4m1R_D0cR3qu3st3r_Tutu}
  • 标题: HGAME 2026
  • 作者: Aristore
  • 链接: https://www.aristore.top/posts/HGAME2026/
  • 版权声明: 版权所有 © Aristore,禁止转载。
评论