Questions about this topic? Sign up to ask in the talk tab.

User:Eax/Assembly System Calls

From NetSec
Jump to: navigation, search

Introduction

In the assembly language there are two ways to call system functions from the executable. The first way is through the native system calls which use the kernel interrupt code int $0x80 in assembly or \xcd\x80 in machine byte code. By placing the required data in the proper registers and calling the interrupt the program passes control to the kernel and it completes the function and returns the flow back to the program. The second way make a system call is by linking the C libraries to your executable. By doing this you will be able to push your arguments onto the stack in reverse order where the first argument is the last to be pushed and use the call command to pass control to the linked function located in the C library.


Unlinked System Calls for 32bit systems

On a 32bit system all system calls follow the same format. The system call to be made is moved into %eax and then depending on the function which you are calling the arguments go into %ebx, %ecx, %edx, %esx and %edi where %ebx would be the first argument to the system call, %ecx would be the second and so forth. Once you have all your registers set in place you can make your int $0x80 interrupt call to pass program flow to the kernel to complete the function.


  function_call(%eax) = function(%ebx,  %ecx,  %edx,  %esx,  %edi)
                ^system          ^arg1  ^arg2  ^arg3  ^arg4  ^arg5
                 call #


This diagram shows that when the system interrupt is called the kernel selects the function to use according to the system call number stored in %eax and then stores the variables in their proper registers as according to the C calling convention. Having a standard for calling functions is important because without one documentation for your executable would be messy and hard to understand.


An example of this would be exit() which is documented as 1:sys_exit:(int error_code);.


 
_start:
 
movl $1, %eax
mov $0, %ebx
int $0x80
 


In this call to the function exit() we placed the system interrupt call number into %eax and then the return value into the first argument %ebx and then made the interrupt call. Other function calls can be more complex and use 3 or more of the registers at once while others will use none at all except for %eax for the system call number itself.

Linked System Calls for 32bit systems

Linked system calls allow for cleaner code and faster development because of their ease of use. In order to take advantage of linked functions you must compile your assembly code with the required library. An example is as follows:


  as exit-lib.s -o exit-lib.o
  ld -dynamic-linker /lib/ld-linux.so.2 \ -o exit-lib exit-lib.o -lc


By assembling your binary like this you are now linking ld-linux.so.2 with your executable which will allow you to use the functions it holds. The main difference between the unlinked and linked system calls is that unlike the unlinked calls where you have to use all the proper registers and make an interrupt; all you have to do with linked calls is push your arguments backwards onto the stack where the first argument is pushed last and to invoke a call instruction to the function you wish to invoke. An example is as follows:


 
_start:
 
pushl $0
call exit
 


As you can see this makes your code shorter, neater, and to the point which is very helpful in assembly where your design and concept may not be clear at first sight to others.


Other Code Comparisons

Here are a few more examples of the two different calling conventions. The first will be shown as a unlinked call and the second would be as a linked call.

Printing to STDOUT 4:sys_write(unsigned int fd, const char *buf, size_t count)

 
.section .data
hello:
   .ascii "hello world\n"
hello_end:
 
.equ hello_len, hello_end - hello
 
.section .text
 
.global _start
 
_start:
movl $1, %ebx
movl $hello, $ecx
movl $hello_len, %edx
movl $4, %eax
int $0x80
 
movl $1, %eax
movl $0, %ebx
int $0x80
 


 
.section .data
hello:
   .ascii "hello world\n"
 
.section .text
 
.global _start
 
_start:
pushl $hello
call printf
 
pushl $0
call exit
 


Making A Directory 39:sys_mkdir(const char *pathname, int mode)


 
.section .data
dir:
   .ascii "/root/Desktop/lol/"
 
.section .text
 
.global _start
 
_start:
movl $dir, %ebx
movl $777, $ecx
movl $39, %eax
int $0x80
 
movl $1, %eax
movl $0, %ebx
int $0x80
 


 
.section .data
dir:
   .ascii "/root/Desktop/lol/"
 
.section .text
 
.global _start
 
_start:
pushl $777
pushl $dir
call mkdir
 
pushl $0
call exit