我正在学习shell代码的缓冲区溢出。在shell中,通过系统调用execve((来生成shell的代码。像mov $0x0, %eax
这样的东西可以用xor %eax, %eax
代替,以避免shell代码中出现NULL。但是有一个int $0x80
。数字0x80是巧合吗?如果中断向量从创建之日起为0x0,该怎么办?有没有办法消除NULL字节?
中断号0是#DE
,除法异常围绕使用int $0
进行系统调用来设计系统是不合理的。
操作系统调用接口选择更高的数字,因为它们完全避开了x86陷阱,也就是异常。正如维基百科所说,0
和0x1f
之间的中断号是为例外情况保留的。
通常Linux为该IDT条目配置陷阱门,因此用户空间根本无法真正模拟int $0
的除法异常;硬件可以分辨出CCD_ 9指令与出现故障的CCD_。如果您尝试这样做,内核将提供SIGSEGV而不是SIGFPE。
但无论如何,要在机器代码中没有0
的情况下引发中断0,div edx
将始终发生#DE
故障,而不管EDX:EAX中的值如何。如果商不是被零除的,它总是会溢出。(或者在没有任何数学推理的情况下,xor eax, eax
/div eax
将被零除。(
在代码(或代码中的字符串(中获取零的另一种更通用的方法是使用自修改代码:通常,代码注入只能在具有读+写+执行权限的页面中进行,因此使用call
来查找EIP,或者您的代码相对于寄存器的位置可能已经已知,例如xor eax, eax
/mov [esp + 123], al
在代码中的某个位置存储零。