Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly x86_64程序集-尝试在x64程序集中编辑数组中的字节时出现SEGFULT_Assembly_Segmentation Fault_X86 64 - Fatal编程技术网

Assembly x86_64程序集-尝试在x64程序集中编辑数组中的字节时出现SEGFULT

Assembly x86_64程序集-尝试在x64程序集中编辑数组中的字节时出现SEGFULT,assembly,segmentation-fault,x86-64,Assembly,Segmentation Fault,X86 64,我下面的教程是针对x86的,并且是使用32位汇编编写的,在学习x64汇编的过程中,我将尝试遵循这一教程。这一直都很顺利,直到本课,我有下面的简单程序,它只是试图修改字符串中的单个字符;它编译的很好,但在运行时会出错 section .text global _start ; Declare global entry oint for ld _start: jmp short message ; Jump to where or message is at so we can do a

我下面的教程是针对x86的,并且是使用32位汇编编写的,在学习x64汇编的过程中,我将尝试遵循这一教程。这一直都很顺利,直到本课,我有下面的简单程序,它只是试图修改字符串中的单个字符;它编译的很好,但在运行时会出错

section .text

global _start ; Declare global entry oint for ld
_start:

    jmp short message ; Jump to where or message is at so we can do a call to push the address onto the stack

    code:   
    xor rax, rax    ; Clean up the registers
    xor rbx, rbx
    xor rcx, rcx
    xor rdx, rdx

    ; Try to change the N to a space
    pop rsi ; Get address from stack
    mov al, 0x20 ; Load 0x20 into RAX
    mov [rsi], al; Why segfault?
    xor rax, rax; Clear again

    ; write(rdi, rsi, rdx) = write(file_descriptor, buffer, length)
    mov al, 0x01    ; write the command for 64bit Syscall Write (0x01) into the lower 8 bits of RAX
    mov rdi, rax    ; First Paramter, RDI = 0x01 which is STDOUT, we move rax to ensure the upper 56 bits of RDI are zero
    ;pop rsi        ; Second Parameter, RSI = Popped address of message from stack
    mov dl, 25  ; Third Parameter, RDX = Length of message
    syscall     ; Call Write

    ; exit(rdi) = exit(return value)    
    xor rax, rax    ; write returns # of bytes written in rax, need to clean it up again
    add rax, 0x3C   ; 64bit syscall exit is 0x3C
    xor rdi, rdi    ; Return value is in rdi (First parameter), zero it to return 0
    syscall     ; Call Exit

    message:
    call code   ; Pushes the address of the string onto the stack
    db 'AAAABBBNAAAAAAAABBBBBBBB',0x0A
罪魁祸首是这样的:

mov [rsi], al; Why segfault?
如果我将其注释掉,那么程序运行正常,输出消息“aaaabbbnbaaaaaaaabbbbbb”,为什么我不能修改字符串

作者代码如下:

global _start


_start:
        jmp short ender

        starter:

        pop ebx                 ;get the address of the string
        xor eax, eax

        mov al, 0x20
        mov [ebx+7], al        ;put a NULL where the N is in the string

        mov al, 4       ;syscall write
        mov bl, 1       ;stdout is 1
        pop ecx         ;get the address of the string from the stack
        mov dl, 25       ;length of the string
        int 0x80

        xor eax, eax
        mov al, 1       ;exit the shellcode
        xor ebx,ebx
        int 0x80

        ender:
        call starter
        db 'AAAABBBNAAAAAAAABBBBBBBB'0x0A
我已经用以下方法编译了:

nasm -f elf <infile> -o <outfile>
ld -m elf_i386 <infile> -o <outfile>
nasm-f elf-o
ld-m elf_i386-o

但即使这样也会导致segfault,页面上的图片显示它工作正常,并将N改为一个空格,但我似乎陷入了segfault的境地:(谷歌在这种情况下没有真正的帮助,所以我转向你stackoverflow,任何指针(没有双关语!)非常感谢

我认为这是因为您试图访问
.text
部分中的数据。通常,出于安全考虑,您不允许写入代码段。可修改的数据应位于
.data
部分。(或者
.bss
如果初始化为零。)

对于不希望使用单独部分的实际外壳代码,请参阅以了解其他解决方法


此外,我决不会建议使用
call
的副作用将其后面的地址推送到堆栈中,以获得指向其后面数据的指针,外壳代码除外

这是外壳代码中的常见技巧(必须独立于位置);32位模式需要调用才能以某种方式获取EIP。
调用
必须具有向后位移,以避免机器代码中出现
00
字节,因此将调用放在创建“返回”的位置您特别想要的地址保存一个
add
lea

即使在可以进行RIP相对寻址的64位代码中,jmp/call/pop的紧凑性也相当于跳过带有负位移的RIP相对LEA的字符串

在外壳代码/受限机器代码用例之外,这是一个糟糕的想法,你应该像普通人一样使用
.data
中的数据和
.text
中的代码(或
.rodata
中的只读数据)这样,您就不会试图在数据旁边执行代码,或者将数据放在代码旁边


(允许外壳代码的代码注入漏洞已经暗示存在具有写入和执行权限的页面,但现代工具链中的正常进程没有任何W+X页面,除非您采取措施使其发生。因此,这是一个很好的安全功能,因此必须击败正常的工具链安全功能/默认设置。)测试外壳代码。)

他没有试图写入.text节内存地址,而是试图写入一个不存在的内存地址。他想要rsi中的堆栈地址,但他做了一个pop rsi,没有mov rsi,rsp@sinkmanu是的,他们是。阅读代码:call将地址放在堆栈中,然后他们将其放入rsi。他们不希望rsp进入rsi。是的,我没有我看不出他没有将消息保存在.data部分。这种技术被称为“跳转调用pop”@MykelStone:i386 Linux历史上有R+X文本和R+X+W数据,因为直到NX位(和AMD64),无法使页面可读但不可执行。不过,始终存在写保护,Linux将其用于可执行文件的文本段。我非常确定,将作者的代码构建为正常的32位可执行文件,并以正常方式运行它时,始终会出现segfaulted。
调用
将指针推送到following数据是我以前在外壳代码示例中见过的东西,但是在外壳代码利用中,您没有把数据放在不同的部分的奢侈。而且代码+数据通常只在RWX页面中工作,通常在堆栈上。TL:DR:一些外壳代码黑客在具有只读文本段的正常可执行文件中不工作。Disabling
randomize\u va\u space
仅在您将其注入某个内容时才起作用。
call
推送以下地址是PIC,代码的其余部分也是PIC@MykelStone。因为您的.text段标记为readonly。