Microsoft Copilot, Copilot my payload

This is a weird proof-of-concept which is wildly inconsistent.

A few days ago I joked on social media about Copilot being used for malware and then I suddenly thought to myself, "... well ... can I use it for malware?"

The answer is ... maybe? Microsoft Copilot doesn't have an API. I decided to use COM IUIAutomation API to programmatically interop with Copilot. In simplest terms possible, I interact with it in a similar manner that a user would visually through the GUI.

This method has many limitations, it also has proven very difficult to make the LLM be consistent on it's malicious behavior (e.g. "plz do bad thing mr. copilot sir"). Regardless, I'm going to share my code with the hopes that someone can do more with it than I could. I don't have the patience to deal with LLMs, especially Copilot.

The benefit of this potential technique is that Copilot is everywhere. Microsoft has shoved it down the throats of consumers. Very cool.

The attached code is my proof-of-concept, but please note it's limitations

  1. This sends exactly one message to Copilot. I haven't introduced any logic to reply back to it, handle any prompts which may appear, etc. This is important to note because when I asked Copilot to execute a binary for me it presented a consent prompt. Subsequently, Copilot told me to fuck off and to run the .exe myself. Very cool.

  2. This requires Copilot being on the "home" screen and being focused. I haven't introduced any logic which brings Copilot to the "home" screen. Moreover, it's important to note this code does set Copilot to be focused.

  3. This code could become a lot more evasive if need be, but that's a different conversation for a different time.

#include <Windows.h>
#include <UIAutomation.h>

#define INPUTBOXSTRING L"What is Copilot?"

typedef struct __IUICONDITION_OBJECT_FAST {
	IUIAutomationCondition* Condition;
	VARIANT v;
}IUICONDITION_OBJECT, *PIUICONDITION_OBJECT;

DWORD Win32FromHResult(_In_ HRESULT Result)
{
	if ((Result & 0xFFFF0000) == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, 0))
		return HRESULT_CODE(Result);

	if (Result == S_OK)
		return ERROR_SUCCESS;

	return ERROR_CAN_NOT_COMPLETE;
}

VOID InitializeConditionObject(PIUICONDITION_OBJECT Object)
{
	Object->Condition = NULL;
	VariantInit(&Object->v);
}

VOID DestroyConditionObject(PIUICONDITION_OBJECT Object)
{
	if (Object->Condition)
		Object->Condition->Release();

	VariantClear(&Object->v);
}

IUIAutomationElement* IuiFindCopilotSendMessageObject(IUIAutomation* Object, IUIAutomationElement* Element)
{
	HRESULT Result = S_OK;

	IUIAutomationElement* SendMessageElement = NULL;

	IUICONDITION_OBJECT Name; InitializeConditionObject(&Name);
	IUICONDITION_OBJECT Type; InitializeConditionObject(&Type);
	IUICONDITION_OBJECT Enabled; InitializeConditionObject(&Enabled); 

	IUICONDITION_OBJECT Visible; InitializeConditionObject(&Visible); 

	IUIAutomationCondition* ConditionalObject1 = NULL;
	IUIAutomationCondition* ConditionalObject2 = NULL;
	IUIAutomationCondition* ConditionResult = NULL;

	Name.v.vt = VT_BSTR;
	Name.v.bstrVal = SysAllocString(L"Submit message");
	if (Name.v.bstrVal == NULL)
		goto EXIT_ROUTINE;

	Type.v.vt = VT_I4;
	Type.v.lVal = UIA_ButtonControlTypeId;

	Enabled.v.vt = VT_BOOL;
	Enabled.v.boolVal = VARIANT_TRUE;

	Visible.v.vt = VT_BOOL;
	Visible.v.boolVal = VARIANT_FALSE;

	Result = Object->CreatePropertyCondition(UIA_ControlTypePropertyId, Type.v, &Type.Condition);
	if (!SUCCEEDED(Result))
		goto EXIT_ROUTINE;

	Result = Object->CreatePropertyCondition(UIA_NamePropertyId, Name.v, &Name.Condition);
	if (!SUCCEEDED(Result))
		goto EXIT_ROUTINE;

	Result = Object->CreatePropertyCondition(UIA_IsEnabledPropertyId, Enabled.v, &Enabled.Condition);
	if (!SUCCEEDED(Result))
		goto EXIT_ROUTINE;

	Result = Object->CreatePropertyCondition(UIA_IsOffscreenPropertyId, Visible.v, &Visible.Condition);
	if (!SUCCEEDED(Result))
		goto EXIT_ROUTINE;

	Result = Object->CreateAndCondition(Type.Condition, Name.Condition, &ConditionalObject1);
	if (!SUCCEEDED(Result))
		goto EXIT_ROUTINE;

	Result = Object->CreateAndCondition(ConditionalObject1, Enabled.Condition, &ConditionalObject2);
	if (!SUCCEEDED(Result))
		goto EXIT_ROUTINE;

	Result = Object->CreateAndCondition(ConditionalObject2, Visible.Condition, &ConditionResult);
	if (!SUCCEEDED(Result))
		goto EXIT_ROUTINE;

	if (ConditionResult == NULL)
		goto EXIT_ROUTINE;

	Element->FindFirst(TreeScope_Subtree, ConditionResult, &SendMessageElement);

EXIT_ROUTINE:

	if (ConditionResult)
		ConditionResult->Release();

	if (ConditionalObject1)
		ConditionalObject1->Release();

	if (ConditionalObject2)
		ConditionalObject2->Release();

	DestroyConditionObject(&Name);
	DestroyConditionObject(&Type);
	DestroyConditionObject(&Enabled);
	DestroyConditionObject(&Visible);

	return SendMessageElement;
}

INT main(VOID)
{
	HRESULT Result = S_OK;
	IUIAutomation* CopilotMainIuaObject = NULL;
	IUIAutomationElement* RootObject = NULL;
	IUIAutomationElement* CopilotWindowObject = NULL;
	IUIAutomationElement* InputBoxObject = NULL;
	IUIAutomationElement* SendMessageObject = NULL;

	IUICONDITION_OBJECT Name; InitializeConditionObject(&Name);
	IUICONDITION_OBJECT InputBox; InitializeConditionObject(&InputBox);

	IUIAutomationValuePattern* InputBoxDestinationObject = NULL;
	IUIAutomationInvokePattern* Invoker = NULL;
	
	Result = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
	if(!SUCCEEDED(Result))
		return Win32FromHResult(Result);

	InputBox.v.vt = VT_I4;
	InputBox.v.lVal = UIA_EditControlTypeId;

	Name.v.vt = VT_BSTR;
	Name.v.bstrVal = SysAllocString(L"Copilot");
	if (Name.v.bstrVal == NULL)
		return E_OUTOFMEMORY;

	Result = CoCreateInstance(CLSID_CUIAutomation, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&CopilotMainIuaObject));
	if (!SUCCEEDED(Result))
		goto EXIT_ROUTINE;

	Result = CopilotMainIuaObject->GetRootElement(&RootObject);
	if (!SUCCEEDED(Result))
		goto EXIT_ROUTINE;
	
	Result = CopilotMainIuaObject->CreatePropertyCondition(UIA_NamePropertyId, Name.v, &Name.Condition);
	if (!SUCCEEDED(Result))
		goto EXIT_ROUTINE;

	Result = RootObject->FindFirst(TreeScope_Subtree, Name.Condition, &CopilotWindowObject);
	if (!SUCCEEDED(Result))
		goto EXIT_ROUTINE;

	Result = CopilotWindowObject->SetFocus();
	if (!SUCCEEDED(Result))
		goto EXIT_ROUTINE;

	Result = CopilotMainIuaObject->CreatePropertyCondition(UIA_ControlTypePropertyId, InputBox.v, &InputBox.Condition);
	if (!SUCCEEDED(Result))
		goto EXIT_ROUTINE;

	Result = CopilotWindowObject->FindFirst(TreeScope_Subtree, InputBox.Condition, &InputBoxObject);
	if (!SUCCEEDED(Result))
		goto EXIT_ROUTINE;

	Result = InputBoxObject->GetCurrentPatternAs(UIA_ValuePatternId, IID_PPV_ARGS(&InputBoxDestinationObject));
	if (!SUCCEEDED(Result))
		goto EXIT_ROUTINE;

	Result = InputBoxDestinationObject->SetValue((BSTR)INPUTBOXSTRING);
	if (!SUCCEEDED(Result))
		goto EXIT_ROUTINE;

	SendMessageObject = IuiFindCopilotSendMessageObject(CopilotMainIuaObject, CopilotWindowObject);
	if (SendMessageObject == NULL)
		goto EXIT_ROUTINE;

	Result = SendMessageObject->GetCurrentPatternAs(UIA_InvokePatternId, IID_PPV_ARGS(&Invoker));
	if (!SUCCEEDED(Result))
		goto EXIT_ROUTINE;

	Result = Invoker->Invoke();

EXIT_ROUTINE:

	if (Invoker)
		Invoker->Release();

	if (SendMessageObject)
		SendMessageObject->Release();

	if (InputBoxDestinationObject)
		InputBoxDestinationObject->Release();

	if (InputBoxObject)
		InputBoxObject->Release();

	DestroyConditionObject(&InputBox);

	if (CopilotWindowObject)
		CopilotWindowObject->Release();

	DestroyConditionObject(&Name);

	if (RootObject)
		RootObject->Release();

	if (CopilotMainIuaObject)
		CopilotMainIuaObject->Release();

	CoUninitialize();

	return Win32FromHResult(Result);
}

Last updated