On Sat, 20 Nov 1999 00:43:26 -0000 Mnemonix <mnemonixat_private> wrote: > This is exploitable. On both Windows NT4 and Windows 2000 the payload can be > found at the ESP - but there is a difference between the two OSs. > NT 4 seems to do a tolower() on the string turning "AAAA" to "aaaa" where as > Windows 2000 preserves the case. Both OS's have the return address > over-written so all you have do do is find an instruction in the memory > space that does a JMP ESP - there are quite a few floating around the place. The problem is getting the return address pointing to something usefull. Due to the nature of the code that overflows the buffer, we can only put lowercase letters from 'a' to 'z' in the buffer. (I am talking about NT) This means that the return address will point to some memory area between 61616161 and 7A7A7A7A. On my machine (NT4, SP5) all of this area was empty/nonpaged or whatever the proper word is. Even if you had some way to jump back to the stack, your shell code should be using only 'a'-'z' letters. This is hard. Also, you can not put more then 200 bytes of code in the buffer. There is a simple solution to this problem. Before processing the RTF file, RICHED32.DLL reads all of it into the memory. The file is stored in a buffer in the heap. This buffer is raw, so if you put some executable code in the RTF file, it will be copied to the heap unchanged (we can even use NULLs - wow!). How do you use this? Remeber how RICHED32.DLL uses the buffer that we overflow? It copies a string from the RTF file to the buffer. Guess what, the string is read from the buffer in the heap I was talking about. There is a source pointer that is incremented while copying. After the copying finishes (because a non 'a'-'z' character is reached), this pointer points to the first offending character, in the heap. After you smash the stack this pointer is located at esp+130 (I am not sure this is the exact offset, but it's close). If you have a file like this: {\rtf\AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOO\PPPPPPPPPP} The first string will be copied into the buffer and will oveflow it. The return address will become 'kkkk'. See the backslash between the O and the P ? The function will stop copying when it reaches the backslash. The pointer at esp+130 will point to the backslash after you smash the stack. You can put some shell code instead of the Ps. The size is practicly unlimited - I tried 40KB and it worked fine. You can also use NULLs. How do you get the execution flow to jump to the shell code? Imagine that you have a single RET instruction at address 61626364 (this is 'abcd'. You can put it instead of the 'kkkk' and make the execution flow jump to the RET. What will happen next? The RET instruction will decrement the ESP and read the next return address. You can put 'abcd' there too. You can fill the stack will 'abcd', causing the same RET instruction to be called many times. If you put 50 'abcd'-s in your string, the next dword on the stack after your last 'abcd' will be the pointer at esp-50. The last RET instruction will read the address from there and the execution flow will jump to the heap. When I tried this, I found out that code CAN be executed on the heap, although the heap descriptor has no execute permissions. I don't know why. If somebody can confirm this it would be great. This way, you can execute the code that you put after the backslash. The only catch is that you need a reachable RET instruction. On my system (NT4, SP5) there were no such instructions. Can somebody verify this with a 9x and 2000 machine? Mnemonix wrote that the shell code is not lowercased on Win2K. Are there any other restrictions? Can you use characters > 128 ? What about Win9x? Are there any DLLs loaded in the 6161616-7A7A7A7A range on there machines? Solar Eclipse solareclipseat_private www.solareclipse.org Just find me a single RET instruction and I will rule the world!
This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 15:13:51 PDT