1

I have a simple assembly code (aarch64) as follows,

 mov x1, #1
 mov x1, #2

and I want to convert it to shellcode.

What I did:

#> as simple.s -o simple.o
#> objcopy -O binary simple.o simple.bin

after that, I checked the content of with xxd

#> xxd simple.bin

However, The value 1 and 2 are not seemed in result binary.

0000000: 2100 80d2 4100 80d2                      !...A...

did I use the objcopy wrongly ?

prgbenz
  • 1,129
  • 4
  • 13
  • 27
  • I also tried `strip simple.bin` before the objcopy. But the result was same. – prgbenz Nov 23 '21 at 12:13
  • BTW, you can't usefully `bl printf` from actual shellcode. That assembles to a relative branch to a PLT stub in another section, which in turn loads a pointer from the GOT entry. All of these things depend on absolute addresses set up by the dynamic linker, and/or their own address, and the randomized address of `printf` in libc.so, so aren't things that can be part of a self-contained position-independent block of machine code that could be injected anywhere. – Peter Cordes Nov 23 '21 at 12:29
  • But also, why bother to link your `simple` executable if you're going to objcopy from the `.o` object file? – Peter Cordes Nov 23 '21 at 12:29
  • More importantly, `as simple.s -o simple` doesn't write `simple.o`, so if that file exists it's probably from an old version of your source. – Peter Cordes Nov 23 '21 at 12:30
  • @PeterCordes you are right, using printf break the shellcode. – prgbenz Nov 23 '21 at 12:56
  • 2
    *However, The value 1 and 2 are not seemed in result binary.* - AArch64 encodes immediate in a complex way, not just using the low 8 or 12 bits of the instruction word literally. ([Range of immediate values in ARMv8 A64 assembly](https://stackoverflow.com/q/30904718)) Look at the machine code for those instructions in the `.o` (`objdump -d foo.o`) and see if it matches your hexdump. Also, the xxd defaults for chunk size and endianness are not great for looking at AArch64 machine code! – Peter Cordes Nov 23 '21 at 13:02
  • Voting to close as not reproducible - the bytes you dumped are exactly the instructions you've written. – Siguza Nov 23 '21 at 13:31

1 Answers1

3

ARM instructions are 32-bit little-endian words, so will be easier to read if you dump them in this format. Use xxd -e simple.bin which outputs:

00000000: d2800021 d2800041                    !...A...

This is the correct encoding for the movz instruction, see the ARMv8 Architecture Reference Manual. The 16-bit immediate is encoded in bits 5-20, which is why the numbers 1 and 2 are not immediately obvious in the hexadecimal representation, but they are there. (Bits 0-4 encode the destination register.) They would be easier to see in binary, but xxd doesn't seem to have a 32-bit little-endian binary mode.

So your output file is perfectly correct.

Nate Eldredge
  • 48,811
  • 6
  • 54
  • 82