12558网页游戏私服论坛

 找回密码
 立即注册
游戏开服表 申请开服
游戏名称 游戏描述 开服状态 游戏福利 运营商 游戏链接
攻城掠地-仿官 全新玩法,觉醒武将,觉醒技能 每周新区 经典复古版本,长久稳定 进入游戏
巅峰新版攻 攻城掠地公益服 攻城掠地SF 新兵种、新武将(兵种) 进入游戏
攻城掠地公 散人玩家的天堂 新开 进入游戏
改版攻城掠 上线即可国战PK 稳定新区 全新改版,功能强大 进入游戏
少年江山 高福利高爆率 刚开一秒 江湖水落潜蛟龙 进入游戏
太古封魔录 开服送10亿钻石 福利多多 不用充钱也可升级 进入游戏
神魔之道 签到送元宝 稳定开新区 送豪华签到奖励 进入游戏
神奇三国 统帅三军,招揽名将 免费玩新区 激情国战,征战四方 进入游戏
龙符 三日豪礼领到爽 天天开新区 助你征战无双 进入游戏
王者之师 免费领豪华奖励 免费玩新区 6元送6888元宝 进入游戏
查看: 255|回复: 0

逆向基础笔记二十四 汇编 指针(五) 系列完结

[复制链接]

312

主题

312

帖子

634

积分

实习版主

Rank: 7Rank: 7Rank: 7

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

代码

#include "stdafx.h"void function(int num){        num=52;}void function2(int* num){        *num=52;}int main(int argc, char* argv[]){        int num=610;        function(num);        printf("%d\n",num);        function2(&num);        printf("%d\n",num);        return 0;}运行结果


可以看到没有通过指针进行传参的数据在function内部修改后并没有影响到本来的数值
而通过指针进行传参的数据在function2内部修改后就影响了本来的数值
反汇编代码

函数外部

num初始化

20:       int num=610;0040D978   mov         dword ptr [ebp-4],262hfunction和输出

21:       function(num);0040D97F   mov         eax,dword ptr [ebp-4]0040D982   push        eax0040D983   call        @ILT+15(function) (00401014)0040D988   add         esp,422:       printf("%d\n",num);0040D98B   mov         ecx,dword ptr [ebp-4]0040D98E   push        ecx0040D98F   push        offset string "%d\n" (0042201c)0040D994   call        printf (00401130)0040D999   add         esp,8function2和输出

23:       function2(&num);0040D99C   lea         edx,[ebp-4]0040D99F   push        edx0040D9A0   call        @ILT+20(function2) (00401019)0040D9A5   add         esp,424:       printf("%d\n",num);0040D9A8   mov         eax,dword ptr [ebp-4]0040D9AB   push        eax0040D9AC   push        offset string "%d\n" (0042201c)0040D9B1   call        printf (00401130)0040D9B6   add         esp,8函数内部

function

8:    void function(int num){0040D870   push        ebp0040D871   mov         ebp,esp0040D873   sub         esp,40h0040D876   push        ebx0040D877   push        esi0040D878   push        edi0040D879   lea         edi,[ebp-40h]0040D87C   mov         ecx,10h0040D881   mov         eax,0CCCCCCCCh0040D886   rep stos    dword ptr [edi]9:        num=52;0040D888   mov         dword ptr [ebp+8],34h10:   }0040D88F   pop         edi0040D890   pop         esi0040D891   pop         ebx0040D892   mov         esp,ebp0040D894   pop         ebp0040D895   retfunction2

12:   void function2(int* num){0040D7E0   push        ebp0040D7E1   mov         ebp,esp0040D7E3   sub         esp,40h0040D7E6   push        ebx0040D7E7   push        esi0040D7E8   push        edi0040D7E9   lea         edi,[ebp-40h]0040D7EC   mov         ecx,10h0040D7F1   mov         eax,0CCCCCCCCh0040D7F6   rep stos    dword ptr [edi]13:       *num=52;0040D7F8   mov         eax,dword ptr [ebp+8]0040D7FB   mov         dword ptr [eax],34h14:   }0040D801   pop         edi0040D802   pop         esi0040D803   pop         ebx0040D804   mov         esp,ebp0040D806   pop         ebp0040D807   ret反汇编分析

function分析

function外部

21:       function(num);0040D97F   mov         eax,dword ptr [ebp-4]0040D982   push        eax0040D983   call        @ILT+15(function) (00401014)0040D988   add         esp,4将[ebp-4]也就是num赋值给eax,然后将eax作为参数压入到堆栈中
用内存窗口观察此时ebp-4的情况:

此时的ebp-4对应地址为0012FF7C,也就是前面的num
function内部

截取出赋值的关键代码
9:        num=52;0040D888   mov         dword ptr [ebp+8],34h留意到此时赋值为[ebp+8](参数),用内存窗口观察其地址并比较和先前的ebp-4的地址

可以看到此时要赋值的地址为0012FF2C,和先前的num地址0012FF7C差别,但值是雷同的:0x262=610
于是就造成了就算修改了这里的地址中的值也不会影响本来的值


小总结

在函数内部得到的参数的值虽然和传入的参数的值一致,但实际的内存地址并不雷同,于是在函数内部修改值并不会影响到本来的值
function2分析

function2外部

23:       function2(&num);0040D99C   lea         edx,[ebp-4]0040D99F   push        edx0040D9A0   call        @ILT+20(function2) (00401019)0040D9A5   add         esp,4将ebp-4的地址传给edx,然后将edx作为参数压入到堆栈中
观察此时ebp-4的情况:

此时ebp-4就是num的地址=0012FF7C
function2内部

截取出关键的赋值代码
13:       *num=52;0040D7F8   mov         eax,dword ptr [ebp+8]0040D7FB   mov         dword ptr [eax],34h起首看[ebp+8]:

会发现此时的ebp+8所存的内容就是num的地址:0012FF7C
这里是将[ebp+8](参数)赋值给eax,赋值后的eax是即是外面的num的

然后再将0x34赋值到参数所存储的内容里

小总结

使用指针作为参数可以实如今函数内部修改后外部的值也可以同步被修改
指针作为参数总结

通过比较指针传参和非指针传参得到了以下结论:
无论是指针传参照旧非指针传参,将参数传入函数内部后,只保证了参数的内容一致,但地址差别
之所以指针传参能够实现修改函数外部值的效果,是因为传入的参数的值就是外部值的地址,传入的是个地址,通过修改同个地址里的值而达到了影响外部值的效果
传入参数差异非指针传参参数是值修改值只修改了函数内部的值,不影响函数外部指针传参参数是址修改值是通过地址来修改的,因而能够影响函数外部使用指针作为参数十分常见,因为通过这种方式就可以不用返回值直接将要返回的数据生存在指针里即可
常见的例子:
NTSTATUS  ZwOpenProcess (    __out PHANDLE  ProcessHandle,                //进程句柄,PHANDLE 句柄指针    __in ACCESS_MASK  DesiredAccess,        //想要的权限    __in POBJECT_ATTRIBUTES  ObjectAttributes,        //指向ObjectAttributes的指针    __in_opt PCLIENT_ID  ClientId                //指向ClientId的指针    )这是一个内核函数,用来打开进程,具体使用细节这里不做重点
这里的ProcessHandle是一个指针,它作为参数就是用来存储打开进程后得到的进程句柄
很多内核函数都接纳了这种形式——指针作为参数来存储要返回的数据
指针作为返回值

先前在数组里跳过了将数组作为返回值来传递,因为当时还没有讲到指针,接下来看看指针作为返回值的情形
错误的返回值

代码

#include "stdafx.h"#include int* function(){        int arr[5]={1,2,3,4,5};        return arr;}int main(int argc, char* argv[]){        int*arr;                arr=function();        int i;                for(i=0;i

本帖子中包含更多资源

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

x
楼主热帖
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-4-20 02:12 , Processed in 0.109375 second(s), 31 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

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