Jumping into ARM assembly


Thought it was more complicated.

--edit:
! C noob warning !
What am I doing wrong ?
Code:
#include <stdio.h>
#include <linux/random.h>

int main() {
  int r;
  r=getrandom(1,1,1);
  printf("le random: %d",r);
  return 0;
}

cc get.c
get.c: In function ‘main’:
get.c:6:5: warning: implicit declaration of function ‘getrandom’ [-Wimplicit-function-declaration]
r=getrandom(1,1,1);
^
/tmp/ccYYdDpw.o: In function `main':
get.c:(.text+0x18): undefined reference to `getrandom'
collect2: error: ld returned 1 exit status
 
Last edited:
Is your kernel version at least 3.17 ?
I get the same error, but my kernel version is 3.16.
Although it probably depends on gcc version.
 
You can't call a Linux syscall directly in C like that, the calling convention doesn't match up. Instead you should use the syscall wrapper function to do so:

Code:
#include <stdio.h>
#include <sys/syscall.h>
#include <linux/random.h>

int main() {
  int r;
  syscall(SYS_getrandom, &r, sizeof(int), 0);
  printf("le random: %d",r);
  return 0;
}

In practice you'd just use the user space functions random or urandom which will call the syscall for you.
 
To have a nice look at what the compiler is doing, go to https://godbolt.org/
Then type the program
Code:
#include <stdio.h>
#include <sys/syscall.h>
#include <linux/random.h>
#include <unistd.h>

int main() {
  int r;
  syscall(SYS_getrandom, &r, sizeof(int), 0);
  printf("le random: %d",r);
  return 0;
}
(I added unistd.h in the include)
Then select "ARM gcc 4.8.2" in the drop down box (it's in fact gcc 5.4.0). You can put some compile flags if you want (like "-mcpu=cortex-a8...", but you should stay at -O0 to have a clear ASM listing). And you'll see how gcc make the call. You have colored highlight also to help understand wich line of C gives you wich block of ASM line. It's yellow for me for the syscall, that gives
Code:
        mov     r1, r7
        movs    r3, #0
        movs    r2, #4
        mov     r0, #384
        bl      syscall

Very nice tool this compiler explorer...
 
To have a nice look at what the compiler is doing, go to https://godbolt.org/
Then type the program
Code:
#include <stdio.h>
#include <sys/syscall.h>
#include <linux/random.h>
#include <unistd.h>

int main() {
  int r;
  syscall(SYS_getrandom, &r, sizeof(int), 0);
  printf("le random: %d",r);
  return 0;
}
(I added unistd.h in the include)
Then select "ARM gcc 4.8.2" in the drop down box (it's in fact gcc 5.4.0). You can put some compile flags if you want (like "-mcpu=cortex-a8...", but you should stay at -O0 to have a clear ASM listing). And you'll see how gcc make the call. You have colored highlight also to help understand wich line of C gives you wich block of ASM line. It's yellow for me for the syscall, that gives
Code:
        mov     r1, r7
        movs    r3, #0
        movs    r2, #4
        mov     r0, #384
        bl      syscall

Very nice tool this compiler explorer...

Nice tool...but exist something for converting Intel x86 code to ARM ? or best convert x86 code to C/C++ ?
 
Awesome ! Thx !

Strange, the syscall 384 is loaded in r0 instead of the usual r7.
 
Last edited:
ARM Calling convention is 1st arg in r0 (that 384), 2nd arg in r1 (that r7, the adress of our r variable), 3rd arg in r2 (that's 4, the size of an int), 4th arg in r3 (that's 0), and other args in the stack (hopefully, only 4 args here).
[doublepost=1476802005,1476801880][/doublepost]
Nice tool...but exist something for converting Intel x86 code to ARM ? or best convert x86 code to C/C++ ?
Well, have a look to notaz's reverse tools github or M-HT github with static re-compile tools and games...

Nothing plug'n play to my knowledge.
 
Ok, and why two consecutive movs ? Isn't only the last one taken into account for the flags ?
 
Ok, and why two consecutive movs ? Isn't only the last one taken into account for the flags ?
According to ARM instruction documents
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0204j/Cihcdbca.html said:
16-bit instructions
The following forms of these instructions are available in pre-Thumb-2 Thumb code, and are 16-bit instructions when used in Thumb-2 code:

MOVS Rd, #imm
Rd
must be a Lo register. imm range 0-255.
It's just a way to put small number (0-255) inside a register.
 
Yes, but two consecutive MOVS's are equivalent to one MOV then one MOVS, since the second one overwrites all of the flags. In this case no instructions are using any conditionals though, so they may as well all be plain 'MOV'.

I guess it's some compiler weirdness, since it really doesn't matter whether you use MOV or MOVS here AFAIK. I'm slightly mystified why it didn't just use MOVS all the way through, since it seems to prefer that, but compilers can be so complex that they don't always appear strictly deterministic, when there are two paths that are equivalent.
 
I get this after the swi 0 :
r0 0xfffffffc 4294967292
This is clearly not a random as executing multiple times gives the same result. I guess it's some kind of pointer.

I still don't get why the "usual" syscall (exit, read, write, mmap etc.) are made with r7, and not this one.
 
I'm just guessing, but did you copy this:
Code:
        mov     r1, r7
        movs    r3, #0
        movs    r2, #4
        mov     r0, #384
        bl      syscall
and changed "bl syscall" to "swi 0" ?
In the code the syscall number is in r0, because it then calls a function named syscall which then does the syscall itself, but not before it moves the function input parameters into registers where syscall expects them (r0->r7, r1->r0, r2->r1, r3->r2).
 
Yup, I did that.
Those moves (r0->r7, r1->r0, r2->r1, r3->r2) look weird and unoptimized, why gcc does that ?
 
Last edited:
Perhaps because syscall is a label to an ARM function call, and that specifies that arguments are in r0-r3 and on the stack as ptitseb posted the other day. I dunno why the compiler didn't decide to inline that function and just build the arguments into the right registers in the first place, but it probably only does that at higher optimisation levels.
 
The syscall function is in an external library, so the compiler can't optimize anything about how it's called or inline it.
 
Ok, so doing that manually still gives me something in r0, but I don't know what to do with it :
r0 0xfffffff2 4294967282
 
Back
Top