繁体   English   中英

谁能帮助我理解这个asm代码(很简单)

[英]Can anyone help me understand this asm code (It's short)

我正在尝试在comp科学中学习shellcode

但我写的有点问题我正在读一本名为The Shellcoder's Handbook的书,它给了我一个不能正常工作的代码这是代码:

    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'

简单地说这应该产生一个shell ...但它不会工作,当我使用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.

我使用yasm和ld编译代码

yasm -f elf64 sclivro.asm

ld -o sclivro sclivro.o

我的操作系统是Debian 6.0 x64

我有英特尔赛扬处理器

我想知道为什么我得到一个seg错误并向我解释。

谢谢你的时间。

这本书告诉我按照以下步骤操作:

  1. 通过将EAX与其自身进行编译来使用空值填充EAX。

  2. 通过在字符串的最后一个字节上复制AL来终止我们的/ bin / sh字符串。 请记住,AL为空,因为我们在之前的指令中排除了EAX。 您还必须计算从字符串开头到J占位符的偏移量。

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

  4. 将存储在EBX中的值(现在是字符串开头的地址)复制到AAAA占位符上。 这是指向要执行的二进制文件的参数指针,这是execve所必需的。 同样,您需要计算偏移量。

  5. 使用正确的偏移量将仍存储在EAX中的空值复制到KKKK占位符上。

  6. EAX不再需要填充空值,因此将execve系统调用(0x0b)的值复制到AL中。

  7. 使用字符串的地址加载EBX。

  8. 将存储在AAAA占位符中的值的地址(这是指向我们的字符串的指针)加载到ECX中。

  9. 使用KKKK中的值的地址加载EDX,指向null的指针。

  10. 执行int 0x80。

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM