일단 내가 Docker을 m1 Macbook air(2021)에 설치하게 된 배경을 설명하겠다. 나는 주로 pwnable을 주로 해, M1 노트북에서는 제대로 디버깅을 할 수가 없었다. 이 때, 나는 parsec이라는 프로그램을 써 집에 있는 컴퓨터 본체를 서버로 하고, 그 컴퓨터에 Virtualbox룰 이용해 ubuntu를 가상화로 돌려 디버깅을 하고 문제를 풀었다. 하지만 이번 경남권 사이버보안경진대회에 참여하면서 그 문제가 터졌었다. 그 대회에서는 지정된 와이파이로만 접속을 해야 해당 대회의 사이트에 들어갈 수 있었다(pwnable 문제도 마찬가지여서 remote도 되지 않았다).
나의 경우 서버에서 문제를 분석하고 그 서버에서 접속했기 때문에 서버에서는 해당 사이트에 들어갈 수 없었다. 나는 당황해서 이 문제를 해결하는데 30분 정도 시간을 소요하게 되었다. 문제를 분석하는데에는 서버를, 문제를 푸는 코드를 짜는데는 m1 맥북을 사용했다(다행히 pwntools는 설치가 되어있는 상황이라 큰 문제는 없었다). 물론 시간은 넉넉하게 주고 문제도 생각보다 금방 해결되었지만, 익숙하지 않아 심리적으로 조금 압박이 생기게 되었다. 그나마 다행이라는 점은 2번째 CTF라는 점일까.
일단 이번 CTF에서 찾은 문제라면 문제를 받고 분석하기 위해서 서버로 바이너리를 옮기는데 시간을 많이 썼다는 점인것 같다. 이번 대회에서 나는 디스코드를 통해서 문제를 옮기고 분석했다. Docker을 이용했다면 좀 더 빠르게 문제를 옮기고 분석을 하지 않았을까라고 생각이 든다.(무엇보다 터미널을 사용하는게 더 멋있어보이기도 하고.)
그래서 나는 돌아오자마자 m1에서도 디버거의 필요성을 느끼게 되었다. 물론 m1에서는 x64를 디버깅할 수 없다라는걸 예전부터 알고 있었다. 그래도 혹시모르니 내가 얻을 수 있는 자료가 있지 않을까 생각이 들어 이것저것 찾게되다가 Docker을 찾게 되었다.
Docker는 컨테이너 기반 오픈소스 가상화 플랫폼이다. VMware나 Virtualbox처럼 가상화를 제공해주는 프로그램이라고 생각하면 된다. 그러면 내가 이전에 사용하는 방식(parsec)이랑 별 차이 없는게 아니냐고 생각할 수도 있다. 사실 큰 차이는 없는 것 같다. 눈에 띄는 차이점이라면 원하는 파일을 옮기는게 좀 더 편하고, 터미널에서 작업해서 가시성과 편리성이 더 좋다는...점? 그 정도인 것 같다.
터미널 위에서 돌아가기 때문에 하나의 컴퓨터처럼 사용하는 것처럼 느껴진다는 점도 있는 것 같다.
각설하고 Dockerfile 설정을 적겠다.
From ubuntu:20.04
ARG DEBIAN_FRONTEND=noiteractive
ENV TZ Asia/Seoul
ENV PYTHONIOENCODING UTF-8
ENV LC_CTYPE C.UTF-8
WORKDIR /root
RUN apt update && apt install -y netcat
RUN apt install vim git gcc ssh curl wget gdb sudo zsh python3 python3-pip libffi-dev build-essential libssl-dev libc6-i386 libc6-dbg gcc-multilib make -y
RUN dpkg --add-architecture i386
RUN apt update
RUN apt install libc6:i386 -y
RUN python3 -m pip install --upgrade pip
RUN pip3 install unicorn
RUN pip3 install keystone-engine
RUN pip3 install pwntools
RUN pip3 install ropgadget
RUN apt install libcapstone-dev -y
RUN git clone https://github.com/longld/peda.git ~/peda
RUN echo "source ~/peda/peda.py" >> ~/.gdbinit
RUN apt install ruby-full -y
RUN gem install one_gadget seccomp-tools
RUN sh -c "$(wget -O- https://github.com/deluan/zsh-in-docker/releases/download/v1.1.2/zsh-in-docker.sh)" - \
-t agnoster \
-p https://github.com/zsh-users/zsh-syntax-highlighting \
vi Dockerfile
Docker build -t ubuntu:pwn --platform linux/amd64 -< Dockerfile
조금 설명을 덧붙히자면 ubuntu와 pwn의 경우, ubuntu는 image이름, pwn은 tag이다.
그리고 --platform linux/amd64의 경우 m1 맥북이면 옵션을 넣고 돌려야한다. 왜냐하면 이 옵션을 넣지않고 실행을 하게 되면 m1이 arm64 아키텍쳐이기 때문에 자동적으로 arm64버전으로 설정하게 된다. 그렇게 되면 gcc-multilib에서 충돌이 일어나서 진행되지 않는다.(이거 때문에 12시간을 날렸다..) 아마도 arm64에서는 gcc-multilib가 없는 것으로 추측이 되는데 자세한 것은 다음에 추가하도록 하겠다.
docker run --name "your name" -it ubuntu:pwn /usr/bin/zsh
docker start "your name"
docker attach "your name"
TIP
git config --add oh-my-zsh.hide-status 1
git config --add oh-my-zsh.hide-dirty 1
아직 Docker에 대해서 정확하게 알지 못하다보니 용어를 잘못 경우가 있는 것 같다. 만약 문제가 된다면 댓글로 남겨주세요...
수정: 해당 방법으로는 pwndbg가 run이 되지 않는다. disassemble까지는 되지만, ptrce에 대한 오류가 있어 run이 되지 않았다. container를 --privileged로 하면 된다고 하는데 m1은 왜 안 되는건지 모르겠다..
출처
https://fascination-euna.tistory.com/entry/Docker-M1-Mac에-Docker-ubuntu-1804-pwnable-환경-세팅하기
https://goodtogreate.tistory.com/entry/대용량-Git-repo-연동시-zsh-쉘-속도-문제-해결
결국 gdb에서 run이 되지 않는데 지금은 어떤 방식으로 m1에서 디버깅하시나요?