本人发现一个新问题!不知道大家以前发现过没有!来一起探讨下!

Description of your first forum.

本人发现一个新问题!不知道大家以前发现过没有!来一起探讨下!

帖子tigerhacker » 星期四, 2006年4月6日 18:34


#include <stdio.h>
void main()
{
int a[2],b[2];
b[1]=4;
printf("%d",a[-1]);
}

//猜猜该代码会不会编译通过,如果可以,那么输出结果是什么?
对于这种代码!delphi同样存在这个问题!有意思!
 
 
 

本人发现一个新问题!不知道大家以前发现过没有!来一起探讨下!

帖子tigerhacker » 星期四, 2006年4月6日 18:38


#include <stdio.h>
void main()
{
int b[2],a[2];
b[1]=4;
printf("%d",a[-1]);
}
//猜猜该代码会不会编译通过,如果可以,那么输出结果是什么?
 
 
 

本人发现一个新问题!不知道大家以前发现过没有!来一起探讨下!

帖子木桩 » 星期四, 2006年4月6日 20:25


转成Delphi的
var b,a:array[2] of integer;
begin
 b[1]:=4;
 showmessage(format('%d',[a[-1]]));
end;

应该是4把,就是b[1]的数据:
存放是 b[0] b[1] a[0] a[1]
a是指针,a[x]后面的数组下标x相当于 @a + x
所以 a[-1] 是 a的地址前一个Integer型数据。
 
 
 

本人发现一个新问题!不知道大家以前发现过没有!来一起探讨下!

帖子木桩 » 星期四, 2006年4月6日 20:32


诶,通过不了...
改 var b,a:array[0..1] of integer; ,结果

E1012 Constant expression violates subrange bounds
范围错误...(Delphi2006 能检查出来...)
 
 
 

本人发现一个新问题!不知道大家以前发现过没有!来一起探讨下!

帖子tigerhacker » 星期四, 2006年4月6日 20:43


木桩,
说的是正确的!我也研究过了!不过呢,我在想的是如果可以这样,那么我们如果拿到一个exe程序
就可以覆盖原代码的数据和读出原代码的数据了!
 
 
 

本人发现一个新问题!不知道大家以前发现过没有!来一起探讨下!

帖子木桩 » 星期四, 2006年4月6日 21:04


其实不同编译器产生的代码不同,想靠这个溢出覆盖后面的部分,麻烦得很。
刚刚试了一下,实际上那段代码在Delphi里根本就不指向b[1]  (假设能运行)
Delphi的顺序和C正好相反,定义 var b,a:array[0..1] of integer; 结果内存里实际存放为:
... a[0] a[1] b[0] b[1] ... (这样a[-1]就是之前的一个变量了)
用这段代码可以证明:

//读取内存的函数
procedure Mem(Address:Pointer;Var Buf;bLength:Cardinal);
Var cBuf:array of byte absolute Buf;    //强制Buf为Byte数组
asm
 mov edx,cBuf           //取 Buf 地址
 mov ebx,Address        //写目标地址到ebx
 mov ecx,bLength
@re:
 mov al,[ebx]
 mov [edx],al

 inc ebx
 inc edx
 dec ecx
 jnz @re                //没完的话,继续
end;

procedure TForm1.Button1Click(Sender: TObject);
var Bufs:array[0..15] of Byte;
   b,a:array[0..1] of integer;
begin
 b[0]:=$10;
 b[1]:=$40;
 a[0]:=$A0;
 a[1]:=$80;
 mem(@a,Bufs,15);
 Showmessage(Format('a[0] = %0.2x%0.2x%0.2x%0.2x'
            +#13#10+'a[1] = %0.2x%0.2x%0.2x%0.2x'
            +#13#10+'b[0] = %0.2x%0.2x%0.2x%0.2x'
            +#13#10+'b[1] = %0.2x%0.2x%0.2x%0.2x',
           [Bufs[3],Bufs[2],Bufs[1],Bufs[0],
            Bufs[7],Bufs[6],Bufs[5],Bufs[4],
            Bufs[11],Bufs[10],Bufs[9],Bufs[8],
            Bufs[15],Bufs[14],Bufs[13],Bufs[12]]));
 a[0]:=a[1]+b[0]+b[1];   //这里要干点什么,不然Delphi发现你后面没用到a,b,用mem()前就释放空间了。
end;
 
 
 

本人发现一个新问题!不知道大家以前发现过没有!来一起探讨下!

帖子tigerhacker » 星期五, 2006年4月7日 09:09


对于C语言,我实验过了,后定义的变量的地址要偏前些
比如,在我的电脑上面
int a[5],b[4],c[3],d;
那么 &a=1310572
    &b=1310556
    &c=1310544
    &d=1310540
如果是 int d,c[3],b[4],a[5];
那么 &a=1310540
    &b=1310560
    &c=1310576
    &d=1310588

我的想法是:对于C语言,变量的内存分配是这样的:编译器编译源文件的时候,先把变量名字压栈,等分配内存的时候再弹栈一个一个的分配内存,不知道是这样么!
 
 
 

本人发现一个新问题!不知道大家以前发现过没有!来一起探讨下!

帖子tigerhacker » 星期五, 2006年4月7日 09:25


再看看这两段代码,我觉得没办法理解问什么
//***********************************************************
#include <stdio.h>
void main()
{
int a[4],b[4],c[8],i;
for (i=0;i<4;i++)[code][/code]
{
a[i]=i;
b[i]=2*i;
}
printf("a[i]=");
for (i=0;i<4;i++)
printf("%d,",a[i]);
printf("\nb[i]=");
for (i=0;i<4;i++)
printf("%d,",b[i]);
for (i=8;i<16;i++)
c[i]=100;
printf("\na[i]=");
for (i=0;i<4;i++)
printf("%d,",a[i]);
printf("\nb[i]=");
for (i=0;i<4;i++)
printf("%d,",b[i]);
printf("\n&a[0]=%d\n&b[0]=%d\n&c[0]=%d\n&i=%d\n",&a,&b,&c,&i);
 for (i=8;i<16;i++)
printf("\n&c[%d]=%d",i,&c[i]);
}
这段代码输出:(a[i],b[i]的值被覆盖)
           a[i]=0,1,2,3,
           b[i]=0,2,4,6,
           a[i]=100,100,100,100
           b[i]=100,100,100,100
           &a[0]=1310576
           &b[0]=1310560
           &c[0]=1310528
           &i=1310524

           &c[8]=1310560
           &c[9]=1310564
           &c[10]=1310568
           &c[11]=1310572
           &c[12]=1310576
           &c[13]=1310580
           &c[14]=1310584
           &c[15]=1310588

//******************************************************************
#include <stdio.h>
void main()
{
int a[4],b[4],i,c[8];
for (i=0;i<4;i++)
{
a[i]=i;
b[i]=2*i;
}
printf("a[i]=");
for (i=0;i<4;i++)
printf("%d,",a[i]);
printf("\nb[i]=");
for (i=0;i<4;i++)
printf("%d,",b[i]);
for (i=8;i<16;i++)
c[i]=100;
printf("\na[i]=");
for (i=0;i<4;i++)
printf("%d,",a[i]);
printf("\nb[i]=");
for (i=0;i<4;i++)
printf("%d,",b[i]);
printf("\na[0]=%d\nb[0]=%d\nc[0]=%d\ni=%d\n",&a,&b,&c,&i);
 for (i=8;i<16;i++)
printf("\n&c[%d]=%d",i,&c[i]);
}

//对于这段代码,和第一段代码就只把  int a[4],b[4],c[8],i;变成 int a[4],b[4],i,c[8];   输出结果为:(a[i],b[i]的值没有被覆盖)
           a[i]=0,1,2,3,
           b[i]=0,2,4,6,
           a[i]=0,1,2,3,
           b[i]=0,2,4,6,
           &a[0]=1310576
           &b[0]=1310560
           &c[0]=1310524
           &i=1310556

           &c[8]=1310556
           &c[9]=1310560
           &c[10]=1310564
           &c[11]=1310568
           &c[12]=1310572
           &c[13]=1310576
           &c[14]=1310580
           &c[15]=1310584
 
 
 

本人发现一个新问题!不知道大家以前发现过没有!来一起探讨下!

帖子木桩 » 星期五, 2006年4月7日 18:12


后定义的变量的地址要偏前些  C就是这样的,不用怀疑,就是你说得那样,
好像只有Pascal是反的,这是编译器不同的问题。所以你说的 “拿到一个exe程序...” 还要分情况来处理覆盖位置,麻烦而且很难实现吧,至少Delphi2006里,很多溢出覆盖法用不上了。

从第一段代码看出
&c[8]=1310560 正好是 &b[0]=1310560 的位置,所以 往 c[8] ~ c[16]里写东西,覆盖a,b也不奇怪。
而代码2的关键,在于&c[8]=1310556 是 &i=1310556
写c[8]就相当于写i,这样明白了吗?看看
for (i=8;i<16;i++)
结果第一次循环就令 i=100; //c[8]=100
这样自然跳出了,从而没有覆盖a,b
 
 
 

本人发现一个新问题!不知道大家以前发现过没有!来一起探讨下!

帖子tigerhacker » 星期六, 2006年4月8日 00:42


你可以打印一下C[8]~C[15],你就觉得奇怪了!还可以打印一下i;
 
 
 

本人发现一个新问题!不知道大家以前发现过没有!来一起探讨下!

帖子tigerhacker » 星期六, 2006年4月8日 00:49


不好意思,刚才拿着半截就开跑,现在知道为什么了,谢谢你,呵呵!~~
能留下你的QQ吗?我个人比较喜欢DELPHI和C,!
 
 
 

本人发现一个新问题!不知道大家以前发现过没有!来一起探讨下!

帖子木桩 » 星期六, 2006年4月8日 09:34


我一般不上QQ的,要的话也给你 443101052
要不还是邮件交流吧 graves@126.com
ps:我只用Delphi
 
 
 

本人发现一个新问题!不知道大家以前发现过没有!来一起探讨下!

帖子tigerhacker » 星期五, 2006年4月14日 16:33


看的出来是个老手了,我一般是用delphi写点软件!c语言做点技术测试什么的!
我加你的QQ!