I'd like to force a coredump from a program (or see its memory at a specific time in some other way). There are a couple of problems though:
- I'm running it under wine (cannot run via winedbg, because开发者_运维问答 the application detects it)
- The application uses exceptions / SEH / other handlers, which capture non-standard events
- Even attaching strace stops the program from working
- I'd like to poke around, so there are no specific areas that I could print
- Well... I don't have the source
I've tried changing the code to both:
xor eax, eax
call eax
and some random stuff which wasn't a real instruction - both time SEH kicked in and rescued the application.
How can I get the information? I need the memory image from a specific time and can patch the exact place where it occurs.
Since you have access to the source code of wine, I'd suggest just altering the wine SEH code, and/or the implementation of the IsDebuggerPresent()
function.
Another option would be to modify the application to suspend itself by raising a SIGSTOP signal. Windows applications in Wine can still access linux APIs by invoking int $0x80
, so you could inject some code like the following:
mov %eax, $20 ;; sys_getpid
int $0x80
mov %ebx, %eax ;; load pid parameter
mov %eax, $37 ;; sys_kill
mov %ecx, $19 ;; sig = SIGSTOP
int $0x80 ;; after executing this instruction, execution will halt
Then you can mmap
ranges from /proc/(pid)/mem
to read out the process's memory, or even attach gdb
and use its generate-core-file
command. Alternately, you could change this to simply raise SIGQUIT
or something to trigger a core dump right then and there (assuming wine hasn't installed a SIGQUIT
handler - but with the right syscalls that can be overcome as well).
Try doing it like MSVC. They call UnhandledExceptionFilter directly which bypasses application's exception handlers. From gs_report.c (some #ifdefs skipped):
/* Make sure any filter already in place is deleted. */
SetUnhandledExceptionFilter(NULL);
UnhandledExceptionFilter((EXCEPTION_POINTERS *)&GS_ExceptionPointers);
TerminateProcess(GetCurrentProcess(), STATUS_STACK_BUFFER_OVERRUN);
Another possibility is to put an empty handler at the head of the list. Something like this:
#include <stdio.h>
#include <excpt.h>
#include <intrin.h>
int main()
{
__try
{
__writefsdword(0, -1); // put chain end marker (-1) in fs:0
*(int*)9 = 0; // trigger the exception
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
printf("Exception!\n"); // this does not appear
}
}
Edit: sorry, I didn't notice "don't have the source" until now. But if you can patch the code, you can probably add "mov fs:[0], -1" to it.
精彩评论