How can I manually increment the instruction pointer from the context?

First, let me say that I am doing here that most people have no legal basis for EVERYONE. 99.99 ...% of all segfaults should lead to a certain end and fun to process them in any, but the simplest situations, will lead to really bad behavior and a damaged stack. If you came here to solve segfault, go to the following link: https://www.securecoding.cert.org/confluence/display/seccode/SIG35-C.+Do+not+return+from+a+computational+exception + signal + handler

However, I am working on the implementation of an environment from an external standard, which has defined the behavior for returning from the signal processor of the computational logic as a missing command. I understand that this is bad, but I do not control it; I cannot just mislead the definition, as for an embedded system with other program elements already written that depend on a certain behavior (they are often security critical and should be able to gracefully exit even when they do ridiculous or terrible things in I don’t have a source further, so I can’t just fix segfault and any existing bad segfault / crash behavior is really desirable, because I imitate the behavior of an existing system).

While the system itself should run on PowerPC with a fixed instruction length, our development takes place in a parallel x86 / x64 environment where instructions do not have a fixed length. I know that the following code works, albeit badly for x86:

#define _GNU_SOURCE #include <signal.h> #include <stdio.h> #include <ucontext.h> #include <sys/mman.h> #define CRASHME *((int*)NULL) = 0 //for x86 #ifdef REG_EIP #define INCREMENT(x) (x)->uc_mcontext.gregs[REG_EIP]++ //for x64 #elif defined REG_RIP #define INCREMENT(x) (x)->uc_mcontext.gregs[REG_RIP]++ //for PPC arch #elif defined PT_NIP #define INCREMENT(x) (x)->uc_mcontext.uc_regs->gregs[PT_NIP]+=4 #endif static void handler(int sig, siginfo_t *si, void *vcontext) { ucontext_t *context = (ucontext_t *)vcontext; INCREMENT(context); } void crashme_function(void) { printf("entered new context, segfaulting!\n"); CRASHME; printf("SEGFAULT handled!\n"); } int main (int argc, char* args) { struct sigaction sa; printf("Printing a thing\n"); sa.sa_flags = SA_SIGINFO; sigemptyset(&sa.sa_mask); sa.sa_sigaction = handler; sigaction(SIGSEGV, &sa, NULL); printf("Entering new context...\n"); crashme_function(); printf("context exited successfully\n"); return(0); } 

The result of executing this code will advance the instruction pointer to 1 in an Intel-based architecture running the Linux 3.11.X kernel, and it will eventually go beyond the instruction. I know that this probably will not work in all instructions. In fact, when executed in my test environment, the handler is entered 6 times (for 6 bytes of instruction), and then execution continues after CRASHME.

It seems that the trivial task is simply to direct the given pointer to the next command, given the existing instruction; the processor does this every cycle. Other settings say: “Look at the instruction table and create your own” or “execute the disassembler”. They are neither necessary nor necessary for the task, since both of them were already made by others and placed (almost?) Exclusively in places of the Internet, where my working computer cannot go, and to which I do not believe, to send my home PC. But where can I find such tables or libraries to perform only the calculation of commands, and without looking at the site on which I already know, I can’t access?

+6
source share
2 answers

Linux kernel sources have an X86 opcode card encoding, which is then parsed using an Awk script to generate a set of tables that can be used to read instructions. It has enough information to give you exact instruction sizes, although you may need to expand it to include information for floating point instructions and some new Intel extensions, such as AVX.

If you have access to the Linux kernel source tree, look at arch / x86 / lib / x85-opcode-map.txt.

This contains all the data needed to determine the size of the commands.

There is an AWK script @ arch / x86 / tools / gen-insn-attr-x86.awk that will read the opcode file and create a series of tables that encode information on the operation code card.

Finally, if you look at arch / x86 / lib / insn.c, there is a function insn_get_length (...) that will give you the length of the instruction using the tables generated on the opcode map. This should be enough for you to answer your specific question: "How big is this instruction."

There is nothing special about this code. You can adapt to user mode without doing anything special.

I assume that accessing the Linux kernel sources should not be a security issue for you, and that there is nothing that would burden you from reading / accepting the GPL code.

+3
source

You can use a library like libdisasm , which should provide you with the necessary information. I did this to connect by writing my own disassembler, but I think using a ready-made library is a lot easier.

In any case, as I wrote in my commentary, I’m not sure what you think you are getting from this. You cannot rely on automatic analysis of the program in this way, and if you want it to recover from a failure, I already said the reason why this is very unrealistic and can cause more problems than it can be solved.

Perhaps you really need a virtual machine.

To execute the code, you also need a little assembly, which restores the registers to the state they were when the exception occurred, and then you go to what you are pointing to.

0
source

All Articles