Remote DeskTop is a Client/Server program that allows a user to operate another Windows computer remotely over a LAN/WAN. The Server component can operate as a service, which means that it must have some sort of authentication process. The last thing you would want is for an unauthorized individual to have complete access to your computer. That necessitates having some sort of encryption scheme. The security scheme I have chosen to use could be considered somewhat extreme for this particular application, but it is one that I had already worked out the details for.
In order for a Client to access a remote desktop computer, he/she would require a UserID and Password to be registered with the Server. After connection, the Client sends the Client Hello, consisting of the plain text UserID and the Public ECC (Elliptical Curve Cryptography) key (256 bit) generated by the Client program. The Server receives that information, verifies the UserID, generates it's own ECC key pair, combines the Client's Public key with it's own Private key to generate an Agreed Secret, and sends back to the Client it's Public ECC key as a Server Hello. The Client then combines the Server's Public key with it's own Private key to form the same Agreed Secret as the Server. The Client uses that Agreed Secret to encrypt a 256 bit Hash of the Password, and sends it to the Server. The Server uses it's own Agreed Secret to decrypt the Password Hash, and verifies it.
Because the Server is basically unmonitored, these extreme measures are necessary. It is my intention to develop a single program that can act as either a Client or a Server, and can connect to the other end or listen for a connection. Under this scenario, the connection would be monitored on both ends, and all this security would be unnecessary. This would allow a user to be remotely assisted without the necessity of opening/forwarding a port.
To facilitate operating a Windows computer remotely, the DeskTop of the remote computer (Server) has to be periodically transmitted to the Client, and the mouse and keyboard activities of the Client have to be sent to the Server and implemented. The DeskTop bitmap of the server is quite large, and may not be the same size as the Clients. To reduce the amount of data to be transmitted, I have chosen to use Steve McMahon's ImgProc (vbaccelerator). He utilized Intel's IJL11.DLL library, which I have upgraded to IJL20.DLL. These tools convert the desktop bitmap to a jpeg, thereby reducing traffic by a factor of over 20. I have arbitrarily chosen a one second desktop update, but that number is open to discussion. I have also arbitrarily chosen to use 80% of the Client's desktop to display the Server's desktop, and the algorithm's used allows the dimensions to be adjusted to suit the Client's needs. Please note that I have only allowed for forms to be configured in Twips.
Every activity (mouse or keyboard) at the Client end needs to be duplicated at the Server end. Each mouse movement to a new pixel location causes 28 bytes to be sent to the outgoing TCP buffer and sent to the Server. The server however can accumulate several of these records before it gets around to processing them. So I added a 100 ms timer that only processes the last one and ignores the rest. That number is again arbitrary, and results in a choppy mouse movement at the Server end.
I would like to find a way to update and send the desktop image only if it changes, in order to reduce the traffic required. For reasons unknown to me, the jpeg changes size slightly every transmission, so I can't use that. I am open to suggestions on how I might accomplish this. As you can probably guess, graphics is not one of my strong suits.
rDeskS can be operated as a service or as a desktop application. In either case it requires NTSVC.OCX. rDskCtrl is utilized to configure both the service and desktop. Further instructions on configuration are included in the ReadMe.txt file with each download. The Server also requires a log file location. The service logs to \Windows\System32\LogFiles\rDesk, and the desktop program logs to a sub directory called Logs in the application directory.
Some necessary features have yet to be added to the programs. Those would include copying data from the Server's desktop to the Client's clipboard, copying files from one computer to the other, and creating a Chat window.
In case you are wondering about the security of the Password storage, the Server stores the Password as a shuffled hash in a database called users.db. A default file called users.db.org is included that contains an Admin UserID and blank password entry. The password is also stored in the Client as a shuffled hash. This shuffle uses the computer's SID as a key, so the shuffled hash cannot be simply copied to another computer, and it is different than the one used on the Server.
Please note that if you operate both the Server and Client on the same computer, the desktop image on the Client will shrink with every update, and mouse activity will not behave properly because the source is the same as the destination. Also, keyboard activity will fail in the IDE because of the well known SendKeys issue.
very good project
Right now I can not test it on my machine because of NTSVC.OCX XD but when I can I try it.
it occurs to me that if the data transfer is very slow with the image you can put an option that the user can regulate the quality of the image,
because there will be people who prefer something functional rather than something very colorful.
and if you want to improve the most, add a text chat and a voice chat if it is not very difficult, since you are familiar with the chats.
Remote DeskTop is a Client/Server program that allows a user to operate another Windows computer remotely over a LAN/WAN. The Server component can operate as a service, which means that it must have some sort of authentication process. The last thing you would want is for an unauthorized individual to have complete access to your computer. That necessitates having some sort of encryption scheme. The security scheme I have chosen to use could be considered somewhat extreme for this particular application, but it is one that I had already worked out the details for.
In order for a Client to access a remote desktop computer, he/she would require a UserID and Password to be registered with the Server. After connection, the Client sends the Client Hello, consisting of the plain text UserID and the Public ECC (Elliptical Curve Cryptography) key (256 bit) generated by the Client program. The Server receives that information, verifies the UserID, generates it's own ECC key pair, combines the Client's Public key with it's own Private key to generate an Agreed Secret, and sends back to the Client it's Public ECC key as a Server Hello. The Client then combines the Server's Public key with it's own Private key to form the same Agreed Secret as the Server. The Client uses that Agreed Secret to encrypt a 256 bit Hash of the Password, and sends it to the Server. The Server uses it's own Agreed Secret to decrypt the Password Hash, and verifies it.
Because the Server is basically unmonitored, these extreme measures are necessary. It is my intention to develop a single program that can act as either a Client or a Server, and can connect to the other end or listen for a connection. Under this scenario, the connection would be monitored on both ends, and all this security would be unnecessary. This would allow a user to be remotely assisted without the necessity of opening/forwarding a port.
To facilitate operating a Windows computer remotely, the DeskTop of the remote computer (Server) has to be periodically transmitted to the Client, and the mouse and keyboard activities of the Client have to be sent to the Server and implemented. The DeskTop bitmap of the server is quite large, and may not be the same size as the Clients. To reduce the amount of data to be transmitted, I have chosen to use Steve McMahon's ImgProc (vbaccelerator). He utilized Intel's IJL11.DLL library, which I have upgraded to IJL20.DLL. These tools convert the desktop bitmap to a jpeg, thereby reducing traffic by a factor of over 20. I have arbitrarily chosen a one second desktop update, but that number is open to discussion. I have also arbitrarily chosen to use 80% of the Client's desktop to display the Server's desktop, and the algorithm's used allows the dimensions to be adjusted to suit the Client's needs. Please note that I have only allowed for forms to be configured in Twips.
Every activity (mouse or keyboard) at the Client end needs to be duplicated at the Server end. Each mouse movement to a new pixel location causes 28 bytes to be sent to the outgoing TCP buffer and sent to the Server. The server however can accumulate several of these records before it gets around to processing them. So I added a 100 ms timer that only processes the last one and ignores the rest. That number is again arbitrary, and results in a choppy mouse movement at the Server end.
I would like to find a way to update and send the desktop image only if it changes, in order to reduce the traffic required. For reasons unknown to me, the jpeg changes size slightly every transmission, so I can't use that. I am open to suggestions on how I might accomplish this. As you can probably guess, graphics is not one of my strong suits.
rDeskS can be operated as a service or as a desktop application. In either case it requires NTSVC.OCX. rDskCtrl is utilized to configure both the service and desktop. Further instructions on configuration are included in the ReadMe.txt file with each download. The Server also requires a log file location. The service logs to \Windows\System32\LogFiles\rDesk, and the desktop program logs to a sub directory called Logs in the application directory.
Some necessary features have yet to be added to the programs. Those would include copying data from the Server's desktop to the Client's clipboard, copying files from one computer to the other, and creating a Chat window.
In case you are wondering about the security of the Password storage, the Server stores the Password as a shuffled hash in a database called users.db. A default file called users.db.org is included that contains an Admin UserID and blank password entry. The password is also stored in the Client as a shuffled hash. This shuffle uses the computer's SID as a key, so the shuffled hash cannot be simply copied to another computer, and it is different than the one used on the Server.
Please note that if you operate both the Server and Client on the same computer, the desktop image on the Client will shrink with every update, and mouse activity will not behave properly because the source is the same as the destination. Also, keyboard activity will fail in the IDE because of the well known SendKeys issue.
J.A. Coutts
Many Trojans use remote desktop operations,Or other remote control software.
i do not know more,You can refer to
Many Trojans use remote desktop operations,Or other remote control software.
Trojans usually want to do things in the background with administrative privileges. In fact, most of the examples I found did exactly that. That is why I considered authentication very necessary for this particular application. The general purpose application that I am currently working on to provide assistance to users that are not very computer literate, I don't believe requires this level of security.
Addendum: The one exception to that is keystrokes. You do not want a man-in-the-middle picking up passwords.
J.A. Coutts
Last edited by couttsj; Feb 4th, 2019 at 01:33 PM.
Keystroke encryption has been added to Remote DeskTop. As alluded to earlier, transmitted keystrokes are vulnerable to a man-in-the-middle attack, and passwords could possibly be picked off by a hacker. Encrypting a one character message is not safe, and can be easily cracked.
The Client program utilizes a User Control to present an image of the Server's desktop. I would have liked to support Unicode, but unfortunately the User Control only supports ASCII. Each keyboard or mouse action is sent from the Client to the Server as a 28 byte record. The first 8 bytes are the record header, the next 4 bytes define the type of action, and the last 16 bytes consist of the data. In the case of keystrokes, only four of those 16 bytes was actually being used, and even that was only really using one byte out of the four allocated. So I created a random 16 byte array, and inserted the key byte into the middle of it. Then I encrypted those 16 bytes, added the Action code and record header, and sent it to the Server.
The Server then decrypted those 16 bytes, extracted the keycode, and duplicated it with the SendKeys command. The Client will not display the character until the DeskTop window is updated by the Server. Because of this, I reduced the screen update time to 500 ms. Because the 16 bytes of data to be encrypted is randomly generated for each keystroke, the middle byte containing the KeyCode will be different each time the same character is transmitted.
ClipBoard Cut & Paste has been added to Remote Desktop. This one has taken a fair amount of effort to implement. Some of those difficulties were created by the Win 10 implementation of ClipBoard History (multiple ClipBoards). Even though it is optional and disabled by default, it still had an impact. Hopefully, all those issues have been resolved.
The ClipBoard can be used to Copy/Cut & Paste text from and to the Remote DeskTop, as well as from the Remote DeskTop to the local Desktop. I considered this feature essential.
I would like to find a way to update and send the desktop image only if it changes, in order to reduce the traffic required. For reasons unknown to me, the jpeg changes size slightly every transmission, so I can't use that. I am open to suggestions on how I might accomplish this. As you can probably guess, graphics is not one of my strong suits.
I would hash the raw pixel data before transmission and compare that hash to the hash of the last image transmitted. If they are different, then it means the image has changed. MD5 or some variant of SHA or even CRC32 are all viable hashing algorithms to do this.
C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter
There's just no reason to use garbage like InputBox. - jmcilhinney
The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber
I would hash the raw pixel data before transmission and compare that hash to the hash of the last image transmitted. If they are different, then it means the image has changed. MD5 or some variant of SHA or even CRC32 are all viable hashing algorithms to do this.
Since the jpeg had already been converted to a byte array, I did an MD5 hash on it and compared it to the previous one. The jpeg was over 20 twenty times smaller than the bitmap, so hashing the jpeg made more sense than converting the bitmap to a byte array and hashing it.
Using a single *whole* image is never going to feel responsive. You have to use a quad tree to subdivide current delta on changing and static quarters, w/ each changing tile further subdivider on changing and static quarters until tile size reaches about 8px (as JPEG uses 8x8 tiles to do compression internally).
Another thing to consider is using a Mirror Driver for the video capture. There must be free/open source impl for the various VNC clones on Windows.
File Copy and File Delete have been added. This required a major change in the design of the Client program. I originally used a User Control, but this proved to be too restrictive when using a separate form with the socket code. Since the socket code does not include any form objects, I used an invisible form for those functions. This allowed me to use a single socket form to support different interface forms. Although the server program did not require the same modification, it was also changed for consistency. They are provided here as separate downloads.
Once the Client is connected, the user can activate the Copy form. This is a simplified copy function without all the bells and whistles of Windows Explorer. It is configured to expand to the size of the Remote DeskTop window without the ability to adjust it's size or location. This is done to minimize the update traffic to and from the Server program while using the Copy part of the program.
When first activated, it displays the root directory of the local and remote computers, with the directories listed on the left and files on the right. Double clicking any directory will display it's files and directories. Clicking on a file will highlight that file and display it's full path in the upper text box. It will also activate the SEND or RECEIVE button as well as the appropriate DELETE. Double clicking the directory listed at the top of the directory list will return that listing to the root directory. Copied files will be highlighted in the destination listing when the copy is complete. I have not yet added a progress bar, but that remains an option for the future.
One of the objectives in developing this program was to improve Remote Desktop performance, particularly at the Server end. To measure this, I used the MS Resource Monitor with the appropriate program selected as image. The Resource Monitor itself was placed in the middle of the Desktop on the Server program, so that changes to the Resource Monitor would provide a consistent set of screen updates. With the Server running on a Win 8.1 computer using an Intel i5 at 2.80GHz, and the Client running on a Win 10 computer using an Intel i3 at 2.00GHz, the following CPU utilizations were recorded.
RemoteC (Win 10) - 2.45 using 4 threads
RemoteS (Win 8.1) - 0.75 using 2 threads
All unnecessary programs were shut down.
Using UltraVNC, I then used the same test conditions to record the following CPU utilizations.
VNC Viewer (Win 10) - 0.11 using 6 threads
VNC Server (Win 8.1) - 1.42 using 11 threads
The VNC Viewer was considerably more efficient than RemoteC, but RemoteS was more efficient than VNC Server. I don't know anything about the internal workings of UltraVNC, but I suspect it's viewer is more efficient because it only updates the portion of the screen that changes. From my point of view, the efficiency at the Server end is more important because it is where the actual work will be done. The other thing to note is that UltraVNC Viewer uses a fixed window size, whereas RemoteC is user adjustable.
J.A. Coutts
Bug Fix: 03/27/2019 Copy file to Remote error
Last edited by couttsj; Mar 27th, 2019 at 11:03 AM.
Ran into another necessary feature that I need to add. Even though access is encrypted password protected, passwords are not very long and vulnerable to brute force attacks. I have recently encountered attempts to break into our server using VNC. UltraVNC requires password protection, and it does support IP Address blocking/permitting, but my idea is to automate the blocking function by adding an IP Address to a block list after a certain number of bad password attempts. Does this sound reasonable?
An error was discovered in RemoteC when copying a file from the local machine to the remote machine. The array ByteBuffer is used in both Socket.frm and frmCopy.frm, but was not properly defined in frmCopy.frm. Because this array is common to both forms, it must be defined as Public, and arrays cannot be defined as Public in a form. They must be defined in a standard module.
Therefore, remove or comment out the following line in Socket.frm:
'Private ByteBuffer() As Byte
and add the following line to a module (ie. modJPG.bas):
Public ByteBuffer() As Byte
I will update the download tomorrow. Sorry for the inconvenience.
The download on post #14 has been updated to fix the bug discovered a couple of days ago. As well, an automated blocking function has been added and demonstrated below.
Code:
Option Explicit
Private BlockList() As Long
Private BlockCount() As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Sub AddToList(sAddress As String)
Dim lAddress As Long
Dim N%
lAddress = ConvToLong(sAddress)
For N% = 0 To UBound(BlockList)
If lAddress = BlockList(N%) Then 'Already in list
BlockCount(N%) = BlockCount(N%) + 1 'Update counter
Exit For
ElseIf BlockList(N%) = 0 Then 'List position is available
BlockList(N%) = lAddress
BlockCount(N%) = 1
If N% = UBound(BlockList) Then
BlockCount(0) = 0 'Free up first position in list
Else
BlockCount(N% + 1) = 0 'Free up next position in list
End If
Exit For
End If
Next N%
End Sub
Private Function ConvToLong(sAddr As String) As Long
Dim sArray() As String
Dim bArray(3) As Byte
Dim lAddr As Long
Dim N%
On Error GoTo ConvToLongErr
sArray = Split(sAddr, ".")
For N% = 0 To 3
bArray(N%) = sArray(N%)
Next N%
CopyMemory ByVal VarPtr(lAddr), bArray(0), 4
ConvToLong = lAddr
ConvToLongErr:
End Function
Private Function OnBlockList(Source As String) As Boolean
Dim I%
Dim lSource As Long
On Error GoTo OnBlockListErr
lSource = ConvToLong(Source)
For I% = 0 To UBound(BlockList)
If lSource = BlockList(I%) Then
If BlockCount(I%) > 5 Then OnBlockList = True
Exit Function
End If
Next I%
OnBlockListErr:
OnBlockList = False
End Function
Private Sub cmdNext_Click()
Const sAddress As String = "192.168.0."
Static lNum As Long
If lNum = 5 Then
lNum = 1
Else
lNum = lNum + 1
End If
Text2.Text = sAddress & CStr(lNum)
Call AddToList(Text2.Text)
Text1.Text = BlockList(0) & " " & BlockCount(0) & vbCrLf _
& BlockList(1) & " " & BlockCount(1) & vbCrLf _
& BlockList(2) & " " & BlockCount(2) & vbCrLf _
& BlockList(3) & " " & BlockCount(3) & vbCrLf _
& BlockList(4) & " " & BlockCount(4) & vbCrLf
If OnBlockList(Text2.Text) Then Debug.Print Text2.Text & " is on Block List!"
End Sub
Private Sub Form_Load()
ReDim BlockList(4)
ReDim BlockCount(4)
End Sub
This routine uses a 5 element round robin array and matching counter array. I used 2 arrays because this routine uses long values to store the IPv4 address, and doesn't support IPv6. IPv6 would require 16 bytes to store addresses. The counter itself being zero identifies an available slot, and when one slot is utilized, it clears the next highest counter (or first one). You will need one command button (cmdNext) and 2 text boxes (text1/text2) to run the simulation, with text1 being multiline.
Just do a Google search for "NTSVC.OCX download". Be sure to verify the hash code to ensure that the code hasn't been tampered with. If you still have difficulty, send me a PM.
FYI, Screen Mirror Drivers seem to be deprecated so since Windows 8.1 their functionality is built into the OS and is exposed through Desktop Duplication API part of DirectX 11.
Maybe this cJpeg can be used instead Intel's dll. You keep the process inside the application code, so there is no need to load a library to make jpegs.
Last edited by georgekar; Apr 13th, 2019 at 03:48 PM.
Except that this pure VB6 encoder is dog slow. I would research what codec the guys at WebRTC are using. Almost sure they are using H.264 (like the MP4 videos from smartphones) for GPU accelerated encoding/decoding on about 100% of present PCs.
FYI, Screen Mirror Drivers seem to be deprecated so since Windows 8.1 their functionality is built into the OS and is exposed through Desktop Duplication API part of DirectX 11.
Graphics work is not exactly my forte, and I have zero experience working with DirectX. According to Microsoft, "To reconstruct the correct desktop image, your client app must first process all the move regions and then process all the dirty regions." That includes the mouse image, and sort of explains what happens with VNC when the network flow is interrupted, as sometimes occurs with WiFi in highly competitive zones. I get a scattered array of partial characters in a rectangular area instead of characters, or I temporarily see one or more red rectangles instead of the real image. With my own program, it just skips that particular screen update, and the mouse image is handled separately.
It is entirely possible that a more sophisticated update mechanism could be more efficient than the jpeg methodology that I have employed, but the tests that I have conducted so far indicate that the jpeg method is twice as efficient at the server end. The client end is not nearly as efficient, but to me the server end is far more important, because that is where the actual work is going to be done. The client end simply reflects what visually happens at the server end. The jpeg coloring is not accurate because of the differing sizes, but for me the outline is more important than the quality of the image.
I will possibly investigate using a more modern update mechanism once I finish these 2 Remote Desktop programs. The personal version is nearing completion and will be posted shortly, and I still have not resolved the Ctrl-Alt-Del/elevation issue on this version. Mind you, the elevation issue is going to have to be addressed on the personal version as well.
J.A. Coutts
Last edited by couttsj; Apr 14th, 2019 at 12:35 PM.
How do you use the project?
I am facing difficulty connecting to another machine. Could you help me with this issue?
I must apologize for not being able to respond to your question. I no longer have a need for this software and no longer maintain it. As a matter of fact, I updated to Win 11 some time ago and do not know if it even runs in Win 11. It is basically an attempt to operate a remote computer, similar to UltraVNC but with enhanced security. Connection issues are usually caused by blocked access. The firewall software must be adjusted to permit outside access to the port in question.
I must apologize for not being able to respond to your question. I no longer have a need for this software and no longer maintain it. As a matter of fact, I updated to Win 11 some time ago and do not know if it even runs in Win 11. It is basically an attempt to operate a remote computer, similar to UltraVNC but with enhanced security. Connection issues are usually caused by blocked access. The firewall software must be adjusted to permit outside access to the port in question.
J.A. Coutts
Is there a video follow the steps, how to operate with it?
Is there a video follow the steps, how to operate with it?
In Start->Run (Win+R) type firewall.cpl and click on the Allow an app or feature through Windows Defender Firewall link and add your app .exe file to the list of allowed apps.
If you want to try UltraVNC instead you might try https://github.com/wqweto/VbVncServer/releases where VbVncServer.exe is a VNC server written as a single VB6 class which can be emdebbed in any Line-Of-Business application for tech support.
This way you can use UltraVNC viewer (or any other VNC client) to connect to your LOB to see user's desktop, control mouse and/or transfer files like AnyDesk/TeamViewer but only when your LOB is running.
In Start->Run (Win+R) type firewall.cpl and click on the Allow an app or feature through Windows Defender Firewall link and add your app .exe file to the list of allowed apps.
If you want to try UltraVNC instead you might try https://github.com/wqweto/VbVncServer/releases where VbVncServer.exe is a VNC server written as a single VB6 class which can be emdebbed in any Line-Of-Business application for tech support.
This way you can use UltraVNC viewer (or any other VNC client) to connect to your LOB to see user's desktop, control mouse and/or transfer files like AnyDesk/TeamViewer but only when your LOB is running.
cheers,
</wqw>
Is there another remote access project with an alternative source code to integrate into my project? Please, I need help.
The viewer is easy, implementing the VNC server is much harder.
Btw, you can embed UltraVNC viewer into a VB6 form. For instance this solution uses embedded UltraVNC viewer.
cheers,
</wqw>
By the way, could you please explain how to incorporate the UltraVNC viewer in a VB6 form? For example, how can I embed the UltraVNC viewer in a vb6 solution?
By the way, could you please explain how to incorporate the UltraVNC viewer in a VB6 form? For example, how can I embed the UltraVNC viewer in a vb6 solution?
Let me try and explain why I put this program together in the first place. I was using UltrVNC to remotely maintain a Windows server. It used a simple encrypted password to gain access. I discovered multiple attempts to break into the server by guessing the UltraVNC password. So I modified the router settings to limit the IP range that could access it. That was all fine and dandy until my partner died from Covid-19 and we suffered an extended power failure at my end. His daughter took over maintaining the network and she was not comfortable with changing the router setting to deal with the new IP range resulting from the power failure. The server was old ( Windows NT 4.0), so I sold the Domain Name and ceased maintaining the server. That ended my desire to develop more secure remote operating software.
J.A. Coutts
Last edited by couttsj; Aug 8th, 2024 at 12:14 PM.