0

So based on this question and its answer :

Why can't you set the instruction pointer directly?

I always thought you cannot change the eip or rip of your process or another process

but when reading this source code from Metasploit framework :

https://github.com/rapid7/metasploit-framework/blob/master/data/templates/src/pe/dll/template.c

on line 66 and 68 its setting up the eip or rip of its child process :

   ctx.Rip = (DWORD64)ep;

but i thought you cannot even change the IP of your own process let alone another process

so am i missing something here?

are we allowed to change the IP of our process and other processes or not? and if so, what is the limit, which processes can we change and which we can't? can we change our own process's IP using something like ctx.RIP or even another process which is not our child?

OneAndOnly
  • 1,048
  • 1
  • 13
  • 33
  • A process cannot itself change any registers in a different process's context, period. Any register values it sets are necessarily set in *its own* context. But it might be possible to induce a child process that hasn't yet been launched to modify its own registers in a desired way after it does launch, or to trick the kernel into starting a new child process with adversary-selected register values. I've not studied the code in question so as to speak specifically to what it's doing, however. – John Bollinger Aug 09 '19 at 12:03
  • 3
    Technically, every process _can_ modify its own IP using a call or jump instruction. Of course, the OS may introduce restrictions on which addresses you can jump to, but technically, you can write whatever you want in there. On certain architectures, the IP or PC is even treated like a general purpose register and can be used as as a target for a move or load instruction. ARM, for example, exposes the program counter as R15. – th33lf Aug 09 '19 at 12:09
  • If a program knows where another process stores its IP on its return stack, and if it has write access to that, it can also change that value. That's why memory protection is so important. – the busybee Aug 09 '19 at 12:20
  • The current accepted answer on the question you linked is correct that **you *can* change your own RIP with a `jmp` instruction**, or any other control-transfer instruction. Writing RIP = jumping; that's exactly what a jump is. You can change RIP in other processes using a debugger, or the same system calls that debuggers use. – Peter Cordes Aug 09 '19 at 12:21
  • @thebusybee: That's changing a return address in memory, not directly changing the current RIP in a register. On Linux you can do the latter with a `ptrace` system call. (Really that's still just changing memory, though: changing the saved RIP in the kernel's task struct for that process while it's suspended.) – Peter Cordes Aug 09 '19 at 12:22
  • 4
    @JohnBollinger: If a process cannot change any registers in a different process’s context, period, how do out-of-process-space debuggers work? – Eric Postpischil Aug 09 '19 at 12:23
  • @EricPostpischil: they work using system calls like Linux's `ptrace`. That works by modifying another process's saved RIP in the kernel's task_struct. So in some sense it's "only" modifying memory, and the target process might have to be suspended, but from the POV of the target process its RIP value does directly change. – Peter Cordes Aug 09 '19 at 12:26
  • 3
    @PeterCordes: That was a rhetorical question. The point is they do change registers in other processors. How they work is irrelevant. (If they change a register by changing the memory containing saved register contents, then the statement “A process cannot change any registers in a different process’s context directly” could be true. But “A process cannot change any registers in a different process’s context, period” is false.) – Eric Postpischil Aug 09 '19 at 12:28
  • @EricPostpischil: agreed. I assumed rhetorical but answered for the benefit of the OP and future readers. – Peter Cordes Aug 09 '19 at 12:29
  • I'm not sure this is an exact duplicate, but it's based on a false premise that's actually answered by the top answer on the first question it links to. If anyone thinks this question really needs an answer, I guess we can reopen this. – Peter Cordes Aug 09 '19 at 12:38
  • I found a duplicate that mentions the `GetThreadContext` / `SetThreadContext` Windows system calls (that are like `ptrace`) that the linked code is using to modify another process's RIP while it's paused. – Peter Cordes Aug 09 '19 at 12:48
  • No, @EricPostpischil, a process cannot *itself* change another process's registers. This is a characteristic of process isolation. But under some circumstances a process can persuade the kernel to change another process's registers. I chose my wording very intentionally there, though perhaps the distinction is not useful. – John Bollinger Aug 09 '19 at 13:01
  • 3
    @JohnBollinger: As I wrote in a previous comment, the statement that a process cannot change registers in a different process “period” is false. The statement that a process cannot change registers in a different process directly would be true. A process can, in fact, execute code that will result in the value in a register in a different process changing. The means by which it is effected is irrelevant. And the fact that the “period” statement is false is important: It leads a person to believe one process cannot so affect another, in contradiction to the truth that it can. – Eric Postpischil Aug 09 '19 at 13:11

0 Answers0