├── README.md ├── alpine+socat+patchelf ├── deploy │ ├── Dockerfile │ ├── build_image.sh │ ├── docker-compose.yaml │ ├── flag │ ├── run_pwn.sh │ └── src │ │ ├── makefile │ │ └── pwn.c └── readme.md ├── alpine+socat+patchelf2 ├── deploy │ ├── Dockerfile │ ├── bin │ │ ├── patchelf │ │ └── pwn │ ├── build_image.sh │ ├── docker-compose.yaml │ ├── flag │ ├── glibc │ │ ├── ld-linux-x86-64.so.2 │ │ └── libc.so.6 │ └── run_pwn.sh └── readme.md ├── alpine+xinetd+chroot+patchelf ├── deploy │ ├── Dockerfile │ ├── build_image.sh │ ├── cat.c │ ├── ctf.xinetd │ ├── docker-compose.yaml │ ├── flag │ ├── ls.c │ ├── run_pwn.sh │ └── src │ │ ├── makefile │ │ └── pwn.c └── readme.md ├── alpine+xinetd+chroot+patchelf2 ├── deploy │ ├── Dockerfile │ ├── bin │ │ ├── cat │ │ ├── ls │ │ ├── patchelf │ │ ├── pwn │ │ └── xinetd │ ├── build_image.sh │ ├── ctf.xinetd │ ├── docker-compose.yaml │ ├── flag │ ├── glibc │ │ ├── ld-linux-x86-64.so.2 │ │ └── libc.so.6 │ └── run_pwn.sh └── readme.md ├── alpine+ynetd+chroot+patchelf ├── deploy │ ├── Dockerfile │ ├── build_image.sh │ ├── cat.c │ ├── docker-compose.yaml │ ├── flag │ ├── ls.c │ ├── run_pwn.sh │ ├── src │ │ ├── makefile │ │ └── pwn.c │ └── ynetd.c └── readme.md ├── alpine+ynetd+chroot+patchelf2 ├── deploy │ ├── Dockerfile │ ├── bin │ │ ├── cat │ │ ├── ls │ │ ├── patchelf │ │ ├── pwn │ │ └── ynetd │ ├── build_image.sh │ ├── docker-compose.yaml │ ├── flag │ ├── glibc │ │ ├── ld-linux-x86-64.so.2 │ │ └── libc.so.6 │ └── run_pwn.sh └── readme.md ├── alpine+ynetd+patchelf ├── deploy │ ├── Dockerfile │ ├── bin │ │ ├── patchelf │ │ ├── pwn │ │ └── ynetd │ ├── build_image.sh │ ├── docker-compose.yaml │ ├── flag │ └── glibc │ │ ├── ld-linux-x86-64.so.2 │ │ └── libc.so.6 └── readme.md ├── kctf+nsjail+socat ├── deploy │ ├── Dockerfile │ ├── build_image.sh │ ├── docker-compose.yaml │ ├── flag │ ├── nsjail.cfg │ ├── run_pwn.sh │ ├── src │ │ ├── makefile │ │ └── pwn.c │ └── start.sh └── readme.md ├── red.pwn.jail ├── deploy │ ├── Dockerfile │ ├── build_image.sh │ ├── docker-compose.yaml │ └── pwn └── readme.md ├── ubuntu+socat ├── deploy │ ├── Dockerfile │ ├── build_image.sh │ ├── docker-compose.yaml │ ├── flag │ ├── run_pwn.sh │ └── src │ │ ├── makefile │ │ └── pwn.c └── readme.md └── ubuntu+xinetd+chroot ├── deploy ├── Dockerfile ├── build_image.sh ├── ctf.xinetd ├── docker-compose.yaml ├── flag ├── run_pwn.sh └── src │ ├── makefile │ └── pwn.c └── readme.md /README.md: -------------------------------------------------------------------------------- 1 | # pwn题部署模板 2 | 编写了常用的`11`种`pwn`题部署模板文件,支持`sha256 proof of work`验证,支持从环境变量中设置`flag`。 3 | 详情可参考每个模板下的`readme.md`文件。 4 | 5 | # 注意事项 6 | 如果是`ubuntu:18.04`以及以下版本,使用`chroot`构造沙箱环境的时候,`dockerfile`对应语句需要更新为: 7 | 8 | ```dockerfile 9 | FROM ubuntu:18.04 10 | # ...... 11 | RUN cp -R /usr/lib* /home/ctf && \ 12 | cp -R /lib* /home/ctf && \ 13 | mkdir /home/ctf/dev && \ 14 | mknod /home/ctf/dev/null c 1 3 && \ 15 | mknod /home/ctf/dev/zero c 1 5 && \ 16 | mknod /home/ctf/dev/random c 1 8 && \ 17 | mknod /home/ctf/dev/urandom c 1 9 && \ 18 | chmod 666 /home/ctf/dev/* 19 | ``` 20 | 21 | 如果是`ubuntu:16.04`,前面的语句需要更新为: 22 | 23 | ```dockerfile 24 | FROM ubuntu:16.04 as runner 25 | # ...... 26 | RUN apt clean && apt autoclean && apt update && apt install -y xinetd && \ 27 | useradd ctf -u 1000 -s /bin/sh 28 | ``` 29 | 30 | 如果是`ubuntu:23.04`及更高版本,需要将用户的`uid`修改为`1001`: 31 | 32 | ```dockerfile 33 | FROM ubuntu:23.04 as runner 34 | 35 | RUN apt update && apt install -y xinetd 36 | 37 | RUN useradd ctf -u 1001 -s /bin/sh 38 | ``` 39 | 40 | # deploy_pwn_template 41 | Templates for deploying pwn challenge in ctf. 42 | 43 | There're four general templates for deploying pwn challenge, `sha256 proof of work` is supported, and setting flag from `env` is supported. 44 | 45 | please read `readme.md` in each template to get more infomation. -------------------------------------------------------------------------------- /alpine+socat+patchelf/deploy/Dockerfile: -------------------------------------------------------------------------------- 1 | # dockerfile for pwn 2 | FROM ubuntu:20.04 as compiler 3 | 4 | WORKDIR /root 5 | 6 | RUN apt update && apt install -y gcc g++ make git autoconf automake libtool 7 | 8 | RUN git clone https://github.com/NixOS/patchelf.git && \ 9 | cd ./patchelf && \ 10 | ./bootstrap.sh && \ 11 | ./configure && \ 12 | make && \ 13 | make install 14 | 15 | WORKDIR /root/ctf 16 | 17 | COPY ./src . 18 | 19 | RUN make pwn && \ 20 | mkdir glibc && \ 21 | cp /lib/x86_64-linux-gnu/libc.so.6 ./glibc/libc.so.6 && \ 22 | cp /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 ./glibc/ld-linux-x86-64.so.2 && \ 23 | patchelf --set-rpath ./glibc ./pwn && \ 24 | patchelf --set-interpreter ./glibc/ld-linux-x86-64.so.2 ./pwn 25 | 26 | 27 | FROM alpine:latest as runner 28 | 29 | USER root 30 | 31 | RUN apk update && \ 32 | apk add --no-cache socat runuser bash && \ 33 | ln -sf `which bash` /bin/sh && \ 34 | adduser ctf -u 1000 -s /bin/sh -D 35 | 36 | WORKDIR /home/ctf 37 | 38 | COPY --from=compiler /root/ctf/pwn . 39 | COPY --from=compiler /root/ctf/glibc ./glibc 40 | 41 | COPY ./flag ./flag 42 | COPY ./run_pwn.sh / 43 | 44 | RUN chmod 644 ./flag && \ 45 | chmod 711 /run_pwn.sh && \ 46 | chown -R root:root . 47 | 48 | EXPOSE 1337 49 | 50 | CMD socat tcp-l:1337,reuseaddr,fork exec:/run_pwn.sh 51 | 52 | 53 | -------------------------------------------------------------------------------- /alpine+socat+patchelf/deploy/build_image.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # build image 5 | docker-compose up -d || docker compose up -d 6 | 7 | # wait for starting container 8 | sleep 5 9 | 10 | # copy file and generate attachment 11 | echo -n "copy file and generate attachment? [y/n] " 12 | read -t 15 ANS 13 | if [ $ANS == "y" ] || [ $ANS == "Y" ] 14 | then 15 | imageid=$(docker ps -n 1 -q) 16 | mkdir ../attachment/glibc -p 17 | cd ../attachment 18 | docker cp ${imageid}:/home/ctf/pwn . 19 | docker cp ${imageid}:/home/ctf/glibc . 20 | echo "copy file and generate attachment success!" 21 | fi -------------------------------------------------------------------------------- /alpine+socat+patchelf/deploy/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | # docker-compose.yaml for pwn 2 | version: "3" 3 | services: 4 | pwn: 5 | build: . 6 | restart: unless-stopped 7 | environment: # unset FLAG if u don't want to generate flag from env 8 | FLAG: flag{this_is_a_real_flag} 9 | ENABLE_POW: 0 # set ENABLE_POW 1 if u want to use proof-of-pow, unset it to not 10 | ports: 11 | - "10001:1337" 12 | -------------------------------------------------------------------------------- /alpine+socat+patchelf/deploy/flag: -------------------------------------------------------------------------------- 1 | flag{this_is_a_fake_flag} 2 | -------------------------------------------------------------------------------- /alpine+socat+patchelf/deploy/run_pwn.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | # set pow using sha256 POW by ENABLE_POW 6 | if [ ! -z $ENABLE_POW ] 7 | then 8 | if [ "$ENABLE_POW" == "1" ] 9 | then 10 | echo "=================proof-of-work=================" 11 | echo "" 12 | rand_str=$(head -c 27 /dev/urandom | base64) 13 | hash_value=$(echo -n "$rand_str" | sha256sum - | cut -c 1-64) 14 | frontend=$(echo "$rand_str" | cut -c -4 ) 15 | backend=$(echo "$rand_str" | cut -c 5- ) 16 | prompt="sha256(XXXX + \"${backend}\") == ${hash_value}" 17 | echo $prompt 18 | echo -n "Gime me XXXX: " 19 | 20 | read -t 300 -r input_hash 21 | 22 | if [ "$input_hash" != "$frontend" ] 23 | then 24 | echo "Proof of work failed!" 25 | exit 2 26 | fi 27 | fi 28 | fi 29 | 30 | unset ENABLE_POW 31 | 32 | # override flag from env 33 | # if environmental variable FLAG is not empty string 34 | if [ ! -z $FLAG ] 35 | then 36 | if [ "$(cat /home/ctf/flag)" != "$FLAG" ] 37 | then 38 | echo $FLAG > /home/ctf/flag 39 | chmod 644 /home/ctf/flag 40 | fi 41 | fi 42 | 43 | # the env will not pass to ctf 44 | unset FLAG 45 | 46 | cd /home/ctf 47 | 48 | # run pwn challenge 49 | exec runuser -u ctf --pty -- timeout 300 ./pwn -------------------------------------------------------------------------------- /alpine+socat+patchelf/deploy/src/makefile: -------------------------------------------------------------------------------- 1 | all: pwn pwn_debug 2 | 3 | pwn: pwn.c 4 | gcc ./pwn.c -o pwn -fstack-protector-all -pie -z now -z noexecstack -O0 -w 5 | strip ./pwn 6 | 7 | pwn_debug: pwn.c 8 | gcc ./pwn.c -o pwn_debug -fstack-protector-all -pie -z now -z noexecstack -O0 -g3 9 | 10 | clean: 11 | rm -rf ./pwn ./pwn_debug 12 | 13 | -------------------------------------------------------------------------------- /alpine+socat+patchelf/deploy/src/pwn.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | setbuf(stdin, 0); 9 | setbuf(stdout, 0); 10 | setbuf(stderr, 0); 11 | puts("Welcome to pwn world!"); 12 | printf("please input your name: "); 13 | char buf[0x80] = {0}; 14 | read(0, buf, 0x10); 15 | if (strncmp(buf, "admin", 5) == 0) { 16 | system("/bin/sh"); 17 | } else { 18 | puts("you are not admin!"); 19 | } 20 | return 0; 21 | } -------------------------------------------------------------------------------- /alpine+socat+patchelf/readme.md: -------------------------------------------------------------------------------- 1 | # 说明 2 | 3 | 使用`alpine + socat + patchelf` 部署`pwn`题 4 | 5 | - 参照模板,将源码和`makefile`放置在`./deploy/src`目录下 6 | - 确保生成目标文件名称为`pwn`,或者根据需要修改`dockerfile`中的`make pwn`语句 7 | - `run_pwn.sh`中可以放置`proof of work`代码或者设置`timeout`时间 8 | - 运行`./build_image.sh`可以生成镜像以及提供给选手的`attachment`文件夹 9 | - 在`./deploy/docker-compose.yaml`文件中修改映射的宿主机端口、`flag`的内容 10 | - 其他需求可自行根据模板文件定制 11 | 12 | # Introduction 13 | 14 | use `alpine + socat + patchelf` to deploy pwn challenge 15 | 16 | - put source file in `./deploy/src` 17 | - make sure the name of target binary is `pwn`, or you can change the `dockerfile` 18 | - set `proof of work` or `timeout` in `run_pwn.sh` 19 | - execute `./build_image.sh` to generate image and then run a container. Also, you can decide to get attachment file, which is offered to player 20 | - change the port mapping in host and the content of flag in `./deploy/docker-compose.yaml` 21 | -------------------------------------------------------------------------------- /alpine+socat+patchelf2/deploy/Dockerfile: -------------------------------------------------------------------------------- 1 | # dockerfile for pwn 2 | FROM ubuntu:20.04 as patchelf 3 | 4 | WORKDIR /root/ctf 5 | 6 | COPY ./bin/patchelf /bin/patchelf 7 | COPY ./bin/pwn ./pwn 8 | 9 | RUN chmod +x ./pwn /bin/patchelf && \ 10 | patchelf --set-rpath ./glibc ./pwn && \ 11 | patchelf --set-interpreter ./glibc/ld-linux-x86-64.so.2 ./pwn 12 | 13 | FROM alpine:latest as runner 14 | 15 | USER root 16 | 17 | RUN apk update && \ 18 | apk add --no-cache socat runuser bash && \ 19 | ln -sf `which bash` /bin/sh && \ 20 | adduser ctf -u 1000 -s /bin/sh -D 21 | 22 | WORKDIR /home/ctf 23 | 24 | COPY --from=patchelf /root/ctf/pwn . 25 | COPY ./glibc ./glibc 26 | 27 | COPY ./flag ./flag 28 | COPY ./run_pwn.sh / 29 | 30 | RUN chmod 644 ./flag && \ 31 | chmod 711 /run_pwn.sh && \ 32 | chmod +x ./glibc/* && \ 33 | chmod +x ./pwn && \ 34 | chown -R root:root . 35 | 36 | EXPOSE 1337 37 | 38 | CMD socat tcp-l:1337,reuseaddr,fork exec:/run_pwn.sh 39 | 40 | 41 | -------------------------------------------------------------------------------- /alpine+socat+patchelf2/deploy/bin/patchelf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoderickChan/deploy_pwn_template/4c2eec13239491733b635e4152b496eaa887f42c/alpine+socat+patchelf2/deploy/bin/patchelf -------------------------------------------------------------------------------- /alpine+socat+patchelf2/deploy/bin/pwn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoderickChan/deploy_pwn_template/4c2eec13239491733b635e4152b496eaa887f42c/alpine+socat+patchelf2/deploy/bin/pwn -------------------------------------------------------------------------------- /alpine+socat+patchelf2/deploy/build_image.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # build image 5 | docker-compose up -d || docker compose up -d 6 | 7 | # wait for starting container 8 | sleep 5 9 | 10 | # copy file and generate attachment 11 | echo -n "copy file and generate attachment? [y/n] " 12 | read -t 15 ANS 13 | if [ $ANS == "y" ] || [ $ANS == "Y" ] 14 | then 15 | imageid=$(docker ps -n 1 -q) 16 | mkdir ../attachment/glibc -p 17 | cd ../attachment 18 | docker cp ${imageid}:/home/ctf/pwn . 19 | docker cp ${imageid}:/home/ctf/glibc . 20 | echo "copy file and generate attachment success!" 21 | fi -------------------------------------------------------------------------------- /alpine+socat+patchelf2/deploy/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | # docker-compose.yaml for pwn 2 | version: "3" 3 | services: 4 | pwn: 5 | build: . 6 | restart: unless-stopped 7 | environment: # unset FLAG if u don't want to generate flag from env 8 | FLAG: flag{this_is_a_real_flag} 9 | ENABLE_POW: 0 # set ENABLE_POW 1 if u want to use proof-of-pow, unset it to not 10 | ports: 11 | - "10001:1337" 12 | -------------------------------------------------------------------------------- /alpine+socat+patchelf2/deploy/flag: -------------------------------------------------------------------------------- 1 | flag{this_is_a_fake_flag} 2 | -------------------------------------------------------------------------------- /alpine+socat+patchelf2/deploy/glibc/ld-linux-x86-64.so.2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoderickChan/deploy_pwn_template/4c2eec13239491733b635e4152b496eaa887f42c/alpine+socat+patchelf2/deploy/glibc/ld-linux-x86-64.so.2 -------------------------------------------------------------------------------- /alpine+socat+patchelf2/deploy/glibc/libc.so.6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoderickChan/deploy_pwn_template/4c2eec13239491733b635e4152b496eaa887f42c/alpine+socat+patchelf2/deploy/glibc/libc.so.6 -------------------------------------------------------------------------------- /alpine+socat+patchelf2/deploy/run_pwn.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | # set pow using sha256 POW by ENABLE_POW 6 | if [ ! -z $ENABLE_POW ] 7 | then 8 | if [ "$ENABLE_POW" == "1" ] 9 | then 10 | echo "=================proof-of-work=================" 11 | echo "" 12 | rand_str=$(head -c 27 /dev/urandom | base64) 13 | hash_value=$(echo -n "$rand_str" | sha256sum - | cut -c 1-64) 14 | frontend=$(echo "$rand_str" | cut -c -4 ) 15 | backend=$(echo "$rand_str" | cut -c 5- ) 16 | prompt="sha256(XXXX + \"${backend}\") == ${hash_value}" 17 | echo $prompt 18 | echo -n "Gime me XXXX: " 19 | 20 | read -t 300 -r input_hash 21 | 22 | if [ "$input_hash" != "$frontend" ] 23 | then 24 | echo "Proof of work failed!" 25 | exit 2 26 | fi 27 | fi 28 | fi 29 | 30 | unset ENABLE_POW 31 | 32 | # override flag from env 33 | # if environmental variable FLAG is not empty string 34 | if [ ! -z $FLAG ] 35 | then 36 | if [ "$(cat /home/ctf/flag)" != "$FLAG" ] 37 | then 38 | echo $FLAG > /home/ctf/flag 39 | chmod 644 /home/ctf/flag 40 | fi 41 | fi 42 | 43 | # the env will not pass to ctf 44 | unset FLAG 45 | 46 | cd /home/ctf 47 | 48 | # run pwn challenge 49 | exec runuser -u ctf --pty -- timeout 300 ./pwn -------------------------------------------------------------------------------- /alpine+socat+patchelf2/readme.md: -------------------------------------------------------------------------------- 1 | # 说明 2 | 3 | 使用`alpine + socat + patchelf` 部署`pwn`题 4 | 5 | - 参照模板,将二进制文件放置在`./bin`目录下 6 | - 参照模板,将运行所需的`glibc`文件放置在`./glibc`目录下 7 | - `run_pwn.sh`中可以放置`proof of work`代码或者设置`timeout`时间 8 | - 运行`./build_image.sh`可以生成镜像以及提供给选手的`attachment`文件夹 9 | - 在`./deploy/docker-compose.yaml`文件中修改映射的宿主机端口、`flag`的内容 10 | - 其他需求可自行根据模板文件定制 11 | 12 | # Introduction 13 | 14 | use `alpine + socat + patchelf` to deploy pwn challenge 15 | 16 | - put binary file in `./bin` 17 | - put glibc runtime file in `./glibc` 18 | - set `proof of work` or `timeout` in `run_pwn.sh` 19 | - execute `./build_image.sh` to generate image and then run a container. Also, you can decide to get attachment file, which is offered to player 20 | - change the port mapping in host and the content of flag in `./deploy/docker-compose.yaml` 21 | -------------------------------------------------------------------------------- /alpine+xinetd+chroot+patchelf/deploy/Dockerfile: -------------------------------------------------------------------------------- 1 | # dockerfile for pwn 2 | FROM ubuntu:20.04 as compiler 3 | 4 | WORKDIR /root 5 | 6 | RUN apt update && apt install -y gcc g++ make git autoconf automake libtool 7 | 8 | RUN git clone https://github.com/NixOS/patchelf.git && \ 9 | cd ./patchelf && \ 10 | ./bootstrap.sh && \ 11 | ./configure && \ 12 | make && \ 13 | make install 14 | 15 | WORKDIR /root/ctf 16 | 17 | COPY ./src . 18 | 19 | RUN make pwn && \ 20 | mkdir glibc && \ 21 | cp /lib/x86_64-linux-gnu/libc.so.6 ./glibc/libc.so.6 && \ 22 | cp /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 ./glibc/ld-linux-x86-64.so.2 && \ 23 | patchelf --set-rpath ./glibc ./pwn && \ 24 | patchelf --set-interpreter ./glibc/ld-linux-x86-64.so.2 ./pwn 25 | 26 | 27 | 28 | FROM alpine:latest as compiler2 29 | 30 | USER root 31 | 32 | WORKDIR /root/ctf 33 | 34 | RUN apk update && \ 35 | apk add --no-cache wget gcc libc-dev make 36 | 37 | RUN wget -q https://github.com/opensuse/xinetd/releases/download/2.3.15.4/xinetd-2.3.15.4.tar.xz && \ 38 | tar xJf xinetd-2.3.15.4.tar.xz && \ 39 | cd xinetd-2.3.15.4 && \ 40 | ./configure && \ 41 | make -j8 && \ 42 | make install 43 | 44 | COPY ./ls.c ./ 45 | COPY ./cat.c ./ 46 | 47 | RUN gcc ./ls.c -o ./ls && \ 48 | gcc ./cat.c -o ./cat 49 | 50 | 51 | FROM alpine:latest as runner 52 | 53 | USER root 54 | 55 | RUN apk update && \ 56 | apk add --no-cache bash coreutils && \ 57 | ln -sf `which bash` /bin/sh && \ 58 | adduser ctf -u 1000 -s /bin/sh -D 59 | 60 | WORKDIR /home/ctf 61 | 62 | COPY --from=compiler /root/ctf/pwn . 63 | COPY --from=compiler /root/ctf/glibc ./glibc 64 | 65 | 66 | COPY ./flag ./ 67 | COPY ./run_pwn.sh / 68 | COPY ./ctf.xinetd /etc/ctf.xinetd 69 | 70 | # compile ls && cat 71 | RUN mkdir ./bin && \ 72 | cp /bin/bash ./bin/sh 73 | 74 | COPY --from=compiler2 /root/ctf/ls ./bin/ls 75 | COPY --from=compiler2 /root/ctf/cat ./bin/cat 76 | COPY --from=compiler2 /usr/local/sbin/xinetd /bin/xinetd 77 | 78 | RUN mkdir ./dev && \ 79 | mknod ./dev/null c 1 3 && \ 80 | mknod ./dev/zero c 1 5 && \ 81 | mknod ./dev/random c 1 8 && \ 82 | mknod ./dev/urandom c 1 9 && \ 83 | chmod 666 ./dev/* 84 | 85 | RUN mkdir -p ./lib ./usr/lib && \ 86 | cp -r -L /lib/*.so* ./lib && \ 87 | cp -R /usr/lib/*.so* ./usr/lib 88 | 89 | RUN chmod 644 ./flag && \ 90 | chmod 711 /run_pwn.sh && \ 91 | chown -R root:root . 92 | 93 | EXPOSE 1337 94 | 95 | CMD xinetd -f /etc/ctf.xinetd -pidfile /run/xinetd.pid -limit 1000 -reuse;sleep infinity; 96 | 97 | 98 | -------------------------------------------------------------------------------- /alpine+xinetd+chroot+patchelf/deploy/build_image.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # build image 5 | docker-compose up -d || docker compose up -d 6 | 7 | # wait for starting container 8 | sleep 5 9 | 10 | # copy file and generate attachment 11 | echo -n "copy file and generate attachment? [y/n] " 12 | read -t 15 ANS 13 | if [ $ANS == "y" ] || [ $ANS == "Y" ] 14 | then 15 | imageid=$(docker ps -n 1 -q) 16 | mkdir ../attachment/glibc -p 17 | cd ../attachment 18 | docker cp ${imageid}:/home/ctf/pwn . 19 | docker cp ${imageid}:/home/ctf/glibc . 20 | echo "copy file and generate attachment success!" 21 | fi -------------------------------------------------------------------------------- /alpine+xinetd+chroot+patchelf/deploy/cat.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int cat_file(const char *file) { 8 | char buf[1024] = {0}; 9 | int fd = open(file, O_RDONLY); 10 | if (fd == -1) { 11 | printf("[!] Fail to open file [%s]\n", file); 12 | return -1; 13 | } 14 | int n = -1; 15 | while ((n = read(fd, buf, 1024)) > 0) { 16 | write(STDOUT_FILENO, buf, n); 17 | } 18 | 19 | return 0; 20 | } 21 | 22 | int cat_files(const char *files[], int n) { 23 | for (int i=0; i 2 | #include 3 | #include 4 | 5 | void show_ls(char filename[]); 6 | int main(int argc,char* argv[]) 7 | { 8 | setbuf(stdin, 0); 9 | setbuf(stdout, 0); 10 | setbuf(stderr, 0); 11 | if(argc == 1) 12 | show_ls("."); 13 | while(--argc) 14 | { 15 | show_ls(*++argv); 16 | printf("\n"); 17 | } 18 | return 0; 19 | } 20 | void show_ls(char filename[]) 21 | { 22 | DIR* dir_ptr; //the directory 23 | struct dirent* direntp; //each entry 24 | 25 | if((dir_ptr = opendir(filename)) == NULL) { 26 | fprintf(stderr,"ls: cannot open [%s] \nUsage: ls DIR1 DIR2 ...\n",filename); 27 | exit(-1); 28 | } 29 | 30 | while((direntp = readdir(dir_ptr)) != NULL) 31 | printf("%s\n",direntp->d_name); 32 | closedir(dir_ptr); 33 | } -------------------------------------------------------------------------------- /alpine+xinetd+chroot+patchelf/deploy/run_pwn.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | # set pow using sha256 POW by ENABLE_POW 6 | if [ ! -z $ENABLE_POW ] 7 | then 8 | if [ "$ENABLE_POW" == "1" ] 9 | then 10 | echo "=================proof-of-work=================" 11 | echo "" 12 | rand_str=$(head -c 27 /dev/urandom | base64) 13 | hash_value=$(echo -n "$rand_str" | sha256sum - | cut -c 1-64) 14 | frontend=$(echo "$rand_str" | cut -c -4 ) 15 | backend=$(echo "$rand_str" | cut -c 5- ) 16 | prompt="sha256(XXXX + \"${backend}\") == ${hash_value}" 17 | echo $prompt 18 | echo -n "Gime me XXXX: " 19 | 20 | read -t 300 -r input_hash 21 | 22 | if [ "$input_hash" != "$frontend" ] 23 | then 24 | echo "Proof of work failed!" 25 | exit 2 26 | fi 27 | fi 28 | fi 29 | 30 | unset ENABLE_POW 31 | 32 | # override flag from env 33 | # if environmental variable FLAG is not empty string 34 | if [ ! -z $FLAG ] 35 | then 36 | if [ "$(cat /home/ctf/flag)" != "$FLAG" ] 37 | then 38 | echo $FLAG > /home/ctf/flag 39 | chmod 644 /home/ctf/flag 40 | fi 41 | fi 42 | 43 | # the env will not pass to ctf 44 | unset FLAG 45 | 46 | cd /home/ctf 47 | 48 | # run pwn challenge 49 | exec timeout 300 chroot --userspec=1000:1000 /home/ctf ./pwn -------------------------------------------------------------------------------- /alpine+xinetd+chroot+patchelf/deploy/src/makefile: -------------------------------------------------------------------------------- 1 | all: pwn pwn_debug 2 | 3 | pwn: pwn.c 4 | gcc ./pwn.c -o pwn -fstack-protector-all -pie -z now -z noexecstack -O0 -w 5 | strip ./pwn 6 | 7 | pwn_debug: pwn.c 8 | gcc ./pwn.c -o pwn_debug -fstack-protector-all -pie -z now -z noexecstack -O0 -g3 9 | 10 | clean: 11 | rm -rf ./pwn ./pwn_debug 12 | 13 | -------------------------------------------------------------------------------- /alpine+xinetd+chroot+patchelf/deploy/src/pwn.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | setbuf(stdin, 0); 9 | setbuf(stdout, 0); 10 | setbuf(stderr, 0); 11 | puts("Welcome to pwn world!"); 12 | printf("please input your name: "); 13 | char buf[0x80] = {0}; 14 | read(0, buf, 0x10); 15 | if (strncmp(buf, "admin", 5) == 0) { 16 | system("/bin/sh"); 17 | } else { 18 | puts("you are not admin!"); 19 | } 20 | return 0; 21 | } -------------------------------------------------------------------------------- /alpine+xinetd+chroot+patchelf/readme.md: -------------------------------------------------------------------------------- 1 | # 说明 2 | 3 | 使用`alpine + xinetd + chroot +patchelf` 部署`pwn`题 4 | 5 | - 参照模板,将源码和`makefile`放置在`./deploy/src`目录下 6 | - 确保生成目标文件名称为`pwn`,或者根据需要修改`dockerfile`中的`make pwn`语句 7 | - `run_pwn.sh`中可以放置`proof of work`代码或者设置`timeout`时间 8 | - 运行`./build_image.sh`可以生成镜像以及提供给选手的`attachment`文件夹 9 | - 在`./deploy/docker-compose.yaml`文件中修改映射的宿主机端口、`flag`的内容 10 | - 其他需求可自行根据模板文件定制 11 | 12 | # Introduction 13 | 14 | use `alpine + xinetd + chroot +patchelf` to deploy pwn challenge 15 | 16 | - put source file in `./deploy/src` 17 | - make sure the name of target binary is `pwn`, or you can change the `dockerfile` 18 | - set `proof of work` or `timeout` in `run_pwn.sh` 19 | - execute `./build_image.sh` to generate image and then run a container. Also, you can decide to get attachment file, which is offered to player 20 | - change the port mapping in host and the content of flag in `./deploy/docker-compose.yaml` 21 | -------------------------------------------------------------------------------- /alpine+xinetd+chroot+patchelf2/deploy/Dockerfile: -------------------------------------------------------------------------------- 1 | # dockerfile for pwn 2 | FROM ubuntu:20.04 as patchelf 3 | 4 | WORKDIR /root/ctf 5 | 6 | COPY ./bin/patchelf /bin/patchelf 7 | COPY ./bin/pwn ./pwn 8 | 9 | RUN chmod +x ./pwn /bin/patchelf && \ 10 | patchelf --set-rpath ./glibc ./pwn && \ 11 | patchelf --set-interpreter ./glibc/ld-linux-x86-64.so.2 ./pwn 12 | 13 | FROM alpine:latest as runner 14 | 15 | USER root 16 | 17 | RUN apk update && \ 18 | apk add --no-cache bash coreutils && \ 19 | ln -sf `which bash` /bin/sh && \ 20 | adduser ctf -u 1000 -s /bin/sh -D 21 | 22 | WORKDIR /home/ctf 23 | 24 | COPY --from=patchelf /root/ctf/pwn . 25 | 26 | COPY ./glibc ./glibc 27 | COPY ./flag ./ 28 | COPY ./run_pwn.sh / 29 | COPY ./ctf.xinetd /etc/ctf.xinetd 30 | COPY ./bin/ls ./bin/ls 31 | COPY ./bin/cat ./bin/cat 32 | COPY ./bin/xinetd /bin/xinetd 33 | 34 | RUN chmod +x ./bin/* && \ 35 | chmod +x /bin/xinetd && \ 36 | cp /bin/bash ./bin/sh 37 | 38 | RUN mkdir ./dev && \ 39 | mknod ./dev/null c 1 3 && \ 40 | mknod ./dev/zero c 1 5 && \ 41 | mknod ./dev/random c 1 8 && \ 42 | mknod ./dev/urandom c 1 9 && \ 43 | chmod 666 ./dev/* 44 | 45 | RUN mkdir -p ./lib ./usr/lib && \ 46 | cp -r -L /lib/*.so* ./lib && \ 47 | cp -R /usr/lib/*.so* ./usr/lib 48 | 49 | RUN chmod 644 ./flag && \ 50 | chmod 711 /run_pwn.sh && \ 51 | chmod +x ./glibc/* && \ 52 | chmod +x ./pwn && \ 53 | chown -R root:root . 54 | 55 | EXPOSE 1337 56 | 57 | CMD xinetd -f /etc/ctf.xinetd -pidfile /run/xinetd.pid -limit 1000 -reuse;sleep infinity; 58 | 59 | 60 | -------------------------------------------------------------------------------- /alpine+xinetd+chroot+patchelf2/deploy/bin/cat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoderickChan/deploy_pwn_template/4c2eec13239491733b635e4152b496eaa887f42c/alpine+xinetd+chroot+patchelf2/deploy/bin/cat -------------------------------------------------------------------------------- /alpine+xinetd+chroot+patchelf2/deploy/bin/ls: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoderickChan/deploy_pwn_template/4c2eec13239491733b635e4152b496eaa887f42c/alpine+xinetd+chroot+patchelf2/deploy/bin/ls -------------------------------------------------------------------------------- /alpine+xinetd+chroot+patchelf2/deploy/bin/patchelf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoderickChan/deploy_pwn_template/4c2eec13239491733b635e4152b496eaa887f42c/alpine+xinetd+chroot+patchelf2/deploy/bin/patchelf -------------------------------------------------------------------------------- /alpine+xinetd+chroot+patchelf2/deploy/bin/pwn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoderickChan/deploy_pwn_template/4c2eec13239491733b635e4152b496eaa887f42c/alpine+xinetd+chroot+patchelf2/deploy/bin/pwn -------------------------------------------------------------------------------- /alpine+xinetd+chroot+patchelf2/deploy/bin/xinetd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoderickChan/deploy_pwn_template/4c2eec13239491733b635e4152b496eaa887f42c/alpine+xinetd+chroot+patchelf2/deploy/bin/xinetd -------------------------------------------------------------------------------- /alpine+xinetd+chroot+patchelf2/deploy/build_image.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # build image 5 | docker-compose up -d || docker compose up -d 6 | 7 | # wait for starting container 8 | sleep 5 9 | 10 | # copy file and generate attachment 11 | echo -n "copy file and generate attachment? [y/n] " 12 | read -t 15 ANS 13 | if [ $ANS == "y" ] || [ $ANS == "Y" ] 14 | then 15 | imageid=$(docker ps -n 1 -q) 16 | mkdir ../attachment/glibc -p 17 | cd ../attachment 18 | docker cp ${imageid}:/home/ctf/pwn . 19 | docker cp ${imageid}:/home/ctf/glibc . 20 | echo "copy file and generate attachment success!" 21 | fi -------------------------------------------------------------------------------- /alpine+xinetd+chroot+patchelf2/deploy/ctf.xinetd: -------------------------------------------------------------------------------- 1 | service ctf 2 | { 3 | disable = no 4 | socket_type = stream 5 | instances = 500 6 | protocol = tcp 7 | wait = no 8 | user = root 9 | type = UNLISTED 10 | port = 1337 11 | bind = 0.0.0.0 12 | server = /bin/bash 13 | 14 | # replace pwn to your program 15 | server_args = /run_pwn.sh 16 | 17 | log_type = FILE /var/log/ctf.xinetd.log 18 | log_on_success = DURATION HOST 19 | log_on_failure = HOST 20 | 21 | # safety options 22 | per_source = 10 # the maximum instances of this service per source IP address 23 | rlimit_cpu = 20 # the maximum number of CPU seconds that the service may use 24 | rlimit_as = 4096M # the Address Space resource limit for the service 25 | # access_times = 2:00-9:00 12:00-24:00 26 | } -------------------------------------------------------------------------------- /alpine+xinetd+chroot+patchelf2/deploy/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | # docker-compose.yaml for pwn 2 | version: "3" 3 | services: 4 | pwn: 5 | build: . 6 | restart: unless-stopped 7 | environment: # unset FLAG if u don't want to generate flag from env 8 | FLAG: flag{this_is_a_real_flag} 9 | ENABLE_POW: 0 # set ENABLE_POW 1 if u want to use proof-of-pow, unset it to not 10 | ports: 11 | - "10001:1337" 12 | -------------------------------------------------------------------------------- /alpine+xinetd+chroot+patchelf2/deploy/flag: -------------------------------------------------------------------------------- 1 | flag{this_is_a_fake_flag} 2 | -------------------------------------------------------------------------------- /alpine+xinetd+chroot+patchelf2/deploy/glibc/ld-linux-x86-64.so.2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoderickChan/deploy_pwn_template/4c2eec13239491733b635e4152b496eaa887f42c/alpine+xinetd+chroot+patchelf2/deploy/glibc/ld-linux-x86-64.so.2 -------------------------------------------------------------------------------- /alpine+xinetd+chroot+patchelf2/deploy/glibc/libc.so.6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoderickChan/deploy_pwn_template/4c2eec13239491733b635e4152b496eaa887f42c/alpine+xinetd+chroot+patchelf2/deploy/glibc/libc.so.6 -------------------------------------------------------------------------------- /alpine+xinetd+chroot+patchelf2/deploy/run_pwn.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | # set pow using sha256 POW by ENABLE_POW 6 | if [ ! -z $ENABLE_POW ] 7 | then 8 | if [ "$ENABLE_POW" == "1" ] 9 | then 10 | echo "=================proof-of-work=================" 11 | echo "" 12 | rand_str=$(head -c 27 /dev/urandom | base64) 13 | hash_value=$(echo -n "$rand_str" | sha256sum - | cut -c 1-64) 14 | frontend=$(echo "$rand_str" | cut -c -4 ) 15 | backend=$(echo "$rand_str" | cut -c 5- ) 16 | prompt="sha256(XXXX + \"${backend}\") == ${hash_value}" 17 | echo $prompt 18 | echo -n "Gime me XXXX: " 19 | 20 | read -t 300 -r input_hash 21 | 22 | if [ "$input_hash" != "$frontend" ] 23 | then 24 | echo "Proof of work failed!" 25 | exit 2 26 | fi 27 | fi 28 | fi 29 | 30 | unset ENABLE_POW 31 | 32 | # override flag from env 33 | # if environmental variable FLAG is not empty string 34 | if [ ! -z $FLAG ] 35 | then 36 | if [ "$(cat /home/ctf/flag)" != "$FLAG" ] 37 | then 38 | echo $FLAG > /home/ctf/flag 39 | chmod 644 /home/ctf/flag 40 | fi 41 | fi 42 | 43 | # the env will not pass to ctf 44 | unset FLAG 45 | 46 | cd /home/ctf 47 | 48 | # run pwn challenge 49 | exec timeout 300 $(which chroot) --userspec=1000:1000 /home/ctf ./pwn -------------------------------------------------------------------------------- /alpine+xinetd+chroot+patchelf2/readme.md: -------------------------------------------------------------------------------- 1 | # 说明 2 | 3 | 使用`alpine + xinetd + chroot +patchelf` 部署`pwn`题 4 | 5 | - 参照模板,将二进制文件放置在`./bin`目录下 6 | - 参照模板,将运行所需的`glibc`文件放置在`./glibc`目录下 7 | - `run_pwn.sh`中可以放置`proof of work`代码或者设置`timeout`时间 8 | - 运行`./build_image.sh`可以生成镜像以及提供给选手的`attachment`文件夹 9 | - 在`./deploy/docker-compose.yaml`文件中修改映射的宿主机端口、`flag`的内容 10 | - 其他需求可自行根据模板文件定制 11 | 12 | # Introduction 13 | 14 | use `alpine + xinetd + chroot +patchelf` to deploy pwn challenge 15 | 16 | - put binary file in `./bin` 17 | - put glibc runtime file in `./glibc` 18 | - set `proof of work` or `timeout` in `run_pwn.sh` 19 | - execute `./build_image.sh` to generate image and then run a container. Also, you can decide to get attachment file, which is offered to player 20 | - change the port mapping in host and the content of flag in `./deploy/docker-compose.yaml` 21 | -------------------------------------------------------------------------------- /alpine+ynetd+chroot+patchelf/deploy/Dockerfile: -------------------------------------------------------------------------------- 1 | # dockerfile for pwn 2 | FROM ubuntu:20.04 as compiler 3 | 4 | WORKDIR /root 5 | 6 | RUN apt update && apt install -y gcc g++ make git autoconf automake libtool 7 | 8 | RUN git clone https://github.com/NixOS/patchelf.git && \ 9 | cd ./patchelf && \ 10 | ./bootstrap.sh && \ 11 | ./configure && \ 12 | make && \ 13 | make install 14 | 15 | WORKDIR /root/ctf 16 | 17 | COPY ./src . 18 | 19 | RUN make pwn && \ 20 | mkdir glibc && \ 21 | cp /lib/x86_64-linux-gnu/libc.so.6 ./glibc/libc.so.6 && \ 22 | cp /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 ./glibc/ld-linux-x86-64.so.2 && \ 23 | patchelf --set-rpath ./glibc ./pwn && \ 24 | patchelf --set-interpreter ./glibc/ld-linux-x86-64.so.2 ./pwn 25 | 26 | 27 | FROM alpine:latest as compiler2 28 | 29 | USER root 30 | 31 | WORKDIR /root/ctf 32 | 33 | RUN apk update && \ 34 | apk add --no-cache gcc musl-dev 35 | 36 | COPY ./ls.c ./ 37 | COPY ./cat.c ./ 38 | COPY ./ynetd.c ./ 39 | 40 | RUN gcc ./ls.c -o ./ls && \ 41 | gcc ./cat.c -o ./cat && \ 42 | gcc ./ynetd.c -o ./ynetd 43 | 44 | 45 | FROM alpine:latest as runner 46 | 47 | USER root 48 | 49 | RUN apk update && \ 50 | apk add --no-cache bash coreutils && \ 51 | ln -sf `which bash` /bin/sh && \ 52 | adduser ctf -u 1000 -s /bin/sh -D 53 | 54 | WORKDIR /home/ctf 55 | 56 | COPY --from=compiler /root/ctf/pwn . 57 | COPY --from=compiler /root/ctf/glibc ./glibc 58 | 59 | COPY ./flag ./ 60 | COPY ./run_pwn.sh / 61 | 62 | # compile ls && cat 63 | RUN mkdir ./bin && \ 64 | cp /bin/bash ./bin/sh 65 | 66 | COPY --from=compiler2 /root/ctf/ls ./bin/ls 67 | COPY --from=compiler2 /root/ctf/cat ./bin/cat 68 | COPY --from=compiler2 /root/ctf/ynetd /bin/ynetd 69 | 70 | RUN mkdir ./dev && \ 71 | mknod ./dev/null c 1 3 && \ 72 | mknod ./dev/zero c 1 5 && \ 73 | mknod ./dev/random c 1 8 && \ 74 | mknod ./dev/urandom c 1 9 && \ 75 | chmod 666 ./dev/* 76 | 77 | RUN mkdir -p ./lib ./usr/lib && \ 78 | cp -r -L /lib/*.so* ./lib && \ 79 | cp -R /usr/lib/*.so* ./usr/lib 80 | 81 | RUN chmod 644 ./flag && \ 82 | chmod 711 /run_pwn.sh && \ 83 | chmod +x ./glibc/* && \ 84 | chmod +x ./pwn && \ 85 | chown -R root:root . 86 | 87 | EXPOSE 1337 88 | 89 | CMD CMD ynetd -p 1337 -lp 500 -se y "/run_pwn.sh" 90 | 91 | 92 | -------------------------------------------------------------------------------- /alpine+ynetd+chroot+patchelf/deploy/build_image.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # build image 5 | docker-compose up -d || docker compose up -d 6 | 7 | # wait for starting container 8 | sleep 5 9 | 10 | # copy file and generate attachment 11 | echo -n "copy file and generate attachment? [y/n] " 12 | read -t 15 ANS 13 | if [ $ANS == "y" ] || [ $ANS == "Y" ] 14 | then 15 | imageid=$(docker ps -n 1 -q) 16 | mkdir ../attachment/glibc -p 17 | cd ../attachment 18 | docker cp ${imageid}:/home/ctf/pwn . 19 | docker cp ${imageid}:/home/ctf/glibc . 20 | echo "copy file and generate attachment success!" 21 | fi -------------------------------------------------------------------------------- /alpine+ynetd+chroot+patchelf/deploy/cat.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int cat_file(const char *file) { 8 | char buf[1024] = {0}; 9 | int fd = open(file, O_RDONLY); 10 | if (fd == -1) { 11 | printf("[!] Fail to open file [%s]\n", file); 12 | return -1; 13 | } 14 | int n = -1; 15 | while ((n = read(fd, buf, 1024)) > 0) { 16 | write(STDOUT_FILENO, buf, n); 17 | } 18 | 19 | return 0; 20 | } 21 | 22 | int cat_files(const char *files[], int n) { 23 | for (int i=0; i 2 | #include 3 | #include 4 | 5 | void show_ls(char filename[]); 6 | int main(int argc,char* argv[]) 7 | { 8 | setbuf(stdin, 0); 9 | setbuf(stdout, 0); 10 | setbuf(stderr, 0); 11 | if(argc == 1) 12 | show_ls("."); 13 | while(--argc) 14 | { 15 | show_ls(*++argv); 16 | printf("\n"); 17 | } 18 | return 0; 19 | } 20 | void show_ls(char filename[]) 21 | { 22 | DIR* dir_ptr; //the directory 23 | struct dirent* direntp; //each entry 24 | 25 | if((dir_ptr = opendir(filename)) == NULL) { 26 | fprintf(stderr,"ls: cannot open [%s] \nUsage: ls DIR1 DIR2 ...\n",filename); 27 | exit(-1); 28 | } 29 | 30 | while((direntp = readdir(dir_ptr)) != NULL) 31 | printf("%s\n",direntp->d_name); 32 | closedir(dir_ptr); 33 | } -------------------------------------------------------------------------------- /alpine+ynetd+chroot+patchelf/deploy/run_pwn.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | # set pow using sha256 POW by ENABLE_POW 6 | if [ ! -z $ENABLE_POW ] 7 | then 8 | if [ "$ENABLE_POW" == "1" ] 9 | then 10 | echo "=================proof-of-work=================" 11 | echo "" 12 | rand_str=$(head -c 27 /dev/urandom | base64) 13 | hash_value=$(echo -n "$rand_str" | sha256sum - | cut -c 1-64) 14 | frontend=$(echo "$rand_str" | cut -c -4 ) 15 | backend=$(echo "$rand_str" | cut -c 5- ) 16 | prompt="sha256(XXXX + \"${backend}\") == ${hash_value}" 17 | echo $prompt 18 | echo -n "Gime me XXXX: " 19 | 20 | read -t 300 -r input_hash 21 | 22 | if [ "$input_hash" != "$frontend" ] 23 | then 24 | echo "Proof of work failed!" 25 | exit 2 26 | fi 27 | fi 28 | fi 29 | 30 | unset ENABLE_POW 31 | 32 | # override flag from env 33 | # if environmental variable FLAG is not empty string 34 | if [ ! -z $FLAG ] 35 | then 36 | if [ "$(cat /home/ctf/flag)" != "$FLAG" ] 37 | then 38 | echo $FLAG > /home/ctf/flag 39 | chmod 644 /home/ctf/flag 40 | fi 41 | fi 42 | 43 | # the env will not pass to ctf 44 | unset FLAG 45 | 46 | cd /home/ctf 47 | 48 | # run pwn challenge 49 | exec timeout 300 chroot --userspec=1000:1000 /home/ctf ./pwn -------------------------------------------------------------------------------- /alpine+ynetd+chroot+patchelf/deploy/src/makefile: -------------------------------------------------------------------------------- 1 | all: pwn pwn_debug 2 | 3 | pwn: pwn.c 4 | gcc ./pwn.c -o pwn -fstack-protector-all -pie -z now -z noexecstack -O0 -w 5 | strip ./pwn 6 | 7 | pwn_debug: pwn.c 8 | gcc ./pwn.c -o pwn_debug -fstack-protector-all -pie -z now -z noexecstack -O0 -g3 9 | 10 | clean: 11 | rm -rf ./pwn ./pwn_debug 12 | 13 | -------------------------------------------------------------------------------- /alpine+ynetd+chroot+patchelf/deploy/src/pwn.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | setbuf(stdin, 0); 9 | setbuf(stdout, 0); 10 | setbuf(stderr, 0); 11 | puts("Welcome to pwn world!"); 12 | printf("please input your name: "); 13 | char buf[0x80] = {0}; 14 | read(0, buf, 0x10); 15 | if (strncmp(buf, "admin", 5) == 0) { 16 | system("/bin/sh"); 17 | } else { 18 | puts("you are not admin!"); 19 | } 20 | return 0; 21 | } -------------------------------------------------------------------------------- /alpine+ynetd+chroot+patchelf/deploy/ynetd.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (c) 2015-2017 Lorenz Panny 4 | * 5 | * This is ynetd version 0.1.2 (24 May 2017). 6 | * Check for newer versions at https://yx7.cc/code. 7 | * Please report bugs to y@yx7.cc. 8 | * 9 | * This program is released under the MIT license; see license.txt. 10 | * 11 | */ 12 | 13 | #define _GNU_SOURCE 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | __attribute__((noreturn)) void version() 31 | { 32 | printf("This is ynetd version 0.1.2 (24 May 2017).\n"); 33 | exit(0); 34 | } 35 | 36 | __attribute__((noreturn)) void help(int st) 37 | { 38 | bool tty = isatty(fileno(stdout)); 39 | 40 | printf("\n"); 41 | printf(" %synetd: a minimalistic inetd%s\n", 42 | tty ? "\x1b[32m" : "", tty ? "\x1b[0m" : ""); 43 | printf(" ---------------------------\n\n"); 44 | printf(" %sinvocation:%s ynetd [$opts] $cmd\n\n", 45 | tty ? "\x1b[33m" : "", tty ? "\x1b[0m" : ""); 46 | 47 | printf(" %sflags:%s\n", 48 | tty ? "\x1b[33m" : "", tty ? "\x1b[0m" : ""); 49 | printf("-h " 50 | "this help text\n"); 51 | printf("-a $addr " 52 | "IP address to bind to (default :: and 0.0.0.0)\n"); 53 | printf("-p $port " 54 | "TCP port to bind to (default 1024)\n"); 55 | printf("-u $user " 56 | "username (default current)\n"); 57 | printf("-d $dir " 58 | "working directory (default user's home if -u else current)\n"); 59 | printf("-sh [yn] " 60 | "invoke /bin/sh to execute $cmd? (default y)\n"); 61 | printf("-si [yn] " 62 | "use socket as stdin? (default y)\n"); 63 | printf("-so [yn] " 64 | "use socket as stdout? (default y)\n"); 65 | printf("-se [yn] " 66 | "use socket as stderr? (default n)\n"); 67 | printf("-lt $lim " 68 | "limit cpu time in seconds (default unchanged)\n"); 69 | printf("-lm $lim " 70 | "limit amount of memory in bytes (default unchanged)\n"); 71 | printf("-lp $lim " 72 | "limit number of processes (default unchanged)\n"); 73 | printf("-rn $val " 74 | "set process priority (default unchanged)\n"); 75 | printf("$cmd " 76 | "command\n"); 77 | printf(" NOTE: $cmd is executed relative to $dir!\n"); 78 | printf(" if in doubt, use absolute paths only.\n"); 79 | printf("\n"); 80 | exit(st); 81 | } 82 | 83 | #define die(S) do { perror(S); exit(-1); } while (0) 84 | 85 | struct config { 86 | struct { 87 | bool set; 88 | uid_t uid; 89 | gid_t gid; 90 | } ids; 91 | 92 | int family; 93 | union { 94 | struct in6_addr ipv6; 95 | struct in_addr ipv4; 96 | } addr; 97 | in_port_t port; 98 | 99 | char *cmd; 100 | char *dir; 101 | bool shell; 102 | bool in, out, err; 103 | struct { 104 | bool set; 105 | rlim_t lim; 106 | } cpu, mem, proc; 107 | struct { 108 | bool set; 109 | int val; 110 | } nice; 111 | }; 112 | 113 | void parse_args(size_t argc, char **argv, struct config *cfg) 114 | { 115 | struct passwd spw, *pw; 116 | char pwbuf[0x100]; 117 | 118 | /* note: to avoid copying all the strings from argv[] to cfg, 119 | * we only write pointers to the arguments into cfg. since only 120 | * main() calls this function, these references are guaranteed 121 | * to stay valid for the lifetime of the program. */ 122 | 123 | #define ARG_YESNO(S, L, V) \ 124 | else if (!strcmp(argv[i], (S)) || !strcmp(argv[i], (L))) { \ 125 | if (++i >= argc) \ 126 | help(1); \ 127 | if (argv[i][1] || (*argv[i] != 'y' && *argv[i] != 'n')) \ 128 | help(1); \ 129 | (V) = *argv[i++] == 'y'; \ 130 | } 131 | 132 | #define ARG_NUM(S, L, V, P) \ 133 | else if (!strcmp(argv[i], (S)) || !strcmp(argv[i], (L))) { \ 134 | if (++i >= argc) \ 135 | help(1); \ 136 | (V) = strtol(argv[i++], NULL, 10); \ 137 | if (P) \ 138 | * (bool *) (P) = true; \ 139 | } 140 | 141 | for (size_t i = 1; i < argc; ) { 142 | if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { 143 | help(0); 144 | } 145 | else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) { 146 | version(); 147 | } 148 | ARG_YESNO("-sh", "--shell", cfg->shell) 149 | ARG_YESNO("-si", "--stdin", cfg->in) 150 | ARG_YESNO("-so", "--stdout", cfg->out) 151 | ARG_YESNO("-se", "--stderr", cfg->err) 152 | else if (!strcmp(argv[i], "-a") || !strcmp(argv[i], "--addr")) { 153 | if (++i >= argc) 154 | help(1); 155 | if (1 == inet_pton(AF_INET6, argv[i], &cfg->addr.ipv6)) 156 | cfg->family = AF_INET6; 157 | else if (1 == inet_pton(AF_INET, argv[i], &cfg->addr.ipv4)) 158 | cfg->family = AF_INET; 159 | else 160 | die("inet_pton"); 161 | ++i; 162 | } 163 | ARG_NUM("-p", "--port", cfg->port, NULL) 164 | else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--user")) { 165 | if (++i >= argc) 166 | help(1); 167 | if (getpwnam_r(argv[i++], &spw, pwbuf, sizeof(pwbuf), &pw) || !pw) 168 | die("getpwnam_r"); 169 | cfg->ids.uid = pw->pw_uid; 170 | cfg->ids.gid = pw->pw_gid; 171 | cfg->ids.set = true; 172 | if (!cfg->dir) { 173 | /* note: pw->pw_dir is local, so we need to copy it. */ 174 | /* note: ideally we should free() this, but it will 175 | * exist until the parent dies anyway. */ 176 | cfg->dir = strdup(pw->pw_dir); 177 | } 178 | } 179 | else if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--dir")) { 180 | if (++i >= argc) 181 | help(1); 182 | cfg->dir = argv[i++]; 183 | } 184 | ARG_NUM("-lt", "--limit-time", cfg->cpu.lim, &cfg->cpu.set) 185 | ARG_NUM("-lm", "--limit-memory", cfg->mem.lim, &cfg->mem.set) 186 | ARG_NUM("-lp", "--limit-processes", cfg->proc.lim, &cfg->proc.set) 187 | ARG_NUM("-rn", "--renice", cfg->nice.val, &cfg->nice.set) 188 | else if (!cfg->cmd) { 189 | cfg->cmd = argv[i++]; 190 | } 191 | else { 192 | help(1); 193 | } 194 | } 195 | 196 | #undef ARG_YESNO 197 | #undef ARG_NUM 198 | 199 | if (!cfg->cmd) 200 | help(1); 201 | } 202 | 203 | int bind_listen(struct config const cfg) 204 | { 205 | int const one = 1; 206 | int lsock; 207 | union { 208 | struct sockaddr_in6 ipv6; 209 | struct sockaddr_in ipv4; 210 | } addr; 211 | socklen_t addr_len; 212 | 213 | if (0 > (lsock = socket(cfg.family, SOCK_STREAM, 0))) 214 | die("socket"); 215 | 216 | if (setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) 217 | die("setsockopt"); 218 | 219 | switch (cfg.family) { 220 | case AF_INET6: 221 | addr.ipv6.sin6_family = cfg.family; 222 | addr.ipv6.sin6_addr = cfg.addr.ipv6; 223 | addr.ipv6.sin6_port = htons(cfg.port); 224 | addr_len = sizeof(addr.ipv6); 225 | break; 226 | case AF_INET: 227 | addr.ipv4.sin_family = cfg.family; 228 | addr.ipv4.sin_addr = cfg.addr.ipv4; 229 | addr.ipv4.sin_port = htons(cfg.port); 230 | addr_len = sizeof(addr.ipv4); 231 | break; 232 | default: 233 | fprintf(stderr, "bad address family?!\n"); 234 | exit(-1); 235 | } 236 | 237 | if (bind(lsock, (struct sockaddr *) &addr, addr_len)) 238 | die("bind"); 239 | 240 | if (listen(lsock, 16)) 241 | die("listen"); 242 | 243 | return lsock; 244 | } 245 | 246 | void handle_connection(struct config const cfg, int sock) 247 | { 248 | struct rlimit rlim; 249 | 250 | /* set resource limits */ 251 | if (cfg.cpu.set) { 252 | rlim.rlim_cur = rlim.rlim_max = cfg.cpu.lim; 253 | if (0 > setrlimit(RLIMIT_CPU, &rlim)) 254 | die("setrlimit"); 255 | } 256 | if (cfg.mem.set) { 257 | rlim.rlim_cur = rlim.rlim_max = cfg.mem.lim; 258 | if (0 > setrlimit(RLIMIT_AS, &rlim)) 259 | die("setrlimit"); 260 | } 261 | if (cfg.proc.set) { 262 | rlim.rlim_cur = rlim.rlim_max = cfg.proc.lim; 263 | if (0 > setrlimit(RLIMIT_NPROC, &rlim)) 264 | die("setrlimit"); 265 | } 266 | 267 | /* renice */ 268 | if (cfg.nice.set && setpriority(PRIO_PROCESS, 0, cfg.nice.val)) 269 | die("setpriority"); 270 | 271 | /* drop privileges */ 272 | if (cfg.ids.set) { 273 | if (setgroups(0, NULL)) 274 | die("setgroups"); 275 | if (setgid(cfg.ids.gid)) 276 | die("setgid"); 277 | if (setuid(cfg.ids.uid)) 278 | die("setuid"); 279 | } 280 | 281 | /* change working directory */ 282 | if (cfg.dir && chdir(cfg.dir)) 283 | die("chdir"); 284 | 285 | /* duplicate socket to stdio */ 286 | if (cfg.in && fileno(stdin) != dup2(sock, fileno(stdin))) 287 | die("dup2"); 288 | if (cfg.out && fileno(stdout) != dup2(sock, fileno(stdout))) 289 | die("dup2"); 290 | if (cfg.err && fileno(stderr) != dup2(sock, fileno(stderr))) 291 | die("dup2"); 292 | if (close(sock)) 293 | die("close"); 294 | 295 | /* FIXME does nobody care about the environment? */ 296 | 297 | /* execute command */ 298 | if (cfg.shell) { 299 | execle("/bin/sh", "sh", "-c", cfg.cmd, NULL, NULL); 300 | die("execle"); 301 | } 302 | else { 303 | /* FIXME support more arguments? */ 304 | execle(cfg.cmd, cfg.cmd, NULL, NULL); 305 | die("execle"); 306 | } 307 | } 308 | 309 | int main(int argc, char **argv) 310 | { 311 | pid_t pid; 312 | int lsock, sock; 313 | struct sigaction sigact; 314 | 315 | /* configuration options */ 316 | struct config cfg = { 317 | .ids = {.set = false}, 318 | 319 | .family = AF_INET6, 320 | .addr = {.ipv6 = in6addr_any}, 321 | .port = 1024, 322 | 323 | .cmd = NULL, 324 | .dir = NULL, 325 | .shell = true, 326 | .in = true, .out = true, .err = false, 327 | .cpu = {.set = false}, .mem = {.set = false}, .proc = {.set = false}, 328 | .nice = {.set = false}, 329 | }; 330 | 331 | /* "parse" arguments */ 332 | parse_args(argc, argv, &cfg); 333 | 334 | /* do not turn dead children into zombies */ 335 | memset(&sigact, 0, sizeof(sigact)); 336 | sigact.sa_flags = SA_NOCLDWAIT | SA_NOCLDSTOP; 337 | if (sigaction(SIGCHLD, &sigact, 0)) 338 | die("sigaction"); 339 | 340 | /* set up listening socket */ 341 | lsock = bind_listen(cfg); 342 | 343 | /* accept loop */ 344 | while (1) { 345 | 346 | if (0 > (sock = accept(lsock, NULL, NULL))) 347 | continue; 348 | 349 | if ((pid = fork())) { 350 | /* parent */ 351 | /* note: if the fork failed, we just drop the connection 352 | * and continue as usual, so we don't catch that case. */ 353 | if (close(sock)) 354 | die("close"); 355 | continue; 356 | } 357 | 358 | /* child */ 359 | if (close(lsock)) 360 | die("close"); 361 | 362 | /* detach from terminal */ 363 | if (0 > setsid()) 364 | die("setsid"); 365 | 366 | handle_connection(cfg, sock); 367 | 368 | } 369 | } 370 | -------------------------------------------------------------------------------- /alpine+ynetd+chroot+patchelf/readme.md: -------------------------------------------------------------------------------- 1 | # 说明 2 | 3 | 使用`alpine + ynetd + chroot +patchelf` 部署`pwn`题 4 | 5 | - 参照模板,将源码和`makefile`放置在`./deploy/src`目录下 6 | - 确保生成目标文件名称为`pwn`,或者根据需要修改`dockerfile`中的`make pwn`语句 7 | - `run_pwn.sh`中可以放置`proof of work`代码或者设置`timeout`时间 8 | - 运行`./build_image.sh`可以生成镜像以及提供给选手的`attachment`文件夹 9 | - 在`./deploy/docker-compose.yaml`文件中修改映射的宿主机端口、`flag`的内容 10 | - 其他需求可自行根据模板文件定制 11 | 12 | # Introduction 13 | 14 | use `alpine + ynetd + chroot +patchelf` to deploy pwn challenge 15 | 16 | - put source file in `./deploy/src` 17 | - make sure the name of target binary is `pwn`, or you can change the `dockerfile` 18 | - set `proof of work` or `timeout` in `run_pwn.sh` 19 | - execute `./build_image.sh` to generate image and then run a container. Also, you can decide to get attachment file, which is offered to player 20 | - change the port mapping in host and the content of flag in `./deploy/docker-compose.yaml` 21 | -------------------------------------------------------------------------------- /alpine+ynetd+chroot+patchelf2/deploy/Dockerfile: -------------------------------------------------------------------------------- 1 | # dockerfile for pwn 2 | FROM ubuntu:20.04 as patchelf 3 | 4 | WORKDIR /root/ctf 5 | 6 | COPY ./bin/patchelf /bin/patchelf 7 | COPY ./bin/pwn ./pwn 8 | 9 | RUN chmod +x ./pwn /bin/patchelf && \ 10 | patchelf --set-rpath ./glibc ./pwn && \ 11 | patchelf --set-interpreter ./glibc/ld-linux-x86-64.so.2 ./pwn 12 | 13 | FROM alpine:latest as runner 14 | 15 | USER root 16 | 17 | RUN apk update && \ 18 | apk add --no-cache bash && \ 19 | ln -sf `which bash` /bin/sh && \ 20 | adduser ctf -u 1000 -s /bin/sh -D 21 | 22 | WORKDIR /home/ctf 23 | 24 | COPY --from=patchelf /root/ctf/pwn . 25 | 26 | COPY ./glibc ./glibc 27 | COPY ./flag ./ 28 | COPY ./run_pwn.sh / 29 | COPY ./bin/ls ./bin/ls 30 | COPY ./bin/cat ./bin/cat 31 | COPY ./bin/ynetd /bin/ynetd 32 | 33 | RUN chmod +x ./bin/* && \ 34 | chmod +x /bin/ynetd && \ 35 | cp /bin/bash ./bin/sh 36 | 37 | RUN mkdir ./dev && \ 38 | mknod ./dev/null c 1 3 && \ 39 | mknod ./dev/zero c 1 5 && \ 40 | mknod ./dev/random c 1 8 && \ 41 | mknod ./dev/urandom c 1 9 && \ 42 | chmod 666 ./dev/* 43 | 44 | RUN mkdir -p ./lib ./usr/lib && \ 45 | cp -r -L /lib/*.so* ./lib && \ 46 | cp -R /usr/lib/*.so* ./usr/lib 47 | 48 | RUN chmod 644 ./flag && \ 49 | chmod 711 /run_pwn.sh && \ 50 | chmod +x ./glibc/* && \ 51 | chmod +x ./pwn && \ 52 | chown -R root:root . 53 | 54 | EXPOSE 1337 55 | 56 | CMD ynetd -p 1337 -lp 500 -se y "/run_pwn.sh" 57 | 58 | 59 | -------------------------------------------------------------------------------- /alpine+ynetd+chroot+patchelf2/deploy/bin/cat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoderickChan/deploy_pwn_template/4c2eec13239491733b635e4152b496eaa887f42c/alpine+ynetd+chroot+patchelf2/deploy/bin/cat -------------------------------------------------------------------------------- /alpine+ynetd+chroot+patchelf2/deploy/bin/ls: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoderickChan/deploy_pwn_template/4c2eec13239491733b635e4152b496eaa887f42c/alpine+ynetd+chroot+patchelf2/deploy/bin/ls -------------------------------------------------------------------------------- /alpine+ynetd+chroot+patchelf2/deploy/bin/patchelf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoderickChan/deploy_pwn_template/4c2eec13239491733b635e4152b496eaa887f42c/alpine+ynetd+chroot+patchelf2/deploy/bin/patchelf -------------------------------------------------------------------------------- /alpine+ynetd+chroot+patchelf2/deploy/bin/pwn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoderickChan/deploy_pwn_template/4c2eec13239491733b635e4152b496eaa887f42c/alpine+ynetd+chroot+patchelf2/deploy/bin/pwn -------------------------------------------------------------------------------- /alpine+ynetd+chroot+patchelf2/deploy/bin/ynetd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoderickChan/deploy_pwn_template/4c2eec13239491733b635e4152b496eaa887f42c/alpine+ynetd+chroot+patchelf2/deploy/bin/ynetd -------------------------------------------------------------------------------- /alpine+ynetd+chroot+patchelf2/deploy/build_image.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # build image 5 | docker-compose up -d || docker compose up -d 6 | 7 | # wait for starting container 8 | sleep 5 9 | 10 | # copy file and generate attachment 11 | echo -n "copy file and generate attachment? [y/n] " 12 | read -t 15 ANS 13 | if [ $ANS == "y" ] || [ $ANS == "Y" ] 14 | then 15 | imageid=$(docker ps -n 1 -q) 16 | mkdir ../attachment/glibc -p 17 | cd ../attachment 18 | docker cp ${imageid}:/home/ctf/pwn . 19 | docker cp ${imageid}:/home/ctf/glibc . 20 | echo "copy file and generate attachment success!" 21 | fi -------------------------------------------------------------------------------- /alpine+ynetd+chroot+patchelf2/deploy/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | # docker-compose.yaml for pwn 2 | version: "3" 3 | services: 4 | pwn: 5 | build: . 6 | restart: unless-stopped 7 | environment: # unset FLAG if u don't want to generate flag from env 8 | FLAG: flag{this_is_a_real_flag} 9 | ENABLE_POW: 0 # set ENABLE_POW 1 if u want to use proof-of-pow, unset it to not 10 | ports: 11 | - "10001:1337" 12 | -------------------------------------------------------------------------------- /alpine+ynetd+chroot+patchelf2/deploy/flag: -------------------------------------------------------------------------------- 1 | flag{this_is_a_fake_flag} 2 | -------------------------------------------------------------------------------- /alpine+ynetd+chroot+patchelf2/deploy/glibc/ld-linux-x86-64.so.2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoderickChan/deploy_pwn_template/4c2eec13239491733b635e4152b496eaa887f42c/alpine+ynetd+chroot+patchelf2/deploy/glibc/ld-linux-x86-64.so.2 -------------------------------------------------------------------------------- /alpine+ynetd+chroot+patchelf2/deploy/glibc/libc.so.6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoderickChan/deploy_pwn_template/4c2eec13239491733b635e4152b496eaa887f42c/alpine+ynetd+chroot+patchelf2/deploy/glibc/libc.so.6 -------------------------------------------------------------------------------- /alpine+ynetd+chroot+patchelf2/deploy/run_pwn.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | # set pow using sha256 POW by ENABLE_POW 6 | if [ ! -z $ENABLE_POW ] 7 | then 8 | if [ "$ENABLE_POW" == "1" ] 9 | then 10 | echo "=================proof-of-work=================" 11 | echo "" 12 | rand_str=$(head -c 27 /dev/urandom | base64) 13 | hash_value=$(echo -n "$rand_str" | sha256sum - | cut -c 1-64) 14 | frontend=$(echo "$rand_str" | cut -c -4 ) 15 | backend=$(echo "$rand_str" | cut -c 5- ) 16 | prompt="sha256(XXXX + \"${backend}\") == ${hash_value}" 17 | echo $prompt 18 | echo -n "Gime me XXXX: " 19 | 20 | read -t 300 -r input_hash 21 | 22 | if [ "$input_hash" != "$frontend" ] 23 | then 24 | echo "Proof of work failed!" 25 | exit 2 26 | fi 27 | fi 28 | fi 29 | 30 | unset ENABLE_POW 31 | 32 | # override flag from env 33 | # if environmental variable FLAG is not empty string 34 | if [ ! -z $FLAG ] 35 | then 36 | if [ "$(cat /home/ctf/flag)" != "$FLAG" ] 37 | then 38 | echo $FLAG > /home/ctf/flag 39 | chmod 644 /home/ctf/flag 40 | fi 41 | fi 42 | 43 | # the env will not pass to ctf 44 | unset FLAG 45 | 46 | cd /home/ctf 47 | 48 | # run pwn challenge 49 | exec timeout 300 $(which chroot) /home/ctf ./pwn -------------------------------------------------------------------------------- /alpine+ynetd+chroot+patchelf2/readme.md: -------------------------------------------------------------------------------- 1 | # 说明 2 | 3 | 使用`alpine + yinetd + chroot +patchelf` 部署`pwn`题 4 | 5 | - 参照模板,将二进制文件放置在`./bin`目录下 6 | - 参照模板,将运行所需的`glibc`文件放置在`./glibc`目录下 7 | - `run_pwn.sh`中可以放置`proof of work`代码或者设置`timeout`时间 8 | - 运行`./build_image.sh`可以生成镜像以及提供给选手的`attachment`文件夹 9 | - 在`./deploy/docker-compose.yaml`文件中修改映射的宿主机端口、`flag`的内容 10 | - 其他需求可自行根据模板文件定制 11 | 12 | # Introduction 13 | 14 | use `alpine + yinetd + chroot +patchelf` to deploy pwn challenge 15 | 16 | - put binary file in `./bin` 17 | - put glibc runtime file in `./glibc` 18 | - set `proof of work` or `timeout` in `run_pwn.sh` 19 | - execute `./build_image.sh` to generate image and then run a container. Also, you can decide to get attachment file, which is offered to player 20 | - change the port mapping in host and the content of flag in `./deploy/docker-compose.yaml` 21 | -------------------------------------------------------------------------------- /alpine+ynetd+patchelf/deploy/Dockerfile: -------------------------------------------------------------------------------- 1 | # dockerfile for pwn 2 | FROM ubuntu:20.04 as patchelf 3 | 4 | WORKDIR /root/ctf 5 | 6 | COPY ./bin/patchelf /bin/patchelf 7 | COPY ./bin/pwn ./pwn 8 | 9 | RUN chmod +x ./pwn /bin/patchelf && \ 10 | patchelf --set-rpath ./glibc ./pwn && \ 11 | patchelf --set-interpreter ./glibc/ld-linux-x86-64.so.2 ./pwn 12 | 13 | FROM alpine:latest as runner 14 | 15 | USER root 16 | 17 | RUN adduser ctf -u 1000 -s /bin/sh -D 18 | 19 | WORKDIR /home/ctf 20 | 21 | COPY --from=patchelf /root/ctf/pwn . 22 | COPY ./glibc ./glibc 23 | COPY ./flag ./flag 24 | COPY ./bin/ynetd /bin/ynetd 25 | 26 | RUN chmod 644 ./flag && \ 27 | chmod +x ./pwn && \ 28 | chmod +x /bin/ynetd && \ 29 | chmod +x ./glibc/* && \ 30 | chown -R root:root . 31 | 32 | EXPOSE 1337 33 | 34 | CMD ynetd -p 1337 -lp 500 -se y -u ctf "timeout 300 ./pwn" 35 | 36 | -------------------------------------------------------------------------------- /alpine+ynetd+patchelf/deploy/bin/patchelf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoderickChan/deploy_pwn_template/4c2eec13239491733b635e4152b496eaa887f42c/alpine+ynetd+patchelf/deploy/bin/patchelf -------------------------------------------------------------------------------- /alpine+ynetd+patchelf/deploy/bin/pwn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoderickChan/deploy_pwn_template/4c2eec13239491733b635e4152b496eaa887f42c/alpine+ynetd+patchelf/deploy/bin/pwn -------------------------------------------------------------------------------- /alpine+ynetd+patchelf/deploy/bin/ynetd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoderickChan/deploy_pwn_template/4c2eec13239491733b635e4152b496eaa887f42c/alpine+ynetd+patchelf/deploy/bin/ynetd -------------------------------------------------------------------------------- /alpine+ynetd+patchelf/deploy/build_image.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # build image 5 | docker-compose up -d || docker compose up -d 6 | 7 | # wait for starting container 8 | sleep 5 9 | 10 | # copy file and generate attachment 11 | echo -n "copy file and generate attachment? [y/n] " 12 | read -t 15 ANS 13 | if [ $ANS == "y" ] || [ $ANS == "Y" ] 14 | then 15 | imageid=$(docker ps -n 1 -q) 16 | mkdir ../attachment/glibc -p 17 | cd ../attachment 18 | docker cp ${imageid}:/home/ctf/pwn . 19 | docker cp ${imageid}:/home/ctf/glibc . 20 | echo "copy file and generate attachment success!" 21 | fi -------------------------------------------------------------------------------- /alpine+ynetd+patchelf/deploy/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | # docker-compose.yaml for pwn 2 | version: "3" 3 | services: 4 | pwn: 5 | build: . 6 | restart: unless-stopped 7 | ports: 8 | - "10001:1337" 9 | -------------------------------------------------------------------------------- /alpine+ynetd+patchelf/deploy/flag: -------------------------------------------------------------------------------- 1 | flag{this_is_a_real_flag} 2 | -------------------------------------------------------------------------------- /alpine+ynetd+patchelf/deploy/glibc/ld-linux-x86-64.so.2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoderickChan/deploy_pwn_template/4c2eec13239491733b635e4152b496eaa887f42c/alpine+ynetd+patchelf/deploy/glibc/ld-linux-x86-64.so.2 -------------------------------------------------------------------------------- /alpine+ynetd+patchelf/deploy/glibc/libc.so.6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoderickChan/deploy_pwn_template/4c2eec13239491733b635e4152b496eaa887f42c/alpine+ynetd+patchelf/deploy/glibc/libc.so.6 -------------------------------------------------------------------------------- /alpine+ynetd+patchelf/readme.md: -------------------------------------------------------------------------------- 1 | # 说明 2 | 3 | 使用`alpine + ynetd + patchelf` 部署`pwn`题 4 | 5 | - 参照模板,将二进制文件放置在`./bin`目录下 6 | - 参照模板,将运行所需的`glibc`文件放置在`./glibc`目录下 7 | - 运行`./build_image.sh`可以生成镜像以及提供给选手的`attachment`文件夹 8 | - 在`./deploy/docker-compose.yaml`文件中修改映射的宿主机端口、`flag`的内容 9 | - 其他需求可自行根据模板文件定制 10 | 11 | # Introduction 12 | 13 | use `alpine + ynetd + patchelf` to deploy pwn challenge 14 | 15 | - put binary file in `./bin` 16 | - put glibc runtime file in `./glibc` 17 | - execute `./build_image.sh` to generate image and then run a container. Also, you can decide to get attachment file, which is offered to player 18 | - change the port mapping in host and the content of flag in `./deploy/docker-compose.yaml` 19 | -------------------------------------------------------------------------------- /kctf+nsjail+socat/deploy/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | 16 | # dockerfile for pwn 17 | # stage1: compiler 18 | FROM ubuntu:20.04 as compiler 19 | 20 | RUN apt update && apt install -y gcc g++ make 21 | 22 | WORKDIR /root/ctf 23 | COPY ./src . 24 | 25 | RUN make pwn 26 | 27 | 28 | # stage2: chroot 29 | FROM ubuntu:20.04 as chroot 30 | 31 | WORKDIR /home/ctf 32 | 33 | RUN useradd ctf -u 1000 -s /bin/sh 34 | 35 | COPY --from=compiler /root/ctf/pwn . 36 | COPY ./flag . 37 | COPY ./run_pwn.sh / 38 | 39 | RUN chmod 644 ./flag && \ 40 | chmod 755 /run_pwn.sh 41 | 42 | 43 | # stage3: kctf nsjail 44 | FROM anjia0532/kctf-docker.challenge:latest 45 | 46 | USER root 47 | 48 | COPY --from=chroot / /chroot 49 | 50 | COPY ./nsjail.cfg / 51 | COPY ./start.sh / 52 | 53 | RUN chmod +x /start.sh 54 | 55 | EXPOSE 1337 56 | 57 | CMD ["/start.sh"] -------------------------------------------------------------------------------- /kctf+nsjail+socat/deploy/build_image.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # build image 5 | docker-compose up -d 6 | 7 | sleep 5 8 | 9 | # copy file and generate attachment 10 | echo -n "copy file and generate attachment? [y/n] " 11 | read -t 15 ANS 12 | if [ $ANS == "y" ] || [ $ANS == "Y" ] 13 | then 14 | imageid=$(docker ps -n 1 -q) 15 | mkdir ../attachment -p 16 | cd ../attachment 17 | docker cp ${imageid}:/chroot/home/ctf/pwn . 18 | docker cp -L ${imageid}:/chroot/lib/x86_64-linux-gnu/libc.so.6 . 19 | docker cp -L ${imageid}:/chroot/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 . 20 | echo "copy file and generate attachment success!" 21 | fi -------------------------------------------------------------------------------- /kctf+nsjail+socat/deploy/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | # docker-compose.yaml for pwn 2 | version: "3" 3 | services: 4 | pwn: 5 | build: . 6 | privileged: true 7 | restart: unless-stopped 8 | environment: # unset FLAG if u don't want to generate flag from env 9 | FLAG: flag{this_is_a_real_flag} 10 | ports: 11 | - "10001:1337" 12 | 13 | -------------------------------------------------------------------------------- /kctf+nsjail+socat/deploy/flag: -------------------------------------------------------------------------------- 1 | flag{this_is_a_fake_flag} 2 | -------------------------------------------------------------------------------- /kctf+nsjail+socat/deploy/nsjail.cfg: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # See options available at https://github.com/google/nsjail/blob/master/config.proto 16 | 17 | name: "default-nsjail-configuration" 18 | description: "Default nsjail configuration for pwnable-style CTF task." 19 | 20 | mode: ONCE 21 | keep_env: true 22 | uidmap {inside_id: "1000"} 23 | gidmap {inside_id: "1000"} 24 | rlimit_as_type: HARD 25 | rlimit_cpu_type: HARD 26 | rlimit_nofile_type: HARD 27 | rlimit_nproc_type: HARD 28 | 29 | cwd: "/home/ctf" 30 | 31 | mount: [ 32 | { 33 | src: "/chroot" 34 | dst: "/" 35 | is_bind: true 36 | }, 37 | { 38 | dst: "/tmp" 39 | fstype: "tmpfs" 40 | rw: true 41 | }, 42 | { 43 | dst: "/proc" 44 | fstype: "proc" 45 | rw: true 46 | }, 47 | { 48 | src: "/dev" 49 | dst: "/dev" 50 | is_bind: true 51 | }, 52 | { 53 | src: "/etc/resolv.conf" 54 | dst: "/etc/resolv.conf" 55 | is_bind: true 56 | } 57 | ] -------------------------------------------------------------------------------- /kctf+nsjail+socat/deploy/run_pwn.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # uncomment to set pow using sha256 5 | :< 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | setbuf(stdin, 0); 9 | setbuf(stdout, 0); 10 | setbuf(stderr, 0); 11 | puts("Welcome to pwn world!"); 12 | printf("please input your name: "); 13 | char buf[0x80] = {0}; 14 | read(0, buf, 0x10); 15 | if (strncmp(buf, "admin", 5) == 0) { 16 | system("/bin/sh"); 17 | } else { 18 | puts("you are not admin!"); 19 | } 20 | return 0; 21 | } -------------------------------------------------------------------------------- /kctf+nsjail+socat/deploy/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # override flag from env 4 | # if environmental variable FLAG is not empty string 5 | if [ ! -z $FLAG ] 6 | then 7 | if [ "$(cat /chroot/home/ctf/flag)" != "$FLAG" ] 8 | then 9 | echo $FLAG > /chroot/home/ctf/flag 10 | chmod 644 /chroot/home/ctf/flag 11 | fi 12 | fi 13 | 14 | # the env will not pass to ctf 15 | unset FLAG 16 | 17 | kctf_setup 18 | 19 | exec kctf_drop_privs socat \ 20 | TCP-LISTEN:1337,reuseaddr,fork \ 21 | EXEC:"nsjail --config /nsjail.cfg -- /run_pwn.sh" -------------------------------------------------------------------------------- /kctf+nsjail+socat/readme.md: -------------------------------------------------------------------------------- 1 | # 说明 2 | 3 | 使用`kctf + nsjail + socat` 部署`pwn`题 4 | 5 | - 参照模板,将源码和`makefile`放置在`./deploy/src`目录下 6 | - 确保生成目标文件名称为`pwn`,或者根据需要修改`dockerfile`中的`make pwn`语句 7 | - `run_pwn.sh`中可以放置`proof of work`代码或者设置`timeout`时间 8 | - 运行`./build_image.sh`可以生成镜像以及提供给选手的`attachment`文件夹 9 | - 在`./deploy/docker-compose.yaml`文件中修改映射的宿主机端口、`flag`的内容 10 | - 确保使用`--privileged`选项启动容器,否则`mount`等系统调用会因权限不足而失败 11 | - 其他需求可自行根据模板文件定制 12 | 13 | # Introduction 14 | 15 | use `kctf + nsjail + socat` to deploy pwn challenge 16 | 17 | - put source file in `./deploy/src` 18 | - make sure the name of target binary is `pwn`, or you can change the `dockerfile` 19 | - set `proof of work` or `timeout` in `run_pwn.sh` 20 | - execute `./build_image.sh` to generate image and then run a container. Also, you can decide to get attachment file, which is offered to player 21 | - make sure to run container with `--privileged`, otherwise some syscall like `mount` would fail because of perimission denied 22 | - change the port mapping in host and the content of flag in `./deploy/docker-compose.yaml` 23 | 24 | -------------------------------------------------------------------------------- /red.pwn.jail/deploy/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM pwn.red/jail 2 | 3 | COPY --from=debian@sha256:98d3b4b0cee264301eb1354e0b549323af2d0633e1c43375d0b25c01826b6790 / /srv 4 | COPY pwn /srv/app/run 5 | COPY flag.txt /srv/app/flag.txt 6 | RUN chmod 755 /srv/app/run -------------------------------------------------------------------------------- /red.pwn.jail/deploy/build_image.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # build image 5 | docker-compose up -d || docker compose up -d 6 | 7 | sleep 3 -------------------------------------------------------------------------------- /red.pwn.jail/deploy/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | # docker-compose.yaml for pwn 2 | version: "3" 3 | services: 4 | pwn: 5 | build: . 6 | restart: unless-stopped 7 | ports: 8 | - "10001:1337" 9 | -------------------------------------------------------------------------------- /red.pwn.jail/deploy/pwn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoderickChan/deploy_pwn_template/4c2eec13239491733b635e4152b496eaa887f42c/red.pwn.jail/deploy/pwn -------------------------------------------------------------------------------- /red.pwn.jail/readme.md: -------------------------------------------------------------------------------- 1 | https://github.com/redpwn/jail 2 | -------------------------------------------------------------------------------- /ubuntu+socat/deploy/Dockerfile: -------------------------------------------------------------------------------- 1 | # dockerfile for pwn 2 | # stage1: compiler 3 | FROM ubuntu:20.04 as compiler 4 | 5 | RUN apt update && apt install -y gcc g++ make 6 | 7 | WORKDIR /root/ctf 8 | COPY ./src . 9 | 10 | RUN make pwn 11 | 12 | 13 | # stage2: runner 14 | FROM ubuntu:20.04 as runner 15 | 16 | USER root 17 | 18 | RUN apt update && apt install -y socat && \ 19 | useradd ctf -u 1000 -s /bin/sh 20 | 21 | WORKDIR /home/ctf 22 | 23 | COPY --from=compiler /root/ctf/pwn . 24 | 25 | COPY ./flag ./flag 26 | COPY ./run_pwn.sh / 27 | 28 | RUN chmod 644 ./flag && \ 29 | chmod 711 /run_pwn.sh && \ 30 | chown -R root:root . 31 | 32 | 33 | EXPOSE 1337 34 | 35 | CMD socat tcp-l:1337,reuseaddr,fork exec:/run_pwn.sh 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /ubuntu+socat/deploy/build_image.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # build image 5 | docker-compose up -d || docker compose up -d 6 | 7 | sleep 5 8 | 9 | # copy file and generate attachment 10 | echo -n "copy file and generate attachment? [y/n] " 11 | read -t 15 ANS 12 | if [ $ANS == "y" ] || [ $ANS == "Y" ] 13 | then 14 | imageid=$(docker ps -n 1 -q) 15 | mkdir ../attachment -p 16 | cd ../attachment 17 | docker cp ${imageid}:/home/ctf/pwn . 18 | docker cp -L ${imageid}:/lib/x86_64-linux-gnu/libc.so.6 . 19 | docker cp -L ${imageid}:/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 . 20 | echo "copy file and generate attachment success!" 21 | fi -------------------------------------------------------------------------------- /ubuntu+socat/deploy/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | # docker-compose.yaml for pwn 2 | version: "3" 3 | services: 4 | pwn: 5 | build: . 6 | restart: unless-stopped 7 | environment: # unset FLAG if u don't want to generate flag from env 8 | FLAG: flag{this_is_a_real_flag} 9 | ENABLE_POW: 0 # set ENABLE_POW 1 if u want to use proof-of-pow, unset it to not 10 | ports: 11 | - "10001:1337" 12 | -------------------------------------------------------------------------------- /ubuntu+socat/deploy/flag: -------------------------------------------------------------------------------- 1 | flag{this_is_a_fake_flag} 2 | -------------------------------------------------------------------------------- /ubuntu+socat/deploy/run_pwn.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # set pow using sha256 POW by ENABLE_POW 5 | if [ ! -z $ENABLE_POW ] 6 | then 7 | if [ "$ENABLE_POW" == "1" ] 8 | then 9 | echo "=================proof-of-work=================" 10 | echo "" 11 | rand_str=$(head -c 27 /dev/urandom | base64) 12 | hash_value=$(echo -n "$rand_str" | sha256sum - | cut -c 1-64) 13 | frontend=$(echo "$rand_str" | cut -c -4 ) 14 | backend=$(echo "$rand_str" | cut -c 5- ) 15 | prompt="sha256(XXXX + \"${backend}\") == ${hash_value}" 16 | echo $prompt 17 | echo -n "Gime me XXXX: " 18 | 19 | read -t 300 -r input_hash 20 | 21 | if [ "$input_hash" != "$frontend" ] 22 | then 23 | echo "Proof of work failed!" 24 | exit 2 25 | fi 26 | fi 27 | fi 28 | 29 | unset ENABLE_POW 30 | 31 | # override flag from env 32 | # if environmental variable FLAG is not empty string 33 | if [ ! -z $FLAG ] 34 | then 35 | if [ "$(cat /home/ctf/flag)" != "$FLAG" ] 36 | then 37 | echo $FLAG > /home/ctf/flag 38 | chmod 644 /home/ctf/flag 39 | fi 40 | fi 41 | 42 | # the env will not pass to ctf 43 | unset FLAG 44 | 45 | cd /home/ctf 46 | 47 | # run pwn challenge 48 | exec runuser -u ctf --pty -- timeout 300 ./pwn -------------------------------------------------------------------------------- /ubuntu+socat/deploy/src/makefile: -------------------------------------------------------------------------------- 1 | all: pwn pwn_debug 2 | 3 | pwn: pwn.c 4 | gcc ./pwn.c -o pwn -fstack-protector-all -pie -z now -z noexecstack -O0 -w 5 | strip ./pwn 6 | 7 | pwn_debug: pwn.c 8 | gcc ./pwn.c -o pwn_debug -fstack-protector-all -pie -z now -z noexecstack -O0 -g3 9 | 10 | clean: 11 | rm -rf ./pwn ./pwn_debug 12 | 13 | -------------------------------------------------------------------------------- /ubuntu+socat/deploy/src/pwn.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | setbuf(stdin, 0); 9 | setbuf(stdout, 0); 10 | setbuf(stderr, 0); 11 | puts("Welcome to pwn world!"); 12 | printf("please input your name: "); 13 | char buf[0x80] = {0}; 14 | read(0, buf, 0x10); 15 | if (strncmp(buf, "admin", 5) == 0) { 16 | system("/bin/sh"); 17 | } else { 18 | puts("you are not admin!"); 19 | } 20 | return 0; 21 | } -------------------------------------------------------------------------------- /ubuntu+socat/readme.md: -------------------------------------------------------------------------------- 1 | # 说明 2 | 3 | 使用`ubuntu + socat` 部署`pwn`题 4 | 5 | - 参照模板,将源码和`makefile`放置在`./deploy/src`目录下 6 | - 确保生成目标文件名称为`pwn`,或者根据需要修改`dockerfile`中的`make pwn`语句 7 | - `run_pwn.sh`中可以放置`proof of work`代码或者设置`timeout`时间 8 | - 运行`./build_image.sh`可以生成镜像以及提供给选手的`attachment`文件夹 9 | - 在`./deploy/docker-compose.yaml`文件中修改映射的宿主机端口、`flag`的内容 10 | - 其他需求可自行根据模板文件定制 11 | 12 | # Introduction 13 | 14 | use `ubuntu + socat` to deploy pwn challenge 15 | 16 | - put source file in `./deploy/src` 17 | - make sure the name of target binary is `pwn`, or you can change the `dockerfile` 18 | - set `proof of work` or `timeout` in `run_pwn.sh` 19 | - execute `./build_image.sh` to generate image and then run a container. Also, you can decide to get attachment file, which is offered to player 20 | - change the port mapping in host and the content of flag in `./deploy/docker-compose.yaml` 21 | -------------------------------------------------------------------------------- /ubuntu+xinetd+chroot/deploy/Dockerfile: -------------------------------------------------------------------------------- 1 | # dockerfile for pwn 2 | # stage1: compiler 3 | FROM ubuntu:20.04 as compiler 4 | 5 | RUN apt update && apt install -y gcc g++ make 6 | 7 | WORKDIR /root/ctf 8 | COPY ./src . 9 | 10 | RUN make pwn 11 | 12 | 13 | # stage2: runner 14 | FROM ubuntu:20.04 as runner 15 | 16 | RUN apt update && apt install -y xinetd && \ 17 | useradd ctf -u 1000 -s /bin/sh 18 | 19 | USER root 20 | 21 | WORKDIR /home/ctf 22 | 23 | COPY --from=compiler /root/ctf/pwn . 24 | 25 | COPY ./flag ./flag 26 | COPY ./ctf.xinetd /etc/xinetd.d/ctf 27 | COPY ./run_pwn.sh / 28 | 29 | RUN chmod 644 ./flag && \ 30 | chmod 711 /run_pwn.sh && \ 31 | chown -R root:root . 32 | 33 | RUN cp -R /usr/lib* . && \ 34 | mkdir ./dev && \ 35 | mknod ./dev/null c 1 3 && \ 36 | mknod ./dev/zero c 1 5 && \ 37 | mknod ./dev/random c 1 8 && \ 38 | mknod ./dev/urandom c 1 9 && \ 39 | chmod 666 ./dev/* 40 | 41 | RUN mkdir ./bin && \ 42 | cp /bin/sh ./bin && \ 43 | cp /bin/ls ./bin && \ 44 | cp /bin/cat ./bin 45 | 46 | EXPOSE 1337 47 | 48 | CMD /etc/init.d/xinetd start;sleep infinity; 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /ubuntu+xinetd+chroot/deploy/build_image.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # build image 5 | docker-compose up -d || docker compose up -d 6 | 7 | sleep 5 8 | 9 | # copy file and generate attachment 10 | echo -n "copy file and generate attachment? [y/n] " 11 | read -t 15 ANS 12 | if [ $ANS == "y" ] || [ $ANS == "Y" ] 13 | then 14 | imageid=$(docker ps -n 1 -q) 15 | mkdir ../attachment -p 16 | cd ../attachment 17 | docker cp ${imageid}:/home/ctf/pwn . 18 | docker cp -L ${imageid}:/lib/x86_64-linux-gnu/libc.so.6 . 19 | docker cp -L ${imageid}:/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 . 20 | echo "copy file and generate attachment success!" 21 | fi -------------------------------------------------------------------------------- /ubuntu+xinetd+chroot/deploy/ctf.xinetd: -------------------------------------------------------------------------------- 1 | service ctf 2 | { 3 | disable = no 4 | socket_type = stream 5 | instances = 500 6 | protocol = tcp 7 | wait = no 8 | user = root 9 | type = UNLISTED 10 | port = 1337 11 | bind = 0.0.0.0 12 | server = /bin/bash 13 | 14 | # replace pwn to your program 15 | server_args = /run_pwn.sh 16 | 17 | log_type = FILE /var/log/ctf.xinetd.log 18 | log_on_success = DURATION HOST 19 | log_on_failure = HOST 20 | 21 | # safety options 22 | per_source = 10 # the maximum instances of this service per source IP address 23 | rlimit_cpu = 20 # the maximum number of CPU seconds that the service may use 24 | rlimit_as = 4096M # the Address Space resource limit for the service 25 | # access_times = 2:00-9:00 12:00-24:00 26 | } -------------------------------------------------------------------------------- /ubuntu+xinetd+chroot/deploy/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | # docker-compose.yaml for pwn 2 | version: "3" 3 | services: 4 | pwn: 5 | build: . 6 | restart: unless-stopped 7 | environment: # unset FLAG if u don't want to generate flag from env 8 | FLAG: flag{this_is_a_real_flag} 9 | ENABLE_POW: 0 # set ENABLE_POW 1 if u want to use proof-of-pow, unset it to not 10 | ports: 11 | - "10001:1337" 12 | -------------------------------------------------------------------------------- /ubuntu+xinetd+chroot/deploy/flag: -------------------------------------------------------------------------------- 1 | flag{this_is_a_fake_flag} 2 | -------------------------------------------------------------------------------- /ubuntu+xinetd+chroot/deploy/run_pwn.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | # set pow using sha256 POW by ENABLE_POW 6 | if [ ! -z $ENABLE_POW ] 7 | then 8 | if [ "$ENABLE_POW" == "1" ] 9 | then 10 | echo "=================proof-of-work=================" 11 | echo "" 12 | rand_str=$(head -c 27 /dev/urandom | base64) 13 | hash_value=$(echo -n "$rand_str" | sha256sum - | cut -c 1-64) 14 | frontend=$(echo "$rand_str" | cut -c -4 ) 15 | backend=$(echo "$rand_str" | cut -c 5- ) 16 | prompt="sha256(XXXX + \"${backend}\") == ${hash_value}" 17 | echo $prompt 18 | echo -n "Gime me XXXX: " 19 | 20 | read -t 300 -r input_hash 21 | 22 | if [ "$input_hash" != "$frontend" ] 23 | then 24 | echo "Proof of work failed!" 25 | exit 2 26 | fi 27 | fi 28 | fi 29 | 30 | unset ENABLE_POW 31 | 32 | # override flag from env 33 | # if environmental variable FLAG is not empty string 34 | if [ ! -z $FLAG ] 35 | then 36 | if [ "$(cat /home/ctf/flag)" != "$FLAG" ] 37 | then 38 | echo $FLAG > /home/ctf/flag 39 | chmod 644 /home/ctf/flag 40 | fi 41 | fi 42 | 43 | # the env will not pass to ctf 44 | unset FLAG 45 | 46 | cd /home/ctf 47 | 48 | # run pwn challenge 49 | exec timeout 300 chroot --userspec=1000:1000 /home/ctf ./pwn -------------------------------------------------------------------------------- /ubuntu+xinetd+chroot/deploy/src/makefile: -------------------------------------------------------------------------------- 1 | all: pwn pwn_debug 2 | 3 | pwn: pwn.c 4 | gcc ./pwn.c -o pwn -fstack-protector-all -pie -z now -z noexecstack -O0 -w 5 | strip ./pwn 6 | 7 | pwn_debug: pwn.c 8 | gcc ./pwn.c -o pwn_debug -fstack-protector-all -pie -z now -z noexecstack -O0 -g3 9 | 10 | clean: 11 | rm -rf ./pwn ./pwn_debug 12 | 13 | -------------------------------------------------------------------------------- /ubuntu+xinetd+chroot/deploy/src/pwn.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | setbuf(stdin, 0); 9 | setbuf(stdout, 0); 10 | setbuf(stderr, 0); 11 | puts("Welcome to pwn world!"); 12 | printf("please input your name: "); 13 | char buf[0x80] = {0}; 14 | read(0, buf, 0x10); 15 | if (strncmp(buf, "admin", 5) == 0) { 16 | system("/bin/sh"); 17 | } else { 18 | puts("you are not admin!"); 19 | } 20 | return 0; 21 | } -------------------------------------------------------------------------------- /ubuntu+xinetd+chroot/readme.md: -------------------------------------------------------------------------------- 1 | # 说明 2 | 3 | 使用`ubuntu + xinetd + chroot` 部署`pwn`题 4 | 5 | - 参照模板,将源码和`makefile`放置在`./deploy/src`目录下 6 | - 确保生成目标文件名称为`pwn`,或者根据需要修改`dockerfile`中的`make pwn`语句 7 | - `run_pwn.sh`中可以放置`proof of work`代码或者设置`timeout`时间 8 | - 运行`./build_image.sh`可以生成镜像以及提供给选手的`attachment`文件夹 9 | - 在`./deploy/docker-compose.yaml`文件中修改映射的宿主机端口、`flag`的内容 10 | - 其他需求可自行根据模板文件定制 11 | 12 | # Introduction 13 | 14 | use `ubuntu + xinetd + chroot` to deploy pwn challenge 15 | 16 | - put source file in `./deploy/src` 17 | - make sure the name of target binary is `pwn`, or you can change the `dockerfile` 18 | - set `proof of work` or `timeout` in `run_pwn.sh` 19 | - execute `./build_image.sh` to generate image and then run a container. Also, you can decide to get attachment file, which is offered to player 20 | - change the port mapping in host and the content of flag in `./deploy/docker-compose.yaml` 21 | --------------------------------------------------------------------------------