当前位置: 首页 > article >正文

对数组名取地址

一、c语言的数组定义的几种形式如下:
char array[100]; 
char array[] = "abcdefg";
char array[]={'a','b','c','d','e','f','g'};
int array[]={1,2,3,4};

二、数组名代表数组的首地址,数组元素可以通过以下方式引用:
array[0] == *(array + 0);  //取第一个元素 
array[1] == *(array + 1); //取第二个元素
printf("%.08x", array); //打印数组地址

三、问题是如果对数组名取地址操作呢,结果会怎样? 下面引用我在网上找到的资料(http://taobaodian.bokee.com/viewdiary.11716434.html):

问题一:
看到一篇文章这么写的。。
int array[10]; 
int (*ptr)[10]; 
ptr=&array;//这里说明&array是指向数组的指针,但为什么&array是指向数组的指针? 
答一:
对数组名取地址在C标准里面是未定义的行为。由于数组名是右值,而&操作符要求操作数具有具体的内存空间,换言之就是一个变量,因此对数组名取地址本来就是非法的,早期的编译器明确规定这是非法的。不过不知道什么原因,现在的编译器多数把&array定义为一个值跟array相同,类型是一个指向数组的地址,注意了,是地址,不是指针。之所以是指向数组的地址,是因为array是一个数组名,它就代表了int array[10]这个数组。而ptr也是定义为一个指向具有10个int数的数组的指针,因此&array能被赋予ptr。
 
问题二:
对于数组b[],b是数组的地址,但b不算变量,有没有一个地方存放b?而且b是不
是存放的就是自己所在的地址。因为我碰到了如下的问题:
定义一个指针数组
char *a[2];
那么a的值和&a的值是不是应该一样?
答二:
数组名是符号地址常量,在编译时求值并存在编译器的符号表里面,其值就是个内存地址;所以你说的有没有一个地方存放b,可以认为程序没有给其分配空间,数组名只是代表了那个数组空间;与指针不一样,指针指向一块空间,同时指针本身也存储在某个空间;可以认为数组名存在在符号表里,符号表是编译器用的,我们管不到;a和&a值是一样的,本来对常量取地址是非法的,但是标准组织没有定对数组名取地址是非法还是合法,所以因编译器而异,VC是合法的。

四、应用

下面是一段获得Shell的内嵌asm的c代码

void GetShell()
{
     __asm{
  mov edi
,  esp ;保留当前esp
  mov ebx
,  ebp ;保留当前ebp

  mov ebp
, esp ;    把当前esp赋给ebp 
  xor eax
,  eax
  
push  eax

  
sub  esp ,  0ch ;保留字符串空间 
  mov byte ptr [ebp
- 0bh] , 6Dh ;  m
  mov byte ptr [ebp
- 0ah] , 73h ;  s
  mov byte ptr [ebp
- 09h] , 76h ;  v
  mov byte ptr [ebp
- 08h] , 63h ;  c
  mov byte ptr [ebp
- 07h] , 72h ;  r
  mov byte ptr [ebp
- 06h] , 74h ;  t
  mov byte ptr [ebp
- 05h] , 2Eh ;   .
  mov byte ptr [ebp
- 04h] , 64h ;  d
  mov byte ptr [ebp
- 03h] , 6Ch ;  l
  mov byte ptr [ebp
- 02h] , 6Ch ;  l
  lea eax
,  [ebp - 0bh]
  
push  eax
  mov eax
,   0x7c883f9c
  call eax ;调用LoadLibrary

  mov ebp
, esp
  xor eax
, eax 
  
push  eax ;压入0,esp- 4 , ; 作用是构造字符串的结尾 0字符。 
  
sub  esp , 10h ;加上上面,一共有12个字节 , ;用来放 " command.com " 。 
  mov byte ptr [ebp
- 0ch] , 63h ;  c
  mov byte ptr [ebp
- 0bh] , 6fh ;  o
  mov byte ptr [ebp
- 0ah] , 6dh ;  m
  mov byte ptr [ebp
- 09h] , 6Dh ;  m
  mov byte ptr [ebp
- 08h] , 61h ;  a
  mov byte ptr [ebp
- 07h] , 6eh ;  n
  mov byte ptr [ebp
- 06h] , 64h ;  d
  mov byte ptr [ebp
- 05h] , 2Eh ;   .
  mov byte ptr [ebp
- 04h] , 63h ;  c
  mov byte ptr [ebp
- 03h] , 6fh ;  o
  mov byte ptr [ebp
- 02h] , 6dh ;  m一个一个生成串 " command.com " .
  lea eax
, [ebp - 0ch] ;   
  
push  eax ;    command . com串地址作为参数入栈
  mov eax
,   0x77bf93c7  ;
  call eax ;     call System函数的地址
  mov ebp
,  ebx; 恢复ebp
  mov esp
,  edi ;恢复esp
 }
}

其生成的机器码为

55  
8B EC
83  EC 4C
53
56
57
8D 7D B4
B9 
13   00   00   00
B8 CC CC CC CC
F3 AB

8B FC 8B DD 8B EC 
33  C0  50
83  EC 0C C6  45  F5 6D C6  45  F6  73
C6 
45  F7  76  C6  45  F8  63  C6  45  F9  72
C6 
45  FA  74  C6  45  FB 2E C6  45  FC  64  C6  45  FD 6C
C6 
45  FE 6C 8D  45  F5  50  B8 9C 3F  88  7C FF D0 8B EC  33  C0  50
83  EC  10  C6  45  F4  63  C6  45  F5 6F C6  45  F6 6D C6  45  F7 6D
C6 
45  F8  61  C6  45  F9 6E C6  45  FA  64  C6  45  FB 2E C6  45  FC  63
C6 
45  FD 6F C6  45  FE 6D 8D  45  F4  50  B8 C7  93  BF  77  FF D0 8B EB 8B E7

5F 5E 5B 8B E5 5D C3

于是,我们可以将这段机器码放到内存中,让eip指向首地址去执行这段代码
unsigned char shellcode[] =
"/x55"
"/x8B/xEC"
"/x83/xEC/x4C"
"/x53"
"/x56"
"/x57"
"/x8D/x7D/xB4"
"/xB9/x13/x00/x00/x00"
"/xB8/xCC/xCC/xCC/xCC"
"/xF3/xAB"
"/x8B/xFC/x8B/xDD/x8B/xEC/x33/xC0/x50"
"/x83/xEC/x0C/xC6/x45/xF5/x6D/xC6/x45/xF6/x73"
"/xC6/x45/xF7/x76/xC6/x45/xF8/x63/xC6/x45/xF9/x72"
"/xC6/x45/xFA/x74/xC6/x45/xFB/x2E/xC6/x45/xFC/x64/xC6/x45/xFD/x6C"
"/xC6/x45/xFE/x6C/x8D/x45/xF5/x50/xB8/x9C/x3F/x88/x7C/xFF/xD0/x8B/xEC/x33/xC0/x50"
"/x83/xEC/x10/xC6/x45/xF4/x63/xC6/x45/xF5/x6F/xC6/x45/xF6/x6D/xC6/x45/xF7/x6D"
"/xC6/x45/xF8/x61/xC6/x45/xF9/x6E/xC6/x45/xFA/x64/xC6/x45/xFB/x2E/xC6/x45/xFC/x63"
"/xC6/x45/xFD/x6F/xC6/x45/xFE/x6D/x8D/x45/xF4/x50/xB8/xC7/x93/xBF/x77/xFF/xD0/x8B/xEB/x8B/xE7"
"/x5F/x5E/x5B/x8B/xE5/x5D/xC3";

int main(int argc, char* argv[])
{
   ((void (*)())&shellcode)();
}

请注意上面怎样调用该shellcode,取数组名地址,然后转换为void (*)()这样的函数指针,编译器解析通过。
反汇编后发现生成指令
call 数组首地址

请注意,此处shellcode和&shellcode的值都是数组的首地址,但含义不一样,请参照上面的说明。

http://www.lryc.cn/news/2421067.html

相关文章:

  • 从下列选项中选择正确的java表达式,java笔试常见的选择题
  • python automl_深度解析AutoML框架——H2O:小白也能使用的自动机器学习平台
  • 小迪安全 第12天:php开发-个人博客项目文章功能显示数据库操作数据接受
  • Spring Cloud Loadbalancer服务均衡负载器
  • 程序员需知的 58 个网站
  • 风云三国2.4问鼎天下修改作弊大全
  • Flickr为在照片中寻找朋友而添加了用户标签
  • 行健设计_【天财男女神季】张行健amp;程迪:十佳第一!=科研人的理性+统计人的责任+学霸情侣...
  • [Vulkan教程]绘制一个三角形/呈现/交换链(Swip chain)
  • vs2005快捷键大全
  • GUI Design Studio----如何创建交互式设计(二)
  • 如何用PS切图和输出网页?
  • 开源软件下载地址
  • 若非群玉山头见,会向瑶台月下逢
  • Vba菜鸟教程
  • 别盲从了,spring 解决循环依赖真的一定需要三级缓存吗?demo结合源码讲解三级缓存的真正目的,一级缓存singletonFactories的真正作用,看到文章最后让面试官眼前一亮
  • 华众 mysql_华众虚拟主机管理系统HZhost三大常见错误!
  • visual studio 2008 开发c++学习(一):参考网上材料
  • 网页中Flash如何下载?网页中Flash下载方法
  • MFC界面库BCGControlBar v32.1 - 可视化管理器和主题升级
  • css的浮动详解
  • qq里测试音色的软件,QQ换音大师2015(QQ消息提示声音修改软件)
  • Flash Player Debugger下载(9/10版本)
  • IT服务方案设计攻略(详)
  • 【web前端期末大作业】学生个人网页设计作品 学生个人网页设计作品 学生个人网页模板 简单个人主页成品
  • PCB板-Solder-Mask-layer与Paste-Mask-layers的区别以及其它各层的详细含义介绍
  • 实现将 GridView 导出到 Excel文件中
  • 怕堵车?路况查询应用帮你查: 路况信息应用横向评测
  • Windows Phone开发之路(10) 进军WP的第一个程序
  • 给网页去色