Windows逆向安全(一)之基础知识(十四)

news2025/1/13 7:22:27

指针

什么是指针

一般关于指针的解释都离不开地址。这里先暂且忘记这个概念

指针其实也是一种数据类型,和先前学习的int float等数据类型没有实质上的区别,只不过这个数据类型是在先前学习的所有数据类型后面加上若干个*号,如char *,int *等等,这种数据类型被称为指针

  • 任意类型后面都可以加上*号,使其成为新的指针数据类型
  • *可以是任意多个

指针的声明

指针的声明其实在前面介绍什么是指针的时候就已经讲到了,例子如下:

struct S1{
        int a;
};

void function(){                
        char* a;
        short** b;
        int*** c;
        long**** d;
        _int64***** e;
        float****** f;
        double******* g;
        S1******** s1;
}

可以看到所有的其它数据类型(包括结构体)后面加上若干个*后就是所谓的指针了

推荐的声明方式如上

但也可以这样将*放在变量前面,但不推荐,因为这样相当于将这个数据类型拆开了,不利于理解

struct S1{
        int a;
};

void function(){                
        char *a;
        short **b;
        int ***c;
        long ****d;
        _int64 *****e;
        float ******f;
        double *******g;
        S1 ********s1;
}

指针的赋值

在说指针的赋值之前先看看先前普通变量的赋值

普通变量的赋值貌似是直接使用 变量=值即可,但其实是编译器简化了赋值的步骤,实际上在赋值前本应该加上要赋值类型

例子如下:

void function(){                
        int a;
    a=610;
    a=(int)610;
}

现在再来看指针的赋值

void function(){                
        char* a;
        a=(char*) 610;
    int** b;
    b=(int**) 610;
}

在要赋的值前面加上指针的类型即可,貌似和普通变量的赋值并无太大差别,此时也注意到这里的指针也和地址没有什么关联

指针的的类型转换这里暂且不提

指针的数据宽度

研究数据宽度方法

先前研究过其它基本变量的数据宽度,会发现char、short、int都是按照4字节来分配的(内存对齐),但实际使用的情况下则是按照其原本类型的数据宽度来赋值或进行其它操作的

如:

void function(){                
        char a;
        short b;
        int c;
        a=1;
        b=2;
        c=3;
}

其对应的反汇编代码为:

11:   void function(){
00401010   push        ebp
00401011   mov         ebp,esp
00401013   sub         esp,4Ch
00401016   push        ebx
00401017   push        esi
00401018   push        edi
00401019   lea         edi,[ebp-4Ch]
0040101C   mov         ecx,13h
00401021   mov         eax,0CCCCCCCCh
00401026   rep stos    dword ptr [edi]
12:       char a;
13:       short b;
14:       int c;
15:       a=1;
00401028   mov         byte ptr [ebp-4],1
16:       b=2;
0040102C   mov         word ptr [ebp-8],offset function+20h (00401030)
17:       c=3;
00401032   mov         dword ptr [ebp-0Ch],3
18:   }
00401039   pop         edi
0040103A   pop         esi
0040103B   pop         ebx
0040103C   mov         esp,ebp
0040103E   pop         ebp
0040103F   ret

可以注意到此时提升的堆栈为4Ch,而默认(空函数时)提升的堆栈为40h

00401013   sub         esp,4Ch

于是此时为三个变量分配的空间是:4Ch-40h=0xC=12=3×4,即为char short int都分配了4个字节

但在这三个变量赋值的时候展现出来的就是其原本的数据类型宽度了

15:       a=1;
00401028   mov         byte ptr [ebp-4],1

在char类型的a中的赋值宽度是 byte,1字节

16:       b=2;
0040102C   mov         word ptr [ebp-8],offset function+20h (00401030)

在int类型的c中的赋值宽度是dword,4字节

研究指针数据宽度

于是如法炮制,按照前面的方法来研究指针的数据宽度

在前面的数据类型后添加*,使其成为指针类型

void function(){                
        char* a;
        short* b;
        int* c;
        a=(char*)  1;
        b= (short*) 2;
        c=(int*)  3;
}

其对应的反汇编代码为

11:   void function(){
00401010   push        ebp
00401011   mov         ebp,esp
00401013   sub         esp,4Ch
00401016   push        ebx
00401017   push        esi
00401018   push        edi
00401019   lea         edi,[ebp-4Ch]
0040101C   mov         ecx,13h
00401021   mov         eax,0CCCCCCCCh
00401026   rep stos    dword ptr [edi]
12:       char* a;
13:       short* b;
14:       int* c;
15:       a=(char*)  1;
00401028   mov         dword ptr [ebp-4],1
16:       b= (short*) 2;
0040102F   mov         dword ptr [ebp-8],2
17:       c=(int*)  3;
00401036   mov         dword ptr [ebp-0Ch],3
18:   }
0040103D   pop         edi
0040103E   pop         esi
0040103F   pop         ebx
00401040   mov         esp,ebp
00401042   pop         ebp
00401043   ret

直接观察对应的赋值语句:

15:       a=(char*)  1;
00401028   mov         dword ptr [ebp-4],1
16:       b= (short*) 2;
0040102F   mov         dword ptr [ebp-8],2
17:       c=(int*)  3;
00401036   mov         dword ptr [ebp-0Ch],3

可以看到,所有赋值的宽度都为dowrd,说明无论是char*、short、int\其数据宽度都为4字节

可以使用同样的方法研究float、double、struct等其它数据类型

并且在这里会注意到,指针类型的赋值和非指针类型的赋值在反汇编中并没有什么区别

总结

无论是什么类型,在其后面加上(无论加几个\都一样)后其数据宽度都变为4字节

指针的加减

例子

指针类型也支持加减的操作,但不支持乘和除(编译器决定的),来看例子:

#include "stdafx.h"

void function(){                
        char* a;
        short* b;
        int* c;
        a=(char*)  1;
        b= (short*) 2;
        c=(int*)  3;

        a++;
        b++;
        c++;

        printf("a:%d\t b:%d\tc:%d\n",a,b,c);

}

int main(int argc, char* argv[])
{
        function();
        return 0;
}

运行结果

在这里插入图片描述

分析

这里会观察到结果并不是想象中的2,3,4;而是2,4,7

细心的小伙伴肯定发现了:

  • 2 = 1 + 1 (char数据宽度为1字节)
  • 4 = 2 + 2 (short数据宽度为2字节)
  • 7 = 3 + 4 (int数据宽度为4字节)

结果是加上了原本各自的数据类型的宽度

拓展例子

前面只是都是一级指针,现在将指针换为二级指针:

void function(){                
        char** a;
        short** b;
        int** c;
        a=(char**)  1;
        b= (short**) 2;
        c=(int**)  3;

        a++;
        b++;
        c++;

        printf("a:%d\t b:%d\tc:%d\n",a,b,c);

}

运行结果

在这里插入图片描述

分析

此时的结果为:

  • 5= 1 + 4 (char* 数据宽度为4字节)

  • 6= 2 + 4 (short* 数据宽度为4字节)

  • 7 = 3 + 4 (int* 数据宽度为4字节)

结果为加上 去掉一个*后的数据宽度

拓展例子二

前面的加法操作都只增加了1,现在再来查看增加大于1时的情况

void function(){                
        char* a;
        short* b;
        int* c;
        a=(char*)  1;
        b= (short*) 2;
        c=(int*)  3;

        a=a+5;
        b=b+5;
        c=c+5;

        printf("a:%d\t b:%d\tc:%d\n",a,b,c);

}

运行结果

在这里插入图片描述

分析

此时的结果为:

  • 6= 1 + 5*1 (char 数据宽度为1字节)
  • 12= 2 + 5*2 (short 数据宽度为2字节)
  • 23 = 3 + 5*4 (int 数据宽度为4字节)

结果为加上 去掉一个*后的数据宽度 × 增加的数值

总结

无论是指针的加亦或是减(这里只演示了加法,但减法同理),其加或减的单位为去掉一个*后的数据宽度

也就是实际增减的数值=去掉一个*后的数据宽度 × 增减的数值

指针类型相减

前面提到的指针的加减都是同一个指针里的加减,但指针之间其实也支持相减操作(不支持相加)

但指针之间的加减要求指针的类型必须一致,即char类型只能和char类型相加减,不能和char**或其它类型相加减

例子

void function(){                
        char* a;
        char* b;
        short* c;
        short* d;
        int* e;
        int* f;

        a=(char*) 200;
        b=(char*) 100;

        c=(short*) 200;
        d=(short*) 100;

        e=(int*) 200;
        f=(int*) 100;

        printf("%d\n",a-b);
        printf("%d\n",c-d);
        printf("%d\n",e-f);

}

运行结果

在这里插入图片描述

分析

此时的结果为:

  • 100 = (200 - 100)/1(char 数据宽度为1字节)
  • 50 = (200 - 100)/2 (short 数据宽度为2字节)
  • 25 = (200 - 100)/4 (int 数据宽度为4字节)

结果为相减完后再除以 原本各自的数据宽度

扩展例子

前面只是都是一级指针,现在将指针换为四级指针:

void function(){                
        char**** a;
        char**** b;
        short**** c;
        short**** d;
        int**** e;
        int**** f;

        a=(char****) 200;
        b=(char****) 100;

        c=(short****) 200;
        d=(short****) 100;

        e=(int****) 200;
        f=(int****) 100;

        printf("%d\n",a-b);
        printf("%d\n",c-d);
        printf("%d\n",e-f);

}

运行结果

在这里插入图片描述

分析

此时的结果为:

  • 25 = (200 - 100)/4(char*** 数据宽度为4字节)
  • 25 = (200 - 100)/4 (short*** 数据宽度为4字节)
  • 25 = (200 - 100)/4 (int*** 数据宽度为4字节)

结果为相减后再除以 去掉一个*后的数据宽度

总结

指针之间的减法,其结果为相减后再除以去掉一个*后的数据宽度

指针之间的比较

指针之间也支持相互比较,但也和上面指针类型相减一样,要求指针类型一致

例子

void function(){                
        char**** a;
        char**** b;

        a=(char****) 200;
        b=(char****) 100;

        if (a>b)
        {
                printf("a>b\n");
        }else{
                printf("a<=b\n");
        }

}

运行结果

在这里插入图片描述

结论

相同类型的指针之间是支持大小比较的

总结

  • 指针的数据宽度为4字节,或者说:无论是什么类型,在其后面加上(无论加几个\都一样)后其数据宽度都变为4字节

  • 指针数值支持进行加减,加减的结果=去掉一个*后的数据宽度 × 增减的数值

  • 指针之间支持减法但不支持加法,其结果为相减后再除以去掉一个*后的数据宽度

  • 指针之间支持比较大小,但要求进行比较的两个指针为相同类型

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/444207.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数字化时代,如何推动实体经济和数字经济的融合

实体经济是一国经济的立身之本和命脉所在&#xff0c;数字经济是当今世界科技革命和产业变革的阵地前沿&#xff0c;推动数字经济和实体经济融合发展&#xff0c;已经成为新形势下主动把握新机遇、打造新引擎、实现经济高质量发展的必然选择。 领域融合 真正能够成为现代社会…

Pyhon实现多线程 —— threading(含源码)

作者主页&#xff1a;爱笑的男孩。的博客_CSDN博客-深度学习,YOLO,活动领域博主爱笑的男孩。擅长深度学习,YOLO,活动,等方面的知识,爱笑的男孩。关注算法,python,计算机视觉,图像处理,深度学习,pytorch,神经网络,opencv领域.https://blog.csdn.net/Code_and516?typecollect个人…

LRU扩展LRU-K、2Q算法实现分析

LRU算法的缓存污染如何解决&#xff1f; 一、LRU-K算法 1、算法思想 LRU-K中的K代表最近使用的次数&#xff0c;因此LRU可以认为是LRU-1。LRU-K的主要目的是为了解决LRU算法“缓存污染”的问题&#xff0c;其核心思想是将“最近使用过1次”的判断标准扩展为“最近使用过K次”…

【CocosCreator入门】CocosCreator组件 | PageView(页面视图)组件

Cocos Creator 是一款流行的游戏开发引擎&#xff0c;具有丰富的组件和工具&#xff0c;其中的PageView组件是一种用于实现分页视图效果的重要组件。它可以让我们在游戏中实现各种分页视图效果&#xff0c;例如引导页、轮播图等。 目录 一、组件介绍 二、组件属性 三、组件使…

OpenCV算法加速的一些学习总结

一、概述 算法加速在实际软件层面应用来说 大数据和复杂计算的过程中 算法优化&#xff0c;指降低算法计算复杂度&#xff0c;设计新算法快速求解&#xff0c;比如Hungarian匹配算法。或牺牲一些内存&#xff0c;预计算一些重复计算的过程&#xff0c;减少程序层面的复杂度。 …

c语言实例练习笔记

本博文参考题目的地址看右边----》C 语言实例 | 菜鸟教程 以下为个人边练习边敲记录&#xff08;解法不一定和官方一样&#xff0c;会自己扩展一些&#xff0c;练习嘛&#xff0c;肯定是学到的都用上&#xff0c;算检验之前的学进去的是不是对的。&#xff09; C 语言实例 - …

【项目管理】ubuntu2204 图片合成视频

ubuntu 22.04 多张图片合成视频&#xff0c;多个视频合成一个大视频 环境&#xff1a; ubuntu 22.04 LTS 工具&#xff1a; ffmpeg ffmpeg 多张图片合成视频 在 ubuntu 下全选目录下的所有文件&#xff0c;右键 rename, 选择 1,2,3,4 即可&#xff1b;当然也可以使用其他命名方…

uni-app 中模拟器真机运行app

之前打包过app&#xff0c;调试方式是用usb连接电脑和手机&#xff0c;过程中也遇到了很多问题&#xff0c;忘记了怎么解决的&#xff0c;今天又遇到了打包app的项目&#xff0c;因为在开发app这方面经验不足&#xff0c;所以踩了很多坑&#xff0c;花了好几个小时才研究好app在…

学系统集成项目管理工程师(中项)系列06a_信息系统安全管理(上)

1. 信息安全 1.1. 保护信息的保密性、完整性、可用性 1.2. 另外也包括其他属性&#xff0c;如&#xff1a;真实性、可核查性、不可抵赖性和可靠性 2. 信息安全属性及目标 2.1. 保密性(Confidentiality&#xff09; 2.1.1. 信息不被泄露给未授权的个人、实体和过程或不被其…

【python】统计代码行数 | 统计当前文件夹里所有代码文件的行数

背景 写了一堆.cs文件 想看看一共写了多少行 代码 import os import chardet# Check if a file has the given extension def has_extension(file, extension):return os.path.splitext(file)[1] extension# Count the number of non-empty lines in a file def count_line…

拍照时脸背光怎么办?拍摄的逆光人像照如何修复才能更好看?

拍摄逆光人像会产生迷人的轮廓光&#xff0c;发丝看起来会很美丽&#xff0c;并可能拍到好看的星芒&#xff0c;但是&#xff01;直接拍摄很可能经常会对不上焦&#xff0c;或者会拍出大黑脸&#xff0c;这时就需要很多技巧啦。 完成一张好的逆光照片需要前期拍摄和后期修图相…

生成式模型与辨别式模型

分类模型可以分为两大类:生成式模型与辨别式模型。本文解释了这两种模型类型之间的区别&#xff0c;并讨论了每种方法的优缺点。 辨别式模型 辨别式模型是一种能够学习输入数据和输出标签之间关系的模型&#xff0c;它通过学习输入数据的特征来预测输出标签。在分类问题中&…

Revit相关问题:符号线,转转问题,生成三维视图

一、Revit符号线如何画粗一些?如何自定义符号线子类别? 1、Revit在族里面符号线的粗细、显示颜色、显示线型为符号线的子类别控制! 你可以通过&#xff0c;管理选项卡新建子类别&#xff0c;然后在画符号线的时候应用该子类别! 新建符号线对象样式 应用子类别 二、Revit三维模…

YOLOv7+单目跟踪

YOLOv7单目跟踪 1. 目标跟踪2. 测距模块2.1 设置测距模块2.2 添加测距 3. 实验效果 相关链接 1. YOLOv5单目测距&#xff08;python&#xff09; 2. YOLOv7单目测距&#xff08;python&#xff09; 3. 具体效果已在Bilibili发布&#xff0c;点击跳转 1. 目标跟踪 用yolov7实现…

Moviepy模块之视频添加图片水印

文章目录 前言视频添加图片水印1.引入库2.加载视频文件3.加载水印图片4.缩放水印图片大小5.设置水印的位置5.1 相对于视频的左上角5.2 相对于视频的左下角5.3 相对于视频的右上角5.4 相对于视频的右下角5.5 相对于视频的左中位置5.6 相对于视频的正中位置5.7 相对于视频的右中位…

【设计模式】23种设计模式之结构型模式

一、适配器设计模式 1、是什么&#xff1f; 1、适配器模式将某个类的接口转换成客户端期望的另一个接口表示&#xff0c;主要的目的是兼容性&#xff0c;让原本因接口不匹配不能一起工作的两个类可以协同工作 2、适配器模式属于结构型模式 3、主要分为三类&#xff1a;类适配…

【机器学习】EM原理和K-mean聚类

一、教程说明 EM算法就是expect maxmise算法&#xff0c;就是“期望最大化”的缩写。本篇首先提出&#xff1a;1 什么是期望&#xff1f; 2 期望最大化是个啥意思&#xff1f;k-mean聚类中如何用EM算法&#xff1f; 所涉及的概念&#xff1a; 期望 期望的加权平均理解 概率…

工业网关开发:IxCahriot测试吞吐量

吞吐量测试可以确定被测试设备或被测试系统在不丢弃包的情况下&#xff0c;设备或系统能够接受并转发的最大有效数据。在测试中以一定的速率发送一定数量的帧&#xff0c;并计算待测设备接收的帧&#xff0c;如果发送的帧与接受的帧数量相等&#xff0c;那么就将发送速率提高并…

ASEMI代理ADA4940-1ACPZ-R7原装ADI车规级ADA4940-1ACPZ-R7

编辑&#xff1a;ll ASEMI代理ADA4940-1ACPZ-R7原装ADI车规级ADA4940-1ACPZ-R7 型号&#xff1a;ADA4940-1ACPZ-R7 品牌&#xff1a;ADI/亚德诺 封装&#xff1a;LFCSP-16 批号&#xff1a;2023 引脚数量&#xff1a;16 安装类型&#xff1a;表面贴装型 ADA4940-1ACPZ-…

ChatGPT 和 Elasticsearch:OpenAI 遇见私有数据

作者&#xff1a;Jeff Vestal 结合 Elasticsearch 的搜索相关性和 OpenAI 的 ChatGPT 的问答功能来查询你的数据。 在此博客中&#xff0c;你将了解如何使用 Elasticsearch 将 ChatGPT 连接到专有数据存储&#xff0c;并为你的数据构建问答功能。 什么是聊天 GPT&#xff1f; …