12558网页游戏私服论坛

 找回密码
 立即注册
游戏开服表 申请开服
游戏名称 游戏描述 开服状态 游戏福利 运营商 游戏链接
攻城掠地-仿官 全新玩法,觉醒武将,觉醒技能 每周新区 经典复古版本,长久稳定 进入游戏
巅峰新版攻 攻城掠地公益服 攻城掠地SF 新兵种、新武将(兵种) 进入游戏
攻城掠地公 散人玩家的天堂 新开 进入游戏
改版攻城掠 上线即可国战PK 稳定新区 全新改版,功能强大 进入游戏
少年江山 高福利高爆率 刚开一秒 江湖水落潜蛟龙 进入游戏
太古封魔录 开服送10亿钻石 福利多多 不用充钱也可升级 进入游戏
神魔之道 签到送元宝 稳定开新区 送豪华签到奖励 进入游戏
神奇三国 统帅三军,招揽名将 免费玩新区 激情国战,征战四方 进入游戏
龙符 三日豪礼领到爽 天天开新区 助你征战无双 进入游戏
王者之师 免费领豪华奖励 免费玩新区 6元送6888元宝 进入游戏
三国霸业 战车-珍宝-觉醒-攻城掠地SF-全新玩法 免费玩新区 攻城掠地私服 进入游戏
手游私服盒子 各类免费游戏 0.1折送海量资源 各类手游私服 进入游戏
皇家MU2 《奇迹 2:传奇》韩国网禅公司《奇迹》正统续作。 3D锁视角Mmrpg 暗黑3+传奇+流放之路+奇迹 进入游戏
查看: 357|回复: 0

逆向基础笔记二十三 汇编 指针(四)

[复制链接]

3782

主题

3782

帖子

214748万

积分

超级版主

Rank: 8Rank: 8

积分
2147483647
发表于 2021-5-7 22:48:19 | 显示全部楼层 |阅读模式
继续更新个人的学习笔记,
其它笔记传送门
逆向基础笔记一 进制篇
逆向基础笔记二 数据宽度和逻辑运算
逆向基础笔记三 通用寄存器和内存读写
逆向基础笔记四 堆栈篇
逆向基础笔记五 标志寄存器
逆向基础笔记六 汇编跳转和比力指令
逆向基础笔记七 堆栈图(重点)
逆向基础笔记八 反汇编分析C语言
逆向基础笔记九 C语言内联汇编和调用协定
逆向基础笔记十 汇编寻找C步伐入口
逆向基础笔记十一 汇编C语言基本类型
逆向基础笔记十二 汇编 全局和局部 变量
逆向基础笔记十三 汇编C语言类型转换
逆向基础笔记十四 汇编嵌套if else
逆向基础笔记十五 汇编比力三种循环
逆向基础笔记十六 汇编一维数组
逆向基础笔记十七 汇编二维数组 位移 乘法
逆向基础笔记十八 汇编 布局体和内存对齐
逆向基础笔记十九 汇编switch比力if else
逆向基础笔记二十 汇编 指针(一)
逆向基础笔记二十一 汇编 指针(二)
逆向基础笔记二十二 汇编 指针(三)
逆向基础笔记二十四 汇编 指针(五) 系列完结
指针四

指针数组

什么是指针数组

首先回顾一下先前关于数组的知识:
所谓数组就是用于存储相同数据类型的聚集
再联合先前关于指针的知识:指针的本质也是一种数据类型
于是当数组中存储的成员的数据类型为指针时,该数组就可以称为指针数组(本质是数组)
代码

#include "stdafx.h"void function(){        int** arr[5]={(int**)1,(int**)2,(int**)3,(int**)4,(int**)5};}int main(int argc, char* argv[]){        function();        return 0;}反汇编代码

9:        int** arr[5]={(int**)1,(int**)2,(int**)3,(int**)4,(int**)5};00401038   mov         dword ptr [ebp-14h],10040103F   mov         dword ptr [ebp-10h],200401046   mov         dword ptr [ebp-0Ch],30040104D   mov         dword ptr [ebp-8],400401054   mov         dword ptr [ebp-4],5小总结


  • 可以看到指针数组其实并没有什么特别之处,只不外存储的数构成员的数据类型为指针而已
  • 指针数组的赋值也和先前对指针的赋值没有什么区别
布局体指针

什么是布局体指针

所谓布局体指针就是在布局体后加上多少个*使其称为一个指针类型
代码

#include "stdafx.h"#include struct S1{        int a;};void function(){        S1* s1=(S1*)0x12345678;    printf("%x\n",s1);}int main(int argc, char* argv[]){        function();        return 0;}运行结果


结果分析

可以看到,这里关于布局体指针的使用貌似和普通的指针没有什么区别,但此时会发现这里还没有操作布局体内部的成员
所以布局体指针的现实使用也并不是如许,下面看一个错误的例子
错误代码

void function(){        S1* s1=(S1*)0x12345678;    int a=s1->a;}只是在上面代码的基础上添加了一个读取布局体成员的语句,查看运行结果
运行结果


运行结果不出所料出错了,开始分析错误的原因
反汇编代码

14:       S1* s1=(S1*)0x12345678;00401038   mov         dword ptr [ebp-4],12345678h15:       int a=s1->a;0040103F   mov         eax,dword ptr [ebp-4]00401042   mov         ecx,dword ptr [eax]00401044   mov         dword ptr [ebp-8],ecx反汇编分析

0.实验前s1和s1->a的状态
s1:

s1->a:

1.为布局体指针s1赋值
14:       S1* s1=(S1*)0x12345678;00401038   mov         dword ptr [ebp-4],12345678h
此时再看看s1->a:

可以发现对s1的赋值操作,改变的不是s1->a的值,而是改变了s1->a的地点
其实从实验前s1和s1->a的状态就可以看出,s1存储的内容并不是直接存储布局体成员的内容,而是存储指向布局体成员的地点
所以这里对于先前对于s1的赋值操作改变的只是成员的地点,而没有改酿成员的值
并且刚开始时,布局体成员并没有被分配对应的内存地点
2.访问s1->a
15:       int a=s1->a;0040103F   mov         eax,dword ptr [ebp-4]00401042   mov         ecx,dword ptr [eax]00401044   mov         dword ptr [ebp-8],ecx此时出错的原因已经显而易见了,先前对s1的赋值操作修改了s1->a的地点,使其指向了一个不可访问的地点而导致出错
精确代码

前面已经知道了出错的原因是访问了不可访问的地点导致出错,并且刚开始布局体成员没有被分配对应的内存地点
于是只要手动为布局体成员分配内存地点即可,这里将使用到malloc函数来进行分配内存地点
malloc函数

void *malloc(size_t size)参数:size,内存块的大小,以字节为单位
返回值:返回一个指针 ,指向已分配大小的内存。如果请求失败,则返回 NULL
相干头文件:malloc.h、alloc.h、stdlib.h
大抵了解了malloc函数,如今来看代码:
#include "stdafx.h"#include                 //这里使用了malloc.hstruct S1{    int a;        int b;        int c;};void function(){        S1* s1=(S1*) malloc(sizeof(S1));        //申请一块空间大小正好为S1大小的内存        s1->a=610;        s1->b=666;        s1->c=52;        printf("%d\n",s1->a);        printf("%d\n",s1->b);        printf("%d\n",s1->c);}int main(int argc, char* argv[]){        function();        return 0;}运行结果


可以看到布局体的成员可以或许正常地被改写和访问
反汇编代码

15:       S1* s1=(S1*) malloc(sizeof(S1));0040D778   push        0Ch0040D77A   call        malloc (00401150)0040D77F   add         esp,40040D782   mov         dword ptr [ebp-4],eax16:       s1->a=610;0040D785   mov         eax,dword ptr [ebp-4]0040D788   mov         dword ptr [eax],262h17:       s1->b=666;0040D78E   mov         ecx,dword ptr [ebp-4]0040D791   mov         dword ptr [ecx+4],29Ah18:       s1->c=52;0040D798   mov         edx,dword ptr [ebp-4]0040D79B   mov         dword ptr [edx+8],34h反汇编分析

1.先看这个malloc函数
15:       S1* s1=(S1*) malloc(sizeof(S1));0040D778   push        0Ch0040D77A   call        malloc (00401150)0040D77F   add         esp,40040D782   mov         dword ptr [ebp-4],eax

  • 压入了参数0C,对应十进制为12,也就是S1的大小
  • 调用malloc函数
  • 堆栈外均衡
  • 将返回值eax赋值给S1
看看返回值eax的内容:

可以看到eax就对应了布局体中的成员
eax=布局体成员首地点,里面的布局体成员连续存储
2.赋值,将610对应十六进制262赋值给[eax],对应前面的003807B8
16:       s1->a=610;0040D785   mov         eax,dword ptr [ebp-4]0040D788   mov         dword ptr [eax],262h实验后:

3.赋值,将666对应十六进制29A赋值给[ecx+4],对应前面的003807BC
17:       s1->b=666;0040D78E   mov         ecx,dword ptr [ebp-4]0040D791   mov         dword ptr [ecx+4],29Ah实验后:

4.赋值,将52对应十六进制34赋值给[edx+4],对应前面的003807C0
18:       s1->c=52;0040D798   mov         edx,dword ptr [ebp-4]0040D79B   mov         dword ptr [edx+8],34h实验后:

小总结


  • 布局体指针和普通的指针现实上并没有什么不同
  • 在对布局体成员进行操作时,须要先对其进行初始化(为每个布局体成员分配内存地点)
  • 布局体指针并不直接存储布局体成员,而是存储了指向布局体成员的地点,该地点里存放着所有布局体成员
数组指针

前面学了指针数组,如今又来个数组指针,中间用布局体指针作了过渡,避免混淆
什么是数组指针

所谓数组指针,就是指向数组的指针(本质是指针)
既然是指针天然满意先前指针的一切特性:指针的赋值、指针的数据宽度、指针的加减、指针类型相减、指针之间比力
这里就不再赘述先前的内容,有须要可回顾:逆向基础笔记二十 汇编 指针(一)
数组指针的声明

int (*px)[2];声明如上,数组指针变量为px,类型为:int(*)[2];该数组指针指向的数组为int[2]
数组指针和指向数组的指针区别

代码

#include "stdafx.h"void function(){        int arr[6]={1,2,3,4,5,6};        //声明一个数组指针,该指针指向数组为:int[2]        int (*px)[2];                //给数组指针赋值,使该数组指针指向arr数组的首地点        px=(int (*)[2]) &arr[0];        //用一个临时变量parr2 存储数组指针        int (*parr2)[2]=px;    //*px为数组的首地点,也就是arr,这里就相当于int* arr2=arr;此时的arr2就是指向数组的指针        int* arr2=*px;    //初始化变量,准备循环    int i;    //循环遍历数组        for(i=0;i
楼主热帖
回复

使用道具 举报

*滑块验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|12558网页游戏私服论坛 |网站地图

GMT+8, 2024-11-28 21:50 , Processed in 0.078125 second(s), 32 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表