Hiding instruction on CISC CPUs

Today I'm somewhat playful, so for fun wrote a little proggy which fiddles with dynamic code generation and instruction hiding. Instruction stream for CISC CPU (like x86 amd amd64) isn't so well defined as it is for RISC CPUs. Thus games could be played with hiding of instructions in the instruction stream. Actually idea for this hack first came to my mind when I realized that we can jump in the middle of instruction on x86 CPU. In my example I hide instruction xor edi, edi inside of machine code for mov eax, imm. Moreover, this code really sets eax regsiter to the immediate value expected. To see the point, start the program, stop just before jump to the generated code (b jumper.c:53) and examine code in buffer (x /3i buf). You'll see:
0xb7f9e000:     jmp    0xb7f9e003
0xb7f9e002:     mov    $0xfbebff31,%eax
0xb7f9e007:     ret    
Now stat executing code step by step with si command (and ask gdb to show what happens with display /i $pc). You'll see the magic in action. Also you may check that EDI value changed just by examining output.
#include <stdio.h>
#include <sys/mman.h>
#include <unistd.h>
#include <errno.h>

unsigned char\* make_exec_buf() {
  int ps = getpagesize();
  unsigned char\* rv = 
    (unsigned char\*)mmap(NULL, ps, PROT_EXEC|PROT_READ|PROT_WRITE, 
                         MAP_PRIVATE | MAP_ANON, -1, 0);
  if (rv == (unsigned char\*)-1) {
    perror("mmap");
    return NULL;
  }
  return rv;
}

void write_magic(unsigned char\* buf) {
#define PUT_BYTE(b) buf[idx++] = (unsigned char)b;
#define PUT_INT(b) \*(int\*)(buf+idx) = b; idx += 4;
  int idx = 0;
  
  PUT_BYTE(0xeb); // jmp hidden
  PUT_BYTE(1);
 visible:
  PUT_BYTE(0xb8); // mov eax, imm32
 hidden:
  PUT_BYTE(0x31); // xor edi, edi
  PUT_BYTE(0xff);
  PUT_BYTE(0xeb); // jmp visible, to make sure what should be don is done
  PUT_BYTE((-5) & 0xff);

  PUT_BYTE(0xc3); // ret
}


inline void set_edi(int v) {
  __asm__ __volatile__ ("movl %0, %%edi\\n" : : "r"(v) );
}

inline int get_edi() {
  int rv;
  __asm__ __volatile__("movl %%edi, %0\\n" :"=r"(rv));
  return rv;
}

int main() {
  int rv;
  unsigned char\* buf = make_exec_buf();
  write_magic(buf);
  set_edi(0xcafe);
  printf("before edi=%x\\n", get_edi());
  rv = ((int (\*)())buf)();
  printf("after edi=%x got %x\\n", get_edi(), rv);
  return 0;
}

Comments:

Post a Comment:
  • HTML Syntax: NOT allowed
About

nike

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today