Security 有人能帮我理解这个asm代码吗

Security 有人能帮我理解这个asm代码吗,security,debugging,assembly,segmentation-fault,debian,Security,Debugging,Assembly,Segmentation Fault,Debian,我正在为一个项目学习外壳代码 计算机科学 但是我在写它的时候有点问题 我在读一本叫《炮弹编码员手册》的书 它给了我一个无法正常工作的代码 代码如下: section .text global _start _start: jmp short GotoCall shellcode: pop rsi xor rax, rax mov byte [rsi + 7], al

我正在为一个项目学习外壳代码 计算机科学

但是我在写它的时候有点问题 我在读一本叫《炮弹编码员手册》的书 它给了我一个无法正常工作的代码 代码如下:

    section     .text
    global _start
_start:
    jmp short      GotoCall
shellcode:
     pop            rsi
     xor            rax, rax
     mov  byte      [rsi + 7], al
     lea            rbx, [rsi]
     mov            [rsi + 8], rbx
     mov            [rsi + 14], rax
     mov  byte      al, 0x0b
     mov            rbx, rsi
     lea            rcx, [rsi + 8]
     lea            rdx, [rsi + 14]
     int            0x80
GotoCall:
     Call            shellcode
     db             '/bin/shJAAAAAAKKKKKK'
简单地说,这应该是产卵壳。。。 但是它不起作用,当我使用gdb调试它时 我得到一个奇怪的代码和一个分段错误

mov  byte      [rsi + 7], al
这是gdb输出: gdb./sclivro

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400085 in _start ()
(gdb) disas _start
Dump of assembler code for function _start:
0x0000000000400080 <_start+0>:  jmp    0x4000a2 <_start+34>
0x0000000000400082 <_start+2>:  pop    %rsi
0x0000000000400083 <_start+3>:  xor    %rax,%rax
0x0000000000400085 <_start+5>:  mov    %al,0x7(%rsi)
0x0000000000400088 <_start+8>:  lea    (%rsi),%rbx
0x000000000040008b <_start+11>: mov    %rbx,0x8(%rsi)
0x000000000040008f <_start+15>: mov    %rax,0xe(%rsi)
0x0000000000400093 <_start+19>: mov    $0xb,%al
0x0000000000400095 <_start+21>: mov    %rsi,%rbx
0x0000000000400098 <_start+24>: lea    0x8(%rsi),%rcx
0x000000000040009c <_start+28>: lea    0xe(%rsi),%rdx
0x00000000004000a0 <_start+32>: int    $0x80
0x00000000004000a2 <_start+34>: callq  0x400082 <_start+2>
0x00000000004000a7 <_start+39>: (bad)  
0x00000000004000a8 <_start+40>: (bad)  
0x00000000004000a9 <_start+41>: imul   $0x414a6873,0x2f(%rsi),%ebp
0x00000000004000b0 <_start+48>: rex.B
0x00000000004000b1 <_start+49>: rex.B
0x00000000004000b2 <_start+50>: rex.B
0x00000000004000b3 <_start+51>: rex.B
0x00000000004000b4 <_start+52>: rex.B
0x00000000004000b5 <_start+53>: rex.WXB
0x00000000004000b6 <_start+54>: rex.WXB
0x00000000004000b7 <_start+55>: rex.WXB
0x00000000004000b8 <_start+56>: rex.WXB
0x00000000004000b9 <_start+57>: rex.WXB
0x00000000004000ba <_start+58>: rex.WXB add    %bpl,(%r14)
End of assembler dump.
程序接收信号SIGSEGV,分段故障。
0x0000000000400085英寸\u开始()
(gdb)disas_启动
函数_start的汇编程序代码转储:
0x0000000000400080:jmp 0x4000a2
0x0000000000400082:pop%rsi
0x0000000000400083:xor%rax,%rax
0x0000000000400085:mov%al,0x7(%rsi)
0x0000000000400088:lea(%rsi),%rbx
0x000000000040008b:mov%rbx,0x8(%rsi)
0x000000000040008f:mov%rax,0xe(%rsi)
0x0000000000400093:mov$0xb,%al
0x0000000000400095:mov%rsi,%rbx
0x0000000000400098:lea 0x8(%rsi),%rcx
0x000000000040009c:lea 0xe(%rsi),%rdx
0x00000000004000a0:int$0x80
0x00000000004000a2:callq 0x400082
0x00000000004000a7:(坏)
0x00000000004000a8:(坏)
0x000000000004000A9:imul$0x414a6873,0x2f(%rsi),%ebp
0x00000000004000b0:rex.B
0x00000000004000b1:rex.B
0x00000000004000b2:rex.B
0x00000000004000b3:rex.B
0x00000000004000b4:rex.B
0x000000000004000b5:rex.WXB
0x00000000004000b6:rex.WXB
0x00000000004000b7:rex.WXB
0x00000000004000b8:rex.WXB
0x00000000004000b9:rex.WXB
0x00000000004000ba:rex.WXB添加%bpl,(%r14)
汇编程序转储结束。
我使用yasm和ld编译代码

yasm-f elf64 sclivro.asm

ld-o sclivro sclivro.o

我的操作系统是Debian 6.0 x64

我有一个英特尔赛扬处理器

我想知道为什么我会出现seg故障错误 并向我解释

谢谢你抽出时间

书中还告诉我要遵循以下步骤:

  • 通过对EAX自身进行xoring,用空值填充EAX

  • 通过在字符串的最后一个字节上复制AL来终止/bin/sh字符串 一串记住,AL是空的,因为我们在上一个- 令人震惊的指示。还必须计算从起点到终点的偏移量 将字符串添加到J占位符

  • 获取存储在ESI中的字符串开头的地址, 并将该值复制到EBX中

  • 复制EBX中存储的值,现在是 字符串,位于AAAA占位符上方。这是指向 要执行的二进制文件,这是Exeve所必需的。再说一次,你需要 计算偏移量

  • 使用 正确的偏移量

  • EAX不再需要用空值填充,因此复制 将execve系统调用(0x0b)插入AL

  • 用字符串的地址加载EBX

  • 加载存储在AAAA占位符中的值的地址,该占位符是 指向字符串的指针,指向ECX

  • 用KKK中的值地址加载EDX,这是一个指向null的指针

  • 执行int 0x80


  • 您发布的外壳代码是针对在32位x86处理器上运行的Linux的——从使用“int0x80”作为系统调用指令可以看出这一点


    不过,您已经在64位模式下编译了它,并尝试运行它。它在第一次访问内存时失败,因为您没有使用“/bin/sh”字符串(在
    RSI
    中)的实际地址,而只使用它显式截断的较低32位(因为您的代码显式声明了
    ESI
    )。后者无效,在64位模式下,堆栈位于地址空间的上端。

    您发布的外壳代码是针对在32位x86处理器上运行的Linux的,从使用“int 0x80”作为系统调用指令可以看出


    不过,您已经在64位模式下编译了它,并尝试运行它。它在第一次访问内存时失败,因为您没有使用“/bin/sh”字符串(在
    RSI
    中)的实际地址,而只使用它显式截断的较低32位(因为您的代码显式声明了
    ESI
    )。在64位模式下,后者无效,堆栈位于地址空间的上端。

    pop rsi指令正在获取字符串的地址


    当您尝试将nul字节放在/bin/sh之后时,您正在覆盖写保护区域。我不确定为什么这段代码应该是特殊的:它看起来就像是对execve()的模糊调用。

    pop rsi指令正在获取字符串的地址


    当您试图将nul字节放在/bin/sh之后时,您正在覆盖一个写保护区域。我不确定为什么这段代码应该是特殊的:它看起来就像是对execve()的模糊调用。

    嗯..我只是想按照书中所说的做。。。我编辑我的帖子,这样你就可以看到它告诉我要做什么。。感谢您回答btw=)是SEGFULT的直接原因是代码试图修改自身,但它位于只读内存区域。外壳代码通常放在可写的堆栈上(但是,现在它不是可执行的,所以这会带来另一个问题)。此外,64位模式具有RIP相对寻址,无需技巧。感谢您为我清除此项=)。我想知道为什么那本书给了我那个密码,也许是因为它太旧了。再次感谢您的时间。还有一件事。。。你知道这方面的好书吗?或者你也可以参考我的网站,最好是x64。不一定是关于外壳代码的,只是一些可以解释我这类事情的东西。。。我编辑我的帖子,这样你就可以看到它告诉我要做什么。。感谢您回答btw=)是SEGFULT的直接原因是代码试图修改