# tl;dr This short post presents a pure Go alternative to `rpc2socks` as a Sliver extension. There is absolutely no reason to use it over `rpc2socks`, but it presented itself as an interesting experiment to explore Sliver extensions in Go and SOCKS5 over SMB. It is available @https://github.com/zimnyaa/smbsocks/ This is all for fun only, I wouldn't recommend this over `rpc2socks`. # usage The solution consists of two components. The server (`rpcsrv.dll`) is meant to be executed at a server that you want to pivot through with `wmiexec`/`atexec`/WinRM/etc. This DLL with open a named pipe and start listening. The client (`rpccli.dll`/`extension.json`) is a Sliver extension. Upon execution, it will try to connect using the current logon token to a remote named pipe. If successful, it will spin up a SSH connection and a local SOCKS proxy. After that, the operator can portforward to that local proxy on the implant side and obtain a way to tunnel connections through the victim. Here's the diagram: ``` operator -(portfwd)> implant -(smbsocks)> target -> segmented network ``` In practice, it looks like this: ![[Pasted image 20231227204621.png]] ![[Screenshot 2023-12-27 at 20.28.43.png]] ![[Screenshot 2023-12-27 at 20.28.49.png]] And on the target side (with a DLL hijack): ![[Pasted image 20231227204734.png]] # socks approach SOCKS5 is spun up with an SSH connection over SMB (very similar to [[grpcssh]]). In short, this is how it works: ```js spin up net.Conn over SMB -> spin up ssh.Conn over net.Conn -> forward Dial function from SSH to the socks server ``` # sliver extension To create a Golang extension for Sliver, some C bootstrapping was required: ```c typedef int (*goCallback)(const char*, int); typedef struct _goArgs { char* argsBuffer; int bufferSize; } goArgs; void callGo(LPVOID param) { dialpipe(param); } __declspec(dllexport) int __stdcall entrypoint(char *argsBuffer, int bufferSize, goCallback callback) { goArgs args; args.argsBuffer = argsBuffer; args.bufferSize = bufferSize; CreateThread(NULL, NULL, callGo, argsBuffer, NULL, NULL); callback("socks thread created.", 22); return 0; } ``` Other than that, two Golang runtimes seem to be doing fine together.