Socat 比如某场比赛的文件目录如下
run.py
1 2 3 4 5 6 7 8 9 10 11 12 import osimport sysif len (sys.argv) != 2 : print ("Usage: %s [port]" % sys.argv[0 ]) sys.exit(1 ) port = sys.argv[1 ] command = 'socat -d -d tcp-l:' + port + ',reuseaddr,fork EXEC:"python -u server.py" ' os.system(command)
前面加个nohup可以在端口一直运行
1 $ nohup socat -d -d tcp-l:[port],reuseaddr,fork EXEC:"python -u server.py"
Docker Docker命令 创建镜像
1 $ docker build . -t [images_name]
查看创建的镜像
创建容器
1 $ docker run --name [container_name] -d [-idt] -p [host_port]:[container_port] [images_name]
-d
表示不进入容器内部
-p
表示将容器内部的port_inner端口映射到port_outer端口
-idt
表示创建守护进程(没有这个容器创建完程序就退出了,不太清楚
查看正在运行的容器
停止容器
1 $ docker stop [container_id]
删除容器
1 $ docker rm [container_id]
删除镜像
进入容器
1 2 $ docker attach [container_id] $ docker exec -it [container_id] bash
常用Dockerfile语法
这里以一道极其简单nc拿flag的题目为例
server.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 from hashlib import sha256import socketserverfrom secret import flagimport signalimport stringimport randomimport osclass Task (socketserver.BaseRequestHandler ): def _recvall (self ): BUFF_SIZE = 2048 data = b'' while True : part = self.request.recv(BUFF_SIZE) data += part if len (part) < BUFF_SIZE: break return data.strip() def send (self, msg, newline=True ): try : if newline: msg += b'\n' self.request.sendall(msg) except : pass def recv (self, prompt=b'[-] ' ): self.send(prompt, newline=False ) return self._recvall() def proof_of_work (self ): random.seed(os.urandom(8 )) proof = '' .join( [random.choice(string.ascii_letters+string.digits) for _ in range (20 )]) _hexdigest = sha256(proof.encode()).hexdigest() self.send(f"[+] sha256(XXXX+{proof[4 :]} ) == {_hexdigest} " .encode()) x = self.recv(prompt=b'[+] Plz tell me XXXX: ' ) if len (x) != 4 or sha256(x+proof[4 :].encode()).hexdigest() != _hexdigest: return False return True def handle (self ): signal.alarm(60 ) if not self.proof_of_work(): self.send(b'[!] Wrong!' ) return self.send(b'here is your flag' ) self.send(flag) class ThreadedServer (socketserver.ThreadingMixIn, socketserver.TCPServer ): pass class ForkedServer (socketserver.ForkingMixIn, socketserver.TCPServer ): pass if __name__ == "__main__" : HOST, PORT = '0.0.0.0' , 10001 server = ForkedServer((HOST, PORT), Task) server.allow_reuse_address = True print (HOST, PORT) server.serve_forever()
DockerFile
1 2 3 4 5 6 7 8 9 10 11 FROM python:3.8 LABEL Description="baby_try" VERSION='1.0' COPY server.py . COPY secret.py . RUN chmod +x server.py EXPOSE 12345 CMD ["python" , "server.py" ]
exp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 import hashlibfrom string import ascii_letters, digitsfrom pwn import *from itertools import producttable = ascii_letters + digits class Solve (): def __init__ (self ): self.sh = remote('127.0.0.1' , 12345 ) def proof_of_work (self ): proof = self.sh.recvuntil(b'[+] Plz tell me XXXX:' ) tail = proof[16 :32 ].decode() _hash = proof[37 :101 ].decode() for i in product(table, repeat=4 ): head = '' .join(i) t = hashlib.sha256((head + tail).encode()).hexdigest() if t == _hash : self.sh.sendline(head.encode()) break def solve (self ): self.proof_of_work() self.sh.recvline() flag = self.sh.recvline()[:-1 ].decode() print (flag) self.sh.close() if __name__ == '__main__' : solution = Solve() solution.solve()
Step1 创建镜像 1 $ docker build . -t baby_try
Step2 启动容器 1 $ docker run --name trytry -d -idt -p 12345:10001 baby_try
将端口映射到本地12345端口
Step3 尝试exp打本地 没什么问题
Step4 挂载服务器 本地没问题后,就要部署到服务器上
使用Docker Compose 在过载服务器的时候还可以编写docker-compose.yml
简化创建镜像和启动容器的步骤,如下
1 2 3 4 5 6 7 8 version: '3' services: checkin: image: signin build: . ports: - "9999:10001" restart: always
然后输入命令一键搭建
遇到的一些问题
镜像搭建太慢
容器创建完程序就退出了
题目本身有问题
此外,pwn题的部署有现成工具:https://github.com/giantbranch/pwn_deploy_chroot
Reference
Soreat_u-How to Setup for Interactive Crypto Problems?