为何以下汇编指令序列会触发SIGILL信号?
拆解这段Shellcode的执行逻辑
你贴的这段GDB反汇编代码是一段很典型的x86_64 Linux Shellcode,核心是构造出执行/bin/sh的环境。而且你提到0x7fffffffdbe4地址之前的指令都是有效指令,程序在该地址已经调用了exit系统调用收尾,那我们就来一步步拆解这段核心指令的作用:
首先是GDB的反汇编输出:
gdb) x/20i $rip => 0x7fffffffdbb0: movabs rax,0x2168732f6e69622f 0x7fffffffdbba: push rax 0x7fffffffdbbb: lea rdi,[rsp] 0x7fffffffdbbf: xor rax,rax 0x7fffffffdbc2: mov BYTE PTR [rdi+0x7],al 0x7fffffffdbc5: mov QWORD PTR [rdi+0x8],rdi 0x7fffffffdbc9: mov BYTE PTR [rdi+0x10],al 0x7fffffffdbcc: mov rsi,QWORD PTR [rdi+0x8] 0x7fffffffdbd0: push rax 0x7fffffffdbd1: push rdi
接下来逐个指令解析:
movabs rax,0x2168732f6e69622f:把十六进制值0x2168732f6e69622f塞进rax寄存器,转成ASCII看是/bin/sh!(因为x86_64是小端序,实际存储是反向的!hs/nib/,push到栈里就会变回正常的/bin/sh!顺序)push rax:把rax里的8字节内容压栈,此时栈顶就是/bin/sh!这个字符串的起始位置lea rdi,[rsp]:把栈顶地址加载到rdi寄存器——rdi是execve系统调用的第一个参数,也就是要执行的程序路径xor rax,rax:这是个高效的清零操作,把rax整个置0,这样rax的低8位al也是0,刚好可以当字符串的结束符mov BYTE PTR [rdi+0x7],al:把0写到rdi+0x7的位置,把/bin/sh!最后那个!替换成0,得到标准C风格的字符串/bin/shmov QWORD PTR [rdi+0x8],rdi:把rdi(也就是/bin/sh的地址)写到rdi+0x8的位置,这里在构造execve的第二个参数——argv数组,argv[0]就是程序路径,后续要补NULL终止符mov BYTE PTR [rdi+0x10],al:把0写到rdi+0x10的位置,给argv数组加上NULL终止符,让数组合法mov rsi,QWORD PTR [rdi+0x8]:把刚才构造好的argv数组地址加载到rsi寄存器,作为execve的第二个参数push rax:把rax里的0压栈,为构造execve的第三个参数envp数组做准备(直接传NULL即可)push rdi:把/bin/sh的地址压栈,后续应该会把rsp作为envp参数,再设置rax为59(execve的系统调用号),触发syscall执行shell,最后到0x7fffffffdbe4调用exit系统调用结束程序
内容的提问来源于stack exchange,提问作者AkaLee
相关产品推荐
相关产品推荐

