diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md new file mode 100644 index 000000000..e3be9093e --- /dev/null +++ b/DEVELOPMENT.md @@ -0,0 +1,79 @@ + +# Development + +## How do I contribute new rules? + +Contributing is easy! All of malcontent's rules are in [YARA](https://virustotal.github.io/yara/) format: just throw a new rule into the `rules/` subdirectory and you are ready to go. + +You can verify that your new rule works by running: + +``` +go run ./cmd/mal analyze +``` + +For debugging rules, it's sometimes useful to use the `yara` command: + +``` +yara -s -w rules/combo/dropper/shell.yara +``` + +## Running tests + +```make test``` + +## Writing rule tests + +Not every rule needs a test, but tests do ensure that a rules behavior stays consistent: + +1. Add a sample to https://github.com/chainguard-dev/malcontent-samples +2. Create a directory within `test_data` using the same directory name as your sample: + +``` +mkdir -p test_data/macOS/2024.Rustdoor/ +``` +3. Create an empty file for a specific sample file with the ending name of ".simple": + +``` +touch test_data/macOS/2024.Rustdoor/fakepdf.sh.simple +``` +4. Refresh all the testdata: `make refresh-sample-testdata` + +## Profiling + +`malcontent` can be profiled by running `--profile=true`. This will generate timestamped profiles in an untracked `profiles` directory: + +``` +bash-5.2$ ls -l profiles/ | grep -v "total" | awk '{ print $9 }' +cpu_329605000.pprof +mem_329605000.pprof +trace_329605000.out +``` + +The traces can be inspected via `go tool pprof` and `go tool trace`. + +For example, the memory profile can be inspected by running: + +``` +go tool pprof -http=:8080 profiles/mem_.pprof +``` +## Troubleshooting + +#### Error: ld: library 'yara' not found + +If you get this error at installation: + +``` +ld: library 'yara' not found +``` + +The `yara` C library is required: + +``` +brew install yara || sudo apt install libyara-devel || sudo dnf install yara-devel || sudo pacman -S yara +``` + +Additionally, ensure that Yara's version is `4.3.2`. + +If this version is not available via package managers, manually download the release from [here](https://github.com/VirusTotal/yara/releases) and build it from source by following [these](https://yara.readthedocs.io/en/latest/gettingstarted.html#compiling-and-installing-yara) steps. + +Once Yara is installed, run `sudo ldconfig -v` to ensure that the library is loaded. diff --git a/Makefile b/Makefile index 926cbaa68..c4a2c1750 100644 --- a/Makefile +++ b/Makefile @@ -117,7 +117,7 @@ bench-windows: .PHONY: out/mal out/mal: mkdir -p out - go build -o out/mal . + go build -o out/mal ./cmd/mal .PHONY: update-third-party update-third-party: diff --git a/README.md b/README.md index 690607f94..9e06f87d2 100644 --- a/README.md +++ b/README.md @@ -1,229 +1,93 @@ -# malcontent - -`malcontent` enumerates program capabilities and malicious behaviors using fragment analysis. - -![screenshot](./images/screenshot.png) - -## Features - -- 15,300+ rules that detect everything from `ioctl`s to malware -- Analyzes binaries from any architecture - - `arm64`, `amd64`, `riscv`, `ppc64`, `sparc64` -- CI/CD-friendly -- Diff-friendly output via Markdown, JSON, or YAML -- Integrates [YARA forge](https://yarahq.github.io/) for rules by Avast, Elastic, FireEye, Google, Nextron, and others - - Other [third-party](third_party/README.md) rules are also included -- Support for archives - - `.apk`, `.gem`, `.gz`, `.jar`, `.tar.gz`, `.tar.xz`, `.tar`, `.tgz`, and `.zip` -- Support for OCI images -- Support for scripting languages such as bash, PHP, Perl, Ruby, NodeJS, and Python -- Tuned for especially excellent performance with Linux programs - -## Shortcomings - -- Minimal rule support for Windows and Java (help wanted!) -- Early in development; output is subject to change - -## Requirements - -A container runtime environment such as Podman or Docker, or local developer tools: - -- [go](https://go.dev/) 1.21+ - - Install via the official installer, `goenv`, Homebrew, or a preferred package manager -- [pkg-config](https://www.freedesktop.org/wiki/Software/pkg-config/) - included in many UNIX distributions -- [yara](https://virustotal.github.io/yara/) - -## Installation - -### Containerized - -`docker pull cgr.dev/chainguard/malcontent:latest` - -### Local - -Install YARA (dependency): - -```shell -brew install yara || sudo apt install libyara-dev \ - || sudo dnf install yara-devel || sudo pacman -S yara ``` - -Install `malcontent`: - -```shell -go install github.com/chainguard-dev/malcontent@latest + _ _ _. . _ _ _ . ___ _. _ . ___ + ( | ) (_| |_ (_ (_) ( \_) | (/_ ( \_) | + + overtly paranoid open-source malware scanner ``` -## Usage +malcontent is a malware scanner and analysis tool for high-risk environments such as CI/CD pipelines. It's goal is to reveal hitherto undiscovered malware, so it is overtly paranoid and highly prone to false positives. -To inspect a binary, pass it as an argument to dump a list of predicted capabilities: +malcontent offers 3 modes of operation depending on your use case: -```shell -mal /bin/ping -``` +* `analyze`: deep analysis of a programs capabilities +* `diff`: show the capability differences between two versions of a program +* `scan`: basic malware scanner -There are flags for controlling output (see the Usage section) and filtering out rules. Here's the `--format=markdown` output: -| RISK | KEY | DESCRIPTION | EVIDENCE | -|--------|-----------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| MEDIUM | [combo/net/scan_tool](https://github.com/chainguard-dev/malcontent/blob/main/rules/combo/net/scan_tool.yara#generic_scan_tool) | may scan networks | [connect](https://github.com/search?q=connect&type=code)
[gethostbyname](https://github.com/search?q=gethostbyname&type=code)
[port](https://github.com/search?q=port&type=code)
[scan](https://github.com/search?q=scan&type=code)
[socket](https://github.com/search?q=socket&type=code) | -| MEDIUM | [net/interface/list](https://github.com/chainguard-dev/malcontent/blob/main/rules/net/interface-list.yara#bsd_ifaddrs) | list network interfaces | [freeifaddrs](https://github.com/search?q=freeifaddrs&type=code)
[getifaddrs](https://github.com/search?q=getifaddrs&type=code) | -| MEDIUM | [net/ip/string](https://github.com/chainguard-dev/malcontent/blob/main/rules/net/ip-string.yara#inet_ntoa) | [converts IP address from byte to string](https://linux.die.net/man/3/inet_ntoa) | [inet_ntoa](https://github.com/search?q=inet_ntoa&type=code) | -| MEDIUM | [net/socket/connect](https://github.com/chainguard-dev/malcontent/blob/main/rules/net/socket-connect.yara#_connect) | [initiate a connection on a socket](https://linux.die.net/man/3/connect) | [\_connect](https://github.com/search?q=_connect&type=code) | -| LOW | [net/hostname/resolve](https://github.com/chainguard-dev/malcontent/blob/main/rules/net/hostname-resolve.yara#gethostbyname2) | [resolve network host name to IP address](https://linux.die.net/man/3/gethostbyname2) | [gethostbyname2](https://github.com/search?q=gethostbyname2&type=code) | -| LOW | [net/icmp](https://github.com/chainguard-dev/malcontent/blob/main/rules/net/icmp.yara#icmp) | [ICMP (Internet Control Message Protocol), aka ping](https://en.wikipedia.org/wiki/Internet_Control_Message_Protocol) | [ICMP](https://github.com/search?q=ICMP&type=code) | -| LOW | [net/interface/get](https://github.com/chainguard-dev/malcontent/blob/main/rules/net/interface-get.yara#bsd_if) | get network interfaces by name or index | [if_nametoindex](https://github.com/search?q=if_nametoindex&type=code) | -| LOW | [net/ip](https://github.com/chainguard-dev/malcontent/blob/main/rules/net/ip.yara#packets) | access the internet | [invalid packet](https://github.com/search?q=invalid+packet&type=code) | -| LOW | [net/ip/multicast/send](https://github.com/chainguard-dev/malcontent/blob/main/rules/net/ip-multicast-send.yara#multicast) | [send data to multiple nodes simultaneously](https://en.wikipedia.org/wiki/IP_multicast) | [multicast](https://github.com/search?q=multicast&type=code) | -| LOW | [net/ip/resolve](https://github.com/chainguard-dev/malcontent/blob/main/rules/net/ip-resolve.yara#gethostbyaddr) | [resolves network hosts via IP address](https://linux.die.net/man/3/gethostbyaddr) | [gethostbyaddr](https://github.com/search?q=gethostbyaddr&type=code) | -| LOW | [net/ip/send/unicast](https://github.com/chainguard-dev/malcontent/blob/main/rules/net/ip-send-unicast.yara#unicast) | send data to the internet | [unicast](https://github.com/search?q=unicast&type=code) | -| LOW | [net/socket/receive](https://github.com/chainguard-dev/malcontent/blob/main/rules/net/socket-receive.yara#recvmsg) | [receive a message from a socket](https://linux.die.net/man/2/recvmsg) | [recvmsg](https://github.com/search?q=recvmsg&type=code) | -| LOW | [net/socket/send](https://github.com/chainguard-dev/malcontent/blob/main/rules/net/socket-send.yara#sendmsg) | [send a message to a socket](https://linux.die.net/man/2/sendmsg) | [\_send](https://github.com/search?q=_send&type=code)
[sendmsg](https://github.com/search?q=sendmsg&type=code)
[sendto](https://github.com/search?q=sendto&type=code) | -| LOW | [process/userid/set](https://github.com/chainguard-dev/malcontent/blob/main/rules/process/userid-set.yara#setuid) | [set real and effective user ID of current process](https://man7.org/linux/man-pages/man2/setuid.2.html) | [setuid](https://github.com/search?q=setuid&type=code) | - -To only show output for the most suspicious behaviors, use `--min-risk=high`, which shows only "HIGH" or "CRITICAL" behaviors. - -## Diff mode to detect supply-chain attacks - -Let's say you are a company that is sensitive to supply-chain compromises. You want to make sure an update doesn't introduce unexpected capability changes. There's a `--diff` mode for that: +*WARNING: This tool is in early development and raises more false-positives than even we would like. We're working on it :)* -```shell -mal diff old_ffmpeg.dylib new_ffmpeg.dylib -``` - -Here is a result using the 3CX compromise as a test case. Each of the lines that beginsl with a "+" represent a newly added capability. - -## Changed: . [⚠️ MEDIUM → 🚨 CRITICAL] - -### 20 new behaviors - -| RISK | KEY | DESCRIPTION | EVIDENCE | -| --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| +CRITICAL | **[3P/signature_base/3cxdesktopapp/backdoor](https://github.com/Neo23x0/signature-base/blob/1b9069ac3d8d5b6dd2b61d3c934bf19b70323011/yara/gen_mal_3cx_compromise_mar23.yar#L251-L275)** | [Detects 3CXDesktopApp MacOS Backdoor component](https://www.volexity.com/blog/2023/03/30/3cx-supply-chain-compromise-leads-to-iconic-incident/), by X\_\_Junior (Nextron Systems) | $op1
$op2
[%s/.main_storage](https://github.com/search?q=%25s%2F.main_storage&type=code)
[%s/UpdateAgent](https://github.com/search?q=%25s%2FUpdateAgent&type=code) | -| +CRITICAL | **[3P/signature_base/nk/3cx](https://github.com/Neo23x0/signature-base/blob/1b9069ac3d8d5b6dd2b61d3c934bf19b70323011/yara/gen_mal_3cx_compromise_mar23.yar#L188-L214)** | [Detects malicious DYLIB files related to 3CX compromise](https://www.sentinelone.com/blog/smoothoperator-ongoing-campaign-trojanizes-3cx-software-in-software-supply-chain-attack/), by Florian Roth (Nextron Systems) | $xc1
$xc2
$xc3 | -| +CRITICAL | **[3P/signature_base/susp/xored](https://github.com/Neo23x0/signature-base/blob/1b9069ac3d8d5b6dd2b61d3c934bf19b70323011/yara/gen_xor_hunting.yar#L2-L20)** | [Detects suspicious single byte XORed keyword 'Mozilla/5.0' - it uses yara's XOR modifier and therefore cannot print the XOR key](), by Florian Roth | $xo1 | -| +CRITICAL | **[3P/volexity/iconic](https://github.com/volexity/threat-intel/blob/62e031ea574efde68dac7d38dc23438466a5302b/2023/2023-03-30%203CX/indicators/rules.yar#L32-L50)** | [Detects the MACOS version of the ICONIC loader.](https://www.reddit.com/r/crowdstrike/comments/125r3uu/20230329_situational_awareness_crowdstrike/), by | $str1
$str2
$str3 | -| +CRITICAL | **[evasion/xor/user_agent](https://github.com/chainguard-dev/malcontent/blob/main/rules/evasion/xor-user_agent.yara#xor_mozilla)** | XOR'ed user agent, often found in backdoors, by Florian Roth | $Mozilla_5_0 | -| +MEDIUM | **[exec/pipe](https://github.com/chainguard-dev/malcontent/blob/main/rules/exec/pipe.yara#popen)** | [launches program and reads its output](https://linux.die.net/man/3/popen) | [\_pclose](https://github.com/search?q=_pclose&type=code)
[\_popen](https://github.com/search?q=_popen&type=code) | -| +MEDIUM | **[fs/permission/modify](https://github.com/chainguard-dev/malcontent/blob/main/rules/fs/permission-modify.yara#chmod)** | [modifies file permissions](https://linux.die.net/man/1/chmod) | [chmod](https://github.com/search?q=chmod&type=code) | -| +MEDIUM | **[net/http/cookies](https://github.com/chainguard-dev/malcontent/blob/main/rules/net/http-cookies.yara#http_cookie)** | [access HTTP resources using cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies) | [Cookie](https://github.com/search?q=Cookie&type=code)
[HTTP](https://github.com/search?q=HTTP&type=code) | -| +MEDIUM | **[net/url/request](https://github.com/chainguard-dev/malcontent/blob/main/rules/net/url-request.yara#requests_urls)** | requests resources via URL | [NSMutableURLRequest](https://github.com/search?q=NSMutableURLRequest&type=code) | -| +MEDIUM | **[ref/path/hidden](https://github.com/chainguard-dev/malcontent/blob/main/rules/ref/path/hidden.yara#dynamic_hidden_path)** | [hidden path generated dynamically](https://objective-see.org/blog/blog_0x73.html) | [%s/.main_storage](https://github.com/search?q=%25s%2F.main_storage&type=code) | -| +MEDIUM | **[shell/arbitrary_command/dev_null](https://github.com/chainguard-dev/malcontent/blob/main/rules/shell/arbitrary_command-dev_null.yara#cmd_dev_null)** | runs commands, discards output | ["%s" >/dev/null](https://github.com/search?q=%22%25s%22+%3E%2Fdev%2Fnull&type=code) | -| +LOW | **[compression/gzip](https://github.com/chainguard-dev/malcontent/blob/main/rules/compression/gzip.yara#gzip)** | [works with gzip files](https://www.gnu.org/software/gzip/) | [gzip](https://github.com/search?q=gzip&type=code) | -| +LOW | **[env/HOME](https://github.com/chainguard-dev/malcontent/blob/main/rules/env/HOME.yara#HOME)** | [Looks up the HOME directory for the current user](https://man.openbsd.org/login.1#ENVIRONMENT) | [HOME](https://github.com/search?q=HOME&type=code)
[getenv](https://github.com/search?q=getenv&type=code) | -| +LOW | **[fs/lock/update](https://github.com/chainguard-dev/malcontent/blob/main/rules/fs/lock-update.yara#flock)** | apply or remove an advisory lock on a file | [flock](https://github.com/search?q=flock&type=code) | -| +LOW | **[kernel/dispatch/semaphore](https://github.com/chainguard-dev/malcontent/blob/main/rules/kernel/dispatch-semaphore.yara#dispatch_sem)** | [Uses Dispatch Semaphores](https://developer.apple.com/documentation/dispatch/dispatch_semaphore) | [dispatch_semaphore_signal](https://github.com/search?q=dispatch_semaphore_signal&type=code) | -| +LOW | **[kernel/hostname/get](https://github.com/chainguard-dev/malcontent/blob/main/rules/kernel/hostname-get.yara#gethostname)** | [get computer host name](https://man7.org/linux/man-pages/man2/sethostname.2.html) | [gethostname](https://github.com/search?q=gethostname&type=code) | -| +LOW | **[net/http/accept/encoding](https://github.com/chainguard-dev/malcontent/blob/main/rules/net/http-accept-encoding.yara#content_type)** | [set HTTP response encoding format (example: gzip)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding) | [Accept-Encoding](https://github.com/search?q=Accept-Encoding&type=code) | -| +LOW | **[random/insecure](https://github.com/chainguard-dev/malcontent/blob/main/rules/random/insecure.yara#bsd_rand)** | [generate random numbers insecurely](https://man.openbsd.org/rand) | [\_rand](https://github.com/search?q=_rand&type=code)
[srand](https://github.com/search?q=srand&type=code) | -| +LOW | **[ref/path/home_library](https://github.com/chainguard-dev/malcontent/blob/main/rules/ref/path/home_library.yara#home_lib_path)** | path reference within ~/Library | [/System/Library/Frameworks/CoreFoundation](https://github.com/search?q=%2FSystem%2FLibrary%2FFrameworks%2FCoreFoundation&type=code)
[/System/Library/Frameworks/Foundation](https://github.com/search?q=%2FSystem%2FLibrary%2FFrameworks%2FFoundation&type=code) | -| +LOW | **[sync/semaphore/user](https://github.com/chainguard-dev/malcontent/blob/main/rules/sync/semaphore-user.yara#semaphore_user)** | uses semaphores to synchronize data between processes or threads | [semaphore_create](https://github.com/search?q=semaphore_create&type=code)
[semaphore_signal](https://github.com/search?q=semaphore_signal&type=code)
[semaphore_wait](https://github.com/search?q=semaphore_wait&type=code) | - -If you like to do things the hard way, you can also generate your own diff using JSON keys. - -```shell -mal --format=json analyze | jq '.Files.[].Behaviors | keys' -``` - -## Supported Flags - -- `--all`: ignore nothing, show all -- `--data-files`: include files that are detected to as non-program (binary or source) files -- `--diff`: show capability drift between two files -- `--format` string: Output type. Valid values are: json, markdown, simple, terminal, yaml (default "terminal") -- `--ignore-self`: ignore the `malcontent` binary -- `--ignore-tags` string: Rule tags to ignore -- `--min-file-risk` - Only show results for files that meet this risk level (any,low,medium,high,critical) -- `--min-risk`: minimum suspicion level to report (any,low,medium,high,critical) -- `--oci`: scan OCI images -- `--omit-empty`: omit files that contain no matches -- `--profile`: capture profiling/tracing information for `malcontent` -- `--stats`: display statistics for risk level and `programkind` -- `--third-party`: include third-party rules, which may have licensing restrictions (default true) -- `--verbose`: turn on verbose output for diagnostic/troubleshooting purposes - -## Samples - -`malcontent` samples are stored in the `malcontent-samples` repository [here](https://github.com/chainguard-dev/malcontent-samples) due to the size of the samples. While the samples were originally stored in this repository, size became a concern and polluted the Git history making the repository difficult to pull. - -The new repository is cloned when running `make test` and the contents of `test_data` are copied into the resulting `samples` directory. This allows for the tests to run as usual. To update sample test data, `make refresh-sample-testdata` will now write updated test data content to the files in `test_data` which can be committed. - -## FAQ - -### How does it work? - -`malcontent` behaves similarly to the initial triage step most security analysts use when faced with an unknown binary: a cursory `strings` inspection. `malcontent` has several advantages over human analysis: -- the ability to match raw byte sequences -- the ability to decrypt data -- a library of 14,500+ YARA rules from experienced security engineers worldwide +## Features -This strategy works, as every program leaves traces of its capabilities in its contents, particularly on UNIX platforms. These fragments are typically `libc` or `syscall` references or error codes. Scripting languages are easier to analyze due to their cleartext nature and are also supported. +- 15,300+ open-source YARA rules +- Analyzes binaries from almost any architecture (arm64, amd64, riscv, ppc64, sparc64), format (ELF, machO, PE), +- Analyzes programs for almost any operating system (Linux, macOS, OpenBSD, FreeBSD, Solaris, Windows) +- Analyzes scripts in almost any language (PERL, Python, shell, Javascript, Typescript, PHP) +- Transparent archive support (`.apk`, `.gem`, `.gz`, `.jar`, `.tar.gz`, `.tar.xz`, `.tar`, `.tgz`, and `.zip`) and OCI archives +- Multiple output formats (JSON, YAML, Markdown, Terminal) +- Includes 3rd party YARA rules from esteemed organizations such as Avast, Elastic, FireEye, Google, JP-CERT, Nextron, and others -### Why not properly reverse-engineer binaries? +## Modes -Mostly because fragment analysis is so effective. Capability analysis through reverse engineering is challenging to get right, particularly for programs that execute other programs, such as malware that executes `/bin/rm`. Capability analysis through reverse engineering that supports a wide array of file formats also requires significant engineering investment. +### Analyze -### Why not just observe binaries in a sandbox? +To analyze a program, pass the path as an argument to `mal analyze`. For example: -The most exciting malware only triggers when the right conditions are met. Nation-state actors, in particular, are fond of time bombs and locale detection. `malcontent` will enumerate the capabilities, regardless of conditions. +![analyze screenshot](./images/analyze.png) -### Why not just analyze the source code? +The analyze mode emits a list of capabilities that are often seen in malware, categorized by risk level. In general, `CRITICAL` findings should be considered malicious. -Sometimes you don't have it! Sometimes your CI/CD infrastructure is the source of compromise. Source-code-based capability analysis is also complicated for polyglot programs, or programs that execute external binaries, such as `/bin/rm`. +### Diff -### How does malcontent work for packed binaries (UPX)? +To detect unexpected capability changes, we have a `diff` mode. Using the [3CX Compromise](https://www.fortinet.com/blog/threat-research/3cx-desktop-app-compromised) as an example: -`malcontent` alerts when an obfuscated or packed binary is detected, such as those generated by [upx](https://github.com/upx/upx). Fragment analysis may still work to a lesser degree. For the full story, we recommend unpacking binaries first. +![diff screenshot](./images/diff.png) -### What related software is out there? +Each of the lines that beginsl with a "+" represent a newly added capability. For use in CI/CD pipelines, you may find the following flags useful: -`malcontent` was initially inspired by [mandiant/capa](https://github.com/mandiant/capa). While `capa` is a fantastic tool, it only works on x86-64 binaries (ELF/PE), and does not work for macOS programs, arm64 binaries, or scripting languages. and offer capability analysis through reverse engineering as a service. If you require more than what malcontent can offer, such as Windows binary analysis, you should check them out. +It's worth noting that none of the "CRITICAL" findings, except for the `evasnion/xor/user_agent`, would have been found pre-3CX compromise. The diff mode is designed to surface subtle unexpected changes that you might not have an explatanion for, such as "why does `libffmpeg.dylib` need access to `chown`? -### How can I help? +* `--format=markdown`: output in markdown for use in GitHub Actions +* `--min-file-risk=critical`: only show diffs for critical-level changes +* `--quantity-increases-risk=false`: disable the heuristics that increase file criticality due to result frequency -If you find malware that `malcontent` doesn't surface suspicious behaviors for, send us a patch! All of the rules are defined in YARA format, and can be found in the `rules/` folder. +### Scan -### Verifying commits and tags +![scan screenshot](./images/scan.png) -In addition to contributed code, automated PRs and commits can be verified by following [these](https://github.com/sigstore/gitsign?tab=readme-ov-file#verifying-commits) steps. +Like other commands, you can even point this tool at a container image: `mal scan --i cgr.dev/chainguard/nginx` -### Troubleshooting +Useful flags: -#### Profiling +* `--include-data-files`: Include files that are detected as non-program (binary or source) files -`malcontent` can be profiled by running `--profile=true`. This will generate timestamped profiles in an untracked `profiles` directory: +## Installation -``` -bash-5.2$ ls -l profiles/ | grep -v "total" | awk '{ print $9 }' -cpu_329605000.pprof -mem_329605000.pprof -trace_329605000.out -``` +### Container -The traces can be inspected via `go tool pprof` and `go tool trace`. +`docker pull cgr.dev/chainguard/malcontent:latest` -For example, the memory profile can be inspected by running: +### Local -``` -go tool pprof -http=:8080 profiles/mem_.pprof -``` +Requirements: -#### Error: ld: library 'yara' not found +- [go](https://go.dev/) - the programming language +- [pkg-config](https://www.freedesktop.org/wiki/Software/pkg-config/) - for dependency handling, included in many UNIX distributions +- [yara](https://virustotal.github.io/yara/) - the rule language -If you get this error at installation: +For example, to install the YARA library on Linux or macOS: -``` -ld: library 'yara' not found +```shell +brew install yara || sudo apt install libyara-dev \ + || sudo dnf install yara-devel || sudo pacman -S yara ``` -The `yara` C library is required: +Install malcontent: -``` -brew install yara || sudo apt install libyara-devel || sudo dnf install yara-devel || sudo pacman -S yara +```shell +go install github.com/chainguard-dev/malcontent/cmd/mal@latest ``` -Additionally, ensure that Yara's version is `4.3.2`. +## Help Wanted -If this version is not available via package managers, manually download the release from [here](https://github.com/VirusTotal/yara/releases) and build it from source by following [these](https://yara.readthedocs.io/en/latest/gettingstarted.html#compiling-and-installing-yara) steps. +![help wanted sign](./images/wanted.jpg) -Once Yara is installed, run `sudo ldconfig -v` to ensure that the library is loaded. +malcontent is an honest-to-goodness open-source project: if you are interested in contributing, check out [DEVELOPMENT.md](DEVELOPMENT.md) \ No newline at end of file diff --git a/malcontent.go b/cmd/mal/mal.go similarity index 100% rename from malcontent.go rename to cmd/mal/mal.go diff --git a/images/analyze.png b/images/analyze.png new file mode 100644 index 000000000..bf8b74bab Binary files /dev/null and b/images/analyze.png differ diff --git a/images/diff.png b/images/diff.png new file mode 100644 index 000000000..2cbdee4a3 Binary files /dev/null and b/images/diff.png differ diff --git a/images/scan.png b/images/scan.png new file mode 100644 index 000000000..b13f04d6e Binary files /dev/null and b/images/scan.png differ diff --git a/images/screenshot.png b/images/screenshot.png deleted file mode 100644 index e7069ab1a..000000000 Binary files a/images/screenshot.png and /dev/null differ diff --git a/images/wanted.jpg b/images/wanted.jpg new file mode 100644 index 000000000..011d62c8a Binary files /dev/null and b/images/wanted.jpg differ