高手都来看看,分析程序的运行结果~~~

sxldfang 2012-06-04 03:58:11
不是病毒,分析理解。

难道C++中 内存都是可以执行的吗?

第一题:
#include <stdio.h>
int main()
{
const short int c1 = 49920;
const int c2 = 1073742008;

int (*pf)() = (int (*)())&c2;
printf("%c%c\n", *(char*)pf()-19, *((char*)pf()+1)-49);
return 0;
}



第二题:
#include <iostream.h>
void main()
{
unsigned char c[]={0xb8,0x78,0x56,0x34,0x12,0xc3}; // mov eax,12345678h / ret
int (*p)()=(int (*)()) &c[0];
cout<<p()<<endl;
}


或者:
#include <iostream.h>
#include <string.h>
void main()
{
unsigned char c[]={0xb8,0x78,0x56,0x34,0x12,0xc3,0}; // mov eax,12345678h / ret
char *p=new char[8];
strcpy(p,(char*)c);
int (*f)()=(int (*)()) p;
cout<<f()<<endl;
delete[]p;
}

...全文
291 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
sxldfang 2012-06-07
  • 打赏
  • 举报
回复
在VS2008中测试,上面各种写法好像都不行了,看来高版本编译器对执行权限的限制是比较严格的啊。
dic_008 2012-06-06
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 的回复:]

引用 14 楼 的回复:
int (*pf)() = (int (*)())&amp;c2;
新手进来观摩,请问这是一种什么写法?

将c2的起始地址强制类型转换为一个函数指针,(该函数无参数,返回int),初始化赋值给pf这个变量。
pf的类型也是一个函数指针,(该函数无参数,返回int)

VC调试(TC或BC用TD调试)时按Alt+8、Alt+6和Alt+5,打开汇……
[/Quote]
大哥,牛X
sxldfang 2012-06-06
  • 打赏
  • 举报
回复
现在不太方便,哪位测试一下这个能否运行

#include <iostream>
using namespace std;
void main()
{
char *p="\hb8\h78\h56\h34\h12\hc3";
int (*f)()=(int (*)()) p;
cout<<f()<<endl;
}
hondely 2012-06-05
  • 打赏
  • 举报
回复

#include <stdio.h>
int main()
{
const short int c1 = 49920;
const int c2 = 1073742008;

int (*pf)() = (int (*)())&c2; //这里int (*pf)()是一个系统里面的指针函数????
printf("%c%c\n", *(char*)pf()-19, *((char*)pf()+1)-49);
return 0;
}



sxldfang 2012-06-05
  • 打赏
  • 举报
回复
的确不错的一道题,要用到的知识点:

 1、十进制数据在计算机内部的存放
 2、可执行文件的加载地址
 3、可执行文件的结构
 4、函数指针
 5、强制类型转换
 6、用指针取内存的值
 7、汇编语言指令及对应的机器码
 8、字符的ASCII码
 9、printf显示字符数据

赵4老师 2012-06-05
  • 打赏
  • 举报
回复
参考“冯·诺伊曼”原理
赵4老师 2012-06-05
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 的回复:]
int (*pf)() = (int (*)())&c2;
新手进来观摩,请问这是一种什么写法?
[/Quote]
将c2的起始地址强制类型转换为一个函数指针,(该函数无参数,返回int),初始化赋值给pf这个变量。
pf的类型也是一个函数指针,(该函数无参数,返回int)

VC调试(TC或BC用TD调试)时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。
对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。
(Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)
想要从本质上理解C指针,必须学习汇编以及C和汇编的对应关系。
从汇编的角度理解和学习C语言的指针,原本看似复杂的东西就会变得非常简单!
指针即地址。“地址又是啥?”“只能从汇编语言和计算机组成原理的角度去解释了。”

提醒:
“学习用汇编语言写程序”

“VC调试(TC或BC用TD调试)时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。
(Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)
想要从本质上理解C指针,必须学习C和汇编的对应关系。”
不是一回事!

不要迷信书、考题、老师、回帖;
要迷信CPU、编译器、调试器、运行结果。
并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。
任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实!
villypugang 2012-06-05
  • 打赏
  • 举报
回复
int (*pf)() = (int (*)())&c2;
新手进来观摩,请问这是一种什么写法?
ycf7740731 2012-06-04
  • 打赏
  • 举报
回复
我是新手,但还是进来看了,看不懂,不好意思!
asyuae 2012-06-04
  • 打赏
  • 举报
回复
蛋疼代码
localxiao 2012-06-04
  • 打赏
  • 举报
回复
你最好去看操作系统的内存管理

重点看看页保护
sxldfang 2012-06-04
  • 打赏
  • 举报
回复
原来在做反汇编时知道,有些数据块是只读的,有的是只写的,有的是可执行的,或者他们的组合,难道C++编译器生成的代码在其所占用的内存范围内都是可执行的吗?有无编译开关可以控制呢?
Nosky100 2012-06-04
  • 打赏
  • 举报
回复
第一个例子使用了MZ头部,Linux下肯定不行啊。
qq120848369 2012-06-04
  • 打赏
  • 举报
回复
阿门, 在虚拟地址空间里你是可以随心所欲的, 操作系统会protect you.
majia2011 2012-06-04
  • 打赏
  • 举报
回复
这个,你的栈和堆,都是可执行段,强力的编译器或者强力的系统,强力啊

现在的小朋友,没经历过,内存管理的原始时代。还好,lz没弄个石器时代的东西,那时候还没有c,呵呵呵。
Qyee16 2012-06-04
  • 打赏
  • 举报
回复
程序被编译后,不就是二进制? move指令本来就是二进制的抽象,用机器码编程,就是01字符串的组合。没什么嘛,至于用二进制编码,感觉需要对硬件地址需要相当的了解。

liuche1990 2012-06-04
  • 打赏
  • 举报
回复
不太明白你说 的"内存都是可以执行的"是什么意思
W170532934 2012-06-04
  • 打赏
  • 举报
回复
底层语言嘛,有指针就会出现很高深的代码。因为所有的东西在计算机内部都是数据,都有地址,而指针就是地址这一类的东西。

64,654

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧