diff --git a/README.md b/README.md new file mode 100644 index 0000000..c377bbc --- /dev/null +++ b/README.md @@ -0,0 +1,40 @@ +# pwn_deploy_chroot + +> A project for deploying ctf pwn challenge use chroot + +中文请点击: + +[README_CN.md](https://github.com/giantbranch/pwn_deploy_chroot/blob/master/README_CN.md) + +## Before + +``` +# Install the latest version docker +curl -s https://get.docker.com/ | sh +# Install docker compose +apt install docker-compose +``` + +## Configuration + +Put your pwn bin to ./bin (**Note that the filename should not contain special characters.**) + +Listen port start from 10000, you can change in config.py + +## Run + +``` +python initialize.py +# please run as root +docker-compose up --build -d +``` + +## Attention + +The flag will be generated by the initialize.py and it store in flags.txt + +The port information corresponding to the pwn program is also inside flags.txt. + +## Reference + +https://github.com/Eadom/ctf_xinetd diff --git a/README_CN.md b/README_CN.md new file mode 100644 index 0000000..1b81fee --- /dev/null +++ b/README_CN.md @@ -0,0 +1,38 @@ +# pwn_deploy_chroot + +> 可以方便地部署多个pwn题到一个docker容器中(使用chroot) + +## 前置 + +``` +# 安装 docker +curl -s https://get.docker.com/ | sh +# 安装 docker-compose +apt install docker-compose +``` + +## 配置 + +将你的pwn二进制程序放到`./bin` 目录(注意文件名不要含有特殊字符,因为后面会这个文件名创建用户名) + +监听端口从10000开始,每多一个pwn就加1,你可以在`config.py`中修改起始监听端口 + +## 启动 + +``` +python initialize.py +# 请用root用户启动 +docker-compose up --build -d +``` + +## 注意 + +flag会由`initialize.py`生成,并写入flags.txt中,并且pwn程序对应的端口信息也在里面 + +## 参考 + +https://github.com/Eadom/ctf_xinetd + + + + diff --git a/bin/pwn1 b/bin/pwn1 new file mode 100644 index 0000000..7fe8867 Binary files /dev/null and b/bin/pwn1 differ diff --git a/bin/pwn1_copy1 b/bin/pwn1_copy1 new file mode 100644 index 0000000..7fe8867 Binary files /dev/null and b/bin/pwn1_copy1 differ diff --git a/bin/pwn1_copy2 b/bin/pwn1_copy2 new file mode 100644 index 0000000..7fe8867 Binary files /dev/null and b/bin/pwn1_copy2 differ diff --git a/config.py b/config.py new file mode 100644 index 0000000..95d3dfb --- /dev/null +++ b/config.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# @Date : 2018-09-17 14:01:13 +# @Author : giantbranch (giantbranch@gmail.com) +# @Link : http://www.giantbranch.cn/ +# @tags : + +FLAG_BAK_FILENAME = "flags.txt" +PWN_BIN_PATH = "./bin" +XINETD_CONF_FILENAME = "pwn.xinetd" +PORT_LISTEN_START_FROM = 10000 + +XINETD = '''service ctf +{ + disable = no + socket_type = stream + protocol = tcp + wait = no + user = root + type = UNLISTED + port = %d + bind = 0.0.0.0 + server = /usr/sbin/chroot + server_args = --userspec=%s /home/%s ./%s + # safety options + per_source = 10 # the maximum instances of this service per source IP address + rlimit_cpu = 20 # the maximum number of CPU seconds that the service may use + rlimit_as = 100M # the Address Space resource limit for the service + #access_times = 2:00-9:00 12:00-24:00 +} + +''' + +DOCKERFILE = '''FROM ubuntu:16.04 + +RUN sed -i 's/archive.ubuntu.com/asia-east1.gce.archive.ubuntu.com/g' /etc/apt/sources.list && apt update && apt-get install -y lib32z1 xinetd && rm -rf /var/lib/apt/lists/ && rm -rf /root/.cache && apt-get autoclean && rm -rf /tmp/* /var/lib/apt/* /var/cache/* /var/log/* +#apt update && apt-get install -y lib32z1 xinetd && rm -rf /var/lib/apt/lists/ && rm -rf /root/.cache && apt-get autoclean && rm -rf /tmp/* /var/lib/apt/* /var/cache/* /var/log/* + +COPY ./'''+ XINETD_CONF_FILENAME +''' /etc/xinetd.d/pwn + +COPY ./service.sh /service.sh + +RUN chmod +x /service.sh + +# useradd and put flag +%s + +# copy bin +%s + +# chown & chmod +%s + +# copy lib,/bin +%s + +CMD ["/service.sh"] +''' + +DOCKERCOMPOSE = '''version: '2' +services: + pwn_deploy_chroot: + image: pwn_deploy_chroot:latest + build: . + container_name: pwn_deploy_chroot + ports: + %s +''' + diff --git a/initialize.py b/initialize.py new file mode 100644 index 0000000..4024f48 --- /dev/null +++ b/initialize.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# @Date : 2018-09-17 14:32:32 +# @Author : giantbranch (giantbranch@gmail.com) +# @Link : http://www.giantbranch.cn/ +# @tags : + +from config import * +import os +import uuid + +def getFileList(): + filelist = [] + for filename in os.listdir(PWN_BIN_PATH): + filelist.append(filename) + filelist.sort() + return filelist + +def generateFlags(filelist): + tmp = "" + flags = [] + if os.path.exists(FLAG_BAK_FILENAME): + os.remove(FLAG_BAK_FILENAME) + with open(FLAG_BAK_FILENAME, 'a') as f: + for filename in filelist: + tmp = "flag{" + str(uuid.uuid4()) + "}" + f.write(filename + ": " + tmp + "\n") + flags.append(tmp) + return flags + +def generateXinetd(filelist): + port = PORT_LISTEN_START_FROM + conf = "" + uid = 1000 + for filename in filelist: + conf += XINETD % (port, str(uid) + ":" + str(uid), filename, filename) + port = port + 1 + uid = uid + 1 + with open(XINETD_CONF_FILENAME, 'w') as f: + f.write(conf) + +def generateDockerfile(filelist, flags): + conf = "" + # useradd and put flag + runcmd = "RUN " + + for filename in filelist: + runcmd += "useradd -m " + filename + " && " + + for x in xrange(0, len(filelist)): + if x == len(filelist) - 1: + runcmd += "echo '" + flags[x] + "' > /home/" + filelist[x] + "/flag.txt" + else: + runcmd += "echo '" + flags[x] + "' > /home/" + filelist[x] + "/flag.txt" + " && " + # print runcmd + + # copy bin + copybin = "" + for filename in filelist: + copybin += "COPY " + PWN_BIN_PATH + "/" + filename + " /home/" + filename + "/" + filename + "\n" + # print copybin + + # chown & chmod + chown_chmod = "RUN " + for x in xrange(0, len(filelist)): + chown_chmod += "chown -R root:" + filelist[x] + " /home/" + filelist[x] + " && " + chown_chmod += "chmod -R 750 /home/" + filelist[x] + " && " + if x == len(filelist) - 1: + chown_chmod += "chmod 740 /home/" + filelist[x] + "/flag.txt" + else: + chown_chmod += "chmod 740 /home/" + filelist[x] + "/flag.txt" + " && " + # print chown_chmod + + # copy lib,/bin + dev = '''mkdir /home/%s/dev && mknod /home/%s/dev/null c 1 3 && mknod /home/%s/dev/zero c 1 5 && mknod /home/%s/dev/random c 1 8 && mknod /home/%s/dev/urandom c 1 9 && chmod 666 /home/%s/dev/* && ''' + ness_bin = '''mkdir /home/%s/bin && cp /bin/sh /home/%s/bin && cp /bin/ls /home/%s/bin && cp /bin/cat /home/%s/bin''' + copy_lib_bin_dev = "RUN " + for x in xrange(0, len(filelist)): + copy_lib_bin_dev += "cp -R /lib* /home/" + filelist[x] + " && " + copy_lib_bin_dev += dev % (filelist[x], filelist[x], filelist[x], filelist[x], filelist[x], filelist[x]) + if x == len(filelist) - 1: + copy_lib_bin_dev += ness_bin % (filelist[x], filelist[x], filelist[x], filelist[x]) + else: + copy_lib_bin_dev += ness_bin % (filelist[x], filelist[x], filelist[x], filelist[x]) + " && " + + # print copy_lib_bin_dev + + conf = DOCKERFILE % (runcmd, copybin, chown_chmod, copy_lib_bin_dev) + + with open("Dockerfile", 'w') as f: + f.write(conf) + +def generateDockerCompose(length): + conf = "" + ports = "" + port = PORT_LISTEN_START_FROM + for x in xrange(0,length): + ports += "- " + str(port) + ":" + str(port) + "\n " + port = port + 1 + + conf = DOCKERCOMPOSE % ports + # print conf + with open("docker-compose.yml", 'w') as f: + f.write(conf) + +def generateBinPort(filelist): + port = PORT_LISTEN_START_FROM + tmp = "\n" + for filename in filelist: + tmp += filename + "'s port: " + str(port) + "\n" + port = port + 1 + print tmp + with open(FLAG_BAK_FILENAME, 'a') as f: + f.write(tmp) + + +filelist = getFileList() +flags = generateFlags(filelist) +generateBinPort(filelist) +generateXinetd(filelist) +generateDockerfile(filelist, flags) +generateDockerCompose(len(filelist)) + + + diff --git a/service.sh b/service.sh new file mode 100644 index 0000000..89b58c1 --- /dev/null +++ b/service.sh @@ -0,0 +1,6 @@ +#!/bin/sh +# Add your startup script + +# DO NOT DELETE +/etc/init.d/xinetd start; +sleep infinity;