use*_*738 2 c memcpy segmentation-fault
我一直在玩memcpy()可以用于恶意目的的想法.我做了几个测试应用程序,看看我是否可以从不同地区"窃取"内存中的数据.到目前为止,我已经测试了三个区域,堆,堆栈和常量(只读)内存.常量内存是我测试中唯一崩溃的内存,引起了MinGW的错误.
这是一个例子来说明我的最新测试:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void removeTerminatingCharacters( char ** string, const int length )
{
int i = 0;
for ( ; i < length; ++i )
if ( !( *string )[i] )
( *string )[i] = '0';
return;
}
int main()
{
int * naive = malloc( sizeof( int ) );
*naive = 0;
char * stolenData = malloc( 2000 );
memset( stolenData, 0, 2000 );
memcpy( stolenData, naive, 1999 );
removeTerminatingCharacters( &stolenData, 2000 );
printf( "%s\n", stolenData );
free( stolenData );
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
0000-0:0Væ1lDk¦#:00000[æ0`Dk00p,:0-0:0MAIN=Computer0USERNAME=JohnDoe0USERPRO
FILE=C:\Users\JohnDoe0WATCOM=C:\watcom0windir=C:\Windows00?æ1+Ik?000S?000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00??????????????????????????000000 00000000 000000?0?0?
00000000000 0 0 ?0000000000 0000000000 0000 00000???????????????????????0???????
0 00000000000000000000000000000000000000000000000
000000000000000000abcdefghijklmnopqrstuvwxyz000000ABCDEFGHIJKLMNOPQRSTUVWXYZ0000
0000â000000Ü0£0P00000000000è0î0Ä 0000000000¬0000000000¦0000¦00000aßGpSsµtFTOd8fe
ä?:0ú?:0-?:0T?:0)?:0`?:0£?:0-?:0p?:0?:0??:0+?:08?:0T?:0¦?:0µ?:0²?:0¶?:03?:0D?:0R
?:0ä :0- :0+ :0a :0v :0?!:0^!:0q!:0ë!:0ñ!:0+!:0±!:0¤":0P":0g":0ó":0¦":0+":0¦":0?
#:0.#:0B#:0W#:0x#:0ë#:00000ALLUSERSPROFILE=C:\ProgramData0APPDATA=C:\Users\Chris
topher\AppData\Roaming0asl.log=Destination=file0CLASSPATH=.;C:\Program Files (x8
6)\Java\jre6\lib\ext\QTJava.zip0CommonProgramFiles=C:\Program Files (x86)\Common
Files0CommonProgramFiles(x86)=C:\Program Files (x86)\Common Files0CommonProgram
W6432=C:\Program Files\Common Files0COMPUTERNAME=COMPUTER0ComSpec=C:\Windows\sys
tem32\cmd.exe0FPPUILang=en-US0FP_NO_HOST_CHECK=NO0HOMEDRIVE=C:0HOMEPATH=\Users\C
hristopher0HuluDesktopPath=C:\Users\JohnDoe\AppData\Local\HuluDesktop\instan
ces\0.9.13.1\HuluDesktop.exe0LOCALAPPDATA=C:\Users\JohnDoe\AppData\Local0LOG
ONSERVER=\\COMPUTER0NUMBER_OF_PROCESSORS=20OnlineServices=Online Services0OOBEUI
Lang=en-US0OS=Windows_NT0Path=.;F:\CodeBlocks\MinGW\bin;F:\CodeBlocks\MinGW;C:\M
inGW\bin;C:\MinGW;C:\Windows\System32;C:\Windows;C:\Windows\System32\wbem;C:\Pro
gram Files\Common Files\Microsoft Shared\Windows Live;C:\Program Files (x86)\Com
mon Files\Microsoft Shared\Windows Live;C:\Windows\System32\WindowsPowerShell\v1
.0;c:\Program Files (x86)\ATI Technologies\ATI.ACE\Core-Static;c:\Program Files
(x86)\Common F0Uô1m+k
Run Code Online (Sandbox Code Playgroud)
我的代码并不漂亮,但它证明了我的观点.如您所见,数据主要是垃圾值,但是从堆中抛出了一些有趣的字符串.
我的主要问题是为什么此操作不会导致内存访问冲突错误?
当您访问未映射的页面时,虚拟内存硬件会捕获内存访问冲突错误.并非每个超出界限的地址都在未映射的页面中.页面大小通常相同.典型的页面大小,如果是4096字节.(页面大小是特定于硬件的:一些芯片具有允许可编程页面大小的内存管理,甚至是不同页面大小的混合,用于不同的内存区域.)有时只有页面的一部分包含有效数据.只是页面的一个片段不可能被取消映射,因此也会映射包含垃圾的部分.此外,内存管理器malloc并不总是将内存返回给操作系统; 他们保留免费区域以供重复使用.这些区域是有效的内存(映射页面).此外,构建指针值,你可以通过侥幸,最终超越越界,并且可以"降落"在与有效对象相对应的内存中.
这就是它在PC上的工作方式,具有虚拟内存操作系统.虚拟内存并不是无处不在.在没有虚拟内存的计算机上(现在是小型嵌入式系统),您可以访问内存中的任何位置.但是,访问某些区域可能会产生改变硬件状态(即I/O寄存器)的副作用.某些地址范围可能会触发"总线错误"类型的CPU异常,因为该范围不存在硬件,因此访问请求超时.除此之外,就有效的程序存储器而言,它不受保护以免受越界访问.
没有记忆保护的操作系统在20世纪60年代被用于早期的交互系统.当个人微型计算机出现时,历史就会重演:再次,由于存储器和CPU不够复杂,它们的操作系统没有内存保护.在这些操作系统上,应用程序经常在彼此的内存空间上踩踏,导致频繁崩溃.(想象一下,有了你memcpy,你不仅可以复制你自己的越界区域,比如之前被释放的一些malloc块,还有来自完全不同的运行程序的区域.)用户有时会发现模式,比如某些程序以某些顺序加载到内存中,问题较少,或应用程序之间的所谓"冲突".