mythicagents / merlin Goto Github PK
View Code? Open in Web Editor NEWCross-platform post-exploitation HTTP Command & Control agent written in golang
License: GNU General Public License v3.0
Cross-platform post-exploitation HTTP Command & Control agent written in golang
License: GNU General Public License v3.0
Hello,
Merlin shared payload for Linux X64 compiled with default settings in Mythic and uses http profile.
Payload .so loaded on Ubuntu 22.04 (x64) with following command:
LD_PRELOAD=/tmp/merlin /usr/bin/whoami
After that, new callback successfully received by Mythic.
Now starts the weird part.
Running shell commands "shell pwd" with Merlin .so payload do not show any output.
While running native commands "pwd", etc generates correct output.
Any ideas/suggestions/hints on how to get output of "shell" commands?
p.s. we use latest versions of mythic, profiles and agents.
When the Merlin agent is built for use with Mythic, it will include the "standard" HTTP/HTTP2/QUIC clients. Those clients are not used with Mythic. There is a Mythic specific client in the clients/mythic
directory that handles all communications with the Mythic server.
When issuing the memfd
from the task box (not using the pop-up window), calling a previously registered file by name, I receive the following error:
[-] merlin ran into an error processing memfd:
'NoneType' object has no attribute 'split'
Traceback (most recent call last):
File "/usr/local/lib/python3.8/site-packages/mythic_payloadtype_container/mythic_service.py", line 216, in callback
final_task = await Command.create_tasking(task)
File "/Mythic/mythic/agent_functions/memfd.py", line 85, in create_tasking
arguments = task.args.get_arg("arguments").split()
AttributeError: 'NoneType' object has no attribute 'split'
./mythic-cli install github https://github.com/MythicAgents/Merlin
2024/05/08 11:29:43 [*] Creating temporary directory
2024/05/08 11:29:43 [*] Cloning https://github.com/MythicAgents/Merlin
Cloning into '/opt/Mythic/tmp'...
2024/05/08 11:29:44 [*] Parsing config.json
[*] Processing Payload Type merlin
[*] merlin already exists. Replace current version? [y/n]: y
2024/05/08 11:29:45 [*] Stopping current container
2024/05/08 11:29:45 [*] Removing current version
2024/05/08 11:29:45 [+] Successfully removed the current version
2024/05/08 11:29:45 [*] Copying new version of payload into place
2024/05/08 11:29:45 [*] Adding service into docker-compose
WARN[0000] /opt/Mythic/docker-compose.yml: `version` is obsolete
No stopped containers
WARN[0000] /opt/Mythic/docker-compose.yml: `version` is obsolete
[+] Building 2.6s (9/12) docker:default
=> [merlin internal] load build definition from Dockerfile 0.1s
=> => transferring dockerfile: 806B 0.0s
=> [merlin internal] load metadata for docker.io/ne0nd0g/merlin-base:v1. 1.0s
=> [merlin internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [merlin internal] load build context 0.1s
=> => transferring context: 447.70kB 0.1s
=> [merlin 1/8] FROM docker.io/ne0nd0g/merlin-base:v1.6.1@sha256:d1d4a31 0.0s
=> CACHED [merlin 2/8] WORKDIR /Mythic 0.0s
=> CACHED [merlin 3/8] COPY [., .] 0.0s
=> CACHED [merlin 4/8] WORKDIR /Mythic/agent 0.0s
=> ERROR [merlin 5/8] RUN go mod download 1.2s
------
> [merlin 5/8] RUN go mod download:
0.722 exec /bin/sh: exec format error
------
failed to solve: process "/bin/sh -c go mod download" did not complete successfully: exit code: 1
2024/05/08 11:29:50 [+] Successfully installed service
2024/05/08 11:29:50 [*] Skipping over C2 Profile
2024/05/08 11:29:50 [*] Processing Documentation for merlin
[*] merlin documentation already exists. Replace current version? [y/n]: y
2024/05/08 11:30:00 [*] Removing current version
2024/05/08 11:30:00 [+] Successfully removed the current version
2024/05/08 11:30:00 [*] Copying new documentation into place
2024/05/08 11:30:00 [+] Successfully installed Payload documentation
2024/05/08 11:30:00 [*] Skipping over C2 Documentation
2024/05/08 11:30:00 [*] Skipping over Wrapper Documentation
Hello,
Using latest Merlin agent on latest Mythic.
When building default Merlin payload, then it fails with following message:
Build Message:
Processing C2 Profile - http:
Step 1/3 - Issuing OPSEC Check
No immediate issues with configuration
Step 2/3 - Issuing Config Check
C2 Profile container and agent configuration match port, 80, and SSL expectations (false)
Step 3/3 - Issuing Start command
Sending Build command
there was an error compiling the agent
StdErr:
exit status 1
StdOut:
# github.com/Ne0nd0g/merlin-agent/v2/commands
/go/pkg/mod/github.com/!ne0nd0g/merlin-agent/[email protected]/commands/shell_freebsd.go:36:12: undefined: fmt
Build: go build -o merlin.bin -buildmode=default -ldflags -s -w -X "main.payloadID=6201ac61-ef45-42ac-b36d-7105b33e3fae" -X "main.profile=http" -X "main.httpClient=go" -X "main.url=http://XX.XX.XX.XX:80/data" -X "main.psk=ohA2fedPRZsaWDHrizzVO8ApZUBC4PQF9u0HTXI5Re0=" -X "main.useragent=Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko" -X "main.sleep=53s" -X "main.skew=19610" -X "main.killdate=1745625600" -X "main.maxretry=7" -X "main.padding=4096" -X "main.verbose=false" -X "main.debug=false" -buildid= -tags=mythic main.go
Any thoughts on that?
To duplicate the problem, from an active call back window, call the Invoke-Assembly
command with an assembly name but WITHOUT an argument for the assembly (e.g., invoke-assembly rubeus.exe
).
The following error will be returned server-side before the command is sent to the agent:
[-] merlin ran into an error processing invoke-assembly:
'NoneType' object has no attribute 'split'
Traceback (most recent call last):
File "/usr/local/lib/python3.8/site-packages/mythic_payloadtype_container/mythic_service.py", line 277, in callback
final_task = await Command.create_tasking(task)
File "/Mythic/mythic/agent_functions/invoke-assembly.py", line 78, in create_tasking
arguments = task.args.get_arg("arguments").split()
AttributeError: 'NoneType' object has no attribute 'split'
The original parameters were:
Original Parameters:
rubeus.exe
Agent Parameters:
{"assembly": "rubeus.exe", "arguments": null}
Display Parameters:
rubeus.exe None
Tasking Location:
parsed_cli
Parameter Group:
Default
To fix, add a check to the invoke-assembly command Python script to call split if there enough arguments.
Hello,
Thank you for great implant.
Some companies forbid use applications with the "GNU General Public License v3.0" license.
I wonder if it is possible to change license to less restrictive licenses like the following:
many thanks in advance.
Hello,
Tried to build Merlin's shared payload for Linux amd64, but no avail.
After some debugging it came out, that building shared .so command "goCMD" is commented out in "container/payload/build/build.go"
// Setup Go command
goArgs := []string{"build", "-o"}
if msg.SelectedOS == "windows" && (mode == "shared" || mode == "raw") {
goArgs = append(goArgs, []string{"main.a", "-buildmode=c-archive", "-ldflags", ldflags}...)
args := []string{"-tags=mythic", "main.go", "dll.go"}
goArgs = append(goArgs, args...)
} else if mode == "shared" {
//goCMD += fmt.Sprintf("build -buildmode=c-shared -o merlin.bin -ldflags %s -tags=mythic,shared main.go shared.go", ldflags)
} else {
goArgs = append(goArgs, []string{"merlin.bin", "-buildmode=default", "-ldflags", ldflags, "-tags=mythic", "main.go"}...)
}
Any ideas/thoughts on how to build shared .so for Linux?
Hello,
I have an issue with the merlin payload on trying to load a profile and add more HTTP headers to it.
I tried a custom http header and the Host header.
The only thing that is able to change is the User-Agent only.
Regards,
When using Mythic to generate raw shell code (build mode "raw"), it calls sRDI's `ConvertToShellcode.py. I've not identified the specific problem, but the latest commit monoxgas/sRDI@9fdd5c4 generates shell code that does not function like it used to. However, the commit before the recent changes does work as expected monoxgas/sRDI@5690685
A work around is to connect to the Merlin docker container, move in the sRDI directory, and check out the last known good commit. After the known working commit is checked out, build a Merlin payload through the Mythic interface like normal.
root@hal:~/mythic# docker exec -it mythic_merlin_1 /bin/bash
root@merlin:/Mythic# cd /opt/merlin/data/src/sRDI
root@merlin:/opt/merlin/data/src/sRDI# git checkout 5690685aee6751d0dbcf2c50b6fdd4427c1c9a0a
Note: checking out '5690685aee6751d0dbcf2c50b6fdd4427c1c9a0a'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
git checkout -b <new-branch-name>
HEAD is now at 5690685 Add arguments.output_format to ConvertToShellcode.py
root@merlin:/opt/merlin/data/src/sRDI#
[*] Mythic Local Version: v3.0.1-rc19
Installed merlin the usual way with sudo ./mythic-cli install
After successful installation (this is the docker version - ne0nd0g/merlin-base:v1.3.0) , seems like merlin docker is failing to connect to RabbitMQ.
This could also be identified using the mythic-cli logs
osboxes@osboxes:~/Desktop/mythic/Mythic$ sudo ./mythic-cli logs merlin
[*] To enable debug logging, set `MYTHIC_ENVIRONMENT` variable to `testing`
[*] Mythic PayloadType Version: 12
[*] PayloadType PyPi Version: 0.1.7
[*] Hostname specified as default 'hostname' value, thus will fetch and use the current hostname of the Docker container or computer
[*] Setting hostname (which should match payload type name exactly) to: merlin
[*] Trying to connect to rabbitmq at: 127.0.0.1:5672
[*] Trying to connect to rabbitmq at: 127.0.0.1:5672
[*] Trying to connect to rabbitmq at: 127.0.0.1:5672
[*] Trying to connect to rabbitmq at: 127.0.0.1:5672
[*] Trying to connect to rabbitmq at: 127.0.0.1:5672
[*] Trying to connect to rabbitmq at: 127.0.0.1:5672
And this goes on forever^
After doing some research it seems like although the correct rabbitmq user and password are set in the env variables inside the merlin docker, 'mythic_service.py' from mythic-payloadtype-container lib , is failing to connect to it.
From rabbitmq logs seems like the attempt is failed because the default 'mythic_password' is used in the connection attempt instead of the actual password in the env variable.
After setting the correct rabbitmq password in 'mythic_password' key in /Mythic/merlin/mythic/rabbitmq_config.json instead , I could see that the connection is successful in logs:
[+] Ready to go!
[*] mythic_service - Waiting for messages in mythic_service with version 12.
[*] mythic_service - total instances of merlin container running: 1
but it still seems to not load merlin correctly in the web UI.
This is as far as I got, as I'm new to the Mythic source code, but from a quick check, looks like other agents (like Medusa ) use the newer 'mythic_container' instead of 'mythic-payloadtype-container' lib, which handles the rabbitmq connection so it might be related to merlin still using the obsolete lib ? (https://github.com/MythicMeta/Mythic_PayloadType_Container/tree/master)
The Merlin agent skew is incorrectly calculated in builder.py
because it uses callback_interval
but should be using callback_jitter
? Skew is currently calculated in milliseconds so a 23% jitter would be calculated as 23 seconds. The calculation should be 23% of the callback_interval
.
ldflags += f' -X \"main.skew={int(c2_params["callback_interval"]) * 1000}\"'
Hey Ne0nd0g,
Just for your information, the agent seems so have some kind of memory issue when downloading bigger files.
During exfil testing, we chunked multiple 1G files, which resulted in the implant crashing every time we started to download one. I tried Windows/Linux/Arm and all result in the same behavior.
I.e. after 1 minute of starting the download/just before crash:
Cheers,
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.