C 语言中有趣第指针操作(转)

http://blog.csdn.net/ghevinn/article/details/37651149(反汇编题目需要分析)

4、取出内存区域的值

在取某内存地址开始的一个区域的值的时候,取出的值取决于用来取值的类型,譬如int为4个byte,char为1个byte,程序如:

void main(){
 int a[2] = {261,0};
 int *pi = a;
 char *p = (char*)pi;
 cout << *(int *)p++ << endl;  //取出p地址,转化为取4个byte,并取出内容,之后p向后移动一位
 cout << *(int *)p << endl;    //取出p地址,转化为取4个byte,并取出内容
 cout << (int)*p << endl;      //取出1个char类型,并转换为int型
 cout << (int)*(char *)pi << endl;  //取出pi地址,转换为char类型,取出内容,并转换为int型
}
程序输出:
261
1
1
5

a的存储区域安排为:byte1=5,byte2=1,byte3~byte8 = 0;
所以*(int *)p++取的为byte1到byte4; 之后的*(int *)p取的是byte2到byte5;
(int)*p取的是byte2;(int)*(char *)pi取的是byte1,之后转换为int型

 

2.strcpy()函数


问:下面是一个简单的密码保护功能,你能在不知道密码的情况下将其破解吗?


#include<stdio.h> 
 
int main(int argc, char *argv[]) 

    int flag = 0; 
    char passwd[10]; 
 
    memset(passwd,0,sizeof(passwd)); 
 
    strcpy(passwd, argv[1]); 
 
    if(0 == strcmp("LinuxGeek", passwd)) 
    { 
        flag = 1; 
    } 
 
    if(flag) 
    { 
        printf("\n Password cracked \n"); 
    } 
    else 
    { 
        printf("\n Incorrect passwd \n"); 
 
    } 
    return 0; 

答:破解上述加密的关键在于利用攻破strcpy()函数的漏洞。所以用户在向“passwd”缓存输入随机密码的时候并没有提前检查“passwd”的容量是否足够。所以,如果用户输入一个足够造成缓存溢出并且重写“flag”变量默认值所存在位置的内存的长“密码”,即使这个密码无法通过验证,flag验证位也变成了非零,也就可以获得被保护的数据了。例如:


$ ./psswd aaaaaaaaaaaaa 
 
Password cracked 
虽然上面的密码并不正确,但我们仍然可以通过缓存溢出绕开密码安全保护。

编译 gcc file -fno-stack-protector

#include<stdio.h>
int main(int argc, char *argv[])
{
int flag = 0;
char passwd[10];
char input[]={'a','a','a','a','a','a','a','a','a','a','\x02','\x00','\x00','\x00'};
memset(passwd,0,sizeof(passwd));
strcpy(passwd, input);
if(0 == strcmp("LinuxGeek", passwd))
{
flag = 1;
}
if(flag==2)
{
printf("\n Password cracked \n");
}
else
{
printf("%x\n",flag);
printf("\n Incorrect passwd \n");

}
return 0;
}

 

posted @ 2014-08-12 22:52  purejade  阅读(182)  评论(0编辑  收藏  举报