subhook icon indicating copy to clipboard operation
subhook copied to clipboard

8 bit relative jump tripping up my use case (instruction 0x79 0x07)

Open gthaker opened this issue 4 years ago • 0 comments

2 byte instruction "jns 0x9" (bytes "0x79 0x07") (jump forward 7 bytes from updated IP) - using 8 bit offset), trips me up.

The function I am trying to subhook_make_trampoline for is as follows:

int fact(int n) {
  if (n < 0) return 0;
  if (n <= 1) return 1;
  int i, ans = 1;
  for (i = 2; i <= n; i++) {
    ans *= i;
  }
  return ans;
}

compiled w/ gcc 9.3 with -ggdb -mmanual-endbr I get:

(gdb) di fact
Dump of assembler code for function fact:
   0x00005555555551e9 <+0>:	push   %rbp
   0x00005555555551ea <+1>:	mov    %rsp,%rbp
   0x00005555555551ed <+4>:	mov    %edi,-0x14(%rbp)
   0x00005555555551f0 <+7>:	cmpl   $0x0,-0x14(%rbp)
   0x00005555555551f4 <+11>:	jns    0x5555555551fd <fact+20>     #  <<< ISSUE IS HERE
   0x00005555555551f6 <+13>:	mov    $0x0,%eax
   0x00005555555551fb <+18>:	jmp    0x555555555233 <fact+74>
   0x00005555555551fd <+20>:	cmpl   $0x1,-0x14(%rbp)
   0x0000555555555201 <+24>:	jg     0x55555555520a <fact+33>
   0x0000555555555203 <+26>:	mov    $0x1,%eax
   0x0000555555555208 <+31>:	jmp    0x555555555233 <fact+74>
   0x000055555555520a <+33>:	movl   $0x1,-0x4(%rbp)
   0x0000555555555211 <+40>:	movl   $0x2,-0x8(%rbp)
   0x0000555555555218 <+47>:	jmp    0x555555555228 <fact+63>
   0x000055555555521a <+49>:	mov    -0x4(%rbp),%eax
   0x000055555555521d <+52>:	imul   -0x8(%rbp),%eax
   0x0000555555555221 <+56>:	mov    %eax,-0x4(%rbp)
   0x0000555555555224 <+59>:	addl   $0x1,-0x8(%rbp)
   0x0000555555555228 <+63>:	mov    -0x8(%rbp),%eax
   0x000055555555522b <+66>:	cmp    -0x14(%rbp),%eax
   0x000055555555522e <+69>:	jle    0x55555555521a <fact+49>
   0x0000555555555230 <+71>:	mov    -0x4(%rbp),%eax
   0x0000555555555233 <+74>:	pop    %rbp
   0x0000555555555234 <+75>:	retq   

Instruction at fact+11 is "jns 0x09" or in raw bytes "0x79 0x07"
In subhook_x86.c it says:

 * Note: We don't support short (8-bit) offsets at the moment, so the
 * caller can assume the operand will be always 4 bytes.
 

What can I do to get around this limitation? It seems 2 byte relative jump instructions (meaning 8 bits of offset) would be used quite often in real world.

gthaker avatar May 29 '21 19:05 gthaker