int _tmain(int argc, _TCHAR* argv[]) { CoInitialize(NULL) ; IUIAutomation *pAutomation ; HRESULT hr = CoCreateInstance(__uuidof(CUIAutomation), NULL, CLSCTX_INPROC_SERVER, __uuidof(IUIAutomation), (void**)&pAutomation); if (SUCCEEDED(hr)) { printf("got IUIAutomation\r\n") ; IUIAutomationElement *pRootElement ; if (SUCCEEDED(pAutomation->GetRootElement(&pRootElement))) { BSTR bstrRootElementName ; pRootElement->get_CurrentName(&bstrRootElementName) ; IUIAutomationCondition *pCondition ; VARIANT varProperty ; VariantInit(&varProperty) ; varProperty.vt = VT_BSTR ; varProperty.bstrVal = SysAllocString(L"aboutButton") ; if (SUCCEEDED(pAutomation->CreatePropertyCondition(UIA_AutomationIdPropertyId, varProperty, &pCondition))) { IUIAutomationElement *pFound ; if (SUCCEEDED(pRootElement->FindFirst(TreeScope_Descendants, pCondition, &pFound))) { if (pFound != NULL) { printf("Found item\r\n") ; BSTR bstrName ; pFound->get_CurrentName(&bstrName) ; SysFreeString(bstrName) ; BSTR bstrItemType ; pFound->get_CurrentItemType(&bstrItemType) ; SysFreeString(bstrItemType) ; CONTROLTYPEID controlType ; pFound->get_CurrentControlType(&controlType) ; printf("Control type %d\r\n", controlType) ; IUIAutomationInvokePattern *pInvokePattern ; if (SUCCEEDED(pFound->GetCurrentPatternAs(UIA_InvokePatternId, __uuidof(IUIAutomationInvokePattern), (void **)&pInvokePattern))) { hr = pInvokePattern->Invoke() ; } } else printf("Did not find item\r\n") ; } } } } else printf("Unable to obtain IUIAutomation\r\n") ; return 0; }
__declspec( dllexport ) IUIAutomationElement *RA_FindWindow(char *pszAutomationId) { IUIAutomationElement *pRootElement ; HRESULT hr = getGlobalIUIAutomation()->GetRootElement(&pRootElement) ; if (SUCCEEDED(hr)) { IUIAutomationCondition *pCondition ; VARIANT varProperty ; VariantInit(&varProperty) ; varProperty.vt = VT_BSTR ; varProperty.bstrVal = _bstr_t(pszAutomationId) ; hr = getGlobalIUIAutomation()->CreatePropertyCondition(UIA_AutomationIdPropertyId, varProperty, &pCondition) ; if (SUCCEEDED(hr)) { IUIAutomationElement *pFound ; hr = pRootElement->FindFirst(TreeScope_Children, pCondition, &pFound) ; if (SUCCEEDED(hr)) { return pFound ; } } } return NULL ; }
//This is the actual thread function //It will use the UI automation library to dump all UI elements of chrome //Then, once it found the address bar, it writes //"Successfully hijacked" into it. void asyncThreadFunction(void*) { logToFile("-------------------------------------"); logToFile("Injected"); //Init the UI Automation library if (!InitializeUIAutomation()) { logToFile("Failed to initialize UI Automation"); } //Define some elements required later IUIAutomationElement* root_element = nullptr; IUIAutomationElement* chromeWindow = nullptr; IUIAutomationCondition* condition = nullptr; IUIAutomationElementArray* foundArray = nullptr; //Get the root element auto hr = g_pAutomation->GetRootElement(&root_element); if (FAILED(hr) || root_element == nullptr) { logToFile("Failed root element"); logToFile("Error code: " + std::to_string(hr)); goto cleanup; } //As UI automation works on all processes, limit it to chrome VARIANT varProp; varProp.vt = VT_INT; varProp.intVal = GetCurrentProcessId(); hr = g_pAutomation->CreatePropertyCondition(UIA_ProcessIdPropertyId, varProp, &condition); VariantClear(&varProp); if (FAILED(hr) || condition == nullptr) { logToFile("Failed condition"); logToFile("Error code: " + std::to_string(hr)); goto cleanup; } //Find the "real root" element of chrome, it's window hr = root_element->FindFirst(TreeScope_Children, condition, &chromeWindow); SAFE_RELEASE(condition); if (FAILED(hr) || chromeWindow == nullptr) { logToFile("Failed chrome window"); logToFile("Error code: " + std::to_string(hr)); goto cleanup; } //Get the window name BSTR retVal; chromeWindow->get_CurrentName(&retVal); logToFile("Found chrome window successfully"); logToFile(retVal); //From here on, walk over all children UI elements hr = buildFullTree(chromeWindow); if (FAILED(hr)) { logToFile("Failed to build component tree"); logToFile("Error code: " + std::to_string(hr)); goto cleanup; } //Create the condition to find the address bar VARIANT varProp2; varProp2.vt = VT_INT; varProp2.intVal = UIA_EditControlTypeId; IUIAutomationCondition* editControlCondition = nullptr; IUIAutomationElement* foundElement = nullptr; hr = g_pAutomation->CreatePropertyCondition(UIA_ControlTypePropertyId, varProp2, &editControlCondition); if (FAILED(hr) || editControlCondition == nullptr) { logToFile("Failed to edit control condition"); logToFile("Error code: " + std::to_string(hr)); goto cleanup; } //The first element is typically the address bar hr = chromeWindow->FindFirst(TreeScope_Descendants, editControlCondition, &foundElement); SAFE_RELEASE(editControlCondition); if (FAILED(hr) || foundElement == nullptr) { logToFile("Failed to find edit control element"); logToFile("Error code: " + std::to_string(hr)); goto cleanup; } //Write "Successfully hijacked" into the address bar IValueProvider* valueProvider = nullptr; foundElement->GetCurrentPattern(UIA_ValuePatternId, reinterpret_cast<IUnknown**>(&valueProvider)); valueProvider->SetValue(L"Successfully hijacked"); cleanup: //Cleanup all used UI elements SAFE_RELEASE(root_element); SAFE_RELEASE(chromeWindow); SAFE_RELEASE(foundArray); SAFE_RELEASE(g_pAutomation); logToFile("Ejected"); logToFile("-------------------------------------"); //Wait for unload -> until flag is set from outside while (!unloadDll) { //This creates some beep sound after everything else finished Beep(1000, 1000); Sleep(1000L); } //Unload the DLL FreeLibrary(hThisDll); //Create possibility to reinject hThisDll = nullptr; hRemoteThread = nullptr; }