我正在尝试学习shell代码,并且在Ubuntu框中不断出现分段错误。
/*shellcodetest.c*/
char code[]="\xeb\x19\x31\xc0\x31\xdb\x31\xd2\x31\xc9\xb0\x04\xb3\x01"\
"\x59\xb2\x05\xcd\x80\x31\xc0\xb0\x01\x31\xdb\xcd\x80\xe8"\
"\xe2\xff\xff\xff\x68\x65\x6c\x6c\x6f\xe8\xd8\xff\xff\xff"\
"\x68\x65\x6c\x6c\x6f\xe8\xce\xff\xff\xff\x68\x65\x6c\x6c"\
"\x6f\xe8\xc4\xff\xff\xff\x68\x65\x6c\x6c\x6f\xe8\xba\xff"\
"\xff\xff\x68\x65\x6c\x6c\x6f";
int main(int argc, char **argv)
{
int (*func)();
func = (int (*)()) code;
(int)(*func)();
}
我不明白为什么会失败。我在想也许是一个空指针。 如果你有任何想法,我可以跟进,这将是伟大的。
答案 0 :(得分:3)
好的,让我们现在检查你的代码。
char code[]="\xeb\x19\x31\xc0\x31\xdb\x31\xd2\x31\xc9\xb0\x04\xb3\x01"\
上面一行创建了一个名为code
的全局字符数组,并使用一堆十六进制进行了初始化。 char[]
的内存将在data-segment
中分配。
int (*func)();
上面的行声明了pointer-to-a-function
,它不带任何参数并返回int
。此内存将在stack
中分配,但此变量应指向存储code
的内存位置
func = (int (*)()) code;
以上几行投射code
(global-character-array
)并使func
(pointer-to-a-function
)指向它!此操作是未定义的行为,因为假定指向stack
的{{1}}变量现在指向code-segment
。
即使作业成功(可能是因为奇迹),然后在下一行中取消它们肯定不会起作用!
有关如何在data-segment
,heap
和stack
段中分配变量的详细信息,请参阅this
答案 1 :(得分:2)
该程序调用大量未定义的行为,因此,根据标准,任何事情都可能发生。对于像这样的程序,分段错误是完全可以接受的结果。
答案 2 :(得分:1)
您可以直接定义:
int (*func)() = (int (*)()) "\xeb\x19\x31\xc0..."
它会起作用。
但它仍然是未定义的行为。
答案 3 :(得分:1)
不是答案,但可能有所帮助。我在64位Ubuntu上拆解它。在32位上它会有所不同。
(gdb) disassemble /mr func,0x60108A
Dump of assembler code from 0x601040 to 0x60108a:
0x0000000000601040 <code+0>: eb 19 jmp 0x60105b <code+27>
0x0000000000601042 <code+2>: 31 c0 xor %eax,%eax
0x0000000000601044 <code+4>: 31 db xor %ebx,%ebx
0x0000000000601046 <code+6>: 31 d2 xor %edx,%edx
0x0000000000601048 <code+8>: 31 c9 xor %ecx,%ecx
0x000000000060104a <code+10>: b0 04 mov $0x4,%al
0x000000000060104c <code+12>: b3 01 mov $0x1,%bl
0x000000000060104e <code+14>: 59 pop %rcx
0x000000000060104f <code+15>: b2 05 mov $0x5,%dl
0x0000000000601051 <code+17>: cd 80 int $0x80
0x0000000000601053 <code+19>: 31 c0 xor %eax,%eax
0x0000000000601055 <code+21>: b0 01 mov $0x1,%al
0x0000000000601057 <code+23>: 31 db xor %ebx,%ebx
0x0000000000601059 <code+25>: cd 80 int $0x80
0x000000000060105b <code+27>: e8 e2 ff ff ff callq 0x601042 <code+2>
0x0000000000601060 <code+32>: 68 65 6c 6c 6f pushq $0x6f6c6c65
0x0000000000601065 <code+37>: e8 d8 ff ff ff callq 0x601042 <code+2>
0x000000000060106a <code+42>: 68 65 6c 6c 6f pushq $0x6f6c6c65
0x000000000060106f <code+47>: e8 ce ff ff ff callq 0x601042 <code+2>
0x0000000000601074 <code+52>: 68 65 6c 6c 6f pushq $0x6f6c6c65
0x0000000000601079 <code+57>: e8 c4 ff ff ff callq 0x601042 <code+2>
0x000000000060107e <code+62>: 68 65 6c 6c 6f pushq $0x6f6c6c65
0x0000000000601083 <code+67>: e8 ba ff ff ff callq 0x601042 <code+2>
0x0000000000601088 <code+72>: 68 65 6c 6c 6f pushq $0x6f6c6c65
第一行的SIGSEGV失败了:
(gdb) display /3i $pc
1: x/3i $pc
=> 0x601040 <code>: jmp 0x60105b <code+27>
0x601042 <code+2>: xor %eax,%eax
0x601044 <code+4>: xor %ebx,%ebx
可能因为跳转到数据段而失败了吗?