第一步 checksec一下,本题为32位。
分析一下保护机制:
一、RELRO: Partial RELRO
- Partial RELRO 提供了一定程度的保护。在这种情况下,部分重定位表在程序启动时被设置为只读。这可以防止一些针对重定位表的攻击,比如通过篡改重定位表中的函数地址来执行恶意代码。但是,与 Full RELRO 相比,保护程度相对较弱。Full RELRO 会将整个重定位表以及全局偏移表(GOT)设置为只读,提供更全面的保护。
二、Stack: Canary found
- 栈保护机制对于防范缓冲区溢出攻击非常重要。当函数被调用时,一个随机值(栈金丝雀值)被放置在栈上。在函数返回之前,程序会检查这个值是否被修改。如果栈金丝雀值被破坏,说明可能发生了栈缓冲区溢出,程序可以采取相应的安全措施,如立即终止程序运行,从而防止攻击者利用缓冲区溢出进一步控制程序执行流程。
三、NX: NX enabled
- 开启 NX(No-Execute)保护意味着将内存分为可执行区域和不可执行区域。数据所在的内存区域被标记为不可执行,这样即使攻击者能够在数据区域注入恶意代码,也无法执行这些代码。增加了攻击者利用缓冲区溢出等漏洞执行任意代码的难度。
四、PIE: PIE enabled
- PIE(Position Independent Executable)使得程序在每次运行时,其代码段和数据段在内存中的地址都是随机化的。这使得攻击者难以预测程序的内存布局,从而增加了利用内存漏洞进行攻击的难度。例如,攻击者通常需要知道特定函数或数据的地址才能进行攻击,但在 PIE 启用的情况下,这些地址在每次程序运行时都可能不同。
第二步 进入主函数,发现关键字眼/bin/sh,我们分析一下含bin的这部分代码
- *(_QWORD *)&var[13]:
- _QWORD 是一个类型定义,通常表示一个64位的无符号整数(在64位系统上)。
- &var[13] 是取数组 var 第14个元素的地址(因为数组索引是从0开始的)。
- (_QWORD *)&var[13] 是将 var[13] 的地址转换为 _QWORD 类型的指针。
- *(_QWORD *)&var[13] 是解引用这个指针,从而获取 var[13] 到 var[13+7](因为一个 _QWORD 是8字节)这一段内存表示的64位值。
- if ( *(_QWORD *)&var[13] ):
- 这个条件判断是检查 var[13] 到 var[13+7] 这8个字节组成的64位值是否不为0。如果这个值不为0,则进入下面的代码块。
- if ( *(_QWORD *)&var[13] == 17LL ):
- 在第一个条件成立的基础上,这个判断是检查这8个字节组成的64位值是否等于17(17LL 表示17的long long类型,即64位整型)。
- 如果这个值确实等于17,那么将执行 system("/bin/sh");。
由于这里是var[13]=17LL,而var数组可以覆盖到了var[15]如图
第三步 编写脚本
为什么乘以14,因为,数组13是第14位(下表为零开始)
运行成功