Skip to content

Latest commit

 

History

History
344 lines (243 loc) · 11.5 KB

README.rst

File metadata and controls

344 lines (243 loc) · 11.5 KB

rpc2socks

rpc2socks is a client-server solution that allows to drop and remotely run a custom RPC + SOCKS-through-SMB server application on a Windows target, from a Unix or Windows host.

The client-server pair can be used as a regular SOCKS5 tunnel (see dedicated section below).

Client and server communicate exclusively through a dedicated named pipe over SMB, using a custom and extensible protocol.

The protocol, as well as the client and server sides can welcome additional so-called RPC commands.

rpc2socks-client is a Python3 package and an interactive script that use impacket to communicate with the server-side through SMB protocol (named pipe).

rpc2socks-server is implemented in C++ as a native, statically-linked, Windows console application (or a Service if enabled at compile-time), supporting both 32-bit and 64-bit architectures.

SOCKS tunnel

SOCKS-through-SMB tunnel is the main feature of rpc2socks.

Properties:

  • SOCKS v5 only
  • TCP only
  • DNS resolution through SOCKS supported
  • No authentication, however user-password auth can be easily added in rpc2socks-server if needed

It is implemented in such a way that it allows to bounce via a Windows host except that the SOCKS proxy here takes its client-side packets from the named pipe connection established between rpc2socks-client and rpc2socks-server. With the SOCKS clients communicating directly with rpc2socks-client.

Thus, rpc2socks-server does not listen on a TCP socket.

    +---------+
    | firefox |
    +-+--+--+-+
      ^  ^  ^
      |  |  |  [SOCKS5 over TCP]
      v  v  v
+-----+--+--+------+
|    rpc2socks     |
|    client CLI    |
| (unix / windows) |
+--------+---------+
         ^
         |  [ rpc2socks-proto  ]
         |  [through named pipe]
         |  [      (SMB)       ]
         v
   +-----+-----+
   | rpc2socks |
   |  server   |
   | (windows) |
   +--+--+--+--+
      ^  ^  ^
      |  |  |  [TCP]
      v  v  v
 +----+--+--+----+
 | The Internets |
 +---------------+

Note that the rpc2socks-proto transport depicted here consists of a single logical link between rpc2socks-client and rpc2socks-server, regardless of the number of established SOCKS connections and clients.

As a side note, the actual logic of the SOCKS proxy is implemented in rpc2socks-server. rpc2socks-client only acts as a bridge between the SOCKS client(s) and rpc2socks-server.

Requirements

Client-side requires Python 3.6+ (Unix or Windows) and use impacket as its sole dependency.

Server-side native statically compiled executable requires at least Windows Vista or Windows Server 2008.

Installation of the Client

rpc2socks client part is located under the cli/ directory.

Although it can be run directly by using the bin/rpc2socks script (both Unix and Windows compatible) - which may work already depending on your environment and as long as impacket dependency is installed - it is safier to have rpc2socks client installed in its own Python virtual environment.

This is because it implements many workarounds to impacket's issues so impacket version is frozen in setup.py in order to avoid any trouble due to a potential future patch changing lib's behavior.

  • Fetch rpc2socks from git-where:

    $ git clone https://example.com/git/rpc2socks.git rpc2socks-git
    
  • Create and activate a virtualenv:

    $ python3 -m venv rpc2socks-venv
    $ . ./rpc2socks-venv/bin/activate
    

    (rpc2socks-venv) $

  • Install rpc2socks:

    (rpc2socks-venv) $ python3 -m pip install -e rpc2socks-git/cli/
    
  • Check rpc2socks script is installed:

    (rpc2socks-venv) $ rpc2socks --help
    

Typical usage flow

  • Launch rpc2socks client CLI by giving it the required credentials to the remote Windows target:
(rpc2socks-venv) $ rpc2socks BLOCKCHAINDOMAIN/Carlos@10.1.2.3
Password for "Carlos":  <TYPE YOUR PASSWORD>

  This is rpc2socks prompt. "?" for help.

rpc2socks>>>
  • Use the inst command to copy the server-side executable that is embedded in the client, to the target through SMB, then remote-execute it using WMI, then connect:
rpc2socks>>> inst
10:14:56.114 checking first if remote exe is not already installed and running
10:15:01.219 remote exe does not seem to be running
10:15:01.220 querying host's arch
10:15:01.234 extracting embedded 32-bit exe
10:15:01.269 dropping 32-bit exe to \\10.1.2.3\ADMIN$\winlfo32.exe
10:15:02.367 created remote process 3988
10:15:02.368 remote execution successful
10:15:04.869 trying to connect
10:15:04.869 creating bridge
10:15:04.872 waiting for connection to \\10.1.2.3[445]\pipe\winlfo32
10:15:05.211 connected to \\10.1.2.3[445]\pipe\winlfo32
10:15:05.211 bridge connected
  • Note that in case WMI is not accessible, you may want to try the inst svc command instead for an SMB-only method. Executable will be copied though SMB, then installed then executed as a service via the Windows Service Manager (still through SMB).
  • At any time you can use the st command (status) to check if connection is still established:
rpc2socks>>> st
PROTO: connected to \\10.1.2.3[445]\pipe\winlfo32
SOCKS: listening on 127.0.0.1:8889

While running and connected to the server-side, rpc2socks-client also listens locally on a TCP port to serve as a SOCKS proxy. It listen on localhost:8889 by default (see --socksbind command line option).

  • Unless you need to reconnect later on (with the co command), use the uninst command to stop remote executable and remove it from filesystem
rpc2socks>>> uninst
10:18:10.581 sending UNSINSTALL command
10:18:10.594 disconnected from \\10.1.2.3[445]\pipe\winlfo32
10:18:12.584 waiting for bridge to close
10:18:13.088 bridge closed
10:18:15.591 deleting remote exe
  • Leave the prompt using the q command (quit)
rpc2socks>>> q

(rpc2socks-venv) $

Known issues

High speed download

High speed download of a single and big data chunk (more than a few dozens of MiB) via the SOCKS tunnel may crash rpc2socks-server.

In some conditions - depending on the running environment on both ends, the connectivity and the size of the requested data chunk - to download data through the SOCKS tunnel of rpc2socks at a high speed rate may cause too much data to be buffered by rpc2socks server-side, due to the client-side not being able to follow up at that speed.

In a worst case scenario, this may lead to an unsubtle skyrocketing of the memory usage of the server-side until shameless crash.

For now, it is strongly advised to limit the download speed of your SOCKS client to 5MiB/s maximum - preferably even lower to stay on the safe side - in case you require a download of more than a few dozens of MiB at once.

Side note: ideally an automatic throttling mechanism should be implemented on the server-side. An extra development time that R&D department could not afford at that moment :)

Double link, One client

More of a FYI for a significant issue that occurred during the development due to some impacket flaws than an actual issue at usage-level.

Because of the reasons described below in the impacket integration section, and in order to deal with impacket's I/O limited capabilities, rpc2socks-client connects to two instances of the same named pipe created by rpc2socks-server. Where one instance is for read-only and the other one for write-only operations, both in blocking mode on client side, with dedicated Python threads and with no (reasonable) timeout so that even SMB transactions that lead to a PENDING state can be successful.

A handshake step takes place at connection-time to "configure" each channel and pair them under a single, well identified "logical connection". This is part of rpc2socks-proto logic and makes the code more complex on both ends.

Notes to maintainers

Compile rpc2socks-server

rpc2socks-server is built with Visual Studio 2019.

Solution file is svc/rpc2socks.sln.

No other version nor compiler tested. Compiler must be C++17 aware.

Embed server executables

In case rpc2socks-server source code gets updated, its newly built executables (32 and 64-bit; console and service) must be re-embedded in rpc2socks-client source code using script tools/embedsrv.py.

This feature is for end-user's convenience so that they do not need to build rpc2socks-server themselves.

Steps:

  1. Open svc/rpc2socks.sln solution file with Visual Studio 2019
  2. Batch build the 4 configurations of rpc2socks-server; that is ConRelease and SvcRelease configurations for both x86 and x64 architectures
  3. Run python3 tools/embedsrv.py. That will update cli/rpc2socks/embexe_data.py.
  4. Commit

impacket integration

This section exists so to keep a feedback of the integration of impacket since it has proven itself cumbersome to be integrated in an asynchronous I/O paradigm in a reliable way and in a project bigger than a single script.

rpc2socks I/O have been made more complex than it should be on both client and server sides, for the sole purpose of working around some significant issues found in impacket.

I/O: most if not all impacket's I/O is blocking, which forces the integrator to create as many threads as required connections since impacket does not give access to the lower layers (the sockets) from a high level class like impacket.smbconnection.SMBConnection for instance.

As a result in rpc2socks-client, two named pipe connections are created - thus two threads dedicated to low-level I/O - and virtually paired so that they can handle respectively read and write operations simultaneously.

SMB: regarding files I/O over SMB - that includes named pipes - impacket does not deal correctly with SMB's PENDING response to a READ request by not canceling the transaction then leaving the caller unnoticed about this specific state in case of a timeout (see impacket.smb3.SMB3.recvSMB). Making any subsequent READ request to fail and to end up with the Windows host forcefully terminating the connection due to protocol violation.

It is worth noting that many impacket's SMB-related example scripts setup huge timeout delays for I/Os - e.g. 100'000 seconds - as a workaround to the issue described above, which is okay'ish for a single script run manually but hardly practicable in bigger projects as timeouts should be handled as being part of I/O interactions.

Side note: impacket's internal state can be spread out commando-style in a Maniac Mansion - i.e. bloc-level vs. instance-level vs. class-level vs. global-level - and its way of dealing with errors may vary across multiple implementations of a same method. See the respective methods of SMB and SMB3 classes for instance.

License

rpc2socks is released under the terms of the BSD-3-Clause license with the following addendum:

If we meet some day, and you think this stuff is worth it, you can buy the
author a beer in return.

See the LICENSE file at the root directory of this project.

Contact Us

We are Lexfo 👋

Twitter: https://twitter.com/LexfoSecurite

GitHub: https://github.com/lexfo