char sh[] = "\x31\xc0\x31\xdb\x31\xc9\x31\xd2\x52\x68\x6e\x2f\x73\x68"
"\x68\x2f\x2f\x62\x69\x89\xe3\x52\x53\x89\xe1\xb0\x0b\xcd\x80";
为什么程序员对这个字符串使用十六进制编码?例如,为什么使用\x31
第一个字符而不是1
?
我通过反汇编程序运行了您的代码。该数组似乎包含一些 x86 linux 的 shellcode:
804a014: 31 c0 xor %eax,%eax #set registers to zero
804a016: 31 db xor %ebx,%ebx
804a018: 31 c9 xor %ecx,%ecx
804a01a: 31 d2 xor %edx,%edx
804a01c: 52 push %edx #push a null word
804a01d: 68 6e 2f 73 68 push $0x68732f6e #push "/bin/sh"
804a022: 68 2f 2f 62 69 push $0x69622f2f
804a027: 89 e3 mov %esp,%ebx
804a029: 52 push %edx #push another null word
804a02a: 53 push %ebx #push pointer to string
804a02b: 89 e1 mov %esp,%ecx
804a02d: b0 0b mov $0xb,%al #system call 11: execve
804a02f: cd 80 int $0x80 #call the system
显然,它/bin/sh
在内存中组装字符串,然后尝试调用该程序。
虽然sh
是char
元素数组,但也可以认为是字节数组。好吧,假设char
它通常是 8 位宽。
因此,如果此变量包含代码,则将其表示为字节数组而不是文本数组会更清楚。例如,可能存在不容易表示为可打印字符的元素。由于内容将由编译器或汇编器生成,因此它最初采用二进制代码块的形式。将其转换为您提供的十六进制表示是最简单和最清晰的。
它是十六进制转义序列。
C11 (n1570),第 6.4.4.4 节字符常量
反斜杠后面的十六进制数字和
x
十六进制转义序列中的字母被视为整数字符常量的单个字符或宽字符常量的单个宽字符构造的一部分。如此形成的十六进制整数的数值指定所需字符或宽字符的值。
要执行它,您可以使用函数指针强制转换。
void (*shell)();
shell = (void(*)()) (&sh);
shell();