Week 1
其实就只打了week1的misc(
Misc
打好基础
Challenge
😛 ENJOY HGAME!
🐲👝🐱👁👠👮👌👞👂🐬🐽🐡👎👮🐪🐿🐾👞🐨👕🐫👤👏👟👍👉🐲👑👍👀👔👭🐩👮🐾👏🐮👑🐨🐩🐠👯👡🐮👍🐨👒🐘🐨🐮👔👍🐸🐥🐡👇🐶👝👏👱🐺👀👌🐢🐦🐦👟👂👮👝🐡🐳🐰👒👄👡🐶👤👀👴🐯🐭🐛👱👎👫🐭🐢🐫👨👭👬👌👲👧🐘🐮👊👕👊👦🐥👎👈👟🐴👈🐭🐶👭🐥🐡🐽👓🐨👝👛🐡👕🐫🐡🐽👯👱👌👁👡🐫🐲🐡🐲🐟🐶👪🐭👳👌👖👲👡👈👯🐘👇🐫🐡👈🐰👕👡🐩👎👁🐳👒👡👣👨👞👞🐫👠👈🐽🐲👤🐩👎👂🐤👟🐬👤🐴👣👛👃👳🐽🐢👃👀🐨👧🐠👎🐹👓👢🐼🐳👁🐱👚🐳👭🐨👔👍🐠👥🐸🐱🐣🐸👖🐰👓🐬👄🐳👱👐👉🐢👝🐠🐤👯👀👎👥🐤👔🐨👊👊👃🐽👱🐪👱👚👍🐵🐶👎🐻👛🐤👂🐳🐾🐟🐨👢👍👥🐼👟👕👙👣🐡👣👭🐿👦🐩👂👬🐞🐢👋🐠👙🐶🐤👥👋🐲👱🐩👕🐝🐺🐯👴👍🐡🐦🐰👍🐨👋👔👤🐚🐻👐🐽👟🐴🐷👎🐴👫👀👤🐦👡🐥👡🐵🐸🐺👫👛👮👲🐬👯👌👔👙👉🐷🐺👁👅🐪👒👈👕👅🐯🐩🐝👰👚👌👂🐵🐽Solution
Base100 -> Base92 -> Base91 -> Ascii85 -> Base64 -> Base62 -> Base58 -> Base45 -> Base32
FLAG
hgame{L4y_a_sO11d_f0unDaTi0n}shiori不想找女友
Challenge
Tremse正在帮Shiori找女友,但是他现在找不到Shiori了!但是他留下了他的头像,你可以帮我找找他在哪里吗🙏
Solution
查看 exif 发现 User Comment 藏有信息
{"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 列,编写脚本提取像素组成新的图片
from PIL import Imageimport 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
hgame{bec0use_lilies_are_7he_b1st}[REDACTED]
Challenge
兔兔说她对一份机密文件进行了“完美的”脱敏处理。还好你在发送之前检查了一下。
提交说明: 附件中包含四段敏感字符串,格式为
[1-4]:.+。用下划线字符_连接去掉序号的四段字符串,包裹hgame{}后提交。例如,若四段敏感字符串分别为1:Example、2:Redacted、3:Secret、4:Strings_!,则提交的 flag 为hgame{Example_Redacted_Secret_Strings_!}。
Solution
1:PAR4D0X

2:AllCl3arToPr0ceed


3:Sh4m1R

至此浮于表面的答案都找到了,还没仔细研究过这个 PDF 文件本身
先使用 pdfid 初步扫描文件
┌──(kali㉿kali)-[~/Desktop]└─$ pdfid manual.pdfPDFiD 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 0PDF 就只有 2 页,但 pdfid 扫出来 3 页,这咋看都不对劲,可能是通过修改 PDF 目录结构隐藏了一页
用 pdf-parser 进一步分析
┌──(kali㉿kali)-[~/Desktop]└─$ pdf-parser manual.pdfThis program has not been tested with this version of Python (3.13.3)Should you encounter problems, please use Python version 3.12.2PDF 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),发现了文件被篡改的痕迹:
-
原始定义(
Object 1, 7, 34):textobj 59 0Type: /PagesKids [1 0 R 7 0 R 34 0 R] <----------Count 3 -
增量更新(
Object 7, 34):textobj 59 0Type: /PagesKids [7 0 R 34 0 R] <----------Count 2
Object 1 就是被隐藏的第一页,定位到隐藏页 Object 1:
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 的数据:
┌──(kali㉿kali)-[~/Desktop]└─$ pdf-parser -o 2 -f manual.pdfThis program has not been tested with this version of Python (3.13.3)Should you encounter problems, please use Python version 3.12.2obj 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 的映射表来还原真实文本
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 的定义
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 的定义
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 的定义:
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 的映射表,提取映射表:
┌──(kali㉿kali)-[~/Desktop]└─$ pdf-parser -o 63 -f manual.pdfThis program has not been tested with this version of Python (3.13.3)Should you encounter problems, please use Python version 3.12.2obj 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:
<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 提取

最后拼起来即可得到 flag
hgame{PAR4D0X_AllCl3arToPr0ceed_Sh4m1R_D0cR3qu3st3r_Tutu}