Skip to content

polyverse/ropoly

Repository files navigation

DEPRECATION NOTICE

Please note that this repository has been deprecated and is no longer actively maintained by Polyverse Corporation. It may be removed in the future, but for now remains public for the benefit of any users.

Importantly, as the repository has not been maintained, it may contain unpatched security issues and other critical issues. Use at your own risk.

While it is not maintained, we would graciously consider any pull requests in accordance with our Individual Contributor License Agreement. https://github.com/polyverse/contributor-license-agreement

For any other issues, please feel free to contact [email protected]


Current Status

Build Status

polyverse/ropoly

Run Instructions for Docker

The container must be run with --privileged

Port 8008 must be mapped to a port on the host with -p in order to interact with client.

The Ropoly directory must be mounted so that it can be accessed from within the container.

Example (run from Ropoly directory; this will allow you to build and run Ropoly for Linux): docker run --rm -it -v $PWD:/go/src/github.com/polyverse/ropoly -p 8008:8008 golang bash

Once in the container, navigate to the Ropoly directory and use "go build" to build Ropoly.

After building Ropoly, use "./ropoly server" to start Ropoly as a server.

Please see docs/Process.md for help getting started.

Command Line Options

server

Runs as a server exposing the API described under "Ropoly API Endpoints."

Usage: ropoly server

daemon

Runs as a daemon that repeatedly scans the server's file system and the libraries of its running processes to check for Polyverse signatures.

Usage: ropoly daemon

ROPoly API Endpoints

/api/v1/pids

Return list of all visible process ids and information about each process.

/api/v1/pids/<pid>[?query=<taints|disasm|gadgets|fingerprint>]

Return information about the memory of the given pid according to the option provided in mode. taints by default.

/api/v1/files/<path>[?query=<taints|disasm|gadgets|fingerprint>]

Return information about the files and directories in the given directory on the server according to the option provided in query. Default option is taints.

/api/v1/uploadedfiles/|<path|>[?query=|<taints|disasm|gadgets|fingerprint>]

Post files to this endpoint to add them to a directory for uploaded files. Fails if a file with the given name already exists, unless overwrite is set to true, in which case it will overwrite the old fingerprint. If you put slashes in path, the needed directories will be recursively created. Get returns information about the files in the directory for uploaded files or a specified subdirectory. Behavior is identical to /api/v1/files/path/to/uploaded/file/directory.

To post a file, use curl -X POST -F "file=@<path/to/myfilename>" localhost:8008/api/v1/uploadedfiles/myfilename.

/api/v1/fingerprints

Return the list of fingerprints stored on the server.

/api/v1/fingerprints/{fingerprint}[?overwrite=true]

Return the contents of the fingerprint with the given name. Post fingerprint file as "fingerprint" to add fingerprint with the given name. Fails if fingerprint with given name already exists, unless overwrite is set to true, in which case it will overwrite the old fingerprint.

/api/v1/fingerprints/{fingerprint}/compare?second=_fingerprint

Compares the first given fingerprint to the one provided in second.

/api/v1/fingerprints/{fingerprint}/eqi?second=fingerprint&func=<offsets-intersection|monte-carlo|envisen-original|shared-offsets>

Compares the first given fingerprint to the one provided in second and uses the EQI function specified in func to calculate EQI. More arguments may be required depending on the EQI function.

/api/v1/fingerprints/{fingerprint}/format

Changes the given fingerprint to the standard format for fingerprints (it will be formatted like a fingerprint generated by Ropoly). The fingerprint must already be a valid JSON fingerprint object.

/api/v1/fingerprints/{fingerprint}/gadget-count

Return the number of gadgets in the fingerprint.

/api/v1/fingerprints/{fingerprint}/survival?second=fingerprint

Returns the number of surviving gadgets from the first fingerprint to the second fingerprint and the total number of gadgets in the first fingerprint.

/api/v1/fingerprints/{fingerprint}/killrate?second=fingerprint

Returns the percentage of gadgets from the first fingerprint that do not survive in the second fingerprint.

/api/v1/fingerprints/{fingerprint}/highest-offset-count?second=fingerprint

Returns the highest number of gadgets sharing an offset from the first fingerprint to the second fingerprint and the total number of gadgets in the first fingerprint.

Query options for /api/v1/pid/<pid> and /api/v1/files/<path>

taints

For libraries in memory if looking at a PID or contained files if looking at a directory, check if each is signed by Polyverse.

disasm

Disassemble adjacent instructions between addresses start and end.

gadgets

Find all gadgets up to instructions instructions.

fingerprint

Generate a fingerprint based on all gadgets up to instructions instructions between addresses start and end. The fingerprint's base address is set to base. If out is set to a name, saves under that name. Otherwise, outputs to client. Will fail if fingerprint with the given name already exists, unless overwrite is set to true, in which case it will overwrite the old fingerprint.

EQI options

offsets-intersection

Simulates all attacks of length gadgets. EQI is the percentage of attacks with no common offset.

monte-carlo

Uses a Monte Carlo method to simulate trials attacks of length between min and max gadgets. EQI is the percentage of attacks with no common offset.

envisen-original

Uses the original formula described at https://github.com/polyverse/EnVisen/blob/master/docs/entropy-index.md as of December 17, 2018.

highest-offset-count

The simplest formula. Finds the most common offset among all gadgets, and returns the percentage of gadgets that cannot be found at that offset.

shared-offsets

Calculates EQI by looking at each gadget individually and checking how many gadgets it shares an offset with. Handles the case of multiple offsets based on the argument passed to multiple-handling, with the default being worst-only.

worst-only

When calculating each gadget's contribution to EQI, considers only the offset with the most contribution to EQI (the offset shared with the most other gadgets). The gadget's other offsets are still considered when calculating other gadgets' contribution to EQI.

worst-only-envisen

Same as worst-only, except in the case of that the gadget survives in place, in which case its contribution to EQI is 0. Equivalent to envisen-original if the quality of movement calculation were substituted with shared-offsets&multiple-handling=worst-only applied to the moved gadgets and scaled by the proportion of moved gadgets compared to total gadgets in the original binary.

closest-only

When calculating each gadget's contribution to EQI, considers only the smallest offset. The gadget's other offsets are still considered when calculating other gadgets' contributions to EQI.

multiplicative

For each gadget, starts with a "quality" value of 1, and multiplies it by the complement of the penalty incurred by each offset (normalized to a number between 0 and 1). This causes EQI to decrease asymptotically as each gadget appears at a greater number of offsets.

additive

Adds the penalty for each gadget offset, so that for example a gadget with two offsets each shared with n other gadgets would incur twice the EQI penalty a gadget with a single offset shared with n other gadgets. The same as count-poly with the default order of 2.0 and single=false.

additive-with-ceiling

Adds the penalty for each gadget offset, but caps the contribution of each individual gadget to the EQI at 100 divided by the total number of gadgets.