I changed my test example to put an unmapped address directly into the
EIP and the kill call does seem to return in that case, and results in
undefined behaviour as you mentioned.
Because of this, and because I really want to know the stored EIP has
been destroyed as it is being overwritten, I think I'm going to take
the approach of recording the location of the stored EIP by
instrumenting calls and then checking any writes to memory against
this. This approach isn't going to be too much extra effort as I'm
already checking writes to memory for different properties.
On Mon, May 18, 2009 at 7:42 PM, nnp <version5@...> wrote:
> 1) Sorry for the confusion. I meant a signal handler registered with
> Pin through PIN_AddContextChangeFunction
>
> 2) No, it doesn't return.
>
> On Mon, May 18, 2009 at 4:16 PM, Lueck, Gregory M
> <gregory.m.lueck@...> wrote:
>>
>>
>> Two observations:
>>
>>>My signal handler is called, it accesses the registers and does its
>>>analysis
>>
>> When you say "signal handler", what do you mean? Your tool should not call
>> sigaction() or signal() directly. Doing so will interfere with Pin's
>> emulation of application signals and will probably break if you run your
>> tool on an application that expects to handle signals. Instead, your tool
>> should call Pin API's such as PIN_AddContextChangeFunction() or
>> PIN_AddSignalInterceptFunction().
>>
>>> cout << "[!] Program attempted to read invalid memory address:
>>>" << addr;
>>> kill(PIN_GetTid(), SIGSEGV);
>>
>> You should check to see if the kill() call returns. If so, your
>> insFetchFunc() will return with an undefiled value. This could be why your
>> tool appears to work.
>>
>> -- Greg
>>
>>>-----Original Message-----
>>>From: pinheads@yahoogroups.com [mailto:pinheads@yahoogroups.com] On Behalf
>>>Of nnp
>>>Sent: Monday, May 18, 2009 10:21 AM
>>>To: pinheads@yahoogroups.com
>>>Subject: Re: [pinheads] Changing the stored EIP pointer kills Pin
>>>
>>>This seems to work as the instruction fetching routine:
>>>
>>>(I'm on Linux in case that makes a difference)
>>>
>>>size_t
>>>insFetchFunc(void *buf, ADDRINT addr, size_t size, VOID *v)
>>>{
>>> size_t copied = PIN_SafeCopy(buf, (VOID*)addr, size);
>>>
>>> if (copied <= 0) {
>>> cout << "[!] Program attempted to read invalid memory address:
>>>" << addr;
>>> kill(PIN_GetTid(), SIGSEGV);
>>> } else {
>>> return copied;
>>> }
>>>}
>>>
>>>My signal handler is called, it accesses the registers and does its
>>>analysis, and when it's finished the signal is delivered to the app
>>>and it terminates with a segmentation fault.
>>>
>>>I guess whether this introduces a race condition or not depends on how
>>>Pin works internally. It would appear my signal handler is superceding
>>>whatever function calls the instruction fetching routine before it
>>>tries to access the bad address and dies. If this is deterministic
>>>then everything would seem OK, but if it is actually a race then I'll
>>>have to take that into account.
>>>
>>>On Mon, May 18, 2009 at 2:26 PM, Lueck, Gregory M
>>><gregory.m.lueck@...> wrote:
>>>>
>>>>
>>>> I don't think it will work to send the signal. When you do
>>>"kill(getpid(),
>>>> x)", Pin receives the signal and queues it up waiting for the next
>>>> "safe point", where a signal can be delivered. The kill() call then
>>>returns
>>>> to your tool. Your tool will then return from the instruction-fetch
>>>> routine, telling Pin there are no instructions to fetch. Pin will then
>>>> trigger the same assertion you saw before. Since the assertion
>>>terminates
>>>> Pin, it will never get to a "safe point" where the signal can be
>>>delivered.
>>>> Thus, your tool's signal handler function will never be called.
>>>>
>>>>
>>>>
>>>> -- Greg
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> ________________________________
>>>>
>>>> From: pinheads@yahoogroups.com [mailto:pinheads@yahoogroups.com] On
>>>Behalf
>>>> Of nnp
>>>> Sent: Monday, May 18, 2009 8:45 AM
>>>> To: pinheads@yahoogroups.com
>>>> Subject: Re: [pinheads] Changing the stored EIP pointer kills Pin
>>>>
>>>>
>>>>
>>>>
>>>> Wow, you weren't lying when you said 'round-about' ;-)
>>>>
>>>> What about just sending the program a SEGV signal via kill in the
>>>> instruction fetcher and then using the context passed to the signal
>>>> handler? The only problem that I could see there is, if between the
>>>> kill and the signal handler then registers somehow get messed with and
>>>> don't accurately reflect what their values would be at the time of the
>>>> crash in an uninstrumented run.... but I can't see how that might
>>>> happen.
>>>>
>>>> nnp
>>>>
>>>> On Mon, May 18, 2009 at 1:10 PM, Lueck, Gregory M
>>>> <gregory.m.lueck@...> wrote:
>>>>>
>>>>>
>>>>>>Thanks for the response. Is there a way to access the register values
>>>>>>from a Pin_AddFetchFunction call back?
>>>>>
>>>>> No. The instruction-fetcher does not know about the register state
>>>(aside
>>>>> from the PC). If you want to read or modify the registers when Pin
>>>fetches
>>>>> from an illegal address, there is a very round-about way you can achieve
>>>>> this.
>>>>>
>>>>> 1) Change your instruction-fetch routine to return a legal, but unusual
>>>>> instruction when it attempts to fetch from an invalid address. For
>>>>> example,
>>>>> you can return the encoding for a UD2 instruction.
>>>>>
>>>>> 2) Set up an instrumentation routine that looks for UD2 instructions.
>>>When
>>>>> you see one, insert an analysis call before the UD2. Pass IARG_CONTEXT
>>>to
>>>>> this analysis call.
>>>>>
>>>>> 3) In your analysis call, you will have a "CONTEXT *" parameter. You can
>>>>> read the registers here, or use PIN_ExecuteAt() to jump to a new
>>>register
>>>>> state.
>>>>>
>>>>>> when I detect such an error is there a graceful way to terminate
>>>>>>the program under test?
>>>>>
>>>>> You can call exit(x) to terminate the process.
>>>>>
>>>>> -- Greg
>>>>>
>>>>>>-----Original Message-----
>>>>>>From: pinheads@yahoogroups.com [mailto:pinheads@yahoogroups.com] On
>>>Behalf
>>>>>>Of nnp
>>>>>>Sent: Monday, May 18, 2009 7:07 AM
>>>>>>To: pinheads@yahoogroups.com
>>>>>>Subject: Re: [pinheads] Changing the stored EIP pointer kills Pin
>>>>>>
>>>>>>Hi Greg,
>>>>>>
>>>>>>Thanks for the response. Is there a way to access the register values
>>>>>>from a Pin_AddFetchFunction call back? For instance, my signal handler
>>>>>>call back uses PIN_GetContextReg on the 'from' context passed in.
>>>>>>Also, when I detect such an error is there a graceful way to terminate
>>>>>>the program under test? (Or should I just attempt to kill 2 birds with
>>>>>>one stone and send the app a kill signal when detecting such an issue.
>>>>>>If this is the recommended approach, does Pin have some sort of hook
>>>>>>to insert a signal artificially or should I just do it the old
>>>>>>fashioned way)
>>>>>>
>>>>>>Cheers,
>>>>>>nnp
>>>>>>
>>>>>>On Mon, May 18, 2009 at 12:17 AM, Lueck, Gregory M
>>>>>><gregory.m.lueck@...> wrote:
>>>>>>>
>>>>>>>
>>>>>>> This is actually a bug we will be fixing soon. If an application
>>>tries
>>>>>>to
>>>>>>> jump to an unmapped address, Pin tries to fetch instructions at that
>>>>>>address
>>>>>>> and causes a crash. When our fix is complete, Pin will notice that
>>>the
>>>>>>> address is unmapped and emulate a SEGV into the application. This is
>>>>>>> the
>>>>>>> same behavior the application would have if it were run natively.
>>>>>> However,
>>>>>>> this fix isn't ready yet.
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> I think you can use PIN_AddFetchFunction() to avoid the problem,
>>>though.
>>>>>>> Actually, this may be a better solution for you anyways. This API
>>>>>>allows
>>>>>>> you to override Pin's instruction-fetcher with your own function.
>>> Your
>>>>>>> function can use PIN_SafeCopy() to attempt to read the instruction
>>>>>>memory.
>>>>>>> If PIN_SafeCopy() fails, you know that the application has gone down
>>>a
>>>>>>> wrong path and is attempting to fetch instructions from an illegal
>>>>>>address.
>>>>>>> You can then print an error, etc.
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> -- Greg
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> ________________________________
>>>>>>>
>>>>>>> From: pinheads@yahoogroups.com [mailto:pinheads@yahoogroups.com] On
>>>>>>Behalf
>>>>>>> Of nnp
>>>>>>> Sent: Friday, May 15, 2009 3:10 PM
>>>>>>> To: pinheads@yahoogroups.com
>>>>>>> Subject: [pinheads] Changing the stored EIP pointer kills Pin
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> So here's something I didn't expect. If you overwrite EBP+4 (the
>>>>>>> stored EIP) with something else, Pin seems to attempt to
>>>>>>> disassemble/instrument the code at this address. It seems if you point
>>>>>>> it at a certain region of memory that isn't actually code, and doesn't
>>>>>>> contain anything Pin would consider to end a basic block, it will
>>>>>>> continue to do this until it gets killed by the OS (presumably for
>>>>>>> attempting to operate on an unmapped address).
>>>>>>>
>>>>>>> For instance, the following program causes Pin to die (ignore any
>>>>>>> extra includes and the weird naming of things, I ripped it out of
>>>>>>> something I was testing). I'm replacing the stored EIP with a pointer
>>>>>>> to the heap. Running this without Pin causes a segmentation fault.
>>>>>>>
>>>>>>> #include <stdlib.h>
>>>>>>> #include <stdio.h>
>>>>>>> #include <string.h>
>>>>>>> #include <fcntl.h>
>>>>>>>
>>>>>>> void smashySmashy(char *userInput)
>>>>>>> {
>>>>>>> asm("movl %0, 4(%%ebp)\n\t"
>>>>>>> :
>>>>>>> : "r"(userInput));
>>>>>>>
>>>>>>> }
>>>>>>>
>>>>>>> int main(int argc, char *argv[])
>>>>>>> {
>>>>>>> char *heapArr = NULL;
>>>>>>> heapArr = malloc(256*sizeof(char));
>>>>>>>
>>>>>>> smashySmashy(heapArr);
>>>>>>>
>>>>>>> return 0;
>>>>>>> }
>>>>>>>
>>>>>>> This is what happens:
>>>>>>>
>>>>>>> nnp@ubuntudeux:~/pin-2.6-25945-gcc.4.0.0-ia32_intel64-
>>>>>>linux/source/tools/xgen$
>>>>>>> time ~/pin-2.6-25945-gcc.4.0.0-ia32_intel64-linux/ia32/bin/pinbin -t
>>>>>>> ../SimpleExamples/obj-ia32/inscount2_mt.so --
>>>>>>> ./test_programs/kill_pin
>>>>>>> A:Source/pin/vm/jit_region.cpp:FetchRegion:1419: No valid instructions
>>>>>>> at 0x806b000: (region not accessible)
>>>>>>>
>>>>>>########################################################################
>>>###
>>>>>>#####
>>>>>>> ## STACK TRACE
>>>>>>>
>>>>>>########################################################################
>>>###
>>>>>>#####
>>>>>>> addr2line -C -f -e
>>>>>>> "/home/nnp/pin-2.6-25945-gcc.4.0.0-ia32_intel64-linux/ia32/bin/pinbin"
>>>>>>> 0x10f280d 0x10f310b 0x12b1b06 0x12c251e 0x1268d31 0x126999a 0x1323a78
>>>>>>> 0x13009f9 0x1306f9d 0x1307ac4 0x139ce32 0x0
>>>>>>> LEVEL_BASE::MESSAGE_TYPE::DumpTrace()
>>>>>>> ??:0
>>>>>>> LEVEL_BASE::MESSAGE_TYPE::Message(std::string const&, bool,
>>>>>>> PIN_ERRTYPE, int, ...)
>>>>>>> ??:0
>>>>>>> LEVEL_VM::REGION::FetchRegion()
>>>>>>> ??:0
>>>>>>> LEVEL_VM::REGION::MakeApplication(LEVEL_VM::SVT_FACTORY const&)
>>>>>>> ??:0
>>>>>>> LEVEL_VM::JIT::CreateContext(LEVEL_VM::SCT_STRUCT_BASE**,
>>>>>>LEVEL_VM::PCTXT**)
>>>>>>> ??:0
>>>>>>> LEVEL_VM::JIT::Compile(LEVEL_CORE::ADDR<1>,
>>>>>>> LEVEL_VM::SCT_STRUCT_BASE*, LEVEL_VM::PCTXT const*)
>>>>>>> ??:0
>>>>>>> LEVEL_VM::VMSVC_Xfer(LEVEL_VM::SCT_STRUCT_BASE*, LEVEL_VM::PCTXT*,
>>>>>>> LEVEL_VM::XFER_TYPE)
>>>>>>> ??:0
>>>>>>> LEVEL_VM::VM::Handle_VMSVC_XFER(LEVEL_VM::SCT_STRUCT_BASE*,
>>>>>>> LEVEL_VM::PCTXT*, LEVEL_VM::VMSVC_ARGS*)
>>>>>>> ??:0
>>>>>>> LEVEL_VM::VM::Dispatch(LEVEL_VM::VMSVC_ARGS*, LEVEL_VM::PCTXT*)
>>>>>>> ??:0
>>>>>>> VmDispatch
>>>>>>> ??:0
>>>>>>> VmEnter
>>>>>>> ??:0
>>>>>>> ??
>>>>>>> ??:0
>>>>>>> Detach Service Count: 2210
>>>>>>> Pin 2.6
>>>>>>> Copyright (c) 2003-2009, Intel Corporation
>>>>>>> @CHARM-VERSION: $Id: version.cpp 25912 2009-03-18 10:31:41Z tevi $
>>>>>>> @CHARM-BUILDER: BUILDER
>>>>>>> @CHARM-COMPILER: gcc 4.0.0
>>>>>>> @CHARM-TARGET: ia32
>>>>>>> @CHARM-CFLAGS: __OPTIMIZE__=1 __NO_INLINE__=__NO_INLINE__
>>>>>>> Aborted
>>>>>>>
>>>>>>> -----------------------------------------
>>>>>>>
>>>>>>> This is a real problem for me because I want to analyse programs that
>>>>>>> have this exact behaviour. i.e. ones that have some sort of
>>>>>>> vulnerability that results in the stored EIP being overwritten.
>>>>>>> Obviously I can't do this if Pin can't survive the problem. Is there
>>>>>>> anything I can do to avoid this? Or is there anything you guys can do
>>>>>>> to patch the behaviour? As there's no source available I've no idea
>>>>>>> what is actually going on in Pin that leads to this problem but if you
>>>>>>> guys could enlighten me, I'd appreciate it.
>>>>>>>
>>>>>>> Cheers,
>>>>>>> nnp
>>>>>>>
>>>>>>> --
>>>>>>> http://www.unprotectedhex.com
>>>>>>> http://www.smashthestack.org
>>>>>>>
>>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>--
>>>>>>http://www.unprotectedhex.com
>>>>>>http://www.smashthestack.org
>>>>>>
>>>>>>
>>>>>>------------------------------------
>>>>>>
>>>>>>Yahoo! Groups Links
>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>
>>>> --
>>>> http://www.unprotectedhex.com
>>>> http://www.smashthestack.org
>>>>
>>>>
>>>
>>>
>>>
>>>--
>>>http://www.unprotectedhex.com
>>>http://www.smashthestack.org
>>>
>>>
>>>------------------------------------
>>>
>>>Yahoo! Groups Links
>>>
>>>
>>>
>>
>
>
>
> --
> http://www.unprotectedhex.com
> http://www.smashthestack.org
>