【发布时间】:2016-12-03 14:25:24
【问题描述】:
我正在学习汇编,所以我正在研究 shellcode。我在 nasm 中写了一个简单的“hello world”程序,但是运行时它崩溃了。
; write.asm
[SECTION .text]
global _start
_start:
jmp short message;
write: ; takes two arguments pushed onto stack -> text, textlen
pop edx ; pop length into edx
pop ecx ; pop ptr to text into ecx
pushad
mov al, 4
mov bl, 1
int 80h ; syscall
popad
ret
exit: ; push exit_code onto stack
mov al, 1
pop ebx ; pop exit_code into ebx
int 80h
main:
pop eax ; pop ptr to message into eax
push 7 ; length of string
push eax ; push ptr to message
call write
xor ebx, ebx; zero out ebx
push ebx
call exit
message:
call main
db 'Hello!', 10
我编译它:
nasm -f elf write.asm
ld -m elf_i386 -o write write.o
然后得到这个:
Segmentation fault (core dumped)
我尝试用 gdb 调试它,但没有帮助。
【问题讨论】:
-
不是字符串 Hello!应该以0结尾?因为它是一个字符串?
-
@rcd 因为这是一个 write 调用,我必须提供字符串的长度,不,它不需要以 null 结尾。
-
在调试器中运行它会显示什么?自从您在
write的开头将其从堆栈中弹出后,您认为ret指令将返回到哪里?也许您忘记了call返回地址被压入堆栈?我怀疑由于您弹出了返回地址加上第一个参数,因此您的代码试图返回内存地址 7,当您调用write返回时,该地址将位于堆栈的顶部。 -
在 pop edx 中,我认为您已经从通话中弹出了返回地址?而不是长度?你检查了吗?
-
@Fluffy 我认为如果 esp 指向您期望的值,您应该跟踪它。我认为您无视调用操纵堆栈的方式。如果它确实指向正确的变量,则在调试器中使用 pop 或 push 检查之前。我怀疑它崩溃是因为执行返回到一个无效的地址。
标签: linux assembly nasm system-calls ld