articles
articles copied to clipboard
SEH执行shellcode的原理
SEH执行shellcode的原理
windbg推导栈溢出导致SEH代码执行
测试代码vc6.0编译,win2000测试
#include "stdafx.h"
#include <string.h>
#include <windows.h>
char shellcode[] =
"\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61"
"\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61"
"\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61"
"\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61"
"\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61"
"\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61"
"\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61"
"\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61"
"\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61"
"\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61"
"\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61"
"\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61"
"\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61"
"\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61";
DWORD MyException(void)
{
printf("There is an exception");
return 1;
}
void test(char * input)
{
char str[200];
int zero=0;
__try
{
strcpy(str,input);
zero=1/zero;
}
__except(MyException())
{
}
}
int main()
{
test(shellcode);
return 0;
}
正常运行产生异常
0:000> g
Thu Nov 1 03:57:43.910 2018 (GMT-8): (374.80): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=0012fb80 ebx=0012ff68 ecx=61616161 edx=77f96dae esi=0012fba8 edi=0012ff79
eip=61616161 esp=0012fae8 ebp=0012fb08 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246
61616161 ?? ???
0:000> kb
ChildEBP RetAddr Args to Child
WARNING: Frame IP not in any known module. Following frames may be wrong.
0012fae4 77f96ba7 0012fba8 0012ff68 0012fbbc 0x61616161
0012fb08 77f96c42 0012fba8 0012ff68 0012fbbc ntdll!ZwSetIoCompletion+0x182
0012fb90 77f9ff6e 0012fba8 0012fbbc 0012fba8 ntdll!ZwSetIoCompletion+0x21d
0012ff78 004010ba 00407030 00401378 00000001 ntdll!KiUserExceptionDispatcher+0xe
0012ff80 00401378 00000001 002f0ba0 002f0bf8 image00400000+0x10ba
0012ffc0 7c581af6 02304b38 0143f6cc 7ffdf000 image00400000+0x1378
0012fff0 00000000 004012c4 00000000 000000c8 KERNEL32!OpenEventA+0x63d
根据调用栈,找到出错函数
分析调试该函数sub_401020
0:000> bp 40107e
0:000> g
Thu Nov 1 04:09:10.129 2018 (GMT-8): Breakpoint 0 hit
eax=00000001 ebx=7ffdf000 ecx=00000000 edx=00000000 esi=00407111 edi=0012ff79
eip=0040107e esp=0012fe88 ebp=0012ff78 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000246
image00400000+0x107e:
0040107e f7f9 idiv eax,ecx
0:000> p
Thu Nov 1 04:09:18.723 2018 (GMT-8): (80.374): Integer divide-by-zero - code c0000094 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000001 ebx=7ffdf000 ecx=00000000 edx=00000000 esi=00407111 edi=0012ff79
eip=0040107e esp=0012fe88 ebp=0012ff78 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00010246
image00400000+0x107e:
0040107e f7f9 idiv eax,ecx
0:000> p
eax=00000001 ebx=7ffdf000 ecx=0012fbbc edx=00000000 esi=00407111 edi=0012ff79
eip=77f9ff64 esp=0012fba0 ebp=0012ff78 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
ntdll!KiUserExceptionDispatcher+0x4:
77f9ff64 8b1c24 mov ebx,dword ptr [esp] ss:0023:0012fba0=0012fba8
在调用0040107e f7f9 idiv eax,ecx
之后产生异常,系统最先调用ntdll!KiUserExceptionDispatcher
处理异常,来看该函数对异常做如何处理
继续跟进,在调用sub_77F96BDD`出错
0:000> p
eax=00000001 ebx=0012fba8 ecx=0012fbbc edx=00000000 esi=00407111 edi=0012ff79
eip=77f9ff69 esp=0012fb98 ebp=0012ff78 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
ntdll!KiUserExceptionDispatcher+0x9:
77f9ff69 e86f6cffff call ntdll!ZwSetIoCompletion+0x1b8 (77f96bdd)
0:000> g
Thu Nov 1 04:15:30.348 2018 (GMT-8): (80.374): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=0012fb80 ebx=0012ff68 ecx=61616161 edx=77f96dae esi=0012fba8 edi=0012ff79
eip=61616161 esp=0012fae8 ebp=0012fb08 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246
61616161 ?? ???
重新调试,继续跟进
再次出错
0:000> p
eax=0012fb80 ebx=0012ff68 ecx=0012fb84 edx=00000000 esi=0012fba8 edi=0012ff79
eip=77f96c3d esp=0012fb10 ebp=0012fb90 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
ntdll!ZwSetIoCompletion+0x218:
77f96c3d e83affffff call ntdll!ZwSetIoCompletion+0x157 (77f96b7c)
0:000> p
Thu Nov 1 04:20:19.410 2018 (GMT-8): (80.374): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=0012fb80 ebx=0012ff68 ecx=61616161 edx=77f96dae esi=0012fba8 edi=0012ff79
eip=61616161 esp=0012fae8 ebp=0012fb08 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246
61616161 ?? ???
出错位置
继续跟进,找到最终出错位置
0:000> p
eax=0012fb80 ebx=0012ff68 ecx=61616161 edx=77f96dae esi=0012fba8 edi=0012ff79
eip=77f96ba5 esp=0012faec ebp=0012fb08 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
ntdll!ZwSetIoCompletion+0x180:
77f96ba5 ffd1 call ecx {61616161}
0:000> p
Thu Nov 1 04:24:39.582 2018 (GMT-8): (80.374): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=0012fb80 ebx=0012ff68 ecx=61616161 edx=77f96dae esi=0012fba8 edi=0012ff79
eip=61616161 esp=0012fae8 ebp=0012fb08 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246
61616161 ?? ???
分析该函数
ecx
由最后一个参数传入
回溯
产生v2
的函数sub_77F96BD6
,该函数就是取得fs:0
中数据
再次分析最先出错的函数
只要将shellcode
或其地址放入这里,造成SEH
异常,即可执行shellcode
。
理论求证
上述过程分析了栈溢出会造成SEH
代码执行,现在来分析一下为什么
sub_401020
开始时会安装SEH
.text:00401020 push ebp
.text:00401021 mov ebp, esp
.text:00401023 push 0FFFFFFFFh
.text:00401025 push offset stru_4060B0
.text:0040102A push offset __except_handler3
.text:0040102F mov eax, large fs:0
.text:00401035 push eax
.text:00401036 mov large fs:0, esp
.text:0040103D sub esp, 0D4h
结构大概是这样的
+----------------------+
| ret_addre |
+----------------------+
| ebp |
+----------------------+
| seh something |
+----------------------+
| seh something |
+----------------------+
| __except_handler |
+----------------------+
| old fs:0 |
+----------------------+
| | <=== esp(fs:0)
+----------------------+
| local variable stack |
+----------------------+
| local variable stack |
+----------------------+
覆盖箭头位置即可,具体原理看参考
参考
0day2