├── docker ├── bin │ └── docker-entrypoint.sh └── docker-compose.yml ├── README.md ├── Dockerfile ├── .github └── workflows │ ├── docker-dockerhub.yml │ └── docker-github.yml └── src └── main.py /docker/bin/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | socat -v -s TCP4-LISTEN:9999,tcpwrap=script,reuseaddr,fork EXEC:"python3 -u /main.py",pty,ctty,setsid,stderr -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 2022 西湖论剑 LockByLock 2 | 3 | > Lock Lock Lock.... 4 | 5 | 本项目使用动态flag,请使用`$FLAG`环境变量传入flag数据(如`CTFd`),题目环境位于`9999`端口 6 | 7 | docker镜像发布于DockerHub:`randark/2022-xhlj-crypto-lockbylock:master` 8 | 9 | 源码储存于Github:https://github.com/CTF-Archives/2022-xhlj-crypto-lockbylock 10 | -------------------------------------------------------------------------------- /docker/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.4' 2 | services: 3 | shadowflag: 4 | image: test 5 | # image: randark/2022-xhlj-crypto-lockbylock:master 6 | environment: 7 | FLAG: "flag{a63b4d37-7681-4850-b6a7-0d7109febb19}" 8 | ports: 9 | - "9999:9999" 10 | restart: unless-stopped -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.10-slim-bullseye 2 | # Randark's permission limit questioning framework 3 | LABEL auther="Randark_JMT" 4 | EXPOSE 9999 5 | 6 | RUN sed -i "s@http://deb.debian.org@https://mirrors.tuna.tsinghua.edu.cn@g" /etc/apt/sources.list 7 | RUN apt-get update && apt install -y socat 8 | 9 | # RUN pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple pycryptodome gmpy2 10 | RUN pip3 install pycryptodome gmpy2 11 | 12 | COPY ./src/main.py / 13 | COPY ./docker/bin/docker-entrypoint.sh / 14 | 15 | ENTRYPOINT [ "/bin/bash","/docker-entrypoint.sh" ] -------------------------------------------------------------------------------- /.github/workflows/docker-dockerhub.yml: -------------------------------------------------------------------------------- 1 | name: Publish Docker image to Dockerhub 2 | 3 | on: 4 | push: 5 | branches: [ "master" ] 6 | pull_request: 7 | branches: [ "master" ] 8 | 9 | jobs: 10 | push_to_registry: 11 | name: Push Docker image to Docker Hub 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Check out the repo 15 | uses: actions/checkout@v3 16 | 17 | - name: Log in to Docker Hub 18 | uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 19 | with: 20 | username: ${{ secrets.DOCKER_USERNAME }} 21 | password: ${{ secrets.DOCKER_PASSWORD }} 22 | 23 | - name: Extract metadata (tags, labels) for Docker 24 | id: meta 25 | uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 26 | with: 27 | images: randark/2022-xhlj-crypto-lockbylock 28 | 29 | - name: Build and push Docker image 30 | uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc 31 | with: 32 | context: . 33 | push: true 34 | tags: ${{ steps.meta.outputs.tags }} 35 | labels: ${{ steps.meta.outputs.labels }} 36 | - name: Docker Hub Description 37 | uses: peter-evans/dockerhub-description@v3 38 | with: 39 | username: ${{ secrets.DOCKER_USERNAME }} 40 | password: ${{ secrets.DOCKER_PASSWORD }} 41 | repository: randark/2022-xhlj-crypto-lockbylock 42 | -------------------------------------------------------------------------------- /.github/workflows/docker-github.yml: -------------------------------------------------------------------------------- 1 | name: Publish Docker image to Github 2 | 3 | on: 4 | push: 5 | branches: [ "master" ] 6 | # Publish semver tags as releases. 7 | tags: [ 'v*.*.*' ] 8 | pull_request: 9 | branches: [ "master" ] 10 | 11 | env: 12 | # Use docker.io for Docker Hub if empty 13 | REGISTRY: ghcr.io 14 | # github.repository as / 15 | IMAGE_NAME: ${{ github.repository }} 16 | 17 | 18 | jobs: 19 | build: 20 | 21 | runs-on: ubuntu-latest 22 | permissions: 23 | contents: read 24 | packages: write 25 | # This is used to complete the identity challenge 26 | # with sigstore/fulcio when running outside of PRs. 27 | id-token: write 28 | 29 | steps: 30 | - name: Checkout repository 31 | uses: actions/checkout@v3 32 | 33 | # Install the cosign tool except on PR 34 | # https://github.com/sigstore/cosign-installer 35 | - name: Install cosign 36 | if: github.event_name != 'pull_request' 37 | uses: sigstore/cosign-installer@f3c664df7af409cb4873aa5068053ba9d61a57b6 #v2.6.0 38 | with: 39 | cosign-release: 'v1.11.0' 40 | 41 | 42 | # Workaround: https://github.com/docker/build-push-action/issues/461 43 | - name: Setup Docker buildx 44 | uses: docker/setup-buildx-action@79abd3f86f79a9d68a23c75a09a9a85889262adf 45 | 46 | # Login against a Docker registry except on PR 47 | # https://github.com/docker/login-action 48 | - name: Log into registry ${{ env.REGISTRY }} 49 | if: github.event_name != 'pull_request' 50 | uses: docker/login-action@28218f9b04b4f3f62068d7b6ce6ca5b26e35336c 51 | with: 52 | registry: ${{ env.REGISTRY }} 53 | username: ${{ github.actor }} 54 | password: ${{ secrets.RANDARK_TOKEN }} 55 | 56 | # Extract metadata (tags, labels) for Docker 57 | # https://github.com/docker/metadata-action 58 | - name: Extract Docker metadata 59 | id: meta 60 | uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 61 | with: 62 | images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} 63 | 64 | # Build and push Docker image with Buildx (don't push on PR) 65 | # https://github.com/docker/build-push-action 66 | - name: Build and push Docker image 67 | id: build-and-push 68 | uses: docker/build-push-action@ac9327eae2b366085ac7f6a2d02df8aa8ead720a 69 | with: 70 | context: . 71 | push: ${{ github.event_name != 'pull_request' }} 72 | tags: ${{ steps.meta.outputs.tags }} 73 | labels: ${{ steps.meta.outputs.labels }} 74 | cache-from: type=gha 75 | cache-to: type=gha,mode=max 76 | -------------------------------------------------------------------------------- /src/main.py: -------------------------------------------------------------------------------- 1 | from Crypto.Util.number import * 2 | from gmpy2 import * 3 | import os 4 | import random 5 | 6 | flag = os.getenv('FLAG') 7 | 8 | class Lock: 9 | def __init__(self, p, q) -> None: 10 | while True: 11 | self.p = p 12 | self.q = q 13 | self.n = self.p * self.q 14 | self.e = random.randint(10**14, 10**15) 15 | 16 | if gcd(self.e, (self.p-1)*(self.q-1)) == 1: 17 | self.d = invert(self.e, (self.p-1)*(self.q-1)) 18 | break 19 | 20 | def lock(self, message: int) -> int: 21 | assert 1 < message < self.n 22 | return powmod(message, self.e, self.n) 23 | 24 | def unlock(self, cipher: int) -> int: 25 | assert 1 < cipher < self.n 26 | return powmod(cipher, self.d, self.n) 27 | 28 | 29 | def secureProcedure(A, B): 30 | global flag 31 | flag = bytes_to_long(flag.encode()) 32 | print('Alice: lock lock lock lock unlock') 33 | msg1 = A.lock(flag) 34 | print(f'Alice: locked msg1 = {msg1}') 35 | print('Alice: lock lock lock lock') 36 | 37 | print('Bob: lock unlock lock lock') 38 | msg2 = B.lock(msg1) 39 | print(f'Bob: locked msg2 = {msg2}') 40 | print('Bob: lock lock lock lock') 41 | 42 | print('Alice: unlock unlock unlock...') 43 | msg3 = A.unlock(msg2) 44 | print(f'Alice: unlocked msg3 = {msg3}') 45 | print('Alice: lock lock lock lock') 46 | 47 | print('Bob: unlock unlock unlock...') 48 | msg = B.unlock(msg3) 49 | 50 | assert msg == flag 51 | print('Bob: lock lock unlock') 52 | print('Bob: lock by lock, lock lock right, unlock unlock unlock...') 53 | print('Alice: right right, lock lock unlock') 54 | print('Bob: lock lock lock, flag lock lock lock.') 55 | print('Alice: lock unlock lock lock, unlock lock lock') 56 | print('Bob: lock lock!') 57 | 58 | 59 | def proxyProcedure(A, B): 60 | print('Agent: lock lock, lock lock lock, unlock lock lock right') 61 | print('Alice: lock!') 62 | print('Bob: lock lock, unlock lock!') 63 | omsg = int(input()) 64 | 65 | print('Alice: lock lock lock lock unlock') 66 | msg1 = A.lock(omsg) 67 | print(f'Alice: locked msg1 = {msg1}') 68 | print('Alice: lock lock lock lock') 69 | 70 | print('Bob: lock unlock lock lock') 71 | msg2 = B.lock(msg1) 72 | print(f'Bob: locked msg2 = {msg2}') 73 | print('Bob: lock lock lock lock') 74 | 75 | print('Alice: unlock unlock unlock...') 76 | msg3 = A.unlock(msg2) 77 | print(f'Alice: unlocked msg3 = {msg3}') 78 | print('Alice: lock lock lock lock') 79 | 80 | print('Bob: unlock unlock unlock...') 81 | msg = B.unlock(msg3) 82 | 83 | 84 | assert msg == omsg 85 | print('Bob: lock, lock, locked lock lock lock unlock') 86 | print('Bob: lock by lock, lock lock right, lock unlock unlock unlock...') 87 | print('Alice: right right, locked lock lock lock unlock') 88 | print('Bob: lock lock!') 89 | 90 | 91 | def main(): 92 | p = getPrime(1024) 93 | q = getPrime(1024) 94 | AliceLock = Lock(p, q) 95 | BobLock = Lock(p, q) 96 | 97 | secureProcedure(AliceLock, BobLock) 98 | 99 | try: 100 | proxyProcedure(AliceLock, BobLock) 101 | proxyProcedure(AliceLock, BobLock) 102 | print('Lock: lock lock lock, unlock lock lock lock, lock lock unlock lock unlock lock, lock.') 103 | except Exception: 104 | print('lock unlock, lock locked, unlocked lock') 105 | 106 | 107 | if __name__ == '__main__': 108 | main() --------------------------------------------------------------------------------