Writing the payload

Photo by Nhu Nguyen on Unsplash

Stage One: General Overview

First of all, what are we trying to achieve here? Our goal is to write shellcode for the Linux 32-bit ARMv6 architecture that will connect back to a remote location over TCP/IPv4 and provide a shell only after the remote client provides a valid password. In order to write the payload, we need to chain several syscalls. The exact order is the following:

1- We create a new socket to manage the new connection.

2- We connect to the target address.

3- We read from the socket and check if the provided password is correct.

4- We duplicate each standard stream into the new connection stream using the dup2 syscall, so the target machine can read and write messages to and from the source machine.

5- We start a shell by using the execve syscall.

Each of these syscalls has a signature we need to address. Certain registers must contain specific values. For example, the r7 register is used to identify the syscall that is executed so it should always contain the syscall number. A whole document containing a full syscall table can be found here.

Photo by Host Sorter on Unsplash

Stage Two: Writing a Syscall

Let’s see an example of how to write a syscall in ARM Thumb state. We’ll use the socket syscall:

// [281] socket(2, 1, 0)

02 20 mov r0, #2 // loads immediate value 2 into r0

01 21 mov r1, #1 // loads immediate value 1 into r1

52 40 eor r2, r2 // zero-outs r2 by xoring it with itself // 281 is out of range for immediate values

// It must be loaded in parts

c8 27 mov r7, #200 // part1: loads immediate value 200 into r7

51 37 add r7, #81 // part2: adds 81 to r7 as (syscall number)

01 df svc #1 // issues the syscall

Here you can see:

The r7 register being used identifying the syscall

register being used identifying the syscall Registers r0 , r1 , and r2 used as parameters for the syscall

, , and used as parameters for the syscall An example of how to deal with immediate values that are out of range

The use of svc instruction to perform a system call

Photo by Sai Kiran Anagani on Unsplash

Stage Three: Writing the full payload

Armed with all our knowledge we are now prepared to chain every syscall and put together our payload. The following Gist was extracted from the source code on my main repository: