gpt4 book ai didi

linux - 基本的 nasm shellcode 崩溃

转载 作者:太空狗 更新时间:2023-10-29 12:00:34 24 4
gpt4 key购买 nike

我正在学习汇编,所以我正在研究 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 调试它,但没有帮助。

最佳答案

我想向您展示如何使用 gdb 找到您的问题:

  1. 启动 gdb 并加载您的程序:>> gdb write
  2. 直接在开始处设置断点:(gdb) b _start。您可以让程序一直运行到出现段错误,但如果堆栈困惑,您很可能什么也看不到。
  3. 将显示设置为在每一步后自动显示堆栈中的 5 个顶部值:(gdb) display/x {unsigned int[5]}$sp
  4. 查看下一个执行行:(gdb) display/i $pc
  5. 现在运行:(gdb) run

调试器命中断点,您会看到系统设置的堆栈:

1: /x {unsigned int[5]}$sp = {0x1, 0xffffd284, 0x0, 0xffffd29d, 0xffffd2b2}

到目前为止一切正常,程序以一个参数启动(顶部的 0x1)- 程序的路径(您可以通过 (gdb) print (char[ 10])*(0xffffd284)).

  1. 执行步骤(gdb) si,现在我们跳转到message 符号。

使用 (gdb) disas 可以看到更多的代码:

(gdb) disas
Dump of assembler code for function message:
=> 0x08048083 <+0>: call 0x8048072 <main>
0x08048088 <+5>: dec %eax
0x08048089 <+6>: gs
0x0804808a <+7>: insb (%dx),%es:(%edi)
0x0804808b <+8>: insb (%dx),%es:(%edi)
0x0804808c <+9>: outsl %ds:(%esi),(%dx)
0x0804808d <+10>: and %ecx,(%edx)
End of assembler dump.

如您所见,您的“Hello”字符串被解释为从 0x08048088

开始的操作
  1. 再做一步:(gdb) si,进入函数main

现在看一下堆栈:

 1: /x {unsigned int[5]}$sp = {0x8048088, 0x1, 0xffffd283, 0x0, 0xffffd29c}

call 指令将返回地址压入堆栈 - 0x08048088 - 您的字符串的地址。好技巧,希望 main 永远不会返回...

  1. 让我们快进到 write 的调用:(gdb) si 3 并进入 (gdb) si

我们看一下栈,正如预期的那样,call 将返回地址添加到栈中:

1: /x {unsigned int[5]}$sp = {0x804807b, 0x8048088, 0x7, 0x1, 0xffffd283}
  1. 您的程序期望指向字符串的指针和长度位于顶部,但事实并非如此。
  2. 让我们快进到函数 write 的返回:(gdb) si 7

看一下堆栈:

1: /x {unsigned int[5]}$sp = {0x7, 0x1, 0xffffd283, 0x0, 0xffffd29c}

下一个操作 - ret 将从堆栈中弹出 0x7 并尝试假定在地址 0x7 处执行,这会导致段错误(如 rcd 所怀疑的那样)。

所以你的问题是你的函数破坏了堆栈。通常,为调用设置堆栈的函数还负责随后清理它。

关于linux - 基本的 nasm shellcode 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38649160/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com