# MISC

# LSD#4

这道题直接看提示

1764492103388

这里用 Py 写个脚本,从 1000x1000 的位置。类似 LSB 隐写,读取红色通道,然后输出即可。

给一个 ai 写的 exp:

from PIL import Image
def decode_red_channel_lsb(image_path, start_x=1000, start_y=1000, size=100):
    # 打开图像
    im = Image.open(image_path)
    pixels = im.load()
    # 提取红色通道 LSB
    red_bits = []
    for y in range(start_y, start_y + size):
        for x in range(start_x, start_x + size):
            red_value = pixels[x, y][0]  # R 通道
            red_bits.append(red_value & 1)  # 取最低位
    print("\n===  搜索Flag ===")
    search_flag_pattern(red_bits)
def search_flag_pattern(bits):
    # 将比特转换为字符串便于搜索
    bit_str = ''.join(str(b) for b in bits)
    # Hero { 的 ASCII 二进制模式
    hero_patterns = {
        'H': '01001000',
        'e': '01100101',
        'r': '01110010',
        'o': '01101111',
        '{': '01111011'
    }
    # 搜索连续的 flag 起始模式
    target_start = ''.join(hero_patterns[char] for char in 'Hero{')
    if target_start in bit_str:
        idx = bit_str.index(target_start)
        # 提取从该位置开始的比特
        flag_bits = bit_str[idx:]
        flag_bytes = bytearray()
        for i in range(0, len(flag_bits) - 7, 8):
            byte_bits = flag_bits[i:i + 8]
            if len(byte_bits) == 8:
                byte_val = int(byte_bits, 2)
                flag_bytes.append(byte_val)
                if byte_val == ord('}'):  # 遇到结束符
                    break
        flag_text = flag_bytes.decode('ascii')
        print(f"🎯 提取到Flag: {flag_text}")
image_path = "secret.png"  # 修改为你的图像路径
decode_red_channel_lsb(image_path)

# Neverland

这题是登录上去直接试着输出 flag,发现权限不足

首先尝试 sudo 提权:

1764492611454

就一个可以用的,显然就是这里

然后看看内容:

TEMP_DIR="/home/peter/git-review-$$"
...
mkdir -p "$TEMP_DIR"
tar -xzf "$USER_ARCHIVE" -C "$TEMP_DIR"
EXTRACTED_DIR=$(find "$TEMP_DIR" -mindepth 1 -maxdepth 1 -type d)
cd "$EXTRACTED_DIR"

这里创建了个临时目录来解压用户提交的 tar.gz

并且没有过滤解压出来的内容,并且自动 cd 到解压出来的内容中的一个目录,此后脚本里的所有 git 命令都会在这个提交的 repo 中运行:

1764493178057

而在执行 commit 命令时,会自动执行 hook,而我们刚好可以控制其中的内容,以 peter 的身份执行任意命令

而检查的部分只是检查了.git/config 是否和 Admin 提交的一致,这就要求我们不能改变 config 文件,也就不能改变其中的内容。

这个文件的作用:
其存储配置按小节划分,包括远程仓库地址,以及拉取推送规则等:

[remote "origin"]
	url=/app
	#可以是本地路径或者 URL
	fetch=+refs/heads/*:refs/remotes/origin
	#拉取时的分支映射规则
[branch "master"]
	remote=origin
	#默认是关联的远程仓库
	merge=refs/heads/master
	#拉取时默认合并规则
[user]
	name=Admin
	email=admin@localhost
[core]
	editor=vim
	hooksPath=.git/hooks
	#默认存放的路径,这决定了我们恶意 hook 应该放在哪里。
	autocrlf=false

所以当我们复用了 Admin 原先的 config,然后构造一个 tar 包结构类似:

exploit/ <-待会被打开的目录,所有git命令将在这执行
  ├── .git/
  │    ├── config
  │    └── hooks/
  │         └── pre-commit    ← 恶意脚本
  ├── README.md
  └── config-tool.py 

随后脚本后面执行 commit 时就会自动执行我们的恶意脚本
将 flagcp 到 /tmp 目录下,然后自行读取

# WEB

# Revoked

首先发现有个 SQL 注入:
1764496715531

甚至还存储了现有的 JWT

1764496753267

我的天,看我一把梭出 admin:

1764496806549

1764496838348

好的好的:

然后才发现这玩意儿是废弃的,坏

通过看后面一题 rev,发现说是有测试账户没有删,但是查询数据库时会发现那个账户是同样具有 admin 权限的 admin1。但就题目而言,与 admin 本身没看出有什么区别。

PS: 在结束后在网上找到了 wp。居然是去爆破 admin1 密码的 hash,蚌埠住

# Tomcat

两次执行同一个东西按理来说是不可能得到不同的结果,而且强行将两个不同的 web 程序的 session 放在一个文件夹来实现共用。此外 compose 提到 bp,盒异味。

# SYSTEM

# Movie Night

还是一题提权,绷不住:

首先看一眼 sudo 除了没什么用的自己提权自己以外没有任何东西

然后稍微尝试一下发现几乎没法访问任何 dev 用户的文件,所以哪里肯定有权限接口,看一下程序:

find / -user dev -ls 2>/dev/null

输出了一大堆,看不懂没关系,但是要注意到在一大堆 proc 中,有一个:

1764503859702

在 tmp 目录下,显然不是正常会有的东西,而且我们是可读可写的。

搜一下什么是 tmux

1764504448133

尝试连接一下:

tmux -S /tmp/tmux-1002 attach

这个语法在教程中似乎并没有,但是问问 ai 应该就行了

得到 shell,获取 flag

1764504999665