Skip to content

Commit

Permalink
add Misc LSB dynamic template
Browse files Browse the repository at this point in the history
  • Loading branch information
Randark-JMT committed Mar 15, 2024
1 parent e681bae commit 9f3732b
Show file tree
Hide file tree
Showing 8 changed files with 163 additions and 57 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
.vscode/
env/
67 changes: 10 additions & 57 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,19 @@

![ctf-docker-template](https://github.com/CTF-Archives/ctf-docker-template/assets/41804496/71e71631-1d10-4076-b63d-8668a7b22a5f)


## About

**ctf-docker-template** 是一个用于支持动态 Flag 的Docker容器模板项目,支持主流的各类CTF平台.
**ctf-docker-template** 是一个用于支持动态 Flag 的Docker容器模板项目,支持主流的各类CTF平台

项目存有一定局限性,但已可适用于绝大多数初中级别题目的命题需求
项目存有一定局限性,但已可适用于绝大多数初中级别题目的命题需求

本仓库内的Docker容器模板支持的 FLAG 注入类型如下:

- `$FLAG`[CTFd](https://github.com/CTFd/CTFd)[NSSCTF](https://www.nssctf.cn/)
- `$GZCTF_FLAG`[GZCTF](https://github.com/GZTimeWalker/GZCTF)
- `$DASCTF`(DASCTF)

三种动态flag部署方式,支持GZCTF、CTFd、安恒DASCTF等支持Docker动态部署题目靶机的平台
三种动态flag部署方式,支持GZCTF、CTFd、安恒DASCTF等支持Docker动态部署题目靶机的平台

> 一般情况下,CTF题目动态FLAG使用环境变量注入的方式来实现:
>
Expand All @@ -25,51 +24,6 @@
**有问题请开issue,好用请点star,有问题的话欢迎通过 [CTF-Archives售后快速服务群](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=KFamhBpmURTZpndhc0MI7_1l3a6Xezrf&authKey=Yenwm7%2B%2F%2FT%2BtSXCSyr%2B7fYS47Ot0MwFqesH4HOLT8ZADE2e9XO6AS96HQvjxh%2B%2BG&noverify=0&group_code=894957229) 联系维护人员寻求帮助**

> [!CAUTION]
> **请注意!!**
>
> **此仓库内的模板仅在Linux环境(linux/amd64)下进行测试并保证可用性,如果为windows(windows/amd64)或者macos(linux/arm)等其他架构,不保证可用性😔**
>
> 建议直接在linux下执行 `git clone` 操作,或者直接从github下载zip版本的源码.
## Structure

在一般情况下,每个模板的文件结构如下:

```
.
├── README.md
├── Dockerfile
├── config # Web容器 中间件配置需要定义的专属
│ └── nginx.conf
├── data # Web容器 且 有数据库需求容器专属
│ └── db.sql
├── docker
│ └── docker-compose.yml
├── service
│ └── docker-entrypoint.sh
└── src
└── main.py
```

- `Dockerfile` 为docker容器编译文件,用于设计docker容器,可在其中设置换源、增添软件包等等

- `config` 文件夹内存放着容器内服务相关的配置文件,如 `nginx` 的配置文件等等

- `data` 文件夹内存放着容器内服务相关的配置文件,如 `nginx` 的配置文件等等

- `docker` 文件夹内存放与docker有关的文件,如 `docker-compose.yml` 文件,内部已经设置好了端口转发和测试用flag,便于测试容器环境

- `service` 文件夹内存放着与服务有关的文件,如 `docker-entrypoint.sh` 用于定义容器的入口点

- `src` 文件夹内存放着题目的项目源码,也可以是pwn题目的二进制文件,即为题目的相关文件

- `flag.php` 用于直接查看flag文件的测试文件,访问可直接查看当前题目根目录下的flag文件,如果文件不存在则会输出error

- `shell.php` 一句话木马,用于测试web容器稳定性

......

## 常见问题

### no_socket with crypto
Expand Down Expand Up @@ -178,7 +132,6 @@ sed -i ""s/\r//"" docker-entrypoint.sh
- 将会话转发给选手的连接
**使用:**
直接将SageMath文件/项目放入 `./src` 目录后执行后续操作,文件名建议使用 `main.sage` ,便于环境识别,如需更改文件名,请在 `./service/docker-entrypoint.sh` 内更改
Expand All @@ -194,7 +147,7 @@ KOH题目是基于HTTP服务与后端评判系统进行交互的,故题目容器
```python
@app.route('/upload', methods=['POST'])
def upload():
pass
pass
```
该路由负责接收用户上传的数据。数据将以表单数据的形式进行上传,参数名为file。
Expand All @@ -211,7 +164,7 @@ requests.post(f'http://{url}/upload', files={

```json
{
"code": 200
"code": 200
}
```

Expand All @@ -224,7 +177,7 @@ requests.post(f'http://{url}/upload', files={
```python
@app.route('/check', methods=['POST'])
def check():
pass
pass
```

当后端完成对/upload路由的访问且没有异常时,将访问/check路由。访问示例代码如下:
Expand All @@ -237,8 +190,8 @@ requests.post(f'http://{url}/check', timeout=10)

```json
{
"code": 200,
"score": 100
"code": 200,
"score": 100
}
```

Expand Down Expand Up @@ -345,11 +298,11 @@ rm -f /home/ctf/usr/local/lib/python3.10/subprocess.py

适用于基于 `war` 程序包部署环境的需求

直接将 `war` 程序包放入 `./src`
直接将 `war` 程序包放入 `./src`

#### LAMP-php80 / LNMP-php73 / nginx-php73

> 部分容器参考 https://github.com/CTFTraining/ 感谢 [陌竹 - mozhu1024](https://github.com/mozhu1024) 师傅 和 [赵总 - glzjin](https://github.com/glzjin) 师傅做出的贡献
> 部分容器参考 [CTF Training](https://github.com/CTFTraining/) 感谢 **[陌竹 - mozhu1024](https://github.com/mozhu1024)** 师傅 和 **[赵总 - glzjin](https://github.com/glzjin)** 师傅做出的贡献
`Apache2` +`PHP 8.0.30`+`10.5.21-MariaDB` 的基础环境,默认暴露端口位于 80

Expand Down
34 changes: 34 additions & 0 deletions misc-lsb-dynamic/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
FROM python:3.10.12-slim-bullseye

# 制作者信息
LABEL auther_template="CTF-Archives"

# apt更换镜像源,并更新软件包列表信息
RUN sed -i 's/deb.debian.org/mirrors.ustc.edu.cn/g' /etc/apt/sources.list && \
sed -i 's/security.debian.org/mirrors.ustc.edu.cn/g' /etc/apt/sources.list
RUN apt-get update

# 通过apt,安装xinetd用于服务转发
RUN apt-get install -y socat

# 通过tuna源,安装必要的python依赖库
# 镜像中并没有更换源,只是在pip语句中每次制定了镜像源
RUN python3 -m pip install -i https://pypi.tuna.tsinghua.edu.cn/simple \
pycryptodome pillow

# 复制容器启动脚本
COPY ./service/docker-entrypoint.sh /
RUN chmod +x /docker-entrypoint.sh

# 新建用户,并进行账户改变
RUN useradd -m ctf
WORKDIR /home/ctf

# 部署程序
COPY ./src /app

# [可选]指定对外暴露端口,对于GZCTF等平台,强制EXPOSE可能会造成非预期端口泄露,请酌情启用
# EXPOSE 9999

# 指定容器入口点
ENTRYPOINT ["/bin/sh","/docker-entrypoint.sh"]
24 changes: 24 additions & 0 deletions misc-lsb-dynamic/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# misc-lsb-dynamic

## 环境说明

实现了基础的 Misc LSB 隐写脚本,并通过 `http.server.SimpleHTTPRequestHandler` 实现了一个简单的 HTTP 服务器

## 如何使用

本模板仅为示例,如果需要修改隐写的基础图像,或者更改隐写逻辑的话,请自行修改 `src/server.py`

执行

```shell
docker build .
```

即可开始编译镜像

也可以在安放好程序文件之后,直接使用 `./docker/docker-compose.yml` 内的 `docker-compose` 文件实现一键启动测试容器

```shell
cd ./docker
docker-compose up -d
```
11 changes: 11 additions & 0 deletions misc-lsb-dynamic/docker/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
version: '3'
services:
test:
build: ../
environment:
# 仅为测试用flag
FLAG: "flag{a63b4d37-7681-4850-b6a7-0d7109febb19}"
ports:
# 设置了暴露端口
- 8080:8080
restart: unless-stopped
25 changes: 25 additions & 0 deletions misc-lsb-dynamic/service/docker-entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/bin/sh

# Get the user
user=$(ls /home)

# Check the environment variables for the flag and assign to INSERT_FLAG
if [ "$DASFLAG" ]; then
INSERT_FLAG="$DASFLAG"
export DASFLAG=no_FLAG
DASFLAG=no_FLAG
elif [ "$FLAG" ]; then
INSERT_FLAG="$FLAG"
export FLAG=no_FLAG
FLAG=no_FLAG
elif [ "$GZCTF_FLAG" ]; then
INSERT_FLAG="$GZCTF_FLAG"
export GZCTF_FLAG=no_FLAG
GZCTF_FLAG=no_FLAG
else
INSERT_FLAG="flag{TEST_Dynamic_FLAG}"
fi

cd /app

python3 /app/server.py $INSERT_FLAG
58 changes: 58 additions & 0 deletions misc-lsb-dynamic/src/server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
from PIL import Image
import http.server
import socketserver
import os
import sys


def string_to_binary(string: str):
return [bin(ord(i))[2:].rjust(8, "0") for i in string]


img_src = Image.open("./src.png").convert("RGB")

flag = sys.argv[1]
print("Flag: {}".format(flag))
flag = "".join([i for i in string_to_binary(sys.argv[1])])
flag = [i for i in flag]
print("FLag binary: {}".format(flag))

W, H = img_src.size

img_dst = Image.new(img_src.mode, (W, H))

for y in range(H):
for x in range(W):
if flag:
pixel = img_src.getpixel((x, y))
pixel = (int(bin(pixel[0])[2:][:-1] + flag.pop(0), 2), pixel[1], pixel[2])
img_dst.putpixel((x, y), pixel)
else:
img_dst.putpixel((x, y), img_src.getpixel((x, y)))

os.mkdir("./http")
img_dst.save("./http/dst.png")


class Handler(http.server.SimpleHTTPRequestHandler):
def __init__(self, *args, **kwargs):
super().__init__(*args, directory="./http", **kwargs)

def do_GET(self):
if self.path == "/":
self.send_response(200)
self.send_header("Content-Disposition", 'attachment; filename="dst.png"')
self.send_header("Content-type", "application/octet-stream")
self.end_headers()

# 读取文件内容并发送给客户端
with open("./http/dst.png", "rb") as file:
self.wfile.write(file.read())
else:
# 调用父类的默认处理方法
super().do_GET()


with socketserver.TCPServer(("0.0.0.0", 8080), Handler) as httpd:
print("Server is running\nhttp://0.0.0.0:8080/")
httpd.serve_forever()
Binary file added misc-lsb-dynamic/src/src.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 9f3732b

Please sign in to comment.