首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

为什么ebx保存在一个简单函数的堆栈框架中,调用gets?

ebx保存在一个简单函数的堆栈框架中,调用gets是因为在函数调用过程中,ebx寄存器被用作基址寄存器,用于访问函数的局部变量和参数。而调用gets函数是为了从标准输入流中读取用户输入的字符串。

在堆栈框架中,函数的局部变量和参数被分配在栈上,而ebx作为基址寄存器可以方便地访问这些局部变量和参数。通过保存ebx的值,函数可以在执行过程中正确地访问和操作这些数据。

调用gets函数是为了从标准输入流中读取用户输入的字符串。gets函数会将用户输入的字符串存储到指定的内存地址中,而ebx寄存器保存了这个内存地址,因此可以将用户输入的字符串保存到函数的局部变量或参数中。

然而,需要注意的是,使用gets函数存在安全风险。gets函数没有对输入的字符串长度进行限制,可能导致缓冲区溢出漏洞,使得恶意用户可以输入超出预期长度的字符串,从而覆盖其他内存区域的数据。为了避免这种安全问题,推荐使用更安全的输入函数,如fgets函数,并且在使用任何输入函数时都应该对输入的长度进行合理的限制和验证。

腾讯云相关产品和产品介绍链接地址:

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

ROP基本原理和实战教学,看这一篇就够了!

ecx ; pop ebx ; ret 简单展示部分内容,与上一个选取原理是一样,为了方便,我们选择最后一行。...图片 当然也可以进行堆栈平衡,在执行完gets()函数后提升堆栈(add esp, 4),堆栈位置如下: 程序在读写数据时候是通过地址查找,如果函数调用之前堆栈函数调用之后堆栈不一致,就可能导致找不到数据或找到数据错误...图片 这样构造使得我们堆栈逻辑更好看,一个函数一个函数顺序执行,从压入形参到结束,显得有条理,但是只要达到目的即可,第一种或许更方便一些。...此处溢出用来获取put函数真实地址,怎么再去进行执行system('bin/sh')呢?如果存在两个溢出点就完美了,可惜只有一个。...怎么构造之前简单了解用户代码入口和系统代码入口,在一个程序运行中有两个入口,一个是main(),另一个是_start(),简单来说,main()函数是用户代码入口,是对用户而言;而_start(

2.1K30

《深入理解计算机系统》(CSAPP)实验三 —— Buf Lab

在此代码,定义了一个32个字节空间buf来存储字符。   Gets()从输入流获取一个字符串,并将其存储到其目标地址(buf)。但是,Gets()无法确定buf是否足够大以存储整个输入。...当Gets遇到此字节时,它将终止字符串。 栈帧结构 ? 首先简单理解下函数调用过程栈帧结构。如上图所示,为函数P调用函数Q时,程序栈帧结构。 当前正在执行过程帧总是在栈顶。...Level 1: Sparkler   Level1 和Level0差不多,唯一区别是 fizz(int) 函数一个整型参数,并且在 fizz函数还要校验cookie, test函数调用getbuf...当调用函数(在本例为getbuf)执行其ret指令时,程序将开始在堆栈上执行指令,而不是返回。通过这种攻击方式,您可以获得该程序几乎可以执行任何操作。您放在堆栈代码称为漏洞利用代码。...在GDB调试堆栈位置也会有差异,因为GDB将堆栈空间用于其自身某些状态。   在调用getbuf代码,使用了某些手段(稳定因素),从而使两次运行之间,getbuf堆栈框架将保持一致。

1.7K20

Win32汇编:过程与宏调用

接着来简单介绍下关于堆栈操作两个寄存器,CPU系统提供了两个特殊寄存器用于标识位于系统栈顶端栈帧....◆堆栈参数传递◆ 在通常情况下ESP是可变,随着栈生产而逐渐变小,而EBP寄存器是固定,只有当函数调用后,发生入栈操作而改变. 1.在32位系统,执行PUSH压栈时,堆栈指针自动减4,再将压栈值复制到堆栈指针所指向内存地址.... 2.在32位系统,执行POP出栈时,从栈顶移走一个值并将其复制给内存或寄存器,然后再将堆栈指针自动加4. 3.在32位系统,执行CALL调用时,CPU会用堆栈保存当前被调用过程返回地址,直到遇到...Sum过程,实现EBX+ECX并将结果保存在EAX寄存器. .data TheSum DWORD ?...一个简单宏: MyCode macro xor eax,eax xor ebx,ebx xor ecx,ecx xor edx,edx endm .code main PROC MyCode

63820

Win32汇编:过程与宏调用

,而ESP寄存器值通常是指向特定位置一个32位偏移值,我们很少需要直接操作ESP寄存器,相反ESP寄存器总是由CALL,RET,PUSH,POP等这类指令间接性修改.接着来简单介绍下关于堆栈操作两个寄存器...◆堆栈参数传递◆在通常情况下ESP是可变,随着栈生产而逐渐变小,而EBP寄存器是固定,只有当函数调用后,发生入栈操作而改变.1.在32位系统,执行PUSH压栈时,堆栈指针自动减4,再将压栈值复制到堆栈指针所指向内存地址....2.在32位系统,执行POP出栈时,从栈顶移走一个值并将其复制给内存或寄存器,然后再将堆栈指针自动加4.3.在32位系统,执行CALL调用时,CPU会用堆栈保存当前被调用过程返回地址,直到遇到RET...Sum过程,实现EBX+ECX并将结果保存在EAX寄存器..dataTheSum DWORD ?....,一旦定义后,宏过程就可以在程序中被调用任意多次,调用宏过程时候,宏内语句块将替换到调用位置,宏本质是替换,但像极了子过程,宏可定义在源程序任意位置,但一般放在.data前面.一个简单宏:MyCode

43030

深入理解计算机系统:内存越界引用和缓冲区溢出

程序运行时,其内存里面一般都包含这些部分: (1)程序参数和程序环境; (2)程序堆栈(堆栈则比较特殊,主要是在调用函数时来保存现场,以便函数返回之后能继续运行),它通常在程序执行时增长,一般情况下...在栈中分配某个字节数组来保存一个字符串,但是字符串长度超出了为数组分配空间。C对于数组引用不进行任何边界检查,而且局部变量和状态信息,都存在。...void echo() { char buf[8] ; gets(buf) ; puts(buf) ; } 输入字符数量   被破坏状态 0—7        无 8—11      ...保存%ebx值 12—15      保存%ebp值 16—19      返回地址 20+         caller中保存状态 执行攻击代码exploit code 用一个指向攻击代码指针覆盖返回地址达到跳转到攻击代码效果...方式一:攻击代码会使用系统调用启动一个shell程序,给供给者提供一组操作系统函数; 方式二:执行一些未授权任务,修复对栈破坏,然后第二次执行ret指令,表面上正常返回到调用者; 蠕虫和病毒区别

45220

Delphi异常机制与SEH

当MOV [EBX], 0发生内存访问错后,系统挂起,查找SEH处理链表,通知ExceptionHandler进行处理,ExceptionHandler,将EBX修复到一个可以访问内存位置,再通知系统恢复环境继续执行...1 、 VCL 顶层异常捕获 在DELPHI开发程序,出错时候,我们很少看到出现一个错误对话框,提示点确定结束程序,点取消调试。而在VC或VB里就很常见,这是为什么呢?...VCL里比较特殊SEH应用吧,过程大概就是,对构造函数进行保护,如果出现异常就调用析构函数释放。...,这个时候VCL又会主动调用析构函数,结果b.free时候就出错了。...所以在析构函数里释放对象时候,一定要注意判断对象是否存在

1.1K10

缓冲区溢出攻击初学者手册(更新版)

其中EIP指向地址总是包含下一个执行代码。 数据段,变量空间和动态缓冲器。 堆栈段,这是用来给函数传递变量和为函数变量提供空间。栈底部位于每一页虚拟内存末端,同时向下运动。...2 函数 函数是一段代码段代码,它被调用,执行一个任务,之后返回执行一个线程。或是把参数传递给函数,通常在汇编语言中,看起来是这样(这是一个简单例子,只是为了了解一下概念)。...主函数调用了function(0); 变量是0,主要把它压入栈,同时调用函数函数使用popl来获取栈变量。完成后,返回0×8054327。...如果代码存在溢出地方,这个返回值会被覆盖,并且指针指向内存一个位置。...如果有溢出存在函数返回值地址是可以变,从而改变程序执行线程。 4 Shellcode 为了简单,Shellcode使用简单汇编指令,我们写在栈上,然后更改返回地址,使它返回到栈内。

1.4K90

CC++ 编写并提取通用 ShellCode

简易 ShellCode 虽然可以正常被执行,但是还存在很多问题,因为上次所编写 ShellCode 采用了硬编址方式来调用相应API函数,那么就会存在一个很大缺陷,如果操作系统版本不统一就会存在调用函数失败甚至是软件卡死现象...为什么要查找 Kernel32.dll 地址而不是 User32.dll,这是因为我们最终目的是调用 MessageBox 这个函数,而该函数位于 User32.dll 这个动态链接库里,默认情况下是无法直接调用....dll 这个动态链接库基地址,而Dll文件本质上也是PE文件,在Dll文件存在一个导出表,其内部记录着该Dll导出函数。...函数 RVA 地址和名字按照顺序存放在上述两个列表,我们可以在列表定位任意函数RVA地址,通过与动态链接库基地址相加得到其真实VA,而计算地址就是我们最终在 ShellCode 调用时需要地址...LoadLibraryA地址 lea edi,[esi-0xc] // 后面会利用edi值来调用不同函数 // ===开辟内存空间,这里是堆栈空间 xor ebx,ebx

44320

恶意样本对抗栈回溯检测机制套路浅析

在本文中我将会简单分析和推测一下这类恶意样本都是通过哪些套路来实现和栈回溯机制对抗。需要注意是,文中讨论堆栈都是代指线程在用户层堆栈,并未涉及内核层堆栈。...命中断点之后,发现无法通过 kv 指令栈回溯来获取该线程当前时刻调用栈序列,能获取到栈帧只有当前所处函数调用。而继续跟进该函数里所调用任何一个函数,发现调用栈仍旧只有一个栈帧。...EBP 始终保持不变 mov esp, ebp ; 将 EBP 值赋给 ESP 寄存器,执行后 ESP 指向地址存储属于调用函数 EBP 值 pop ebp ; 弹出保存在调用函数...EBP 并赋给 EBP 寄存器 ret ; 弹出保存在调用函数调用位置下一条指令地址给 EIP 寄存器 根据以上函数调用逻辑容易知道,在函数体代码任何位置,EBP...要是样本 ShellCode 更进一步,窃取其他线程堆栈部分数据覆盖到自己构造堆栈高内存部分,那么在调试器或检测系统在栈回溯时,遍历到上层调用项,被诱导进入另一个线程调用栈序列,那么获取到数据就可能已经不是当前线程数据了

76120

5.5 汇编语言:函数调用约定

函数是任何一门高级语言中必须要存在,使用函数式编程可以让程序可读性更高,充分发挥了模块化设计思想精髓,今天我将带大家一起来探索函数实现机理,探索编译器到底是如何对函数这个关键字进行实现,并使用汇编语言模拟实现函数编程参数传递调用规范等...不同两次函数调用,所形成栈帧也不相同,当由一个函数进入另一个函数时,就会针对调用函数开辟出其所需栈空间,形成此函数独有栈帧,而当调用结束时,则清除掉它所使用栈空间,关闭栈帧,该过程通俗讲叫做栈平衡...这种调用方式规定函数调用者在将参数压入栈后,再将控制权转移到被调用函数,被调用函数通过栈顶指针ESP来访问这些参数。函数返回时,由调用者程序负责将堆栈平衡清除。...CDECL调用约定特点是简单易用,但相比于其他调用约定,由于栈平衡操作需要在函数返回后再进行,因此在一些情况下可能会带来一些性能上开销。...它通常采用被调用者平衡堆栈方式,类似于STDCALL调用约定。但是,FASTCALL约定规定函数前两个参数在ECX和EDX寄存器传递,节省了压入堆栈所需指令。

27520

汇编角度看函数堆栈调用

下面以主函数调用求和函数分析函数堆栈调用 带着以下一个问题来探索: (1)形参内存空间开辟和清理是由调用方还是由被调用方执行? (2)主函数调用函数结束后,主函数从哪里开始执行?...[pop 寄存器] 功能:出栈,以一个寄存器接受出栈数据。包含两个动作:将栈数据保存在寄存器,同时栈顶指针向下(高地址)偏移。...这就是为什么当我们访问未初始化内存内容,看到是如下图情况。...2.0040104E mov esp,ebp使得被调用函数栈帧回退。此时栈帧空间内容还存在。 3.pop ebp 两个动作,出栈,并将出栈值赋给ebp。...所以形参内存是由调用方清理。 2.将eax寄存器值`30`放入[ebp-0Ch]指向四字节内存块。 到这里,函数堆栈调用过程就完全展示出来了。

61120

5.5 汇编语言:函数调用约定

函数是任何一门高级语言中必须要存在,使用函数式编程可以让程序可读性更高,充分发挥了模块化设计思想精髓,今天我将带大家一起来探索函数实现机理,探索编译器到底是如何对函数这个关键字进行实现,并使用汇编语言模拟实现函数编程参数传递调用规范等...不同两次函数调用,所形成栈帧也不相同,当由一个函数进入另一个函数时,就会针对调用函数开辟出其所需栈空间,形成此函数独有栈帧,而当调用结束时,则清除掉它所使用栈空间,关闭栈帧,该过程通俗讲叫做栈平衡...这种调用方式规定函数调用者在将参数压入栈后,再将控制权转移到被调用函数,被调用函数通过栈顶指针ESP来访问这些参数。函数返回时,由调用者程序负责将堆栈平衡清除。...CDECL调用约定特点是简单易用,但相比于其他调用约定,由于栈平衡操作需要在函数返回后再进行,因此在一些情况下可能会带来一些性能上开销。...它通常采用被调用者平衡堆栈方式,类似于STDCALL调用约定。但是,FASTCALL约定规定函数前两个参数在ECX和EDX寄存器传递,节省了压入堆栈所需指令。

24820

系统调用(int 0x80)详解

大家好,又见面了,我是你们朋友全栈君 1、系统调用初始化 在系统启动时,会在sched_init(void)函数调用set_system_gate(0x80,&system_call),设置中断向量号...为什么不能保存到用户态堆栈,如果保存了用户态堆栈,那么,这些栈内存区域,用户程序就可以必改定,那么,程序就很容易被攻击了,直接修改CS:EIP对应栈内存,那么,你懂^_^。...现场信息是保存在当前进程内核态堆栈,由于已经进入了内核态,在_system_call函数执行push操作,此时被push数据是存储也就在内核栈。...//系统调用函数返回值入栈 关于进程状态变化,参考书上说明,这部分,理解还不够,后续再分析???...当在中断处理函数(陷阱门)执行时,是可被中断(中断门),因为eflags标志TF被设置为允许中断。因而有可能在时钟中断函数(do_timer),本进程时间片可能被修改为0。

1.3K40

函数栈帧创建与销毁

前言 最近在学习C语言过程遇到了一些问题,在询问老师和查询相关资料基础上了解到了函数栈帧相关概念,对下列问题也有了答案。 局部变量是如何创建? 未初始化局部变量为什么是随机值?...(如果给一个变量未初始化,打印该变量内容就会出现一些没有实际意义文字或字母) 函数是如何调用?(过程是什么样?) 函数调用过程是如何传参? 形参和实参有什么联系和区别?...栈帧维持着函数调用所需要各种信息,包括函数入参、函数局部变量、函数执行完成后下一步要执行指令地址、寄存器信息等。...EBP是"基址指针"(BASE POINTER), 它最经常被用作高级语言函数调用"框架指针"(frame pointer)。...二、函数栈帧介绍 每个函数调用时都会建立栈帧,在接下来调试过程我将会进一步解释。

50420

5.10 汇编语言:汇编过程与结构

例如,要将从堆栈中弹出值存储到BX寄存器,可以使用以下指令: POP EBX 从汇编代码角度来看,POP指令将从堆栈取出一个值,并将其存储到目的操作数,它是一个出栈操作。...在函数调用时,PUSH指令被用于向堆栈推送函数参数,这些参数可以是寄存器、立即数或者内存某个值。在函数返回之前,POP指令被用于将堆栈顶部值弹出,并将其存储到寄存器或者内存。...因此,被调用函数必须知道其在堆栈上分配内存大小,并将该大小与其ret指令参数相匹配,以便调用函数可以正确恢复堆栈指针位置。 当平栈由调用者完成时,调用函数需要在调用函数之前平衡堆栈。...因此,调用函数需要知道子函数堆栈上分配内存大小,并在调用函数之前向堆栈提交额外空间。调用函数可以使用add esp, N指令来恢复堆栈指针位置,其中 N 是被调用函数堆栈上分配内存大小。...该指令会将新基准指针ebp 压入堆栈同时将当前基准指针ebp存储到另一个寄存器ebx,然后将堆栈指针esp减去指定大小值,获取新基地址,并将新基地址存储到ebp

19520

5.10 汇编语言:汇编过程与结构

例如,要将从堆栈中弹出值存储到BX寄存器,可以使用以下指令:POP EBX从汇编代码角度来看,POP指令将从堆栈取出一个值,并将其存储到目的操作数,它是一个出栈操作。...在函数调用时,PUSH指令被用于向堆栈推送函数参数,这些参数可以是寄存器、立即数或者内存某个值。在函数返回之前,POP指令被用于将堆栈顶部值弹出,并将其存储到寄存器或者内存。...因此,被调用函数必须知道其在堆栈上分配内存大小,并将该大小与其ret指令参数相匹配,以便调用函数可以正确恢复堆栈指针位置。当平栈由调用者完成时,调用函数需要在调用函数之前平衡堆栈。...因此,调用函数需要知道子函数堆栈上分配内存大小,并在调用函数之前向堆栈提交额外空间。调用函数可以使用add esp, N指令来恢复堆栈指针位置,其中 N 是被调用函数堆栈上分配内存大小。...该指令会将新基准指针ebp 压入堆栈同时将当前基准指针ebp存储到另一个寄存器ebx,然后将堆栈指针esp减去指定大小值,获取新基地址,并将新基地址存储到ebp

38120

大神洗礼第四讲——函数相关及编程技巧

2、 Call Convention(函数调用约定) 、_cdecl a、 参数从右向左压入堆栈 b、 函数调用者修改堆栈 c、 在win32应用程序里,宏APIENTRY,WINAPI,...每一个调用函数都包含清空堆栈代码,所以产生可执行文件大小会比调用_stdcall函数大。...、_stdcall a、 压栈方式与_cdecl一样,与之不一样堆栈平衡不是由函数调用者完成,而是自身完成,在退出时自己清空堆栈。...3、 跟踪汇编代码看函数参数调用机制 我们看这样一个简单函数, 编译器翻译汇编指令如下: 、void Test1(){}  1 void Test1() 2 { 3 013516E0...} 29 在main函数调用结果printf("%d\n", MyFunc()); 2012110222341843.png 练习: 、无参数情况(不在堆栈上展开) 1 void

625100

封包式游戏功能原理与实现

封包式功能实现步骤 1、定位到游戏发包函数 2、通过发包函数定位到明文发包函数 3、通过明文发包函数定位到封包加密函数 4、复制整个封包加密函数到自己dll 5、组包调用游戏功能 整个过程看似简单...不过,发包函数在下断点时候,可能会碰到下面两个棘手问题: 1、明明对 send() 函数下断了,缺断不下来 2、由于游戏中存在一个发包线程,所以即使断下 send() 函数,也无法回溯出有用逻辑...2、搜索 send 函数特征,定位到重写 send 函数 线程发包 接下来解决第二个问题,游戏单独起了一个线程进行发包 线程发包形态和特点 1、发包函数很频繁 2、任何功能在发包函数断下,调用堆栈都是一样...判断方法是对比 WSASend 和找到地址调用堆栈。 我们发现两个调用堆栈地址是相同,说明还没有跳出发包线程。需要继续追 eax 来源然后下写入断点。 ?...在加密封包内容处下断点,喊话让游戏断下,并且在堆栈中找到第一个返回地址 ? 分析这个 call 相关参数, esi 是一个结构体指针 ? +0 位置指向一个函数表 ?

3.5K30

1.4 编写简易ShellCode弹窗

由于如上机制存在,导致user32.dll模块地址不确定,也就会导致其地址内部API函数地址也会发生一定变化,下图仅作为参考图; 在获取到MessageBoxA函数内存地址以后,我们接着需要获取一个...返回值传递:函数返回时将返回值存储在EAX寄存器。 栈使用:函数调用前,调用者将参数压入栈;被调用者在返回前清理栈,以确保栈平衡。...函数调用:在调用函数之前,调用者将返回地址(Return Address)和EBP寄存器值保存在,并将ESP寄存器指向参数列表最后一个元素;在函数返回之后,调用者通过将之前保存EBP和返回地址弹出栈...总之,stdcall调用约定将参数按照从右到左顺序压入栈,由被调用者清理栈,返回值存储在EAX寄存器函数调用者和被调用者都需要遵循一定栈使用规则。...在实际编程,一般还是先将地址赋值给eax寄存器,然后再CALL调用相应寄存器实现调用,比如现在笔者有一个lyshark(a,b,c,d)函数,如果我们想要调用它,那么它汇编代码就应该编写为: push

24910

C语言 | C++ 堆栈工作机制

我们知道,局部变量是存储在堆栈;debug 时,查看堆栈可以知道函数调用顺序;函数调用时传递参数,事实上是把参数压入堆栈,听起来,堆栈一个大杂烩。...这时 main 以及之前函数对应堆栈帧已经存在堆栈中了,如下图所示: 图1 参数入栈  当 foo 函数调用,首先,caller(此时caller为main函数)把 foo 函数两个参数:a...个字节)如下图所示: 图6 我还不知道编译器为什么这么设计,或许是为了在堆栈插入调试数据,不过这无碍我们今天讨论。...在 foo 函数中用到通用寄存器是 EBX,ESI,EDI,将它们压入堆栈,如图所示: 图7 至此,一个完整堆栈帧建立起来了。...事实上,调试器正是这么做,这也就是为什么调试时我们查看函数调用顺序时总是说“查看堆栈”了。

7.7K88
领券