AArch 64 Bytes: Part 2 (64-bit Immediate Values)

Kevin Thomas
3 min readNov 1, 2021

--

debraj9121 pixabay

For a complete table of contents of all the lessons please click below as it will give you a brief of each lesson in addition to the topics it will cover. https://github.com/mytechnotalent/AArch64-Bytes

Today we will cover the concept of handling 64-bit immediate values.

This will be very relevant when dealing with moving larger values around.

The MOV instruction will handle only a 16-bit quantity therefore wasting the other 48-bits of a given general purpose register in AArch 64.

Say we want to move the value 0x1337deadbeeffeed into X0.

mov   x0, #0xfeed
movk x0, #0xbeef, lsl #0x10
movk x0, #0xdead, lsl #0x20
movk x0, #0x1337, lsl #0x30

To test this out let’s create a simple main.s file.

  1 .global _start
2 .section .text
3
4 _start:
5 mov x0, #0xfeed // move data into x0
6 movk x0, #0xbeef, lsl #0x10 // move data into lsl #0x10
7 movk x0, #0xdead, lsl #0x20 // move data into lsl #0x20
8 movk x0, #0x1337, lsl #0x30 // move data into lsl #0x30
9
10 sys_exit: // subroutine to exit
11 mov x0, #0 // use 0 return code
12 mov x8, #93 // sys_exit syscall
13 svc 0 // call kernel
14 ret // return to where called

Let’s create a simple makefile.

  1 main:
2 as -o main.o *.s -g --gdwarf-2
3 ld -s -o main main.o
4
5 release:
6 as -o main.o *.s --strip-local-absolute
7 ld -s -o main main.o
8
9 clean:
10 rm *.o
11 rm main
12

Let’s fire it up in GDB (with GEF enhancement https://github.com/hugsy/gef)

┌──(developer㉿kali)-[~]
└─$ gdb -q ./main
GEF for linux ready, type `gef' to start, `gef config' to configure
93 commands loaded for GDB 10.1.90.20210103-git using Python engine 3.9
[*] 3 commands could not be loaded, run `gef missing` to know why.
Reading symbols from ./main...
(No debugging symbols found in ./main)
gef➤ info file
Symbols from "/home/developer/main".
Local exec file:
`/home/developer/main', file type elf64-littleaarch64.
Entry point: 0x400078
0x0000000000400078 - 0x0000000000400098 is .text
gef➤ b *0x400078
Breakpoint 1 at 0x400078
gef➤ r

Let’s look around…

●→   0x400078                  mov    x0,  #0xfeed                      
0x40007c movk x0, #0xbeef, lsl #16
0x400080 movk x0, #0xdead, lsl #32
0x400084 movk x0, #0x1337, lsl #48
0x400088 mov x8, #0x5d
0x40008c mov x0, #0x41

Let’s look at X0.

$x0  : 0x0
...
●→ 0x400078 mov x0, #0xfeed

Let’s si and look at X0 again.

$x0  : 0xfeed
...
● 0x400078 mov x0, #0xfeed
→ 0x40007c movk x0, #0xbeef, lsl #16

Let’s si and look at X0 again.

$x0  : 0xbeeffeed
...
● 0x400078 mov x0, #0xfeed
0x40007c movk x0, #0xbeef, lsl #16
→ 0x400080 movk x0, #0xdead, lsl #32

Let’s si and look at X0 again.

$x0  : 0xdeadbeeffeed
...
● 0x400078 mov x0, #0xfeed
0x40007c movk x0, #0xbeef, lsl #16
0x400080 movk x0, #0xdead, lsl #32
→ 0x400084 movk x0, #0x1337, lsl #48

Let’s si and look at X0 again.

$x0  : 0x1337deadbeeffeed
...
● 0x400078 mov x0, #0xfeed
0x40007c movk x0, #0xbeef, lsl #16
0x400080 movk x0, #0xdead, lsl #32
0x400084 movk x0, #0x1337, lsl #48
→ 0x400088 mov x8, #0x5d

Success! Now we have an idea how to parse data in a very efficient manner. This is also useful when reversing as it will become obvious what data is being manipulated when understanding how this works.

--

--