rapid7 / metasploit-framework

Metasploit Framework
https://www.metasploit.com/
Other
34.1k stars 13.96k forks source link

Docker metasploit does not run on ARM processors #18588

Closed MikeAnast closed 10 months ago

MikeAnast commented 11 months ago

It seems that docker image of the metasploit framework does work on ARM processors .

To reproduce it:

  1. Pull the latest docker image from docker hub.
  2. Run the command
    docker run -it --rm  metasploitframework/metasploit-framework /bin/bash -c "./msfconsole -x 'show exploits;exit'"
  3. The error below is observed: image
adfoster-r7 commented 11 months ago

Does this build script work for you? It will create a new docker image:

./docker/bin/msfconsole --rebuild

And running:

./docker/bin/msfconsole
MikeAnast commented 11 months ago

hi, thanks for your reply. I have the following error when i am trying to build the new image: image

There is a problem with the mingw-w64-gcc package.

The same error exists when I try to build the image from the Dockerfile: image

adfoster-r7 commented 11 months ago

Interesting! I believe we only require mingw in Docker for compiling the the runtime payloads that are generated by some of our dynamic encryption modules:

https://github.com/rapid7/metasploit-framework/blob/15bf3cb4728fec91fa8915b61fd57f6e03a4def5/modules/payloads/stagers/windows/x64/encrypted_reverse_tcp.rb#L30

So I'm thinking it could be conditionally skipped at build time for the docker ARM env for now

MikeAnast commented 11 months ago

I deleted the package mingw-w64-gcc from the Dockerfile. Now there is an issue on impacket library on alpine linux images, not sure why: image

I try to solve this by using libraries (added on Dockerfile) suggested in posts like the following: https://stackoverflow.com/questions/71372066/docker-fails-to-install-cffi-with-python3-9-alpine-in-dockerfile

I think if I manage to solve this error, the image will build successfully.

adfoster-r7 commented 11 months ago

Looks like adding libffi might work; Also potentially pulling in a newer base alpine image like in - https://github.com/rapid7/metasploit-framework/pull/18570

MikeAnast commented 11 months ago

Managed to build the arm docker image ! Can i create a pull request with a new dockerfile named Dockerfile.arm ?

adfoster-r7 commented 11 months ago

Awesome! Instead of creating a new file, I wonder if it's possible to keep having a single Dockerfile, and conditionally compile the ARM vs Intel dependencies instead? 🤔

I believe it's possible to do via this approach https://www.docker.com/blog/faster-multi-platform-builds-dockerfile-cross-compilation-guide/

MikeAnast commented 11 months ago

Your suggestion is very nice ! i managed to create a single multi-stage Dockerfile. I used a build argument named architecture on which i define the platform architecture. On the Dockerfile i use the following stages (see the pics) image image image

So, by using the below command, I successfully built and ran Metasploit for both AMD and ARM architectures.

docker build -f Dockerfile.t --build-arg architecture=amd64 -t metasploit_amd .
docker build -f Dockerfile.t --build-arg architecture=arm64 -t metasploit_arm .

I tried to use the built-in variable named TARGETPLATFORM, as the attached blog suggests, but for some reason, I couldn't make it work (Maybe this is a fault of my Docker Engine version, the value of this always empty)

Of courses this needs to be tested more! Let me know your thoughts on that

adfoster-r7 commented 11 months ago

I tried to use the built-in variable named TARGETPLATFORM, as the attached blog suggests, but for some reason, I couldn't make it work

I took a quick look, and I think you can't use docker build, you need to use docker buildx instead. Does that work for you? 👀

From the original post, it looks like they'll change the behavior of docker build in the future - but for now docker buildx should be used:

In order to build multi-platform container images, we will use the docker buildxcommand. Buildx is a Docker component that enables many powerful build features with a familiar Docker user experience. All builds executed via buildx run with Moby Buildkit builder engine. Buildx can also be used standalone or, for example, to run builds in a Kubernetes cluster. In the next version of Docker CLI, the docker buildcommand will also start to use Buildx by default.

MikeAnast commented 11 months ago

Indeed, on the previous comment's commands i didn't used the buildx command. I tried to build the below Dockerfile but it didn't work for some reason.

FROM ubuntu:latest AS base
RUN echo "architecture is equal to ${TARGETPLATFORM}"

If you build it with the following command, it should echo the defined architecture:

docker buildx build --platform=linux/arm64 .

but not in my case.

adfoster-r7 commented 11 months ago

How about with adding ARG explicitly, as well as writing to a temporary file just to test the result:

FROM ubuntu:latest AS base
ARG TARGETPLATFORM
RUN echo "architecture is equal to ${TARGETPLATFORM}" >> platform.txt

For my env I built the docker image with buildx, and for some reason for my env I needed to export to docker:

docker buildx build --platform=linux/arm64 --output type=docker --tag build_test:latest .

And then ran it locally to verify the file contents that I generated were as I expected:

$ docker run -it build_test:latest /bin/sh
# cat platform.txt
architecture is equal to linux/arm64
MikeAnast commented 11 months ago

what about the following Dockerfile

ARG architecture
FROM ubuntu:latest AS base
ARG TARGETPLATFORM

FROM base AS branch-version-arm64
RUN echo "this is the stage that sets ${TARGETPLATFORM}"

FROM base AS branch-version-amd64
RUN echo "this is the stage that sets ${TARGETPLATFORM}"

FROM branch-version-${architecture} AS final
RUN echo "PLATFORM is ${TARGETPLATFORM}"

and build it with the following command

docker buildx build --platform=linux/arm64 --build-arg architecture=arm64 --output type=docker --tag build_test:latest .

my main problem is on line FROM branch-version-${architecture} AS final i could use ${TARGETPLAFORM} but because the value is linux/arm64 and have the / i have an error because it cant contain that symbol.

If somehow we can parse that then we can remove completely the architecture variable from the build.

adfoster-r7 commented 11 months ago

Hm! If you want to put up a PR for whatever you think is the easiest approach for building both the new ARM setup and old setup - we could get that landed and available for users on Dockerhub first, and then we could look at consolidating the improving/codegolfing the setup afterwards :+1:

adfoster-r7 commented 10 months ago

Will mark this as closed now, thanks for the contribution! :+1: