gcc编译器器中运行结果怎么复制?求解答

用javac编译后运行结果是这个?求解答。如果可以生成可执行文件发给我hacking_ 谢谢啊 。_百度知道[保留] 把函数复制到堆上并运行的方法 - ChinaUnix.net
[保留] 把函数复制到堆上并运行的方法
http://www.chinaunix.net 作者:&&发表于: 11:45:28
有需求见此贴,所谓的动态执行&http://bbs.chinaunix.net/thread--1.html&
实现如下:
[table=95%][tr][td][font=FixedSys]void&add(int&a,&int&b)
{
&&&&&&&&printf("a+b=%d\n",&a+b);
}
char&*get_call_addr(char&*p,&int&len)&
{
&&&&&&&while(len--&&&&(*p&!=&(char)0xe8&))
&&&&&&&&&&&&&&&p++;
&&&&&&&if&(len)
&&&&&&&&&&&&&&&return&p;
&&&&&&&else
&&&&&&&&&&&&&&&return&0;
}
void&set_call(int&call_addr,&int&fun_addr)
{
&&&&&&&&int&ip&=&call_addr&+&5;
&&&&&&&&int&set_call_addr&=&call_addr&+&1;
&&&&&&&(*(int&*)set_call_addr)&=&fun_addr&-&
}
int&main()
{
&&&&&&&&&char&*p&=&(char&*)malloc(100);
&&&&&&&&&
&&&&&&&&&memcpy(p,&add,&100);
&&&&&&&&&void&(*pf)(int,&int)&=&(void(*)(int,&int))p;
&&&&&&&&&&char&*call_addr&=&get_call_addr(p,&100);
&&&&&&&&&&if&(call_addr)&{
&&&&&&&&&&&&&&&&&&set_call((int)call_addr,&(int)printf);
&&&&&&&&&&&&&&&&&&pf(10,&20);
&&&&&&&&&&}
&&&&&&&&&return&0;
}
[/font][/td][/tr][/table]
上面的代码能实现,将函数复制到&malloc&出来的内存里正确执行,原理就是修改里面的&call&指令偏移值。
这里能正确运行,但这种方法并不保险。
实际情况可能是:1、编译器产生的代码是多变的。2、刚刚好其它指令里没有&0xe8&这个机器码,要经过很多重判断(否则是话就大错特错了,:mrgreen:&)
二、还有就是用直接调用的方法,或类似方法
[table=95%][tr][td][font=FixedSys]void&foo()
{
&&&&&&&&&&printf("I'm&foo()...\n");
}
int&main()
{
&&&&&&&&&&char&*p&=&(char&*)malloc(20);
&&&&&&&&&&int&pf&=&(int)
&&&&&&&&&&p[0]&=&0
&&&&&&&&&&p[1]&=&0x15;
&&&&&&&&&&*((int&*)&p[2])&=&(int)&
&&&&&&&&&&p[6]&=&0xc3;
&&&&&&&&&&(void&(*)())p();
&&&&&&&&&&return&0;
}
[/font][/td][/tr][/table]
虽然,正确调用得到了保证,但要传递参数的话,要多动点脑子:)
& 回复于: 23:55:41
:shock:&:shock:&那段地址有运行的权限吗
& 回复于: 23:57:19
& 回复于: 23:59:59
引用:原帖由&agaric&于&&23:55&发表&[url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=9010516&ptid=1237275]
:shock:&:shock:&那段地址有运行的权限吗&
这个......应该是OS相关,有些OS确实可能无法执行(一般此类则较为安全)
& 回复于: 00:04:46
mik兄,这段时间忙啥呢?呵呵
& 回复于: 00:12:58
没啥忙的,人懒惰了啥都不想干,啥都不想忙。
& 回复于: 00:20:54
很好的贴。
请问以下问号处怎么理解?
void&set_call(int&call_addr,&int&fun_addr)
{
&&&&&&&&int&ip&=&call_addr&+&5;&&&//?
&&&&&&&&int&set_call_addr&=&call_addr&+&1;
&&&&&&&(*(int&*)set_call_addr)&=&fun_addr&-&&&//?
}
& 回复于: 00:29:27
你&objdump&一下&add()&来看看会明白很多:)
& 回复于: 00:34:09
这样做又什么好处吗?还是特殊要求?
& 回复于: 00:35:09
引用:原帖由&mik&于&&00:29&发表&[url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=9010598&ptid=1237275]
你&objdump&一下&add()&来看看会明白很多:)&
& 回复于: 00:41:24
:em17:&希望能再深层次的讲解下~明天再来关注~
& 回复于: 01:47:59
将函数复制到&malloc&出来的内存里正确执行,可以有效的
函数复制到堆.
直接调用的方法有些笨,但总体来说不是一种好方法
& 回复于: 10:02:40
我不明白,程序加载后,printf这些就已经是绝对地址了,按理说他以前那种调用方法也没错。
call指令是以当前自身地址+偏移去调用函数是不?也就是说call后面跟的地址是个偏移?如果这样的话,他那样写是错了。
但我记得call也有直接用绝对地址跳转的方式,需要怎么设编译选项吗?
& 回复于: 10:16:27
引用:原帖由&zx_wing&于&&10:02&发表&[url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=9011725&ptid=1237275]
我不明白,程序加载后,printf这些就已经是绝对地址了,按理说他以前那种调用方法也没错。
call指令是以当前自身地址+偏移去调用函数是不?也就是说call后面跟的地址是个偏移?如果这样的话,他那样写是错了。&...&
我查了手册,确实编译器最常用的opecode=E8这宗相对跳转的方式。
绝对地址调用(opcode=9A)可以用,但是在函数指针的时候,例如他这里call到堆上去执行就是用的绝对地址调用(call&*eax)。
倒还真没有太好的解决方法。编译器应该没有选项使用绝对地址调用[&本帖最后由&zx_wing&于&&10:19&编辑&]
& 回复于: 11:15:38
mik,我突然有点糊涂了。opcode=e8的时候call后面的地址是偏移吗?我objdump出来是绝对地址啊
& 回复于: 12:09:55
你要能把函数栈搞到堆上去,才数你牛.
& 回复于: 12:22:26
:mrgreen:&:mrgreen:&:mrgreen:
& 回复于: 12:27:30
不错,LZ的示例代码很好,对一类重定位起了很好的解释。
& 回复于: 17:04:41
Linux&blog41&2.6.18-4-686-bigmem&#1&SMP&Mon&Mar&26&18:37:22&UTC&&GNU/Linux
gcc&version&4.1.2&&(prerelease)&(Debian&4.1.1-21)
Segmentation&fault&(core&dumped)
& 回复于: 21:44:07
引用:原帖由&zx_wing&于&&11:15&发表&[url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=9012289&ptid=1237275]
mik,我突然有点糊涂了。opcode=e8的时候call后面的地址是偏移吗?我objdump出来是绝对地址啊&
e8&后面是个&offset&值,要不你贴出来看看&:)
& 回复于: 11:22:33
引用:原帖由&mik&于&&21:44&发表&[url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=9016720&ptid=1237275]
e8&后面是个&offset&值,要不你贴出来看看&:)&
额,都不用贴了。
你在测试程序里面多写几个函数,都调用printf,在x86下面编译后应该是call到PLT表再call到printf的。
我objdump出来后每个函数里调用printf时call后面的offset都一样的。按理说这个offset会根据当前eip的不同而不同啊。
另外一个问题是,我看原帖作者后来改用传函数地址再用指针方式调用,这样用的是9A也就是call&*eax这样的绝对寻址,按理说不该错啊。
& 回复于: 11:32:45
char&*p&=&(char&*)malloc(100);
&&&&&&&&&
&&&&&&&&&memcpy(p,&add,&100);
&&&&&&&&&void&(*pf)(int,&int)&=&(void(*)(int,&int))p;
可以改成
&char&*p&=&(char&*)malloc(100);
&&&&&&&&&
&&&&&&&&&memcpy(p,&add,&100);
&&&&&&&&&void&(*pf)(int,&int)&=&(void(*)(int,&int))*p;
& 回复于: 11:50:19
引用:原帖由&zx_wing&于&&11:22&发表&[url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=9019770&ptid=1237275]
额,都不用贴了。
你在测试程序里面多写几个函数,都调用printf,在x86下面编译后应该是call到PLT表再call到printf的。
我objdump出来后每个函数里调用printf时call后面的offset都一样的。按理说这个offset&...&
没问题呀,这个方法类似的贴的第二个方法,直接调用。
[attach]280335[/attach]
估计他是输入时错了。[&本帖最后由&mik&于&&11:51&编辑&]
& 回复于: 11:56:27
汗~&你怎么会想改成这样
& 回复于: 13:21:33
怎么就可以让它运行了呢,我的vc无法通过编译,存在错误
gcc下&出现&段错误
& 回复于: 00:37:34
引用:原帖由&zx_wing&于&&11:22&发表&[url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=9019770&ptid=1237275]
额,都不用贴了。
你在测试程序里面多写几个函数,都调用printf,在x86下面编译后应该是call到PLT表再call到printf的。
我objdump出来后每个函数里调用printf时call后面的offset都一样的。按理说这个offset&...&
兄弟,你对&PIC&的了解有多深呀,来探讨一下吧。:)&
懒得去研究&ELF&格式的来龙去脉。&objdump&来粗略分析一下,gcc&的生成&PIC&代码的大致情况:
gcc&会生成一个&PLT&表格和&GOT&表格。
main()
{
&&&&&&&printf("hi\n"&);
&&&&&&&printf("%d\n",&1);
}
PLT&表开始的&0x10&个字节,可能是供给&linker&去使用的。
一、PLT&头部:
&&puts@plt-0x10&:
&8048294: ff&35&9c&95&04&08&&&& pushl&&0x804959c&&&&&&&&&&&//&&这有何用?&估计信息类,供&linker&用
&804829a: ff&25&a0&95&04&08&&&& jmp&&&&*0x80495a0&&&&&&&&&//&&&可能供&linker&链接真正的库函数代码
&&00&&&&&&&&&&&&&&&& add&&&&%al,(%eax)
接下来,构建一个&puts@PLT&&和&printf@PLT&
&&puts@plt&:
&80482a4: ff&25&a4&95&04&08&&&& jmp&&&&*0x80495a4&&&&&&&&&//&转到&GOT
&80482aa: 68&00&00&00&00&&&&&&& push&&&$0x0&&&&&&&&&&&&&&&&&&&&//&??&库函数的识别码?&估计类似功能号吧
&80482af: e9&e0&ff&ff&ff&&&&&&& jmp&&&&8048294&&_init+0x18&&&&&&&&&&//&此处与上一行又从&GOT&中转回来,这后走回
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//&PLT&头部
&&printf@plt&:
&80482c4: ff&25&ac&95&04&08&&&& jmp&&&&*0x80495ac&&&&&&&&&&&&&&&&&&&&&&&//&转到&GOT
&80482ca: 68&10&00&00&00&&&&&&& push&&&$0x10&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//&库函数&ID&
&80482cf: e9&c0&ff&ff&ff&&&&&&& jmp&&&&8048294&&_init+0x18&&&&&&&&//&同样从&GOT&中转回来,&走回&PLT&头部
二、下面是&GOT&表格:
&&_GLOBAL_OFFSET_TABLE_&:
&8049598: cc&&&&&&&&&&&&&&&&&&& int3&&&
&&&&&&&&&&&&&&&&&&&& xchg&&&%eax,%esp
&804959a: 04&08&&&&&&&&&&&&&&&& add&&&&$0x8,%al
...
[color=Red]&80495a4: aa&&&&&&&&&&&&&&&&&&& stos&&&%al,%es:&(%edi)&&&&//&此处又转回&puts@PLT
&&&&&&&&&&&&&&&&&&&& (bad)&&
&&08&&&&&&&&&&&&&&&& add&&&&$0x8,%al[/color]
&80495a8: ba&[color=Red]82&04&08&ca[/color]&&&&&&& mov&&&&$0xca080482,%edx&&//&此处又转回&printf@PLT
&80495ad: 82&&&&&&&&&&&&&&&&&&& (bad)&&
&80495ae: 04&08&&&&&&&&&&&&&&&& add&&&&$0x8,%al
&80495b0: da&&&&&&&&&&&&&&&&&&& .byte&0xda
&&&&&&&&&&&&&&&&&&&& (bad)&&
&&08&&&&&&&&&&&&&&&& add&&&&$0x8,%al
三、&PLT&头部的几行&objdump&显示不出来,jmp&的关键的地方,供&linker&链接。
-------------------------------------------------------
大致情况是:
1、PLT&里含一个表头部分,gcc&为每个库函数建产一个&PLT&表项。
2、GOT&里是符号表,供&PLT&表项取信息
3、最终在&PLT&表头产跳转到关键的链接。
流徎:&call&printf&&&-&&&&printf@PLT&&-&&&GOT&entry&-&&&printf@PLT&&-&&&PLT&头部&-&&&linker
& 回复于: 00:50:15
汗,一不小心给自己打了个臭蛋
& 回复于: 14:14:42
汗一个,&都2008年了.&现如今还有不带DEP支持的CPU吗?&系统装完第一件事就是打开DEP保护.
& 回复于: 14:27:06
引用:原帖由&mik&于&&00:37&发表&[url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=9023721&ptid=1237275]
兄弟,你对&PIC&的了解有多深呀,来探讨一下吧。:)&
懒得去研究&ELF&格式的来龙去脉。&objdump&来粗略分析一下,gcc&的生成&PIC&代码的大致情况:
gcc&会生成一个&PLT&表格和&GOT&表格。
main()
{
&&&&...&
以前研究过,不过不是x86平台的。
x86的也看过一点。周末不想细看了,明天上班了再来看:lol:
& 回复于: 14:29:06
引用:原帖由&醉卧水云间&于&&14:14&发表&[url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=9025668&ptid=1237275]
汗一个,&都2008年了.&现如今还有不带DEP支持的CPU吗?&系统装完第一件事就是打开DEP保护.&
CPU倒是有这功能,但操作系统不一定用嘛。
而且我记得DEP是栈保护,不是堆保护
& 回复于: 15:11:21
引用:原帖由&zx_wing&于&&14:29&发表&[url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=9025703&ptid=1237275]
CPU倒是有这功能,但操作系统不一定用嘛。
而且我记得DEP是栈保护,不是堆保护&
windows&系统现在都有&DEP&功能的。
linux&倒是要打补丁才支持。
& 回复于: 19:48:06
引用:原帖由&zx_wing&于&&14:29&发表&[url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=9025703&ptid=1237275]
CPU倒是有这功能,但操作系统不一定用嘛。
而且我记得DEP是栈保护,不是堆保护&
就凭这句话,&就可以看出你是非专业的.&
把函数移动到堆或栈上去执行那是几十年前的事了,&翻这种老账意义不大.
& 回复于: 19:49:39
引用:原帖由&醉卧水云间&于&&19:48&发表&[url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=9027347&ptid=1237275]
就凭这句话,&就可以看出你是非专业的.&
把函数移动到堆或栈上去执行那是几十年前的事了,&翻这种老账意义不大.&
恩&得加紧学习了
偶也是非专业的。。。
& 回复于: 22:02:11
引用:原帖由&醉卧水云间&于&&19:48&发表&[url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=9027347&ptid=1237275]
就凭这句话,&就可以看出你是非专业的.&
把函数移动到堆或栈上去执行那是几十年前的事了,&翻这种老账意义不大.&
就凭这句话,就看出人家是非专业的,汗~,你也太非专业了吧。
我就相信 zx_wing 是专业人士,每个人术有专攻,zx_wing&攻的领域你就比不上他。
本来顶楼的代码只是根据其它贴子作出一个演示而已,主要意义还是简单演示函数重定位。
说清楚了:我是非专业的。没你专业,so别来喷我。
& 回复于: 09:08:59
:mrgreen:&引用:原帖由&醉卧水云间&于&&19:48&发表&[url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=9027347&ptid=1237275]
就凭这句话,&就可以看出你是非专业的.&
把函数移动到堆或栈上去执行那是几十年前的事了,&翻这种老账意义不大.&
嘿嘿,被你看出来了。我对DEP本来就不怎么懂的。
不过如果兄弟愿意给我讲讲,我觉得我还是可以很快理解的:mrgreen:&
不过我还是不知道什么我的回复里面有什么地方说错了吗?:em14:
& 回复于: 09:41:04
引用:原帖由&醉卧水云间&于&&19:48&发表&[url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=9027347&ptid=1237275]
就凭这句话,&就可以看出你是非专业的.&
把函数移动到堆或栈上去执行那是几十年前的事了,&翻这种老账意义不大.&
我刚才去baidu了一把,跳出来一堆windowsXP和DEP的网页,我看瞄了一眼,确实是我说错了哈。
如果兄弟一来就告诉我是Execute&Disable&Bit我就知道了,不会说只能栈保护。之所以说是栈保护,是隐约记得某个兄弟曾经告诉过我说有个什么高档技术叫NX还是DEP可以保护栈,当时也没细究,不知道原来就是Execute&Disable&Bit。
这里顺便给跟我一样不知道DEP这个东东的兄弟扫个盲哈。我估计DEP是MS的一个叫法,其实也不是什么高档东西,intel最初的CPU的分页中type属性只有R/W(读写),没有X(可执行)。于是从PAE开始到X64,就在页表中加了一个X位控制某个页是否可以执行,称为Execute&Disable&Bit。很多RISC&CPU天生就有执行位,所以也不稀奇了。
技术这个东西,换个马甲出来还真不认识它:mrgreen:
& 回复于: 14:34:44
能否解释以下(char)0xe8&是什么含义
还要把函数调到堆上运行在现实中有什么用途呢
& 回复于: 14:55:52
引用:原帖由&jiangf&于&&14:34&发表&[url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=9032738&ptid=1237275]
能否解释以下(char)0xe8&是什么含义
还要把函数调到堆上运行在现实中有什么用途呢&
0xe8是call指令的机器码。这里是在寻找call指令,以便于修改其要call到的地址。
函数复制到堆上执行的情况很多,一个典型的用法是动态给系统打patch,也就是说一个程序在运行的时候给它打上一个patch。通常的做法就是malloc一块内存,把patch的code放到里面,然后动态修改正在执行的程序,让它在合适的时候跳转到这块内存执行。
今年的OLS大会有一篇文章就是关于这个的,叫《A&Runtime&Code&Modification&Method&for&Application&Programs》
可以从这个帖子下载http://linux.chinaunix.net/bbs/viewthread.php?tid=1020847&page=1#pid6676746(文章第二个连接中的245页)
& 回复于: 15:55:44
呵呵~~&其实关键问题就两个:
1.&DEP
2.&Compiler
& 回复于: 16:57:15
现代操作系统都不会允许数据段被执行吧
& 回复于: 18:59:49
怎么编译?&我用gcc&编译失败
& 回复于: 22:02:07
俺非专业,闪啦。。。。。。。。。:mrgreen:&:mrgreen:&:mrgreen:
& 回复于: 15:08:13
引用:原帖由&agaric&于&&23:55&发表&[url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=9010516&ptid=1237275]
:shock:&:shock:&那段地址有运行的权限吗&
自已申请的空间怎会没权限,除非操作系统不允许执行堆空间代码[&本帖最后由&chzht001&于&&15:10&编辑&]
& 回复于: 17:02:26
heap的地址范围,在data&segment里,&&而操作系统一般只允许code&segment有运行的权力。
& 回复于: 17:15:33
引用:原帖由&goldenfort&于&&17:02&发表&[url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=9042291&ptid=1237275]
heap的地址范围,在data&segment里,&&而操作系统一般只允许code&segment有运行的权力。&
操作系统如何让data&segment没有可执行的权利?
想当然尔[&本帖最后由&zx_wing&于&&17:16&编辑&]
& 回复于: 18:19:36
在这儿说的很清楚
http://www.x86.org/ddj/aug98/aug98.htm
segment&的&&base&和limit&合起来决定了地址的范围,&Segment&Access&Rights
决定&segment的读写执行等权限
& 回复于: 22:12:50
这种东西用汇编最省事
& 回复于: 22:41:03
引用:原帖由&goldenfort&于&&18:19&发表&[url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=9042930&ptid=1237275]
在这儿说的很清楚
http://www.x86.org/ddj/aug98/aug98.htm
segment&的&&base&和limit&合起来决定了地址的范围,&Segment&Access&Rights
决定&segment的读写执行等权限&
现在的操作系统都忽视了段式管理,都是基于平坦的内存管理模式。
cs、ds、ss 的&base&都是&0。&limit&都是&4G。
没错,确实只有以&code&segment 管理的空间才具有执行权限。但是可以以&ds&&存取内存,而以&cs 来管理执行。
举个例子说明:
1、分配的堆空间指针&p&地址是: 0x,在堆空间有一段代码。
2、假如有像以下这两条指令来执行:
  mov&$0x,&%eax
  call&*%eax
&&&&----------------------------------
&像这条&call&*%eax 执行一点问题都没有,eip 寄存器装入值&0x,processor 就去&0x 读取指令。
这里它是基于&code&segment&的,code&segment&的&base&是&0,&&limit&是&4G。
堆空间地址&0x&的可以基于&ds&segment&去存取。
换句话来说,cs&和&ds&所管理的线性空间是重叠的。
二、以上所述,管理的是虚拟地址空间,是个线性地址空间。
  但是,来到物理地址空间,情况就不同了,采用页式管理机制,打开的&PAE&功能后,PDE、PTE&结构的&NX&标志可以控制页面的执行权限,若&OS&将堆栈空间所对应的页面设为&NX(不可执行)的话,那么堆栈就失去了执行权限。
  OS&通过对页面&NX&控制,从而实现数据执行保护(DEP)。
& 回复于: 00:06:35
闲的没事干,从内存拷贝内存!函数指针指过去一定能用。
复制的没有重定位不能执行。
建议去研究dladdr,&dlclose,&dlerror,&dlopen,&dlsym,&dlvsym这些函数,有你需要的。
& 回复于: 07:47:15
传递参数应该可以用数组调用
& 回复于: 09:08:28
引用:原帖由&xiaofeizhu&于&&00:06&发表&[url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=9044737&ptid=1237275]
闲的没事干,从内存拷贝内存!函数指针指过去一定能用。
复制的没有重定位不能执行。
建议去研究dladdr,&dlclose,&dlerror,&dlopen,&dlsym,&dlvsym这些函数,有你需要的。&
呵呵,可是你知道对共享库的支持的底层是什么样的吗?
& 回复于: 09:25:48
mik你最近闲不?
我建议你去写个链接器,这属于不难又好玩的事情。
要写的话短消息我哈,我发一些比较有用的资料给你。
& 回复于: 10:53:38
发来大家共享下嘛:mrgreen:&:mrgreen:&:mrgreen:
& 回复于: 13:25:30
把大家的观点总结一下就是正确的结论.
& 回复于: 22:03:19
引用:原帖由&xiaofeizhu&于&&00:06&发表&[url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=9044737&ptid=1237275]
闲的没事干,从内存拷贝内存!函数指针指过去一定能用。
复制的没有重定位不能执行。
建议去研究dladdr,&dlclose,&dlerror,&dlopen,&dlsym,&dlvsym这些函数,有你需要的。&
:outu:&就你忙,忙就不要回复这些无聊的东东。
:outu:&就你懂这道理,懂也不要在不明白前因后果的提前下乱喷人,好不。我P~
& 回复于: 22:19:13
引用:原帖由&zx_wing&于&&09:25&发表&[url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=9045578&ptid=1237275]
mik你最近闲不?
我建议你去写个链接器,这属于不难又好玩的事情。
要写的话短消息我哈,我发一些比较有用的资料给你。&
说实在,就是闲也没心思写。偶就情愿下班回家到看看电视上上网,啥都不想干。哎~ 真惰!
话说回来,我现在最有兴趣的是自己写一个虚拟机,要完完全全的模拟CPU真实环境。
虽然有很多款虚拟机软件,也有很多开源的。但是功能还不够强大,不足以完全去分析一个CPU或OS。
qemu&这个还是挺不错,虽未达到我的要求,或许我不会用而已。
写一个我所要求的CPU模拟机难度大呀,花功夫又多,要对CPU以外围的各个细节要完完全全掌握理解才行。
zx_wing:&貌似你是这方面的工作的吧,发些这方面的资料给我吧,linker&方面的资料也行。thx~
& 回复于: 22:28:19
zx_wing:&
AMD&自家的模拟器&simnow 就非常不错,功能很强大,网上有免费下载。可惜是体验版,没多大功能,有没有办法搞到&simnow&正式版呀? 正式版要给&AMD 发邮件索取。偶给它发邮件,它不鸟偶,哈哈
& 回复于: 09:40:33
引用:原帖由&mik&于&&22:19&发表&[url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=9051346&ptid=1237275]
说实在,就是闲也没心思写。偶就情愿下班回家到看看电视上上网,啥都不想干。哎~ 真惰!
话说回来,我现在最有兴趣的是自己写一个虚拟机,要完完全全的模拟CPU真实环境。
虽然有很多款虚拟机软件,&...&
你要qemu的资料哦,汗,先发消息的时候直接说嘛,害我打了一堆字。
qemu资料主要是http://qemu.org/上的,还有就是qemu作者的论文《QEMU,&a&Fast&andPortableDynamic&Translator》(见附件)
qemu中CPU模拟这块是相对简单的,以你的汇编功底应该很快就看懂。设备模拟那块不用看了,和你的需求关系不大。
另外虚拟机软件都不能完全模拟CPU的真实环境,它们都是结果型的,例如你执行一条指令,它保证指令执行的效果和真是平台一样,但不保证过程和真实平台一样。
只有仿真器软件才保证执行过程和真实CPU一样(例如期间打断了pipeline之类),这都是用于厂商验证产品的,而且奇慢无比。目前开源的我只知道HP的ski,但是仿真自家的CPU。x86的好像还没有开源的。[&本帖最后由&zx_wing&于&&09:42&编辑&]
& 回复于: 20:47:50
拿个板凳顶顶吧~
& 回复于: 13:51:30
沉的还真快啊,好像没多少人来深入分析此问题:(
& 回复于: 19:42:59
水炒鸡蛋,,,
& 回复于: 18:30:34
我始终不能运行成功,是不是因为linux的保护机制使得不能在堆栈执行code?用了gdb调试发现一些奇怪的现象,也通过objdump看了,还是理解不到。各位大大抽点时间帮我解下惑吧,谢谢了啊!
系统环境:
[table=95%][tr][td][font=FixedSys][root@c]#&cat&/etc/redhat-release&
Red&Hat&Enterprise&Linux&Server&release&5.3&(Tikanga)
[root@c]#&uname&-i
x86_64[/font][/td][/tr][/table]
源代码:
[table=95%][tr][td][font=FixedSys][color=#000000][color=#0000cc][[/color]root@vcsone154&c[color=#0000cc]][/color][color=#0000cc]#[/color]&cat&fun_in_heap1[color=#0000cc].[/color]c&
[color=#0000cc]#[/color][color=#ff0000]include[/color]&[color=#0000cc]&[/color]stdio[color=#0000cc].[/color]h[color=#0000cc]&[/color]
[color=#0000cc]#[/color][color=#ff0000]include[/color]&[color=#0000cc]&[/color]stdlib[color=#0000cc].[/color]h[color=#0000cc]&[/color]
[color=#0000ff]void[/color]&add[color=#0000cc]([/color][color=#0000ff]int[/color]&a[color=#0000cc],[/color]&[color=#0000ff]int[/color]&b[color=#0000cc])[/color]
[color=#0000cc]{[/color]
&&&&&&&&[color=#ff0000]printf[/color][color=#0000cc]([/color][color=#ff00ff]"a+b=%d\n"[/color][color=#0000cc],[/color]&a[color=#0000cc]+[/color]b[color=#0000cc])[/color][color=#0000cc];[/color]
[color=#0000cc]}[/color]
[color=#0000ff]char[/color]&[color=#0000cc]*[/color]get_call_addr[color=#0000cc]([/color][color=#0000ff]char[/color]&[color=#0000cc]*[/color]p[color=#0000cc],[/color]&[color=#0000ff]int[/color]&len[color=#0000cc])[/color]&
[color=#0000cc]{[/color]
&&&&&&&[color=#0000ff]while[/color][color=#0000cc]([/color]len[color=#0000cc]-[/color][color=#0000cc]-[/color]&[color=#0000cc]&[/color][color=#0000cc]&[/color]&[color=#0000cc]([/color][color=#0000cc]*[/color]p&[color=#0000cc]![/color][color=#0000cc]=[/color]&[color=#0000cc]([/color][color=#0000ff]char[/color][color=#0000cc])[/color]0xe8&[color=#0000cc])[/color][color=#0000cc])[/color]
&&&&&&&&&&&&&&&p[color=#0000cc]+[/color][color=#0000cc]+[/color][color=#0000cc];[/color]
&&&&&&&[color=#0000ff]if[/color]&[color=#0000cc]([/color]len[color=#0000cc])[/color]
&&&&&&&&&&&&&&&[color=#0000ff]return[/color]&p[color=#0000cc];[/color]
&&&&&&&[color=#0000ff]else[/color]
&&&&&&&&&&&&&&&[color=#0000ff]return[/color]&0[color=#0000cc];[/color]
[color=#0000cc]}[/color]
[color=#0000ff]void[/color]&set_call[color=#0000cc]([/color][color=#0000ff]int[/color]&call_addr[color=#0000cc],[/color]&[color=#0000ff]int[/color]&fun_addr[color=#0000cc])[/color]
[color=#0000cc]{[/color]
&&&&&&&&[color=#0000ff]int[/color]&ip&[color=#0000cc]=[/color]&call_addr&[color=#0000cc]+[/color]&5[color=#0000cc];[/color]
&&&&&&&&[color=#0000ff]int[/color]&set_call_addr&[color=#0000cc]=[/color]&call_addr&[color=#0000cc]+[/color]&1[color=#0000cc];[/color]
&&&&&&&[color=#0000cc]([/color][color=#0000cc]*[/color][color=#0000cc]([/color][color=#0000ff]int[/color]&[color=#0000cc]*[/color][color=#0000cc])[/color]set_call_addr[color=#0000cc])[/color]&[color=#0000cc]=[/color]&[color=#0000cc]([/color][color=#0000ff]int[/color][color=#0000cc])[/color][color=#0000cc]([/color][color=#ff0000]printf[/color]&[color=#0000cc]-[/color]&ip[color=#0000cc])[/color][color=#0000cc];[/color]
[color=#0000cc]}[/color]
[color=#0000ff]int[/color]&main[color=#0000cc]([/color][color=#0000cc])[/color]
[color=#0000cc]{[/color]
&&&&&&&&&[color=#0000ff]char[/color]&[color=#0000cc]*[/color]p&[color=#0000cc]=[/color]&[color=#0000cc]([/color][color=#0000ff]char[/color]&[color=#0000cc]*[/color][color=#0000cc])[/color][color=#ff0000]malloc[/color][color=#0000cc]([/color]100[color=#0000cc])[/color][color=#0000cc];[/color]
&&&&&&&&&
&&&&&&&&&[color=#ff0000]memcpy[/color][color=#0000cc]([/color]p[color=#0000cc],[/color]&add[color=#0000cc],[/color]&100[color=#0000cc])[/color][color=#0000cc];[/color]
&&&&&&&&&[color=#0000ff]void[/color]&[color=#0000cc]([/color][color=#0000cc]*[/color]pf[color=#0000cc])[/color][color=#0000cc]([/color][color=#0000ff]int[/color][color=#0000cc],[/color]&[color=#0000ff]int[/color][color=#0000cc])[/color]&[color=#0000cc]=[/color]&[color=#0000cc]([/color][color=#0000ff]void[/color][color=#0000cc]([/color][color=#0000cc]*[/color][color=#0000cc])[/color][color=#0000cc]([/color][color=#0000ff]int[/color][color=#0000cc],[/color]&[color=#0000ff]int[/color][color=#0000cc])[/color][color=#0000cc])[/color]p[color=#0000cc];[/color]
&&&&&&&&&&[color=#0000ff]char[/color]&[color=#0000cc]*[/color]call_addr&[color=#0000cc]=[/color]&get_call_addr[color=#0000cc]([/color]p[color=#0000cc],[/color]&100[color=#0000cc])[/color][color=#0000cc];[/color]
&&&&&&&&&&[color=#0000ff]if[/color]&[color=#0000cc]([/color]call_addr[color=#0000cc])[/color]&[color=#0000cc]{[/color]
&&&&&&&&&&&&&&&&&&set_call[color=#0000cc]([/color][color=#0000cc]([/color][color=#0000ff]int[/color][color=#0000cc])[/color]call_addr[color=#0000cc],[/color]&[color=#0000cc]([/color][color=#0000ff]int[/color][color=#0000cc])[/color][color=#ff0000]printf[/color][color=#0000cc])[/color][color=#0000cc];[/color]
&&&&&&&&&&&&&&&&&&pf[color=#0000cc]([/color]10[color=#0000cc],[/color]&20[color=#0000cc])[/color][color=#0000cc];[/color]
&&&&&&&&&&[color=#0000cc]}[/color]
&&&&&&&&&[color=#0000ff]return[/color]&0[color=#0000cc];[/color]
[color=#0000cc]}[/color]
[/color][/font][/td][/tr][/table]
编译及运行结果:
[table=95%][tr][td][font=Fixedsys][root@c]#&gcc&-g&fun_in_heap1.c&&&&&&&&&&&
fun_in_heap1.c:&In&function&in&set_call():
fun_in_heap1.c:24:&warning:&cast&to&pointer&from&integer&of&different&size
fun_in_heap1.c:24:&warning:&cast&from&pointer&to&integer&of&different&size
fun_in_heap1.c:&In&function&in&main():
fun_in_heap1.c:32:&warning:&incompatible&implicit&declaration&of&built-in&function&in&memcpy()
fun_in_heap1.c:38:&warning:&cast&from&pointer&to&integer&of&different&size
[root@c]#&./a.out&
Segmentation&fault[/font][/td][/tr][/table]
gdb调试结果:
[table=95%][tr][td][font=FixedSys][color=#000000][color=#0000cc]([/color]gdb[color=#0000cc])[/color]&br&37
Breakpoint&1&at&0x400653[color=#0000cc]:[/color]&[color=#ff0000]file[/color]&fun_in_heap1[color=#0000cc].[/color]c[color=#0000cc],[/color]&[color=#ff0000]line[/color]&37[color=#0000cc].[/color]
[color=#0000cc]([/color]gdb[color=#0000cc])[/color]&start
Breakpoint&2&at&0x400594[color=#0000cc]:[/color]&[color=#ff0000]file[/color]&fun_in_heap1[color=#0000cc].[/color]c[color=#0000cc],[/color]&[color=#ff0000]line[/color]&29[color=#0000cc].[/color]
Starting&program[color=#0000cc]:[/color]&[color=#0000cc]/[/color]opt[color=#0000cc]/[/color]home[color=#0000cc]/[/color]twang2[color=#0000cc]/[/color][color=#ff0000]test[/color][color=#0000cc]/[/color]c[color=#0000cc]/[/color]a[color=#0000cc].[/color]out&
main&[color=#0000cc]([/color][color=#0000cc])[/color]&at&fun_in_heap1[color=#0000cc].[/color]c[color=#0000cc]:[/color]29
29&&&&&&&&&&&&&&&[color=#0000ff]char[/color]&[color=#0000cc]*[/color]p&[color=#0000cc]=[/color]&[color=#0000cc]([/color][color=#0000ff]char[/color]&[color=#0000cc]*[/color][color=#0000cc])[/color][color=#ff0000]malloc[/color][color=#0000cc]([/color]100[color=#0000cc])[/color][color=#0000cc];[/color]
[color=#0000cc]([/color]gdb[color=#0000cc])[/color]&cont
Continuing[color=#0000cc].[/color]
Breakpoint&1[color=#0000cc],[/color]&main&[color=#0000cc]([/color][color=#0000cc])[/color]&at&fun_in_heap1[color=#0000cc].[/color]c[color=#0000cc]:[/color]37
37&&&&&&&&&&&&&&&&&&&&&&&&set_call[color=#0000cc]([/color][color=#0000cc]([/color][color=#0000ff]int[/color][color=#0000cc])[/color]call_addr[color=#0000cc],[/color]&[color=#0000cc]([/color][color=#0000ff]int[/color][color=#0000cc])[/color][color=#ff0000]printf[/color][color=#0000cc])[/color][color=#0000cc];[/color]
[color=#0000cc]([/color]gdb[color=#0000cc])[/color]&s
set_call&[color=#0000cc]([/color]call_addr[color=#0000cc]=[/color][color=#0000cc],[/color]&fun_addr[color=#0000cc]=[/color]4195288[color=#0000cc])[/color]&at&fun_in_heap1[color=#0000cc].[/color]c[color=#0000cc]:[/color]21
21&&&&&&&&&&&&&&[color=#0000ff]int[/color]&ip&[color=#0000cc]=[/color]&call_addr&[color=#0000cc]+[/color]&5[color=#0000cc];[/color]
[color=#0000cc]([/color]gdb[color=#0000cc])[/color]&n
22&&&&&&&&&&&&&&[color=#0000ff]int[/color]&set_call_addr&[color=#0000cc]=[/color]&call_addr&[color=#0000cc]+[/color]&1[color=#0000cc];[/color]
[color=#0000cc]([/color]gdb[color=#0000cc])[/color]&n
[color=red]23&&&&&&&&&&&&&(*(int&*)set_call_addr)&=&(int)(printf&-&ip);
[/color][color=#0000cc]([/color]gdb[color=#0000cc])[/color]&[color=#ff0000]printf[/color]&[color=#ff00ff]"%x\n"[/color][color=#0000cc],[/color]&[color=#0000cc]([/color][color=#0000ff]int[/color][color=#0000cc])[/color][color=#0000cc]([/color][color=#ff0000]printf[/color]&[color=#0000cc]-[/color]&ip[color=#0000cc])[/color]
[color=red]c3b052db
[/color][color=#0000cc]([/color]gdb[color=#0000cc])[/color]&[color=#ff0000]printf[/color]&[color=#ff00ff]"%x\n"[/color][color=#0000cc],[/color]&[color=#0000cc]([/color][color=#0000cc]*[/color][color=#0000cc]([/color][color=#0000ff]int[/color]&[color=#0000cc]*[/color][color=#0000cc])[/color]set_call_addr[color=#0000cc])[/color]
fffffecb
[color=#0000cc]([/color]gdb[color=#0000cc])[/color]&n
24&&&&&&[color=#0000cc]}[/color]
[color=#0000cc]([/color]gdb[color=#0000cc])[/color]&[color=#ff0000]printf[/color]&[color=#ff00ff]"%x\n"[/color][color=#0000cc],[/color]&[color=#0000cc]([/color][color=#0000cc]*[/color][color=#0000cc]([/color][color=#0000ff]int[/color]&[color=#0000cc]*[/color][color=#0000cc])[/color]set_call_addr[color=#0000cc])[/color]
[color=red]e44b83a3[/color]
[color=#0000cc]([/color]gdb[color=#0000cc])[/color]&[color=#ff0000]set[/color]&[color=#0000cc]([/color][color=#0000cc]*[/color][color=#0000cc]([/color][color=#0000ff]int[/color]&[color=#0000cc]*[/color][color=#0000cc])[/color]set_call_addr[color=#0000cc])[/color][color=#0000cc]=[/color]0xc3b052db
[color=#0000cc]([/color]gdb[color=#0000cc])[/color]&s
main&[color=#0000cc]([/color][color=#0000cc])[/color]&at&fun_in_heap1[color=#0000cc].[/color]c[color=#0000cc]:[/color]38
38&&&&&&&&&&&&&&&&&&&&&&&&pf[color=#0000cc]([/color]10[color=#0000cc],[/color]&20[color=#0000cc])[/color][color=#0000cc];[/color]
[color=#0000cc]([/color]gdb[color=#0000cc])[/color]&s
Program&received&[color=#ff0000]signal[/color]&[color=#ff0000]SIGSEGV[/color][color=#0000cc],[/color]&Segmentation&fault[color=#0000cc].[/color]
0xbf48010&in&[color=#0000cc]?[/color][color=#0000cc]?[/color]&[color=#0000cc]([/color][color=#0000cc])[/color]
[/color][/font][/td][/tr][/table]
奇怪的问题是:23行(*(int&*)set_call_addr)&=&(int)(printf&-&ip);执行之后打印(*(int&*)set_call_addr)的值却发现跟(int)(printf&-&ip)的值不一样。即使强行设置成一样的也仍然是Segment&Fault。Segment&Fault除了内存访问越界,对当前内存没有执行权限也会产生它吗?
& 回复于: 05:29:27
1)很好的帖子。学习。
2)迁移过去的,必须是可重定位代码。
3)代码在Text区和Heap区都可以运行。堆分配有时用来存放数据,有时用来装入代码。或装入数据代码混合体。
4)支持造轮子。造过轮子,才能真正明白这轮子到底是咋回事。
5)CPU模拟器连结果也只能部分模拟。与时间相关的,与硬件相关的,很难或没法模拟。zx_wing能不能起帖说说模拟?让我们学学?
& 回复于: 11:45:28
引用:原帖由&zx_wing&于&&14:55&发表&[url=http://bbs3.chinaunix.net/redirect.php?goto=findpost&pid=9032987&ptid=1237275]
0xe8是call指令的机器码。这里是在寻找call指令,以便于修改其要call到的地址。
函数复制到堆上执行的情况很多,一个典型的用法是动态给系统打patch,也就是说一个程序在运行的时候给它打上一个patch。通常的&...&
这个动态给系统打patch是属于dynamic&upgrade的技术吧?哪里有介绍dynamic&upgrade比较好的资料?网上找了些,是用java实现的,没怎么看明白。
原文链接:
转载请注明作者名及原文出处

我要回帖

更多关于 从命令行运行编译器 的文章

 

随机推荐