{"id":17015433,"url":"https://github.com/plusls/pwn-server","last_synced_at":"2025-10-09T02:14:30.016Z","repository":{"id":110306360,"uuid":"143808296","full_name":"plusls/pwn-server","owner":"plusls","description":" A tool for easy manage a pwn server","archived":false,"fork":false,"pushed_at":"2018-10-29T17:37:08.000Z","size":50,"stargazers_count":19,"open_issues_count":0,"forks_count":2,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-04-12T09:40:58.617Z","etag":null,"topics":["ctf-tools","pwn"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/plusls.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2018-08-07T02:28:33.000Z","updated_at":"2024-06-26T10:36:34.000Z","dependencies_parsed_at":null,"dependency_job_id":"609ac108-1c7b-49cc-8d1b-d0eae6e6ea17","html_url":"https://github.com/plusls/pwn-server","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/plusls/pwn-server","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plusls%2Fpwn-server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plusls%2Fpwn-server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plusls%2Fpwn-server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plusls%2Fpwn-server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/plusls","download_url":"https://codeload.github.com/plusls/pwn-server/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plusls%2Fpwn-server/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279000783,"owners_count":26082906,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-09T02:00:07.460Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ctf-tools","pwn"],"created_at":"2024-10-14T06:28:39.855Z","updated_at":"2025-10-09T02:14:30.011Z","avatar_url":"https://github.com/plusls.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pwn-server\n\n这是一个自动化部署pwn题的工具\n\n有如下特性：\n\n1.自动化部署pwn\n\n2.所有的pwn题都在不同的容器中，pwn-server将会自动化的创建容器\n\n3.只占用一个端口，会根据不同的token将连接分发到不同的容器\n\n4.支持一题多flag\n\n5.自动记录pwn题流量\n\n6.自动标记出读取了flag的流量\n\n7.防fork bomb\n\n8.支持多镜像，既不同容器可以指定不同的docker镜像\n\n### 依赖\n\nfanotify\n\n```\npip3 install git+https://github.com/google/python-fanotify.git --user\n```\n\n\n\n### 使用\n\n第一次使用时需要build基础容器\n\nbuild基础容器：\n\n```\ndocker build --tag cnss/pwn ./docker/pwndocker\n```\n\n\n\n启动pwn-server\n\n```python\nsudo python3 pwnserver.py\n```\n\n目前并没有封装为服务，无守护程序\n\n注：关闭容器后容器将会被自动删除\n\n由于使用了fanotify，所以必须要有root权限\n\n**请务必保证pwn目录下的文件是可执行的！！！**\n\n\n\n### 自动化部署pwn\n\n与其它脚本不同，用pwn-server部署pwn题只需要将pwn的二进制文件丢入pwn文件夹，pwn-server会自动的识别pwn题\n\n#### pwn题目录结构\n\n仓库中默认有2个题目在目录pwn下\n\npwn目录结构：\n\n```sh\npwn\n├── note\n│   ├── RNote3\n│   ├── startdocker.sh\n│   └── startpwn.sh\n└── pwn1\n    ├── printf\n    ├── startdocker.sh\n    └── startpwn.sh\n```\n\n其中包含了2个pwn题 分别为note和pwn1\n\nstartdocker.sh默认为\n\n```sh\n/usr/sbin/xinetd -dontfork\n```\n\n这是docker运行时执行的命令\n\nstartpwn.sh为xinetd会执行的命令，对于pwn1而言就是\n\n```sh\nstdbuf -i 0 -o 0 -e 0 ./printf\n```\n\n#### 多flag支持\n\n对于每一个connect，在连接上后会要求输入token，之后交由**get_pwn_data.py**处理\n\n若是要支持多flag则可做以下设置\n\n```python\ndef get_pwn_data(token):\n    '''参数为token 返回该token对应的题目名和flag以及image_tag'''\n    if token == 'note_01':\n    \treturn ('note', \"cnss{it_is_note_01}\", \"cnss/pwn\")\n    elif token == 'note_02':\n        return ('note', 'cnss{it_is_note_02}', \"cnss/pwn\")\n\n    if token == 'pwn1_01':\n    \treturn ('pwn1', \"cnss{it_is_pwn1}\", \"cnss/pwn\")\n\n    return('', '', '')\n```\n\n**token=note_01**\n\n```bash\n[*] Switching to interactive mode\n[DEBUG] Received 0x51 bytes:\n    \"*** Error in `./RNote3': munmap_chunk(): invalid pointer: 0x00007fd7f0bd7afd ***\\n\"\n*** Error in `./RNote3': munmap_chunk(): invalid pointer: 0x00007fd7f0bd7afd ***\n$ ls -al ../\n[DEBUG] Sent 0xb bytes:\n    'ls -al ../\\n'\n[DEBUG] Received 0x154 bytes:\n    'total 25\\n'\n    'drwxr-xr-x 1 pwn  pwn  4096 Aug 15 05:56 .\\n'\n    'drwxr-xr-x 1 root root 4096 Aug 15 03:33 ..\\n'\n    '-rw-r--r-- 1 pwn  pwn   220 Aug 31  2015 .bash_logout\\n'\n    '-rw-r--r-- 1 pwn  pwn  3771 Aug 31  2015 .bashrc\\n'\n    'drwxrwxrwx 1 root root    0 Aug 15 04:58 bin\\n'\n    '-rwxrwxrwx 1 root root   19 Aug 15 05:56 flag\\n'\n    '-rw-r--r-- 1 pwn  pwn   655 May 16  2017 .profile\\n'\ntotal 25\ndrwxr-xr-x 1 pwn  pwn  4096 Aug 15 05:56 .\ndrwxr-xr-x 1 root root 4096 Aug 15 03:33 ..\n-rw-r--r-- 1 pwn  pwn   220 Aug 31  2015 .bash_logout\n-rw-r--r-- 1 pwn  pwn  3771 Aug 31  2015 .bashrc\ndrwxrwxrwx 1 root root    0 Aug 15 04:58 bin\n-rwxrwxrwx 1 root root   19 Aug 15 05:56 flag\n-rw-r--r-- 1 pwn  pwn   655 May 16  2017 .profile\n$ cat ../flag\n[DEBUG] Sent 0xc bytes:\n    'cat ../flag\\n'\n[DEBUG] Received 0x13 bytes:\n    'cnss{it_is_note_01}'\ncnss{it_is_note_01}$  \n```\n\n**token=note_02**\n\n```bash\n[*] Switching to interactive mode\n[DEBUG] Received 0x51 bytes:\n    \"*** Error in `./RNote3': munmap_chunk(): invalid pointer: 0x00007fad2858cafd ***\\n\"\n*** Error in `./RNote3': munmap_chunk(): invalid pointer: 0x00007fad2858cafd ***\n$ cat ../flag\n[DEBUG] Sent 0xc bytes:\n    'cat ../flag\\n'\n[DEBUG] Received 0x13 bytes:\n    'cnss{it_is_note_02}'\ncnss{it_is_note_02}$  \n\n```\n\ndocker 容器列表\n\n```bash\ndocker ps\nCONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES\n335ac415ef15        7d472f349e2d        \"/bin/sh -c /ctf/pwn…\"   4 minutes ago       Up 4 minutes        1337/tcp            note_02\n92de3f097e93        7d472f349e2d        \"/bin/sh -c /ctf/pwn…\"   7 minutes ago       Up 7 minutes        1337/tcp            note_01\n\n```\n\n当然，可以自定义该函数与ctf平台进行交互，从而做到反作弊\n\n#### 多镜像支持\n\n考虑到不同题目可能要求的运行环境不同，pwnserver支持不同题目使用不同的镜像，只需要在**get_pwn_data**中设置即可\n\n### 关于容器\n\n对于每个不同的token，都会启动不同的容器，也就是说同一个题会有多个容器。\n\n但是对于相同的token则不会启动多个容器\n\n### 关于fork bomb\n\n每个容器都有资源限制，限制了pid的数量\n\n正常情况下父进程被发送SIGPIPE后子进程也会被杀死，所以在socket断开后fork炸弹一般会失效\n\n当然，例外情况也是有的，详情见BUG\n\n### 关于log\n\n对于流量将会被自动记录在log目录下，若是一个连接获取了flag，那条log的文件名中将会包含flag\n\n例如：\n\n```bash\nplusls@pwn:~/pwn/pwn-server/log$ ls -al\ntotal 44\ndrwxrwxr-x 2 plusls plusls  4096 Aug 18 01:34 .\ndrwxrwxr-x 9 plusls plusls  4096 Aug 18 01:27 ..\n-rw-r--r-- 1 root   root   12949 Aug 18 01:34 log.note.note_02.1534527196.572956.log\n-rw-r--r-- 1 root   root   12237 Aug 18 01:34 log.note.note_02.1534527217.5434923-flag.log\n-rw-r--r-- 1 root   root    1025 Aug 18 01:31 log.sh.sh.1534527057.2515137.log\n-rw-r--r-- 1 root   root     507 Aug 18 01:31 log.sh.sh.1534527099.9255965-flag.log\n```\n\n判断一个连接是否成功拿到flag使用了fainotify，想了解实现可以阅读源码\n\n### config.json\n\npwn-server使用config.json来配置\n\n```json\n{\n    // 监听的地址\n    \"address\": {\n        \"ip\": \"0.0.0.0\",\n        \"port\": 8888\n    },\n    // 尚未使用\n    \"sqlserver\": \"\",\n    // 放置pwn题的位置\n    \"pwn_dir\": \"./pwn\",\n    // 存放log的位置\n    \"log_dir\": \"./log\",\n    // 该目录下存放着xinetd的配置文件\n    \"pwmdocker_dir\": \"./docker/pwndocker\",\n    // 数据目录 目前只用来存放flag\n    \"data_dir\": \"./data\"\n}\n```\n\n\n\n### TO DO\n\n~~1.自动化管理容器~~\n\n~~2.标记出成功getflag的log~~\n\n3.细化容器权限控制\n\n### BUG\n\n目前已知在某些情况下socket断开后程序仍会继续运行...\n\nsocket断开后程序结束的原因是SIGPIPE，当往一个写端关闭的管道或socket连接中连续写入数据时会引发SIGPIPE信号，从而导致程序结束\n\n若是程序无任何写操作并进入死循环，则会出现冗余进程\n\n例如\n\n```c\n#include \u003cstdio.h\u003e\n#include \u003cstdlib.h\u003e\n#include \u003cstring.h\u003e\n#include \u003cunistd.h\u003e\n\nint main()\n{\n    setbuf(stdout, NULL);\n    setbuf(stdin, NULL);\n    setbuf(stderr, NULL);\n\n    char s[0x300];\n    while (1) {\n        memset(s, 0, 0x300);\n        printf(\"Please input somthing:\");\n        read(0, s, 0x300);\n        printf(\"Your input is:\");\n        printf(s);\n    }\n    return 0;\n}\n```\n\nprintf被改为system后程序就没有任何写操作了，因此不会触发SIGPIPE，从而不会被结束","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fplusls%2Fpwn-server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fplusls%2Fpwn-server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fplusls%2Fpwn-server/lists"}