-1

So when movl (in intel x84-64 machine code) is called and has a register as the destination, it sets the higher order bytes of the register to 0. So how can i use the movl instruction such that I preserve the original value of the register? In this situation, we cant use rsi / rdi for movl instructions (only esi and edi). For example, if I go

movq %rsp, %rax

and then call

movl %eax, %edx

is there a way to call movl / do something after movl such that rdx can then contain the original value that was in %rsp?

The reason I cant do something like movq %rax, %rdx is because I dont have those commands available to me. I'm doing a ROP attack where i only have movl instructions available to me in the gadget farm. I also have access to andb, orb, cmpb and testb instructions.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • 1
    `movl %rsi, %rdx`? – melpomene May 16 '18 at 06:41
  • Zero-extending discards the bits; there isn't a hidden copy anywhere. You have to keep a copy of any data you want in memory or an architectural register. You can use 64-bit AND and OR operations (or shifts/rotates) to merge the low 32 from one register with the high 32 from another, if you want... – Peter Cordes May 16 '18 at 06:45
  • 1
    BTW, how does `%rsi` or `%rdi` come into it at all? Your code example uses RSP, not RSI. – Peter Cordes May 16 '18 at 06:49
  • `xorq %rdx, %rdx; xorq %rsi, %rdx`? – melpomene May 16 '18 at 06:50
  • 1
    The answer to your question is movq %rax, %rdx, but since that apparently isn’t the answer you are looking for, there must be something missing from your question. – prl May 16 '18 at 07:04
  • 1
    @Devam: You know that [`movq` is the same opcode as `movl`](http://felixcloutier.com/x86/MOV.html), right? Just with a REX prefix making the operand-size 64-bit? It's still one of the most efficient instructions you can use on modern CPUs, [even having zero latency on IvyBridge+ and Ryzen](https://stackoverflow.com/questions/44169342/can-x86s-mov-really-be-free-why-cant-i-reproduce-this-at-all). NVM, you finally clarified your restrictions seconds after I commented. – Peter Cordes May 16 '18 at 07:13
  • and `MOV`s will need REX prefix regardless of register size if you're copying the 8 upper registers – phuclv May 16 '18 at 08:33

1 Answers1

1

You can't glue together multiple gadgets can you? You need to find a single sequence that gets a value you want into a register and jumps to that register.

Anything that truncates the high 32 bits of your pointer is not useful; the bits are gone and you can't get them back except by copying from the original again. (Or if you can find some sequence of rotates and/or shld something / ror rax,32).

Writing a 32-bit register doesn't just "hide" the upper bits, it throws them away. This is not reversible. You have to keep a copy of any data you want in memory or an architectural register.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847