【问题标题】:What if system call number were 0 in a buffer overflow attack?如果系统调用号在缓冲区溢出攻击中为 0 怎么办?
【发布时间】:2021-01-04 06:09:43
【问题描述】:

我正在学习使用 shellcode 的缓冲区溢出。在 shellcode 中通过系统调用 execve() 来生成 shell。像mov $0x0, %eax 这样的东西可以用xor %eax, %eax 代替,以避免在shellcode 中出现NULL。但是有一个int $0x80。数字 0x80 是巧合吗?如果中断向量从创建之日起是 0x0 怎么办?有没有办法消除那个 NULL 字节?

【问题讨论】:

  • 你的 shellcode 可能是可写的,因为它通常是这样被注入的。所以你可以使用自我修改。 int 方法已过时,您有 syscallsysenter 作为奖励,它们没有零字节。
  • 32 位 Linux 对每个系统调用使用中断向量 0x80。这是一个任意的选择,但却是一个固定的选择。你没有理由去做int $0x0,它只会出现段错误而没有做任何有用的事情。系统调用号,用于选择是否调用readwritefork等,在%eax中传递,而不是作为中断向量。
  • 等等,你是在问如果 Linux 的设计不同并且使用中断 0 而不是 0x80 会怎样,在这种情况下你将如何编写没有零字节的 shellcode?然后就像 Jester 说的那样,您需要使用自修改代码。如果这就是您的意思,那么如果您在标题中说“是”(虚拟语气)而不是“是”(指示性语气),您的问题会更清楚。你的意思是“中断向量”而不是“系统调用号”。
  • 谢谢 Nate,我已经修改了我的问题。

标签: assembly x86 system-calls buffer-overflow shellcode


【解决方案1】:

中断号 0 是 #DE,除法例外。 围绕使用 int $0 进行系统调用来设计系统并不合理。

OS 系统调用接口选择更高的数字,因为它们可以轻松避开 x86 陷阱(即异常)。 As Wikipedia says00x1f 之间的中断号是为异常保留的。


通常 Linux 会为该 IDT 条目配置陷阱门,因此用户空间根本无法真正模拟带有 int $0 的除法异常;硬件可以分辨出int 指令与出现故障的div 之间的区别。如果您尝试这样做,内核会提供 SIGSEGV 而不是 SIGFPE。

但无论如何,要在机器代码中不带0 的情况下引发中断 0,div edx 将始终出现#DE 错误,无论 EDX:EAX 中的值如何。如果不是被零除,商将始终溢出。 (或者没有任何数学推理,xor eax, eax / div eax 将被零除。)


另一种更通用的在代码(或字符串以及代码)中获取零的方法是使用自修改代码:通常代码注入只能在具有读+写+执行权限的页面中进行,所以要么使用call 找出 EIP,或者您的代码相对于寄存器的位置可能已经知道,例如xor eax, eax / mov [esp + 123], al 在代码中的某个位置存储零。

【讨论】:

    猜你喜欢
    • 2011-11-12
    • 2019-10-23
    • 1970-01-01
    • 2021-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-30
    相关资源
    最近更新 更多