缓冲区溢出–可执行文件结构|网络攻防课堂笔记

缓冲区溢出--可执行文件结构|网络攻防课堂笔记

image-20221104110537537

今天上课总算是开始讲逆向的内容了, 但是这门课也快结束了, 上了今天这节之后只剩下下周的两节课, 而《网络安全》这本书的内容才上了一半不到, 后面就是一些更加高级和深入的网络安全知识网络安全防护与管理技术, 这本书即使是在课程结束之后也很值得继续阅读学习, 超赞。

下面是一些关于可执行文件的存储结构的课程学习, 做一下上课笔记

程序的组织结构

程序在内存中的存放形式:程序运行时,计算机会在内存区域开辟一段连续的内存块,包括代码段数据段堆栈段三部分

进程的虚拟内存空间布局:

image-20221104081039942

在默认情况下Windows系统将高地址的2GB空间分配给内核(也可配置1GB)而Linux则是将高地址的1GB分配给内核。这些分配给内核的空间成为内核空间, 用户不可访问, 剩下的空间成为用户空间。

代码段(.text)

  • 也称文本段, 由编译器产生, 存放程序的二进制机器码只读数据(比如程序的可执行命令)
  • .text段是只读的, 且大小在运行时事固定的。任何尝试向.text段写入信息的操作都会导致段错误。

数据段:

用于存储全局变量, 主要包括已初始化的数据段.data, 未初始化的数据段.bss, 存储程序运行时动态分配的堆heap,存储函数调试信息的数据结构栈stack, 环境变量/命令行参数

堆(Heap)

位于BSS段以上,存储程序运行时分配的变量

  • 大小不固定,可动态扩张/缩减。由malloc(),new()等内存分配函数实现。当调用new()等函数时,新分配内存被动态添加到堆上(堆扩张);当利用free(), delete()等函数释放内存时,内存从堆中被剔除(堆缩减)

  • 堆内存释放由应用程序控制

    通常一个new要对应一个delete,如果程序没有释放,程序结束后操作系统会自动回收

栈(Stack)

函数调用时的临时信息结构,如函数调用传递的参数、函数返回地址、函数的局部变量等

  • 程序运行时由编译器按需分配,不需要时自动清除

  • 栈的特性:先进后出(FILO)

  • 栈的基本操作:

    • PUSH操作/压栈:

    向栈中添加数据,数据放置在栈顶;

    • POP操作/出栈:

    在栈顶移去1个元素,并将栈的大小减1

堆和栈的区别

  • 分配和管理方式不同
    • 堆:动态分配,其空间的分配和释放都由程序员控制。
    • 栈:由编译器自动管理
  • 产生碎片不同
    • 堆:频繁的new()/delete()或malloc()/free()势必会造成内存空间的不连续,造成大量碎片,使程序效率降低
    • 栈:先进后出的队列,永远不可能有一个内存块从栈中间弹出
  • 生长方向不同
    • 堆:向着内存地址增加的方向增长
    • 栈:向着内存地址减小的方向增长,由内存的高地址向低地址方向增长

不同类型变量的内存位置

  1. 有初始化赋值的static静态变量有初始化赋值的main函数之前定义的变量存放在数据段.data
  2. 常用的自定义变量(无初始化赋值) 无初始化赋值的main函数之前定义的变量存放在.bss
  3. 常用的自定义变量(有初始化赋值) 存放在栈stack
  4. malloc操作分配的变量空间存放在堆heap

image-20221104100717055

一个简单Patch操作的Demo

image-20221104083025365

程序使用IDA反汇编

image-20221104085052665

image-20221104090456113

image-20221104090529564

先将鼠标定位到跳转的地方jz short loc_40107c使用Patch programChange byte功能把jz改为jnz, 之后跳转结果就会与原本相反(正确的密码会显示错误,密码错误的时候跳转到正确通过)

image-20221104091306195

正常来说输入正常密码1234567的时候密码正确就应该直接退出了, 输入其他的密码就会显示密码错误, 但是结果与之相反, 这就是jz被改为jnz的效果了

image-20221104090737804

  • 文件偏移地址(file offset):

    数据在PE文件中相对文件开头的偏移

  • 装载基址(lmage Base) :

    PE文件装入虚拟内存的基地址,默认情况下,EXE文件的基址为OxO0400000,DLL文件的基址是0x10000000

  • 虚拟内存地址(virtual address,VA) :

    PE文件中的指令被装入(虚拟)内存后的地址

  • 相对虚拟地址(Relative Virtual Address,RVA):

    VA相对于基址的偏移量

image-20221104092721334

函数栈

每个函数独占自己的栈帧(Stack Frame)空间, 当前运行函数栈帧总在栈顶。

32位操作系统一般提供两个特殊寄存器表示当前运行的函数栈帧:

  • 基指针寄存器EBP

    EBP指针指向系统栈中正在运行函数栈帧底部

  • 栈指针寄存器ESP

    ESP指针指向系统栈中正在运行函数栈帧栈顶

当栈帧函数返回时, 对应栈帧函数的空间就会被回收, 比如下图为栈帧1的当前运行函数返回时ESP和EBP的指针变化

image-20221104101852814

函数栈中, 一般包含下面几个重要数据:

  1. 局部变量

    在特定过程或函数中可以访问的变量

  2. 栈帧状态信息

    当前函数栈帧的栈底信息(栈顶信息可以通过栈帧平衡计算得到,不需要保存), 用于返回时恢复前一函数栈帧状态继续执行

  3. 函数返回地址

    从函数返回后主程序继续执行的指令地址

    返回地址就是主程序中CALL指令后一条指令的地址

程序执行的吓一跳指令地址存放在指令寄存器EIP中

对于64位操作系统, 栈底指针寄存器RBP, 栈顶指针寄存器RSP, 指令寄存器RIP(和32位操作系统的区别在于一个是E一个是S)

调用约定

主要有四种调用约定, __cdecl, __stdcall, __fastall, __thiscall, 不同的调用约定对应不同类型的函数, 这个感觉并不是太重要所以就不详细说了, 后面有需要。

不同的调用约定区别主要在于参数入栈顺序(从左到右或从右到左), 入栈参数的存储寄存器, 堆栈清理方选择, 能否调用不定参数函数, this指针存放的寄存器

字节序

  • 大端序

    数据的高位存储在内存低地址, 数据的低位存储在内存高地址

  • 小端序

    数据的高位存储在内存高地址, 数据的低位存储在内存低地址

大型UNIX服务器CPU, TCP/IP网络协议, Java虚拟机使用大端序

Intel系列CPU一般使用小端序

字符数组不管是在大端序还是小端序其存储顺序是相同的

变量 大端序 小端序
WORD w = 0x5678 56 78 78 56
WORD dw = 0x12345678 12 34 56 78 87 65 43 21
char str[] = "ABCD" 41 42 43 44 00 41 42 43 44 00

GCC常用的编译选项

编译选项 说明
-o 指定编译生成的可执行文件名称
-m32 生成32位可执行文件: 在64位平台下编译32位程序时使用, 需要安装相应的32位库文件
-g 生成额外调试信息, 方便使用GDB调试器调试程序
-fno-stack-protector 禁止栈保护(GCC4.1引入)
-z execstack 启用可执行栈, 在GCC4.1中默认禁用
-no-pie 用于关闭PIE功能, 开启PIE功能意味着编译器将随机化ELF文件的内存装载基址

More

上面这些内容只是一个简单的章节开端, 还没有开始真正的缓冲区溢出的攻击, 后面上课做笔记再继续更新吧

  1. 常用调试工具介绍Ollydbg, Immunity, Debugger, x64dbg, WinDbg
  2. 缓冲区溢出
    • 栈溢出
    • 格式化字符串溢出
    • 整数溢出
    • 堆溢出
  3. 利用缓冲区溢出加载Shellcode
  4. 缓冲区溢出的防御机制

2022_11_04 第11周星期五 11:00

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇