start	end	text
0	3620	Hi, I'm Alessandro, a security researcher at DualSecure,
3620	8680	and today I'm with my colleague Olivier to showcase our RDP interception tool, PyRDP.
8720	12580	PyRDP is a tool that can be used to perform real-time RDP interception,
12580	16860	which were designed to support both honeypots for malware research and offensive capabilities
16860	23000	for intrusion test engagement. Today we'll be highlighting core features for both use cases.
23180	28080	In this section, I'm going to introduce you to PyRDP's core feature set,
28080	31340	which can be used in both offensive and defensive contexts.
31760	36840	In the environment for this demo, we have the PyRDP system deployed in front of a Windows Server
36840	44240	2016 system. PyRDP is running on a Linux system and deployed using our Docker image. The client
44240	50320	will be a Windows 10 system running Microsoft Terminal Services, also known as MSTSC.
50640	55460	In its default mode of operation, PyRDP will collect a lot of information,
55460	59380	but only output significant events in its logs.
60200	65820	The player component, which has more granular information, will be demoed later.
67160	74220	Let's take a look at the default flags to use PyRDP. In this example, we run it via Docker,
74640	80760	and we map a volume here to make sure that we have access to the artifacts generated with PyRDP
80760	91400	after our demo, after the interactions. The "-p", here, is to give the host access to the port,
91400	98420	so RDP being on 3389. This will ensure that any connection to 3389 on the host is redirected to
98420	106200	the Docker image. This is the Docker image name of the latest PyRDP. The monster in the middle
106200	113540	executable that is used here, and this is the target server. So whenever something connects
113540	123120	on 3389 on this system, it will then forward the connection to this IP address and do its
123120	131500	monster in the middle capabilities. Let's start the PyRDP man in the middle.
134570	141170	You can see that SSL information or private key and certificate are generated upon the start
141170	146490	because we didn't give them in the Docker image in the volume. So they don't exist
146490	152370	and they are created on the fly. This should probably be customized for most users.
155300	162540	Now let's take a look at what we have if a user connects and plays around. I'm going to start
162540	172990	the Microsoft client here. You can see the certificate error that is being generated.
173670	182030	The PyRDP system by default will create a certificate for a hostname called www.example.com.
182030	190410	This is probably not the best. You should generate a certificate more adapted to the target
190410	198710	or the user that you're trying to fool. We provide a tool called PyRDP clone cert to do that. Clone
198710	203610	cert will connect to a specific server and copy the information from the certificate
205950	210290	in a certificate key pair that you can then use with PyRDP.
211470	219530	So this is the reason why we built this tool is to train user to avoid clicking through certificate.
219530	223330	Since if there is an attack tool that is efficient,
223930	232670	then user will be enticed to be more careful. Just like what FireSheep did with the SSL attacks.
232670	239350	It changes the mentality of a lot of people and made TLS enabled by default everywhere.
239350	244130	Well with PyRDP we hope that system administrator will be more careful about those certificate
244130	251810	errors and deploy a PKI internally, which is very rarely the case in our engagements that we see.
252510	254690	So we're going to click on yes.
256590	263890	Now we can see several interesting things happened on the log section of the screen.
263890	270390	You can see that the client random is logged, which is very interesting if you ever take
270390	278710	packet capture, you can then decrypt and do very granular protocol level analysis of the RDP connection.
280580	287080	On the system we get a password prompt, which is different than the usual password prompt,
287250	294920	because we downgrade the authentication and it's now interactive, it's now part of the session.
294920	298780	So I'm gonna write the password.
303340	305920	Made a little mistake here.
311530	321250	Okay, I'm in. So there's a secret file on the desktop.
322470	331330	But you can see in the logs that channel information is logged, username,
331970	336230	since it was not typed and not sent by the client, is not there.
337470	341730	You can see that clipboard data was instantly intercepted.
342990	350190	And you can see that there is a credential candidates from heuristic here, scary demo gods.
352630	357350	This is being done with a heuristic since it doesn't happen at the protocol level.
357350	364030	We are interactively entering credentials inside the started RDP sessions. That's because we are
364030	371190	downgrading the client's request for NLA, since NLA will resist two monster in the middle attacks.
371190	377590	This attack resistance is rather complex and has been partially circumvented in specific cases,
377590	380570	which we will cover in the honeypot section later.
383360	392580	By default, the clipboard content is intercepted. And we can see it, we'll demo it right now.
393080	402080	So if we open this many secret file and we put it in the clipboard, you can see
402080	409520	right away, instantly, that it was intercepted on the server side, in the logs.
409640	417660	What's interesting that you might not have noticed here, is that I didn't interact with
417660	425820	the mstsc client when the output showed in the logs. So let me just give you an example
425820	433400	to highlight it again. So I copied in notepad, not even touching the mstsc client screen.
433400	442200	However, the information was sent to the server. So the clipboard content is being very shared,
442200	450920	very enthusiastically, with mstsc. And also, this is what happens with most RDP clients.
454910	458350	Let's copy a few more times, just to see...
460570	464890	You should be aware that this goes beyond this.
464890	472950	So this Windows machine is in a VirtualBox system, running the mstsc client. The VirtualBox
472950	480110	will also notify the guest, Windows 10, of clipboard events that happen on my host.
480230	487810	So this is very interesting, because, for example, if I would paste a log line here
487810	494590	on my clipboard, what we would expect is the information to flow from my host, to my guest,
494590	502610	from the guest OS clipboard, to the mstsc client, and then to the intercepted system.
504030	511630	And, the expected happened. You can see that the clipboard data is visible here.
511630	519290	And it happened pretty fast. So this is a very interesting capability,
519290	526190	that will probably allow some information to be leaked, if we ever intercept bad actors,
526190	531090	or in a penetration testing context, you can gather a lot of information,
531090	536050	if an administrator leaves an RDP window open in the background for a long time.
536050	540830	You'll be able to get clipboard content with, most likely, sensitive information,
540830	546330	including passwords, if the user uses a password manager like KeePass.
552810	559090	What happens here is that PyRDP just receives a message about new clipboard content,
559090	565410	and will send to the client a message saying, I need it. The content is then never forwarded
565410	572910	to the server. So it's just a standard operation. There's no update of the clipboard on the server
572910	580890	side. So next up in the demo is the file collector. RDP allows clients to share a drive
580890	603440	upon connection. Let's configure it. So let's disconnect. We go in local resources,
603440	611140	and then we can share whole map drives. That's interesting, because the share is
611140	628740	not at a very granular level. So this gives a lot of opportunity for attacker. A new warning is
630320	638620	given to the user, saying that it's potentially dangerous, and it can harm the computer. So that's
638620	652530	interesting, and it's new. It was not there on older MSTSC clients. Same certificate error.
654750	682160	Okay, let's take a look at the file share in action. So we can see that the C drive
682160	689360	on engineering 13, which is my client, is visible through the RDP session.
690100	697260	What happens if we click on it, is we get access to the information on it,
697260	704260	and we see at the same time information being collected by the PyRDP system.
708350	717790	If we open the secret.txt file on the root of the C drive, we also notice that the information
717790	731610	was saved by PyRDP in the output folder. To finalize this part of the demo,
732950	737530	we're gonna stop PyRDP and look at the artifacts generated.
749960	759940	The PyRDP output folder has several items in it. Replays, which are recordings of the exact
760480	768880	sessions, including keystrokes and screen capture, which can be replayed later.
771170	786530	There are logs and there are files. If we look at the logs, we can see that the SSL log is also
786530	794090	available here. So this is very useful, again, if you do packet capture in order to decrypt them
794090	800950	with Wireshark or other tools. There is a JSON log, which will be covered later,
800950	805730	and there is a man-in-the-middle log, which is the exact output that was available
806370	818790	from inside, that you could see on the command line. And if we look at the files,
818790	837410	then you can see all the files that were collected by the system. So we can take a look at the
841890	849530	secret file that we saw earlier, loaded from the C drive, is here with the content. The mapping
849530	862490	of the files to the events is available through the log files. This concludes the PyRDP demo
862490	870570	of the monster-in-the-middle component. If you need fine-grained content, like keystrokes,
870570	876410	and see the screen during an active attack, you need to combine the use of the PyRDP MITM tool
876410	884050	with the PyRDP player. Let's launch both tools right now. Here I'm bringing up the previous
884050	889710	command that we used to run just the monster-in-the-middle component, and now I'm going
889710	901870	to add "-i", and an IP address to this execution. The "-i"-flags tells PyRDP to send recorded
901870	909130	RDP events to a PyRDP player over the network. This allows a player that is decoupled from the
909130	916650	attacker's machine, like the setup we have here. Now we are going to launch the player on my local
916650	933390	system, pyrdp-player. You can see that it is a Qt interface, and that it has tabs for live
933390	941830	connections and replays, so live activity and replay, or previously recorded activities.
941850	947710	Let's connect a client to the monster-in-the-middle and see what the player sees.
954300	960800	In order for the demonstration to be complete, we'll ensure that we have a map drive here.
960800	965580	So the C drive is shared upon an RDP connection.
967360	977410	Then let's connect. You can see that there is some activity already happening in the player interface.
980120	987900	Now, you see that a tab opens called engineering13, which is the hostname that is sent by the client.
989540	996340	The screen is visible, including the pointer position, which is hard to see right now, but if
996340	1011140	we see here with the yellow dot. Now if we enter the credential, you can see on the below interface
1012840	1024320	exactly the keystrokes being inputted, including special characters like space and shift or control.
1025400	1033200	So this is very interesting and important to have an accurate representation of the connection,
1034100	1040720	which could be used in many contexts. And you can see that you have also a pixel-perfect
1041280	1048120	representation of the interactions. This can really demonstrate the impact
1048120	1054480	of an attack on RDP to executives, for instance.
1057370	1063850	Additionally, if the client mapped a drive, you can explore his drive without his knowledge.
1063850	1073250	So we can browse here and we can double... we can right-click and download a file
1073250	1082090	on our local system. RDP demo. Download this here.
1084160	1093470	You can also browse and explore the user's file system. So here, for example,
1093470	1101550	we are loading into Dave's files and looking at his documents. And we can download the many
1101550	1120570	secrets files again on our system. RDP demo. Here we go. This is a pretty interesting demonstration
1120570	1127630	of the dangers of mapping a drive. You basically allow the server to query anything using File.io
1127630	1134190	on your mapped drive. Normally, that is fine. But as you can see, with PyRDP,
1134190	1139390	it can be abused. And it could also be abused with a malicious RDP server.
1141170	1147010	Another feature of the player is the Take Control button that you can see right here.
1147530	1153970	This will be demonstrated later by Alex in the offensive section of the demo.
1155070	1159790	Lastly, is the ability to replay previous captures.
1161960	1167120	This is called a replay in PyRDP's context with the player.
1167940	1174320	I'm gonna demonstrate to you by loading a previous capture for our previous demo.
1175480	1185320	So this is Susan's interactions. So what we see right now is the initial state. You can
1185320	1195360	change the speed, play. And once you play, you do have the keyboard and clipboard events
1195360	1200700	at the bottom of the screen. You can also seek in the video.
1202580	1211260	We see the clipboard data also here. You can scale the window so that it's easier to see
1211260	1221170	globally, especially with 4K environments. And you can increase the speed of the replay.
1222050	1227850	So this is very good if you're hunting for a specific session for a specific interaction.
1231610	1235720	This concludes our demonstration of the player's features.
1237890	1243710	PyRDP also comes with a converter tool that can be used to convert pre-recorded replay files
1243710	1251410	into videos. The converter tool also accepts PCAPs and can output to replay files.
1251990	1256430	Let's take a look at its option.
1261960	1267800	Here we will convert a previously recorded session into a video that we will play.
1268760	1271200	PyRDP convert.
1272160	1288300	MP4 has the format of output. The input file is a RDP replay.
1289200	1329490	And let's have a default output file name. Now let's look at the resulting file.
1346510	1351750	In this section we will describe PyRDP's features that are useful in the context of running
1351750	1358330	honeypots. Part of PyRDP's honeypot features is a headless mode. This enables server-side
1358330	1365470	deployments, running it on non-x86 systems like a Raspberry Pi, and allowed us to significantly
1365470	1374210	reduce the size of our docker image. For example, this is a cloud system where we want to deploy
1374210	1384210	PyRDP and we are going to run the headless image. This is the command line from PyRDP.
1385380	1393700	This pulls in the latest master branch image and we are going to use the slim tag so that
1393700	1401020	we are going to use the smaller version of our image without the graphical interface features
1401020	1408120	and the video conversion features. Now let's see how long it takes.
1413830	1423730	The new image is 70 megabytes, which is pretty good for a Python docker image with native code,
1423730	1432490	down from 600 megabytes for our latest release. And you can see that the service is running right
1432490	1438950	now. Headless mode also means that we needed a headless player, otherwise keystroke data is
1438950	1450150	unavailable for command line enthusiasts. Let's see the headless player in action.
1452530	1459370	We can remove the port, it's no longer required for the player, but we still need the volume mount.
1463140	1471460	If we look at the options, we can see a dash dash headless at the bottom. So usually the
1471460	1477420	player is the graphical interface with the Qt, but the new headless feature allows us to look
1477420	1500950	at replay files without the GUI. The Lena file. The dump is one shot deal. You get all of the
1500950	1508430	output at once, but you can go back and see everything that was collected, including clicks
1509040	1517650	and stuff that was sent during the connection. So as is common with the beginning of RDP sessions,
1517650	1523040	you see a lot of control character released and pressed in order to reset everything.
1523520	1535280	Then you can see that I entered credentials, so the password is scary demo gods,
1535280	1543220	and I made a mistake here, so this is a lowercase o. You can see also the backspace that are
1543220	1551180	pressed, so I started with demo instead of scary, so de backspace backspace scary,
1551180	1554380	but then I made a mistake, so I authenticated again.
1555880	1562400	You can see that as soon as I was authenticated, the clipboard was shared, and this was my notes
1563020	1570800	was sent to the server. Then you can see some clicks, and then during that demo, I pasted
1570800	1578160	several secrets to show how easy it was to leak data to the server system and easy for
1578760	1587180	pyrdp to correct, and then I disconnected, which ends the stream. So with the headless player,
1587180	1591640	you have access to all of this from the command line, instead of having to load
1591640	1598140	the graphical interface. Another feature specific to honeypot use cases is credential replacement.
1598580	1602940	This allows your honeypot to accept any credentials entered by the client,
1602940	1606760	and relay to the server the correct set of credentials for login.
1606760	1610860	For instance, although the user for this VM is pyrdp,
1610860	1615380	I will be able to log in using admin and a garbage password.
1616300	1625580	So let's do the demonstration. For this, I'm going to go back to using the man in the middle.
1626060	1634300	As you can see below, I'm gonna input the correct credentials for the VM,
1637850	1650020	and start the man in the middle. Now, using the mstsc client, I'm gonna put a different username
1650020	1659010	here, admin lulz, to make sure that it doesn't exist, and I'm gonna attempt to, I'm gonna try
1659010	1670660	to connect to the honeypot. I have the warning because I have a mapped drive, and I have an
1670660	1692830	error. Let's try again. Okay, transient error. So we have the certificate error,
1697600	1704410	and we got connected. And if you look at the log, you can see that in the client info,
1704920	1712380	the admin lulz was supplied. pyrdp has the ability to intercept files in transit,
1712380	1717720	and to allow client file system exploration from the interactive player. Last year,
1717720	1722440	these capabilities were extended to allow active file querying from the monster in the middle
1722440	1729280	component. When a client connects, pyrdp will list mapped drives and download all the files
1729280	1735100	which match a specific list of allowed files patterns. Let's see this in action.
1736060	1746760	So, we issue the same MITM command as during normal operation, but we add the crawl
1748240	1760420	flag. Let's run it. Now, we connect from the Windows system,
1760420	1765280	and its files using a mapped drive, and its files will be
1765860	1773200	explored by the man-in-the-middle component. Let's connect.
1774280	1781170	So, we have the certificate error. Yes. Now, what we see here...
1782660	1790130	Oh, we need to authenticate before the file system is exposed to the server by the client.
1796240	1804860	We authenticated. And now, what we see here is a begin-crawling-disk C,
1804860	1814260	saving secret to pyrdp-output-files-clodia-secret.txt. So, this file was at the root of the C drive,
1814260	1819760	and so this is why it was the first to be collected, and it was quite fast.
1819760	1825820	You'll also be able to notice that the directory structure is respected.
1825900	1835200	So, as the crawling happens in the background, the files are going to be recreated locally on
1835200	1841700	the pyrdp system. Oh, we can see it's starting now. So, it matched a directory in the users
1843360	1854440	folder, and documents, stuff.ssh, and then stuff.passwords.keypass.database, a flag,
1854440	1860960	and so on. And you'll see also that temporary files and executables under the user directory
1860960	1868580	are going to be saved by default. So, it can take a while to gather all these files based
1868580	1874900	on network conditions. The list of files to collect or to ignore can be tweaked on the
1874900	1880260	command line. So, with this feature, we hope that we'll be able to gather very interesting
1880260	1884640	information, especially on Honeypot's system deployed in the wild.
1886420	1892180	Pyrdp can also be used as an offensive security tool to gain a foothold or pivot within a network.
1892180	1897840	Let's look at some attack techniques. Session hijacking can be used to take over an intercepted
1897840	1903780	RDP connection. First, pyrdp-mitm is launched with the target server and the player address to
1903780	1920560	connect to, in this case, localhost. Next, the player is launched and waits for intercepted
1920560	1925300	sessions. The player can handle multiple sessions at the same time and will automatically display
1925300	1932560	the live feed of the connected session. Clients who connect to the malicious server will receive
1932760	1937780	a certificate prompt. The certificate can be customized to spoof the common name of the server.
1938040	1941540	The likelihood of the certificate being accepted is considerably high,
1941540	1946320	since most companies do not deploy fully signed private key infrastructures for RDP.
1947760	1952500	After a successful connection is intercepted, the player can be used to monitor the screen
1952500	1963990	and input of the session. When the attacker clicks the take control button, pyrdp takes over
1963990	1969050	the session and redirects all player inputs to the server and all server output to the player.
1969050	1974970	The real RDP client appears frozen during the hijack. Once the attacker is done, the session
1974970	1980590	is returned to the client, which unfreezes. This technique is noisy, but looks like a network error
1980590	1987270	to the untrained eye. After the real client recovers control, there may be artifacts on
1987270	1992290	the screen because the server and client will be out of sync. In order to avoid that, the screen
1992290	1997230	should be left as closely as possible to its original arrangement when control is removed.
1999390	2003850	Hiring a specific server does not scale well during engagements, because it will most likely
2003850	2009070	redirect intercepted sessions to a server which isn't the one that the client tried to connect to.
2009230	2013910	Pyrdp supports transparent proxying with the help of a few firewall rules.
2014130	2017010	Note that this technique only works on Linux and requires
2017010	2020910	running pyrdp as root to use IP transparent sockets.
2022290	2026710	Use the firewall rule templates from the documentation directory and modify them to
2026710	2032790	reflect your environment. Here, we use the address range that we will ARP spoof. Because we're spoofing
2032790	2038750	the subnet we are in, we exclude our own IP address to prevent packet production loops in IP tables.
2039710	2044290	Next, create a custom routing table for pyrdp's intercepted connections.
2044290	2047190	Table ID is a number identifying the table.
2049210	2053390	Ensure that IP forwarding is enabled and create a pre-routing rule that will
2053390	2058630	mark all traffic distant to the server range for transparent proxying by pyrdp.
2075800	2081200	The last firewall rule is used to mark traffic coming back from the servers to the clients for
2081200	2105870	transparent proxy. The last step is to ensure that marked packets use the pyrdp routing table
2105870	2110390	created earlier, which will be responsible for delivering the marked packets to pyrdp
2110390	2124610	through the loopback interface. With the firewall configured, make sure to launch pyrdp as root and
2124610	2138600	provide the transparent switch to enable transparent proxying. Start vendor cap on your
2138600	2151770	land facing interface and ARP spoof the subnet to intercept. Here, we set ARP spoof internal to true
2151770	2156750	because we are spoofing our own subnet. This is not required when spoofing an adjacent subnet.
2156750	2160230	For the demonstration, we are only spoofing one client.
2172260	2177080	When the victim attempts to connect to their destination server, they will be intercepted by
2177080	2182140	pyrdp, which will then establish a connection with the intended server. This technique scales
2182140	2191890	well for internal engagements and works in combination with other attacks. The last technique
2191890	2197130	that we will cover is command injection, which automates session hijacking to seamlessly run a
2197130	2202550	payload for an intercepted connection. Using the same transparent proxy configuration as the previous
2202550	2209530	technique, start pyrdp with a PowerShell payload that acts as a stager. This stager will query a
2209530	2214630	web server which hosts the real malicious payload and execute it in the context of the intercepted
2214630	2220750	session. The payload delay and payload duration parameters are used to control when the payload
2220750	2227810	should be executed and how long to hijack the session for. The malicious payload consists of
2227930	2233210	a simple PowerShell reverse shell for demonstration purposes. This shell will connect back to the
2233210	2244570	pyrdp workstation on port 888. Start Metasploit's multi-handler to cache the reverse shell once it
2244570	2261250	is established. Next, use Python's built-in web server to host the payload that the stager will
2261250	2272790	retrieve. Make sure to disable exit on session so that multiple sessions can be intercepted.
2289740	2295120	Lastly, start armscoping to intercept RDP sessions as they are established.
2329500	2334220	Once a session is intercepted, everything will proceed as normal from the client's point of view
2334220	2339840	until the payload delay is reached. After the delay has elapsed, the client session will appear
2339840	2345520	to freeze while the payload is being delivered and executed. The stager retrieves the code from
2345520	2349680	the server and executes it, causing the reverse shell to connect to the Metasploit listener
2349680	2353480	and giving the attacker covert access to the target server.
2366320	2370980	Even if the client later disconnects from the server, the reverse shell persists.
2371540	2375900	This technique is powerful and can easily result in multiple sessions when using less
2375900	2388470	detectable payloads. This concludes our brief tour of pyrdp's features. If you'd like to see
2388470	2394450	the full feature set or get the source code, make sure to check out the pyrdp GitHub. Lastly,
2394450	2399370	if you have any war stories to share, we'd be happy to hear about them. Thanks for watching!
