我正在尝试学习项目的shellcode 在comp科学
但我写它有点问题 我正在读一本名为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错误错误 并向我解释。
感谢您的时间。
这本书告诉我按照以下步骤操作:
通过将EAX与自身进行编辑来使用空值填充EAX。
通过在AL的最后一个字节上复制AL来终止我们的/ bin / sh字符串 串。请记住,AL是空的,因为我们在之前的任务中排除了EAX ous指示。您还必须从头开始计算偏移量 J占位符的字符串。
获取存储在ESI中的字符串开头的地址, 并将该值复制到EBX中。
复制存储在EBX中的值,现在是开头的地址 字符串,超过AAAA占位符。这是指向的参数指针 要执行的二进制文件,这是execve所必需的。再一次,你需要 计算偏移量。
使用以下方法将仍存储在EAX中的空值复制到KKKK占位符上 正确的抵消。
EAX不再需要填充空值,因此请复制我们的值 execve系统调用(0x0b)到AL。
使用我们的字符串地址加载EBX。
加载存储在AAAA占位符中的值的地址,即a 指向我们的字符串的指针,进入ECX。
使用KKKK中的值的地址加载EDX,指向null的指针。
执行int 0x80。
答案 0 :(得分:3)
您发布的shellcode适用于在32位x86处理器上运行的Linux - 从使用“int 0x80”作为系统调用指令可以看出。
你已经在64位模式下编译了它,并尝试运行它。在第一次内存访问时失败,因为您没有使用“/ bin / sh”字符串的真实地址(位于RSI
中),而只是显式截断的低32位它(因为你的代码明确声明ESI
)。后者在64位模式下无效,您的堆栈位于地址空间的上端0xffff....(64bit addr)
。
答案 1 :(得分:1)
pop rsi指令获取字符串的地址。
当您尝试在/ bin / sh之后放置nul字节时,您正在覆盖写保护区域。我不确定为什么这段代码应该是特殊的:它看起来像是对execve()的混淆调用。