12558网页游戏私服论坛

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

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

[复制链接]

505

主题

505

帖子

1020

积分

实习版主

Rank: 7Rank: 7Rank: 7

积分
1020
发表于 2021-7-18 17:40:47 | 显示全部楼层 |阅读模式
继承更新个人的学习笔记,
其它笔记传送门
逆向底子笔记一 进制篇
逆向底子笔记二 数据宽度和逻辑运算
逆向底子笔记三 通用寄存器和内存读写
逆向底子笔记四 堆栈篇
逆向底子笔记五 标志寄存器
逆向底子笔记六 汇编跳转和比较指令
逆向底子笔记七 堆栈图(重点)
逆向底子笔记八 反汇编分析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

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
楼主热帖
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-11-28 05:23 , Processed in 0.078125 second(s), 31 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

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