diff --git a/README.md b/README.md index 39ff250..2b7f61b 100644 --- a/README.md +++ b/README.md @@ -34,10 +34,11 @@ With the input streams, mitigations, and vulnerabilities for the executable to e 1. Ensure you have Docker installed. 2. Install the required Python 3 packages via `poetry install --no-dev`. 3. Build the Docker image: `docker build --tag zeratool_lib -f docker/Dockerfile.zeratool_lib .`. -4. Ensure the Docker API is accessible by: +4. Add `zeratool_lib` to PYTHONPATH: `export PYTHONPATH=/path/to/repo/docker/zeratool_lib/zeratool_lib`. +5. Ensure the Docker API is accessible by: - Running the module as `root`; or - Changing the Docker socket permissions (unsecure approach) via `chmod 777 /var/run/docker.sock`. -5. Build the arguments' adapter via `cd others/argv_adapter && make`. +6. Build the arguments' adapter via `cd others/argv_adapter && make`. ## Development diff --git a/automatic_exploit_generation/cli.py b/automatic_exploit_generation/cli.py index 2c758df..f32e9cb 100644 --- a/automatic_exploit_generation/cli.py +++ b/automatic_exploit_generation/cli.py @@ -74,13 +74,9 @@ def exploit( if generated_exploit: print( "The exploiter could generate an exploit with the outcome of" - f" {generated_exploit.outcome.name} and the following payloads:" + f" {generated_exploit.outcome.name} and the following payloads:\n" ) - - for payload in generated_exploit.payloads: - print(f"- For {payload.input_stream.name}:\n") - hexdump.hexdump(payload.content) - print("") + hexdump.hexdump(generated_exploit.payload) else: print("The exploiter coudn't generate any exploit.") diff --git a/automatic_exploit_generation/exploiters/zeratool/zeratool.py b/automatic_exploit_generation/exploiters/zeratool/zeratool.py index a1c5e22..b08939e 100644 --- a/automatic_exploit_generation/exploiters/zeratool/zeratool.py +++ b/automatic_exploit_generation/exploiters/zeratool/zeratool.py @@ -12,6 +12,7 @@ exploit_pb2, exploit_pb2_grpc, ) + from commons.exploit import Exploit from commons.input_streams import InputStreams from commons.mitigations import Mitigations @@ -22,7 +23,7 @@ get_sensitive_functions_names, ) from commons.weaknesses import Weaknesses - +from time import sleep def _is_sublist_of_list(needle: list, stack: list) -> bool: return set(needle).issubset(set(stack)) @@ -69,16 +70,16 @@ def _run_exploitation_in_container( container = client.containers.run( Configuration.ZERATOOL_IMAGE_NAME, detach=True, - tty=True, + auto_remove=True, ports={"13000/tcp": 13000}, publish_all_ports=True, ) - container_ip = container.attrs["NetworkSettings"]["IPAddress"] + container_ip = '0.0.0.0' + sleep(3) exploit = self._request_exploitation_to_grpc_service( container_ip, overflow_only, format_only, win_funcs ) - - container.remove(force=True) + container.kill() return exploit diff --git a/docker/Dockerfile.zeratool_lib b/docker/Dockerfile.zeratool_lib index 941a09b..e768450 100644 --- a/docker/Dockerfile.zeratool_lib +++ b/docker/Dockerfile.zeratool_lib @@ -1,15 +1,15 @@ -FROM python:3.10 +FROM python:3.11 # Install and configure Poetry RUN pip3 install poetry # Setup the convertor from pyproject.toml to requirements.txt -RUN pip3 install click toml +RUN pip3 install click toml tomli RUN wget https://raw.githubusercontent.com/jla524/requirements/main/requirements/convert.py -O /convert.py # Convert Zeratool's dependencies COPY /docker/zeratool_lib /zeratool_lib -RUN python3 /convert.py --noversion /zeratool_lib +RUN python3 /convert.py --no-version /zeratool_lib RUN mv /zeratool_lib/requirements.txt /requirements.zeratool_lib.txt # Copies service's dependencies @@ -17,9 +17,12 @@ COPY /docker/requirements.txt /requirements.service.txt # Convert module's dependencies COPY /pyproject.toml /pyproject.toml -RUN python3 /convert.py --noversion / +RUN python3 /convert.py --no-version / RUN mv /requirements.txt /requirements.aeg.txt +# Download the commons library +RUN git clone https://github.com/CyberReasoningSystem/commons /commons + # Install all dependencies RUN pip3 install -r /requirements.service.txt RUN pip3 install -r /requirements.aeg.txt @@ -30,8 +33,15 @@ COPY /automatic_exploit_generation /automatic_exploit_generation COPY /docker/protobuf /protobuf COPY /docker/zeratool_lib_service.py /zeratool_lib_service.py -# Download the commons library -RUN git clone https://github.com/CyberReasoningSystem/commons /commons +# Install Radare2 +RUN set -xe; \ + wget https://github.com/radareorg/radare2/releases/download/5.9.0/radare2_5.9.0_amd64.deb; \ + dpkg -i radare2_5.9.0_amd64.deb; \ + rm radare2_5.9.0_amd64.deb \ + ; + +# Install 32-bit libc +RUN apt-get update && apt-get -y install libc6-i386 # Set PYTHONPATH ENV PYTHONPATH=/zeratool_lib/zeratool_lib:/protobuf:/automatic_exploit_generation:/commons @@ -41,3 +51,4 @@ EXPOSE 13000 # Run the service CMD ["python3", "/zeratool_lib_service.py"] + diff --git a/docker/zeratool_lib_service.py b/docker/zeratool_lib_service.py index 75445b3..41685e8 100644 --- a/docker/zeratool_lib_service.py +++ b/docker/zeratool_lib_service.py @@ -15,35 +15,49 @@ YEAR_IN_SECONDS = 365 * 60 * 60 * 24 -def _create_temp_binary(content: bytes) -> tempfile.TemporaryFile: - binary = tempfile.TemporaryFile() - - binary.write(content) - binary.flush() - - os.chmod(binary.name, stat.S_IXUSR) - - return binary +def _create_temp_binary(content: bytes) -> str: + binary = tempfile.NamedTemporaryFile(delete=False) + try: + binary.write(content) + binary.flush() + path = binary.name + finally: + binary.close() + os.chmod(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) + return path class EService(exploit_pb2_grpc.ExploitServiceServicer): def Exploit(self, request, _): - temp_file = _create_temp_binary(request.binary) - - input_stream = ZeratoolInputStreams(request.input_stream) - overflow_only = request.overflow_only - format_only = request.format_only - win_funcs_used = request.serialized_win_funcs.split(",") - - result = exploit( - temp_file.name, - input_stream, - overflow_only=overflow_only, - format_only=format_only, - win_funcs=win_funcs_used, - ) - - return exploit_pb2.exploit(pickledExploit=pickle.dumps(result)) + temp_path = _create_temp_binary(request.binary) + try: + input_stream = ZeratoolInputStreams(request.input_stream) + overflow_only = request.overflow_only + format_only = request.format_only + win_funcs_used = request.serialized_win_funcs.split(",") + if len(win_funcs_used) == 1 and win_funcs_used[0] == '': + win_funcs_used = None + + print("temp_path: ", temp_path) + print("overflow_only: ", overflow_only) + print("format_only: ", format_only) + print("win_funcs_used: ", win_funcs_used) + + result = exploit( + temp_path, + input_stream, + overflow_only=overflow_only, + format_only=format_only, + win_funcs=win_funcs_used, + ) + + return exploit_pb2.exploit(pickledExploit=pickle.dumps(result)) + finally: + if os.path.exists(temp_path): + try: + os.unlink(temp_path) + except OSError: + pass def serve() -> None: diff --git a/pyproject.toml b/pyproject.toml index 55ca965..2d81c7d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,8 +15,15 @@ grpcio = "^1.54.2" protobuf = "^4.23.2" click = "^8.1.3" hexdump = "^3.3" +requests = "<2.32" +angr = "^9.2.52" +claripy = "^9.2.52" +ipython = "^8.13.2" +r2pipe = "^1.8.0" +timeout-decorator = "^0.5.0" +tqdm = "^4.65.0" commons = {path = "../commons"} -zeratool_lib = {path = "../zeratool_lib"} +zeratool_lib = {path = "../zeratool_lib", develop = true} [tool.poetry.dev-dependencies] black = "^22.6.0"