1
- using System . Net ;
2
- using System . Net . Security ;
3
- using System . Net . Sockets ;
1
+ using System . Drawing ;
2
+ using System . Drawing . Imaging ;
4
3
5
4
namespace Devolutions . IronRdp . ConnectExample
6
5
{
@@ -10,9 +9,9 @@ static async Task Main(string[] args)
10
9
{
11
10
var arguments = ParseArguments ( args ) ;
12
11
13
- if ( arguments == null )
12
+ if ( arguments == null )
14
13
{
15
- return ;
14
+ return ;
16
15
}
17
16
18
17
var serverName = arguments [ "--serverName" ] ;
@@ -21,15 +20,95 @@ static async Task Main(string[] args)
21
20
var domain = arguments [ "--domain" ] ;
22
21
try
23
22
{
24
- await Connect ( serverName , username , password , domain ) ;
23
+ var ( res , framed ) = await Connection . Connect ( buildConfig ( serverName , username , password , domain , 1980 , 1080 ) , serverName ) ;
24
+ var decodedImage = DecodedImage . New ( PixelFormat . RgbA32 , res . GetDesktopSize ( ) . GetWidth ( ) , res . GetDesktopSize ( ) . GetHeight ( ) ) ;
25
+ var activeState = ActiveStage . New ( res ) ;
26
+ var keepLooping = true ;
27
+ while ( keepLooping )
28
+ {
29
+ var readPduTask = framed . ReadPdu ( ) ;
30
+ Action ? action = null ;
31
+ byte [ ] ? payload = null ;
32
+ if ( readPduTask == await Task . WhenAny ( readPduTask , Task . Delay ( 1000 ) ) )
33
+ {
34
+ var pduReadTask = await readPduTask ;
35
+ action = pduReadTask . Item1 ;
36
+ payload = pduReadTask . Item2 ;
37
+ Console . WriteLine ( $ "Action: { action } ") ;
38
+ }
39
+ else
40
+ {
41
+ Console . WriteLine ( "Timeout" ) ;
42
+ break ;
43
+ }
44
+ var outputIterator = activeState . Process ( decodedImage , action , payload ) ;
45
+
46
+ while ( ! outputIterator . IsEmpty ( ) )
47
+ {
48
+ var output = outputIterator . Next ( ) ! ; // outputIterator.Next() is not null since outputIterator.IsEmpty() is false
49
+ Console . WriteLine ( $ "Output type: { output . GetType ( ) } ") ;
50
+ if ( output . GetType ( ) == ActiveStageOutputType . Terminate )
51
+ {
52
+ Console . WriteLine ( "Connection terminated." ) ;
53
+ keepLooping = false ;
54
+ }
55
+
56
+ if ( output . GetType ( ) == ActiveStageOutputType . ResponseFrame )
57
+ {
58
+ var responseFrame = output . GetResponseFrame ( ) ! ;
59
+ byte [ ] responseFrameBytes = new byte [ responseFrame . GetSize ( ) ] ;
60
+ responseFrame . Fill ( responseFrameBytes ) ;
61
+ await framed . Write ( responseFrameBytes ) ;
62
+ }
63
+ }
64
+ }
65
+
66
+ saveImage ( decodedImage , "output.png" ) ;
67
+
25
68
}
26
- catch ( Exception e )
69
+ catch ( Exception e )
27
70
{
28
71
Console . WriteLine ( $ "An error occurred: { e . Message } ") ;
29
72
}
30
73
}
31
74
32
- static Dictionary < string , string > ParseArguments ( string [ ] args )
75
+ private static void saveImage ( DecodedImage decodedImage , string v )
76
+ {
77
+ int width = decodedImage . GetWidth ( ) ;
78
+ int height = decodedImage . GetHeight ( ) ;
79
+ var data = decodedImage . GetData ( ) ;
80
+
81
+ var bytes = new byte [ data . GetSize ( ) ] ;
82
+ data . Fill ( bytes ) ;
83
+ for ( int i = 0 ; i < bytes . Length ; i += 4 )
84
+ {
85
+ byte temp = bytes [ i ] ; // Store the original Blue value
86
+ bytes [ i ] = bytes [ i + 2 ] ; // Move Red to Blue's position
87
+ bytes [ i + 2 ] = temp ; // Move original Blue to Red's position
88
+ // Green (bytes[i+1]) and Alpha (bytes[i+3]) remain unchanged
89
+ }
90
+ #if WINDOWS // Bitmap is only available on Windows
91
+ using ( var bmp = new Bitmap ( width , height ) )
92
+ {
93
+ // Lock the bits of the bitmap.
94
+ var bmpData = bmp . LockBits ( new Rectangle ( 0 , 0 , bmp . Width , bmp . Height ) ,
95
+ ImageLockMode . WriteOnly , System . Drawing . Imaging . PixelFormat . Format32bppArgb ) ;
96
+
97
+ // Get the address of the first line.
98
+ IntPtr ptr = bmpData . Scan0 ;
99
+ // Copy the RGBA values back to the bitmap
100
+ System . Runtime . InteropServices . Marshal . Copy ( bytes , 0 , ptr , bytes . Length ) ;
101
+ // Unlock the bits.
102
+ bmp . UnlockBits ( bmpData ) ;
103
+
104
+ // Save the bitmap to the specified output path
105
+ bmp . Save ( "./output.bmp" , ImageFormat . Bmp ) ;
106
+ }
107
+ #endif
108
+
109
+ }
110
+
111
+ static Dictionary < string , string > ? ParseArguments ( string [ ] args )
33
112
{
34
113
if ( args . Length == 0 || Array . Exists ( args , arg => arg == "--help" ) )
35
114
{
@@ -38,7 +117,7 @@ static Dictionary<string, string> ParseArguments(string[] args)
38
117
}
39
118
40
119
var arguments = new Dictionary < string , string > ( ) ;
41
- string lastKey = null ;
120
+ string ? lastKey = null ;
42
121
foreach ( var arg in args )
43
122
{
44
123
if ( arg . StartsWith ( "--" ) )
@@ -97,222 +176,21 @@ static void PrintHelp()
97
176
Console . WriteLine ( " --help Show this message and exit." ) ;
98
177
}
99
178
100
- static async Task Connect ( String servername , String username , String password , String domain )
101
- {
102
- Config config = buildConfig ( servername , username , password , domain ) ;
103
-
104
- var stream = await CreateTcpConnection ( servername , 3389 ) ;
105
- var framed = new Framed < NetworkStream > ( stream ) ;
106
179
107
- ClientConnector connector = ClientConnector . New ( config ) ;
108
-
109
- var ip = await Dns . GetHostAddressesAsync ( servername ) ;
110
- if ( ip . Length == 0 )
111
- {
112
- throw new Exception ( "Could not resolve server address" ) ;
113
- }
114
-
115
- var socketAddrString = ip [ 0 ] . ToString ( ) + ":3389" ;
116
- connector . WithServerAddr ( socketAddrString ) ;
117
-
118
- await connectBegin ( framed , connector ) ;
119
- var ( serverPublicKey , framedSsl ) = await securityUpgrade ( servername , framed , connector ) ;
120
- await ConnectFinalize ( servername , connector , serverPublicKey , framedSsl ) ;
121
- }
122
180
123
- private static async Task < ( byte [ ] , Framed < SslStream > ) > securityUpgrade ( string servername , Framed < NetworkStream > framed , ClientConnector connector )
124
- {
125
- byte [ ] serverPublicKey ;
126
- Framed < SslStream > framedSsl ;
127
- var ( streamRequireUpgrade , _) = framed . GetInner ( ) ;
128
- var promise = new TaskCompletionSource < byte [ ] > ( ) ;
129
- var sslStream = new SslStream ( streamRequireUpgrade , false , ( sender , certificate , chain , sslPolicyErrors ) =>
130
- {
131
- promise . SetResult ( certificate ! . GetPublicKey ( ) ) ;
132
- return true ;
133
- } ) ;
134
- await sslStream . AuthenticateAsClientAsync ( servername ) ;
135
- serverPublicKey = await promise . Task ;
136
- framedSsl = new Framed < SslStream > ( sslStream ) ;
137
- connector . MarkSecurityUpgradeAsDone ( ) ;
138
-
139
- return ( serverPublicKey , framedSsl ) ;
140
- }
141
-
142
- private static async Task connectBegin ( Framed < NetworkStream > framed , ClientConnector connector )
143
- {
144
- var writeBuf = WriteBuf . New ( ) ;
145
- while ( ! connector . ShouldPerformSecurityUpgrade ( ) )
146
- {
147
- await SingleConnectStep ( connector , writeBuf , framed ) ;
148
- }
149
- }
150
-
151
- private static Config buildConfig ( string servername , string username , string password , string domain )
181
+ private static Config buildConfig ( string servername , string username , string password , string domain , int width , int height )
152
182
{
153
183
ConfigBuilder configBuilder = ConfigBuilder . New ( ) ;
154
184
155
- configBuilder . WithUsernameAndPasswrord ( username , password ) ;
185
+ configBuilder . WithUsernameAndPassword ( username , password ) ;
156
186
configBuilder . SetDomain ( domain ) ;
157
- configBuilder . SetDesktopSize ( 800 , 600 ) ;
187
+ configBuilder . SetDesktopSize ( ( ushort ) height , ( ushort ) width ) ;
158
188
configBuilder . SetClientName ( "IronRdp" ) ;
159
189
configBuilder . SetClientDir ( "C:\\ " ) ;
160
190
configBuilder . SetPerformanceFlags ( PerformanceFlags . NewDefault ( ) ) ;
161
191
162
192
return configBuilder . Build ( ) ;
163
193
}
164
194
165
- private static async Task ConnectFinalize ( string servername , ClientConnector connector , byte [ ] serverpubkey , Framed < SslStream > framedSsl )
166
- {
167
- var writeBuf2 = WriteBuf . New ( ) ;
168
- if ( connector . ShouldPerformCredssp ( ) )
169
- {
170
- await PerformCredsspSteps ( connector , servername , writeBuf2 , framedSsl , serverpubkey ) ;
171
- }
172
- while ( ! connector . State ( ) . IsTerminal ( ) )
173
- {
174
- await SingleConnectStep ( connector , writeBuf2 , framedSsl ) ;
175
- }
176
- }
177
-
178
- private static async Task PerformCredsspSteps ( ClientConnector connector , string serverName , WriteBuf writeBuf , Framed < SslStream > framedSsl , byte [ ] serverpubkey )
179
- {
180
- var credsspSequenceInitResult = CredsspSequence . Init ( connector , serverName , serverpubkey , null ) ;
181
- var credsspSequence = credsspSequenceInitResult . GetCredsspSequence ( ) ;
182
- var tsRequest = credsspSequenceInitResult . GetTsRequest ( ) ;
183
- TcpClient tcpClient = new TcpClient ( ) ;
184
- while ( true )
185
- {
186
- var generator = credsspSequence . ProcessTsRequest ( tsRequest ) ;
187
- var clientState = await ResolveGenerator ( generator , tcpClient ) ;
188
- writeBuf . Clear ( ) ;
189
- var written = credsspSequence . HandleProcessResult ( clientState , writeBuf ) ;
190
-
191
- if ( written . GetSize ( ) . IsSome ( ) )
192
- {
193
- var actualSize = ( int ) written . GetSize ( ) . Get ( ) ;
194
- var response = new byte [ actualSize ] ;
195
- writeBuf . ReadIntoBuf ( response ) ;
196
- await framedSsl . Write ( response ) ;
197
- }
198
-
199
- var pduHint = credsspSequence . NextPduHint ( ) ! ;
200
- if ( pduHint == null )
201
- {
202
- break ;
203
- }
204
-
205
- var pdu = await framedSsl . ReadByHint ( pduHint ) ;
206
- var decoded = credsspSequence . DecodeServerMessage ( pdu ) ;
207
-
208
- if ( null == decoded )
209
- {
210
- break ;
211
- }
212
-
213
- tsRequest = decoded ;
214
- }
215
- }
216
-
217
- private static async Task < ClientState > ResolveGenerator ( CredsspProcessGenerator generator , TcpClient tcpClient )
218
- {
219
- var state = generator . Start ( ) ;
220
- NetworkStream stream = null ;
221
- while ( true )
222
- {
223
- if ( state . IsSuspended ( ) )
224
- {
225
- var request = state . GetNetworkRequestIfSuspended ( ) ! ;
226
- var protocol = request . GetProtocol ( ) ;
227
- var url = request . GetUrl ( ) ;
228
- var data = request . GetData ( ) ;
229
- if ( null == stream )
230
- {
231
- url = url . Replace ( "tcp://" , "" ) ;
232
- var split = url . Split ( ":" ) ;
233
- await tcpClient . ConnectAsync ( split [ 0 ] , int . Parse ( split [ 1 ] ) ) ;
234
- stream = tcpClient . GetStream ( ) ;
235
-
236
- }
237
- if ( protocol == NetworkRequestProtocol . Tcp )
238
- {
239
- stream . Write ( Utils . Vecu8ToByte ( data ) ) ;
240
- var readBuf = new byte [ 8096 ] ;
241
- var readlen = await stream . ReadAsync ( readBuf , 0 , readBuf . Length ) ;
242
- var actuallyRead = new byte [ readlen ] ;
243
- Array . Copy ( readBuf , actuallyRead , readlen ) ;
244
- state = generator . Resume ( actuallyRead ) ;
245
- }
246
- else
247
- {
248
- throw new Exception ( "Unimplemented protocol" ) ;
249
- }
250
- }
251
- else
252
- {
253
- var client_state = state . GetClientStateIfCompleted ( ) ;
254
- return client_state ;
255
- }
256
- }
257
- }
258
-
259
- static async Task SingleConnectStep < T > ( ClientConnector connector , WriteBuf buf , Framed < T > framed )
260
- where T : Stream
261
- {
262
- buf . Clear ( ) ;
263
-
264
- var pduHint = connector . NextPduHint ( ) ;
265
- Written written ;
266
- if ( pduHint != null )
267
- {
268
- byte [ ] pdu = await framed . ReadByHint ( pduHint ) ;
269
- written = connector . Step ( pdu , buf ) ;
270
- }
271
- else
272
- {
273
- written = connector . StepNoInput ( buf ) ;
274
- }
275
-
276
- if ( written . GetWrittenType ( ) == WrittenType . Nothing )
277
- {
278
- return ;
279
- }
280
-
281
- // will throw if size is not set
282
- var size = written . GetSize ( ) . Get ( ) ;
283
-
284
- var response = new byte [ size ] ;
285
- buf . ReadIntoBuf ( response ) ;
286
-
287
- await framed . Write ( response ) ;
288
- }
289
-
290
- static async Task < NetworkStream > CreateTcpConnection ( String servername , int port )
291
- {
292
- IPHostEntry ipHostInfo = await Dns . GetHostEntryAsync ( servername ) ;
293
- IPAddress ipAddress = ipHostInfo . AddressList [ 0 ] ;
294
- IPEndPoint ipEndPoint = new ( ipAddress , port ) ;
295
-
296
- TcpClient client = new TcpClient ( ) ;
297
-
298
- await client . ConnectAsync ( ipEndPoint ) ;
299
- NetworkStream stream = client . GetStream ( ) ;
300
-
301
- return stream ;
302
- }
303
-
304
195
}
305
-
306
- public static class Utils
307
- {
308
- public static byte [ ] Vecu8ToByte ( VecU8 vecU8 )
309
- {
310
- var len = vecU8 . GetSize ( ) ;
311
- byte [ ] buffer = new byte [ len ] ;
312
- vecU8 . Fill ( buffer ) ;
313
- return buffer ;
314
- }
315
- }
316
- }
317
-
318
-
196
+ }
0 commit comments