# tl;dr > `sliver` version: 1.15.29 This post is first in a series of articles that aim to highlight inner workings of various open-source command&control frameworks, starting with [Sliver](https://github.com/BishopFox/sliver) as my favourite one. These articles are meant to improve awareness of techniques red team operators (who do not develop C&C, like me) use on a daily basis. They are only focused on Windows evasion at the moment. I will mostly use diagrams based on Sliver's source code to illustrate my points or provide examples. Sliver's usage is available on the [Sliver wiki](https://github.com/BishopFox/sliver/wiki). # implant obfuscation and export formats Implant obfuscation is a definite strong suit of `sliver`. It is written in Golang, and uses `garble` for obfuscation together with `go-donut` for shellcode creation. > **OPSEC note:** Only now are EDR/AV vendors trying to catch up with `sliver`'s obfuscation ability. Use a custom loader if you can, but at the moment sliver has way less signatures that most other frameworks. # staging `sliver` only supports the MSF staging protocol served either over TCP or HTTP/S. It is as simple as it gets: ``` data = (DWORD)len(shellcode) + shellcode ``` Staging shellcode is just MSF shellcode, except always pointing at a random URL ending in a pre-configured staging extension (`.woff` by default) > **OPSEC note:** obviously, use custom staging for `sliver` (if you want staging, anyway). Be aware that implants are *big*, and plan accordingly (careful with various stompilng techniques). > **OPSEC note:** recently, `sliver` started supporting shikata-ga-nai. I'd still go with a custom staging/encoding solution over it though. # C2 communication `sliver` provides procedurally obfuscated C2 communication, structured approximately like so: ```c obfuscate(encrypt(protobuf(C2_message))) ``` For an average operator, this means that most of the communication profile hassle is gone. Still, there is something that can be configured and possible detections a user should be aware of. I will try to copy as little information about C2 communication for the wiki as possible. Go read it (or the code) if you want more detail. At the moment, I will assume that no EDR can decrypt `sliver`'s C2 traffic, and will only look at how binary blob transfer is implemented. If you are interested in how `sliver`'s asymmetric key exchange works under the hood, refer [here](https://github.com/BishopFox/sliver/wiki/Transport-Encryption). ## http/s The design goals for the HTTP/S channel are best [explained by the developers](https://github.com/BishopFox/sliver/wiki/HTTP(S)-C2#under-the-hood). What we, as operators, are interested in, are [configuration options we can influence](https://github.com/BishopFox/sliver/wiki/HTTP(S)-C2#under-the-hood). We can do that by modifying `~/.sliver/configs/http-c2.json`. > **OPSEC note:** it is recommended to do the following: > - change or rotate extensions and filenames used in procedural URL generation > - mimic legitimate browser request headers (just take them directly from `Burp Suite`) > - mimic legitimate response headers (again, just steal them from some web app) > - consider domain fronting (thankfully, the Host header can now be configured) ## mtls/wg Mutual TLS and WireGuard transports are very similar in nature – they establish a two-way channel either via a TLS channel, or the WireGuard VPN tunnel protocol. > **OPSEC note:** Ultimately, these are recommended if outbound traffic is not restricted/proxied. The traffic will look pretty standard for a WireGuard tunnel or MTLS ¯\\_(ツ)_/¯ ## dns DNS transport is currently optimized [for speed, not evasion](https://github.com/BishopFox/sliver/wiki/DNS-C2). Data is base58 or base32-encoded and sent in QNAME. > **OPSEC note:** sometimes, DNS is the only way to reach external networks from isolated systems (i.e. terminal servers). Most of the time DNS whitelisting/detection is not present in the environment, but if it is, `sliver` will not care about evading them. ## pivots Sliver supports both TCP and SMB pipe pivoting. Both connections are treated basically the same as any other transport. > **OPSEC note:** this means that inspection of named pipe data exchange shows encrypted data after the initial key exchange. This is usually fine, and most detections will work on remotely-accessible named pipe creation, [like this one](https://blog.menasec.net/2019/04/detecting-namedpipe-pivoting-using.html). It is possible to `migrate` in a process that routinely creates remotely-accessible named pipes, and mimic the naming convention. ## beacon mode vs session mode `sliver` supports two implant modes – `beacon` mode and `session` mode.`session` mode is full-on interactive, while `beacons` periodically check in to report on tasks and receive new ones. > **OPSEC note:** `beacon` mode is usually superior for evading detection, but: > - pivots will not be available > - interactive functionality (like interactive `shell`, which should not be used anyway) will not be available as well > - tasks are FIFO, so if a user screws up and runs a long task, short ones will have to wait > > IMO, it is best to create an implant as a `beacon`, and then enable interactive mode for a period of time if you need the functionality. # generic commands If `ls`, `download` and `cd` are picked up, we are all doomed anyway, so this section only focuses on some special cases. ## `ps` The `ps` command opens a handle to all processes to read the architecture and other stuff. > **OPSEC note:** ~~filter by the process name when listing processes~~ (does not work) or use a BOF that does not do that. ## networking `sliver` supports SOCKS5, portforwards, and reverse portforwards (since recently). This allows for a complete living-off-the-land aproach with tool execution. > **OPSEC note:** it should be said, however, that suspicious traffic is still there. Make sure that during AD enumeration, `sliver` is running somewhere where it is not suspicious to make excessive DNS/LDAP queries. ## shell Single-command execution is just `exec.Command` with output redirection. The resulting process is spawned as a child process. > **OPSEC note** No PPID spoofing/argument rewriting is available to you. Be careful with what you run. If the argument string is signatured by the EDR, you will lose the session as the parent of a suspicious process. > For some reason, `sliver` on Linux creates loads of defunct child processes. IDK why that happens, but I blame `execute -o`. `shell` is just what you would expect – an interactive shell run as a child process with real-time output redirection. This is **not** OPSEC. `sliver` developers even tell you that: ``` [server] sliver (ARAB_ECCLESIA) > shell ? This action is bad OPSEC, are you an adult? (y/N) ``` > **OPSEC note:** if you use `shell`, you are not an adult. ## procdump Process dumping functionality is a syscall-rewritten version of minidump. If evasion is enabled, DLL unhooking is also done prior to calling `OpenProcess`. > **OPSEC note:** despite the dumping process itself is as safe as it can be with MiniDumpWriteDump, `sliver` does not do handle duplication or any kernel-level evasion (which would require a vulnerable driver to be loaded). Dumping `lsass` could be still caught because of that. Consider either using a method that does additional evasion. Examples would be: evasion methods implemented in [EDRSandblast](https://github.com/wavestone-cdt/EdrSandblast), the [nanodump](https://github.com/helpsystems/nanodump) BOF included in the `armory` since v1.5, or alternative credential gathering methods like `credman` or Terminal Service dumping. ## runas/impersonate/getsystem Token duplication is done in a pretty standard manner: ```j OpenProcess(pid) -> OpenProcessToken -> _syscall_ ImpersonateLoggedOnUser -> DuplicateTokenEx ``` User impersonation just iterates over all processes until it finds a suitable one. There's also `maketoken` functionality, which creates a new logon for token duplication: ```j _syscall_ LogonUser -> _syscalls_ ImpersonateLoggedOnUser ``` `getsystem`, on the other hand, just injects shellcode via `RemoteTask` with SeDebugPrivilege with the injection technique described below. > **OPSEC note:** duplicating a SYSTEM token is dangerous, and `sliver`'s approach to `getsystem` is correct, IMO. In general, be careful with impersonation, even when dangerous calls like `LogonUser` and `ImpersonateLoggedOnUser` are made with syscalls. # third-party tool execution `sliver`'s third-party tool execution techniques (and other functionality that requires process injection, i.e. `migrate`) are based on a single non-configurable injection technique. It can be summed up as: ```j remote injection: OpenProcess -> DuplicateHandle -> _syscall_ VirtualAllocEx -> _syscall_ WriteProcessMemory -> _syscall_ VirtualProtectEx (ER) -> _syscall_ CreateRemoteThread local injection: VirtualAlloc -> VirtualProtect -> CreateThread ``` > **OPSEC note:** this is *the* standard approach for remote process injection, and it should be picked up by most advanced EDRs. If there is an alternative to remote process injection in your toolset (e.g. BOFs adapted to launch with `sliver`) consider using that in mature environments. Syscalls won't always save you from detection. > **OPSEC note:** If you can't get around process injection, consider modifying the source code yourself to implement your favourite process injection technique instead of writing an issue on Github. Aside from using direct syscalls for remote injection, the evasion option `sliver` includes here is DLL unhooking, done in a following manner: ```j ReadFile(ntdll.dll) -> LoadDll -> VirtualProtect (RWX) -> memcpy -> VirtualProtect(RX) ``` > **OPSEC note:** this means that the VirtualProtect call is done with a hooked version of ntdll.dll. If there is a detection based on remapping `.text` of ntdll to RWX, this can be caught. The evasion module also includes PPID spoofing functionality, but it is not used. ## execute-assembly `execute-assembly` uses the aforementioned injection technique, and the entire process looks something like this: ```j DonutFromAssembly(assembly, args) -> StartProcess -> //process output redirected to pipe inject -> read pipe ``` > **OPSEC note:** this means that, aside from injection detections, `execute-assembly` can raise alerts based on anomalous child process creation and on unexpected process behaviour (notepad.exe extensively communicating over LDAP, for example). > **OPSEC note:** the `donut` configuration used by default during `execute-assembly` bypasses AMSI/WLDP by patching with non-syscall VirtualProtect. This is usually good for OPSEC, until it isn't. ## execute-assembly (inline with --in-process) Newer versions of `sliver` come with an inline option for loading CLR with Ne0nd0g's `go-clr`. This is the preferred method for loading C# tooling right now in sliver. > **OPSEC note:** `inline-assembly` obviously loads the CLR in the corrent process, which may serve as an IoC. Built-in AMSI and ETW bypasses just RW->RX patch `AmsiScanBuffer/AmsiInitialize/AmsiScanString/EtwEventWrite` with a `RET`. ## spawndll/sideload `spawndll` is very similar to `execute-assembly`, except it uses sRDI for DLL->shellcode conversion. Detections should be pretty much the same. ## BOF (v1.5 yay!) With v1.5, `sliver` has added support for Beacon Object Files, extensions for Cobalt Strike. For Beacon Object File execution, `sliver` uses [CoffLoader](https://github.com/trustedsec/COFFLoader) under the hood. The process looks something like this: ```j memmod.LoadLibrary(CoffLoader) -> build argument buffer (with BOF bytes) -> call CoffLoader exported function ``` > **OPSEC note:** I prefer this method over `execute-assembly`, but possible detection may be built around: > - reflective DLL loading > - the CoffLoader DLL signature