Vulnerability Development mailing list archives
Re: GetPC code (was: Shellcode from ASCII)
From: noir <noir () gsu linux org tr>
Date: Thu, 20 Nov 2003 00:12:15 +0200 (EET)
hey Aaron, thanks for enlighting us about the internals of all this FPU stuff. highly appreciated. i did actually take it from the FPU exception handler and to be honest never looked into the intel manuals for what it really does ;> i can think of yet another getPC technique for some Unixes (at least on Solaris x86 and sparc), i will leave it as a challenge to the list. hint: involves a kernel service ;) best luck, - noir On Tue, 18 Nov 2003, Aaron Adams wrote:
Hey Noir, I've been looking into FPU stuff a bit lately and decided to look into what you described a little deeper. I decided I'd give you and the list the details of what the deal is with this. Basically, you can do a GetPC procedure without simulating any exception. In fact, the data stored by fnstenv isn't influenced by the exception nor is it actually an exception record. fstenv/fnstenv is commonly used by FPU exception handler code though, to analyze the state of the FPU environment that an exception occured within. Although you are triggering an exception, all of the exception bits in the control word are masked by default when the environment is initialized. As such, if an exception occurs the only result will be the appropriate exception flag being set within the status word. So, keeping this in mind we'll see what actually allows the GetPC to be possible. Basically, the state of the FPU environment, following the first floating point instruction, is always maintained. The fnstenv/fstenv instructions can be used to save the state of the environment to the location pointed to by it's operand. So the only requirement to actually using fstenv/fnstenv is to have previously executed an FP instruction. The structure stored by fnstenv is defined as user_fpregs_struct in sys/user.h and is saved as so: 0 | Control Word 4 | Status Word 8 | Tag Word 12 | FPU Instruction Pointer Offset ... ... As you explained, the FPU Instruction Pointer will be the address of the previously executed FP instruction. And as seen above it's located at offset 12 within the structure. Because we can specify the location that fnstenv stores the structure I came up with something that can kind of simplify obtaining the PC. It can be seen in the following code, which is the smallest way I could come up with to do a GetPC procedure. fldz fnstenv -12(%esp) popl %ecx addb 10, %cl nop So, when this is executed you'll have the current pc in ecx when you hit nop. It's pretty similar to what you did, but hopefully it clarifies some stuff. ttyl. Aaron Adams On Fri, 27 Jun 2003, noir wrote:"""First thoughts on the second challenge: You can't use any of the call opcodes, but you might be able to setup a quick exception handler in the known mapped space. Cause a fault, and then find the address of your fault causing instruction in the structure that's passed. (Again I'm talking NT).I'm not sure this could be done (same problem) but, keep this in mind anyway :- ) [hint] gera """ i have spend good 20 minutes on this, i don't have the solution yet due to lack of time but i thought this might be interesting for the list. basicly, i'm simulating a floating point exception (division by zero) and then grabbing the EIP(pc) from the exception record. PC is the location of the fdivs instruction since that instruction created the exception condition so we add 11 on top to make %eax point to the nop instruction. (ATT syntax) xor %eax, %eax push %eax fdivs (%esp) fnstenv (%esp) mov 0xc(%esp), %eax add $0xd, %eax nop - noir sup mate ? ;)
Current thread:
- Re: GetPC code (was: Shellcode from ASCII) Aaron Adams (Nov 18)
- Re: GetPC code (was: Shellcode from ASCII) noir (Nov 19)