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

news2024/11/16 2:36:12

指针二

先前介绍了指针的一些基本的知识,但都没有提到地址的概念,下面承接之前的笔记,继续学习指针

下面要介绍三个相关的内容:获取变量的数据类型 、 取变量地址和取地址中存储的数据

获取变量的数据类型

在C语言中可以使用下面的方法获取一个变量的数据类型:

代码

#include "stdafx.h"
#include <typeinfo>
void function(){                
        char**** a;
        printf("%s\n",typeid(a).name());
}
int main(int argc, char* argv[])
{
        function();
        return 0;
}

运行结果

在这里插入图片描述

使用方式

通过上面的例子可以知道使用方式首先要包含一个相关的头文件typeinfo

然后使用该头文件的方法typeid(变量).name()即可获得变量对应的数据类型

取变量地址

在C语言中可以在变量前加上&符号来获取一个变量的地址

首先看看取回来地址的类型

取地址的返回类型

#include "stdafx.h"
#include <typeinfo>
void function(){                
        char a;
        short b;
        int c;
        char* d;
        printf("%s\n",typeid(&a).name());
        printf("%s\n",typeid(&b).name());        
        printf("%s\n",typeid(&c).name());
        printf("%s\n",typeid(&d).name());
}

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

运行结果

在这里插入图片描述
分析结果

不难发现,所有取地址返回的类型都为原本变量的类型后加个*,也契合了本笔记的主题——指针

取地址的内容

通过前面的分析得出了取出的地址类型是一个指针类型,现在要观察其存储的内容

代码

#include "stdafx.h"
#include <typeinfo>
//为了方便观察地址 先声明为全局变量
int a;
void function(){
    a=610;
        int* b=&a;
    printf("%x\n",b);
}

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

运行结果

在这里插入图片描述
反汇编代码

11:       a=610;
00401038   mov         dword ptr [a (00427c48)],262h
12:       int* b=&a;
00401042   mov         dword ptr [ebp-4],offset a (00427c48)
13:       printf("%x\n",b);

通过a的赋值语句可以看到a存储在00427c48这个内存地址中

11:       a=610;
00401038   mov         dword ptr [a (00427c48)],262h

再看下面的指针赋值语句

12:       int* b=&a;
00401042   mov         dword ptr [ebp-4],offset a (00427c48)

这里的offset a是vc6.0为了方便使用者查看生成的,实际上的语句为:

mov dword ptr ss:[ebp-0x4],0x427C48

也就是直接将全局变量a的地址00427c48赋给b

代码二

前面声明的变量为全局变量,现在来看看局部变量的情况:

#include "stdafx.h"
#include <typeinfo>
void function(){
    //这里a声明为局部变量
        int a=610;
        int* b=&a;
        printf("%x\n",b);
}

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

运行结果二

在这里插入图片描述
此时的地址显然就是一个堆栈中的地址,对应了变量存储在堆栈中

反汇编代码二

11:       int a=610;
00401038   mov         dword ptr [ebp-4],262h
12:       int* b=&a;
0040103F   lea         eax,[ebp-4]
00401042   mov         dword ptr [ebp-8],eax
13:       printf("%x\n",b);

可以看到此时是通过lea指令将变量a的地址ebp-4传给eax,然后再将eax赋值给b

取地址中存储数据

前面讲了如何获取一个变量的地址,那么在获取完地址后,再说说如何获取这地址中存储的数据

在C语言中,在一个指针类型的变量前面加上*符号,即可取出该地址里所存储的内容

取地址数据的返回类型

如法炮制,观察取地址数据的返回类型

代码

#include "stdafx.h"
#include <typeinfo>
void function(){
        int***a=(int***) 610;
        printf("%s\n",typeid(*a).name());
        printf("%s\n",typeid(**a).name());
        printf("%s\n",typeid(***a).name());
}
int main(int argc, char* argv[])
{
        function();
        return 0;
}

运行结果

在这里插入图片描述

分析结果

不难发现,所有取地址数据返回的类型都为原本变量的类型后减个*,可以说是和&取地址正好相反

不同的是对于多级指针,可以一次使用多个*来多次取地址中存储的数据

取地址数据的内容

前面了解了*符号的使用,现在来看个稍微复杂点的例子

代码

#include "stdafx.h"
#include <typeinfo>
int a;
void function(){
        a=610;
        int* b=&a;
        int** c=&b;
        int*** d=&c;
        c=*d;
        b=*c;
        a=*b;

    b=**d;
    a=**c;   

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

反汇编代码

11:       a=610;
00401038   mov         dword ptr [a (00427c50)],262h
12:       int* b=&a;
00401042   mov         dword ptr [ebp-4],offset a (00427c50)
13:       int** c=&b;
00401049   lea         eax,[ebp-4]
0040104C   mov         dword ptr [ebp-8],eax
14:       int*** d=&c;
0040104F   lea         ecx,[ebp-8]
00401052   mov         dword ptr [ebp-0Ch],ecx
15:       c=*d;
00401055   mov         edx,dword ptr [ebp-0Ch]
00401058   mov         eax,dword ptr [edx]
0040105A   mov         dword ptr [ebp-8],eax
16:       b=*c;
0040105D   mov         ecx,dword ptr [ebp-8]
00401060   mov         edx,dword ptr [ecx]
00401062   mov         dword ptr [ebp-4],edx
17:       a=*b;
00401065   mov         eax,dword ptr [ebp-4]
00401068   mov         ecx,dword ptr [eax]
0040106A   mov         dword ptr [a (00427c50)],ecx
18:
19:       b=**d;
00401070   mov         edx,dword ptr [ebp-0Ch]
00401073   mov         eax,dword ptr [edx]
00401075   mov         ecx,dword ptr [eax]
00401077   mov         dword ptr [ebp-4],ecx
20:       a=**c;
0040107A   mov         edx,dword ptr [ebp-8]
0040107D   mov         eax,dword ptr [edx]
0040107F   mov         ecx,dword ptr [eax]
00401081   mov         dword ptr [a (00427c50)],ecx
21:
22:       a=***d;
00401087   mov         edx,dword ptr [ebp-0Ch]
0040108A   mov         eax,dword ptr [edx]
0040108C   mov         ecx,dword ptr [eax]
0040108E   mov         edx,dword ptr [ecx]
00401090   mov         dword ptr [a (00427c50)],edx

分析反汇编

首先将各变量信息整理出来,方便后面分析:

在这里插入图片描述

代码中涉及的变量较多,这里只拿最复杂的 a=***d来作分析,其它留作样例

22:       a=***d;
00401087   mov         edx,dword ptr [ebp-0Ch]
0040108A   mov         eax,dword ptr [edx]
0040108C   mov         ecx,dword ptr [eax]
0040108E   mov         edx,dword ptr [ecx]
00401090   mov         dword ptr [a (00427c50)],edx

1.这里的ebp-0Ch对应的是d的地址,此时就是将d赋值给edx

00401087   mov         edx,dword ptr [ebp-0Ch]

在这里插入图片描述
结合内存里的数据可以得到:d的地址=ebp-0Ch=0012FF20,d=[ebp-0Ch]=0012FF24

这里的代码相当于

00401087   mov         edx,0012FF24h(d)

2.将前面edx地址里存储的数据赋值给eax,此时的[edx]存储的其实就是c

0040108A   mov         eax,dword ptr [edx]

在这里插入图片描述
结合内存里的数据可以得到:d=edx=0012FF24,[edx]=0012FF28=c

这里的代码相当于

0040108A   mov         eax,0012FF28(c)

3.将前面eax地址里存储的数据赋值给ecx,此时的[eax]存储的其实就是b

0040108C   mov         ecx,dword ptr [eax]

在这里插入图片描述结合内存里的数据可以得到:c=eax=0012FF28,b=[eax]=00427C50

这里的代码相当于

0040108C   mov         ecx,00427C50(b)

4.将前面ecx地址里存储的数据赋值给edx,此时的[ecx]存储的其实就是a

0040108E   mov         edx,dword ptr [ecx]

在这里插入图片描述
结合内存里的数据可以得到:b=ecx=00427C50,a=[ecx]=262h=610

这里的代码相当于

0040108E   mov         edx,262h

5.最后将edx赋值给a

00401090   mov         dword ptr [a (00427c50)],edx

小总结

可以看到,被赋值变量 = * 赋值变量 在汇编中的形式为:mov 被赋值变量,[赋值变量]

如果有多个*,则多执行几次来取值

总结

  • 可以在变量前加上&符号来获取变量地址

  • 取地址返回的类型都为原本变量的类型后加个*,也就是个指针类型

  • 在一个指针类型的变量前面加上*符号,即可取出该地址里所存储的内容

  • 取地址数据返回的类型都为原本变量的类型后减个*,可以说是和&取地址正好相反

  • 对于多级指针,可以一次使用多个*来多次取地址中存储的数据

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

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

相关文章

Sleep:预测认知能力的最佳纺锤波检测参数

导读 目的&#xff1a;睡眠纺锤波的改变与认知障碍有关。这一发现增加了人们对识别基于睡眠的认知和神经退行性疾病生物标志物(包括睡眠纺锤波)的兴趣。然而&#xff0c;围绕纺锤波定义和算法参数设置的灵活性带来了方法上的挑战。本研究的目的是描述纺锤波检测参数设置如何影…

Dynamic Slicing for Deep Neural Networks

0、摘要 程序切片已广泛应用于各种软件工程任务中。然而&#xff0c;现有的程序切片技术只能处理由指令和变量构建的传统程序&#xff0c;而不能处理由神经元和突触组成的神经网络。在本文中&#xff0c;我们提出了 NNSlicer&#xff0c;这是第一种基于数据流分析的深度神经网络…

android studio shape形状图形

1.创建shape 2定义椭圆 <?xml version"1.0" encoding"utf-8"?> <shape xmlns:android"http://schemas.android.com/apk/res/android"android:shape"oval"><!--指定形状椭圆--><!--指定形状内部颜色--><…

Ubuntu与window实现文件共享——Samba使用

前言 &#xff08;1&#xff09;我们在使用Linux开发的时候&#xff0c;因为Linux中写程序没有Windows的工具方便&#xff0c;所以经常是先在windows环境下编写程序&#xff0c;之后再将文件上传给Linux进行编译。 &#xff08;2&#xff09;这样就存在一个问题&#xff0c;因为…

vue使用Howler实现音乐播放器

vue使用Howler实现音乐播放器 前言一、引入依赖二、封装组件 前言 本文使用Howler.js进行播放。使用siriwave做的播放动画具体文档地址如下 名称地址Howlerhttps://howlerjs.com/siriwavehttps://github.com/kopiro/siriwave 最后实现效果如下&#xff1a; 实现暂停、开始、…

教你如何根据需求编写测试用例,不用写一行代码,使用ChatGPT4自动完成。

首先来张效果图&#xff0c;需求我是放到requirements.txt文档里&#xff0c;输出的测试用例是放到test_case1.txt&#xff0c;整个代码我是让ChatGPT4自动给我写的。 我用的prompt提示语是&#xff1a; 我的想法是这样&#xff0c;通过Python代码&#xff0c;和API keys来实现…

传统制造企业在引入项目管理机制时项目组织结构的重要性

在传统的工业设备制造行业,针对以订单项目为驱动的业务模式,建立一套成熟完备的项目管理机制十分重要,同时也是企业提升自身管理水平精细度的内在要求。项目管理作为外企普遍应用的成熟管理模式,如何将其引入并与民企现存的传统职能型管理模式融合,实现成功嫁接,值得大家思考并…

AD9208之8通道高速采集

板卡概述 FMC168 是 一 款 基 于 VITA57.4 标 准 的2GSPS/2.6GSPS/3GSPS 采样率 14 位分辨率 Double FMC子卡模 块&#xff0c;该模块可以实现 8 路 14-bit、2GSPS/2.6GSPS/3GSPS 采样率模 拟信号采集。该板卡 ADC 器件采用 ADI 公司的 AD9208 芯片,该芯片 与 AD9689 完全…

快商通AI技术再获殊荣,荣膺厦门市“科学技术进步奖”

近日&#xff0c;快商通AI科研项目荣获厦门市“科学技术进步奖”&#xff0c;这是对快商通AI技术研究成果的高度肯定&#xff0c;也是快商通在人工智能领域的又一重大突破。 快商通作为一家技术领先的企业&#xff0c;始终坚持 核心技术自主研发 &#xff0c;致力于将自然语言…

【Linux命令行与shell脚本编程】 一,Shell简介

Linux命令行与shell脚本编程 第一章 Shell简介 目录 Linux命令行与shell脚本编程一,Shell简介1.1 终端(终端仿真器) 41.2 shell 提示符1.2.1 命令历史记录1.2.2 光标移动1.2.3 与 bash手册交互 命令的构成 一,Shell简介 1.1 终端(终端仿真器) 4 让用户访问 shell 使用图形用…

国产操作系统新机遇——小程序容器

信息技术应用创新不仅是各行各业实现数字转型的关键起点&#xff0c;而且还是我国加强网络安全和信息安全的重要手段。 现阶段&#xff0c;微软&#xff0c;谷歌和苹果等外国公司在操作系统市场上占据着几乎垄断的行业地位。国内操作系统行业正在努力改变过去过于分散的状态&a…

从FMCW毫米波雷达系统的性能参数理解4D成像毫米波雷达的设计思路

本文编辑&#xff1a;调皮哥的小助理 站在设计雷达的角度看&#xff0c;其实无论是传统的3D毫米波雷达&#xff0c;还是如今的4D毫米波成像雷达&#xff0c;其雷达系统性能参数都遵循一个原则&#xff0c;即&#xff1a; d res ⋅ v res ⋅ θ res d max ⁡ ⋅ v max ⁡ ⋅ …

全志v851s GPIO 应用程序编写

1. 查看硬件电路图SCH_Schematic1_2022-11-23 &#xff0c;查找合适的gpio 作为使用pin 在这里我们选取 GPIOH14&#xff08;注意目前开发使用这个pin 作为触摸屏的pin脚&#xff0c;需要将触摸屏connect断开&#xff09; &#xff0c;因为 可以通过排插使用杜邦线将其引出&am…

scala特质trait

目录 说明案例动态混入 说明 Scala 语言中&#xff0c;采用特质 trait&#xff08;特征&#xff09;来代替接口的概念&#xff0c;也就是说&#xff0c;多个类具有相同的特质&#xff08;特征&#xff09;时&#xff0c;就可以将这个特质&#xff08;特征&#xff09;独立出来…

rabbitMQ学习总结

RabbitMQ 生产者通过-》通道-》交换机-》投到消息队列-》再通过通道-》消费者 分布式架构 何谓分布式系统 通俗一点: 就是一个请求由服务器端的 多个服务 (服务或者系统)协同处理完成 和单体架构不同的是&#xff0c;单体架构是一个请求发起ivm调度线程(确切的是tomcat线程池)…

yolov5-fastapi-demo更换中文标签

本章是基于yolov5-fastapi-demo项目的更改 WelkinU/yolov5-fastapi-demo: FastAPI Wrapper of YOLOv5 (github.com) 首先&#xff0c;因为训练的时候设置的标签是英文&#xff0c;换成中文要重新训练&#xff0c;而且使用中文训练也很繁琐要改很多东西&#xff0c;因此可以直…

防雷接地国家规范标准介绍与施工技术要点

防雷接地是一种防止雷电对建筑物、设备和人身安全造成危害的措施。在防雷接地系统中&#xff0c;将建筑物、设备、金属构件等导体与地面形成良好的导电连接&#xff0c;以便将雷电通过接地体排放到地下&#xff0c;从而保护建筑物、设备和人身安全不受雷击的影响。防雷接地系统…

mybatis粗心使用导致内存溢出

现象 服务响应变慢&#xff0c;线程日志也出现Java heap space内存溢出的错误&#xff0c;这个服务属于基础业务服务&#xff0c;出现问题要尽快的排查 分析 因为设置了gc日志和jmap启动相关参数 所以我们进行分析&#xff0c;这里模拟线上环境将堆大小参数调整到了128m&am…

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

指针四 指针数组 什么是指针数组 首先回顾一下先前关于数组的知识&#xff1a; 所谓数组就是用于存储相同数据类型的集合 再结合先前关于指针的知识&#xff1a;指针的本质也是一种数据类型 于是当数组中存储的成员的数据类型为指针时&#xff0c;该数组就可以称为指针数…

2023年的深度学习入门指南(7) - SIMD和通用GPU编程

2023年的深度学习入门指南(7) - SIMD和通用GPU编程 深度学习从一开始就跟GPU有不解之缘&#xff0c;因为算力是深度学习不可或缺的一部分。 时至今日&#xff0c;虽然多任务编程早已经深入人心&#xff0c;但是很多同学还没有接触过CPU上的SIMD指令&#xff0c;更不用说GPGPU…