Memory 使用外壳代码修改内存中的字节

Memory 使用外壳代码修改内存中的字节,memory,assembly,shellcode,Memory,Assembly,Shellcode,我一直在尝试创建一个简单的shell代码块,它允许我通过做一些简单的事情来修改字符串,比如更改一个字母,然后打印出来 _start: jmp short ender starter: xor ecx, ecx ;clear out registers xor eax, eax xor ebx, ebx xor edx, edx pop esi ;p

我一直在尝试创建一个简单的shell代码块,它允许我通过做一些简单的事情来修改字符串,比如更改一个字母,然后打印出来

_start:
        jmp short ender
starter:
        xor ecx, ecx            ;clear out registers
        xor eax, eax
        xor ebx, ebx
        xor edx, edx
        pop esi                 ;pop address of string into esi register

        mov byte [esi+1], 41    ;try and put an ASCII 'A' into the second letter of the string
                                ;at the address ESI+1

        mov ecx, esi            ;move our string into the ecx register for the write syscall
        mov al, 4               ;write syscall number
        mov bl, 1               ;write to STDOUT
        mov dl, 11              ;string length
        int 0x80                ;interrupt call
ender:
        call starter
        db 'hello world'
它应该打印出“哈罗世界”。当我尝试用
mov
这样的命令修改一个字节的内存时,就会出现问题(segfault)

mov字节[esi+1],41

虽然GDB和
pop-esi
命令工作正常,但我还是运行了该程序,
esi
加载了字符串的地址,所有内容都有效。我不明白为什么我不能修改有效地址的字节值。我只是通过运行NASM和ld生成的可执行文件来测试这个“外壳代码”,我并没有将它放在C程序或任何东西中,因此程序集中存在缺陷

额外信息

我将x64 Linux与以下构建命令一起使用:

nasm -f elf64 shellcode.asm -o shellcode.o
ld -o shellcode shellcode.o
./shellcode

我已经粘贴了完整的代码

如果我不得不猜测的话,我会说
db
hello world`是作为代码而不是数据编译的,因此具有读取和执行权限,但没有写入权限。所以你实际上违反了页面保护


要改变这一点,您需要将字符串放在
节.data
节中,并使用nasm的变量语法来查找它。为了按原样修改数据,您需要调用以修改页面上的权限,并对其进行写入。注意:这些不会保留回可执行文件-
mmap()
MAP\u PRIVATE
确保了这一点。

您可能遇到了。我尝试将
节.data
放在
db'hello world'
上方的行上,但它仍然出现故障:(至于将字符串更改为变量,这对shellcode不起作用。地址中有空字节,我记得读到过这样的内容,您不能在shellcode中使用静态地址。@user99545
节。data
会将变量放在内存中与函数返回地址完全不同的位置,这就是您需要的'当前依赖。在缓冲区溢出类型的外壳代码中,您将位于堆栈上-因此您将是可写的(但不是可执行的!)-不幸的是,因为您正在有效地构建一个程序,而不是可执行数据,这就是问题所在。您在空字节计数上完全正确-通常编写外壳代码是为了避免这些情况,包括在运行时对字符串进行必要的解码,因为
0
终止字符串…这意味着您不能使字符串溢出带有say
strcpy
的缓冲区。