this is foo.asm
extern choose;
[section .data]
num1st dq 3
num2nd dq 4
[section .text]
global main
global myprint
main:
push qword [num2nd]
push qword [num1st]
call choose
add esp,8
mov ebx,0
mov eax,1
int 0x80
; pop qword [num1st]
; pop qword [num2nd]
myprint:
mov edx,[esp+8]
mov ecx,[esp+4]
mov ebx,1
mov eax,4
int 0x80
; pop qword [num1st]
; pop qword [num2nd]
ret
it is a C-asm-program
this is bar.c
void myprint(char * msg ,int len);
int choose(int a,int b)
{
if (a>=b){
myprint("the 1st one\n",13);}
else {
myprint("the 2nd one\n",13);}
return 0;
}
nasm -f elf64 foo.asm
gcc -c bar.c
gcc -s -o foobar bar.o foo.o
./foobar ,it says segmentation fault core dumped
I use gdb to debug ,but it says missing debuginfo-install, I am also trying to install it.
maybe the problem has sth to do with the 86_64 arch...
Segmentation fault when pushing on stack (NASM)
after watched this link,I add some 'pop' into it but it doesn't work
Arguments are not passed on the stack in 64-bit mode, unless you have more than 6 of them. The first two arguments will be in RDI and RSI.
There's also a difference in how you should use system calls in 64-bit mode. The syscall number and arguments should be placed in the following registers (source):
syscall nr rax
arg 1 rdi
arg 2 rsi
arg 3 rdx
arg 4 r10
arg 5 r9
arg 6 r8
And the sys_write syscall number in 64-bit mode is 1, not 4. Also, instead of int 0x80 you should use syscall. Performing syscalls with int 0x80 might work in 64-bit mode depending on how your kernel has been configured, but you still need to consider how function arguments are passed.
Related
C code
#include <stdio.h>
int fibonacci(int);
int main()
{
int x = fibonacci(3);
printf("Fibonacci is : %d",x);
return 0;
}
Assembly
section .text
global fibonacci
fibonacci:
push ebp;
mov ebp, esp;
; initialize
mov dword [prev], 0x00000000;
mov dword [cur], 0x00000001;
mov byte [it], 0x01;
mov eax, dword [ebp + 8]; // n = 3
mov byte [n], al;
getfib:
xor edx,edx;
mov dl, byte [n];
cmp byte [it] , dl;
jg loopend;
mov eax,dword [prev];
add eax, dword [cur];
mov ebx, dword [cur];
mov dword [prev], ebx;
mov dword [cur] , eax;
inc byte [it];
jmp getfib;
loopend:
mov eax, dword [cur];
pop ebp;
ret;
section .bss
it resb 1
prev resd 1
cur resd 1
n resb 1
I was trying to run this assembly function in C code and on debugging , i saw that value in variable x in C code is right but there is some error coming when i use the printf function
Need Help on it
Command to compile:
nasm -f elf32 asmcode.asm -o a.o
gcc -ggdb -no-pie -m32 a.o ccode.c -o a.out
Click Below Pictures if they seem blurred
Below is debug before printf execute
Below is after printf execute
Your code does not preserve the ebx register which is a callee-preserved register. The main function apparently tries to do some rip-relative addressing to obtain the address of the format string for printf using ebx as a base register. This fails because your code overwrote ebx.
To fix this issue, make sure to save all callee-saved registers before you use them and then restore their value on return. For example, you can do
fibonacci:
push ebp
mov ebp, esp
push ebx ; <---
...
pop ebx ; <---
pop ebp
ret
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I have a x64 processor and I'm looking into shellcode.
I have the following code:
section .text
global _start
_start:
push rax
mov rbx, 0x68732f6e69622f2f
shr rbx, 0x8
push rbx
mov rdi, rsp
;mov rdi, com
mov al, 59
syscall
When compiled with the foolowing command:
nasm -g -f elf64 execve.asm
And linked with:
ld execve.o -o execve
It runs fine. It opens a shell. If i get the shellcode from it:
"\x50\x48\xbb\x2f\x2f\x62\x69\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\xb0\x3b\x0f\x05"
And use this C program:
int main(void)
{
const char shellcode[] = "\x50\x48\xbb\x2f\x2f\x62\x69\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\xb0\x3b\x0f\x05";
(*(void (*)()) shellcode)();
return 0;
}
Compile it:
gcc -fno-stack-protector -z execstack -o ex2 ex.c
If run it returns a segmentation fault, but it should execute a shell. Why?
Help is appreciated!
Your standalone assembly depends on registers rsi and rdx being zeroed.
(As you can see from http://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/
sys_execve takes three arguments through registers rdi, rsi, and rdx, and Linux will also accept it if rdi is a correct filename and rsi and rdx are zero).
This may be the case when the program starts, but it's not when you run the instructions from within the
middle of a program.
Consequently if rsi, and rdx have garbage in them, the syscall will fail and the instruction stream
will continue executing the garbage bytes it'll find after the syscall instruction, eventually leading to a crash (this is indeed, what's happening in your case, as you can see if you run the program through gdb)
The simplest way to make the syscall succeed is by zeroing out 2nd and the third argument:
section .text
global _start
_start:
xor rax, rax
xor rsi, rsi ; zero 2nd argument
xor rdx, rdx ; zero 3rd argument
push rax
mov rbx, 0x68732f6e69622f2f
shr rbx, 0x8
push rbx
mov rdi, rsp
mov al, 59
syscall
Corresponding C code:
int main(void)
{
char shellcode[] =
"\x48\x31\xc0\x48\x31\xd2\x48\x31\xf6\x50\x48\xbb\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\xb0\x3b\x0f\x05"
;
((void (*)()) shellcode)();
return 0;
}
You left out the \x6e.
This causes segv because the exec fails and there isn't a return after the syscall.
From what I understand, when a parameter is passed in a function call in C, the callee can find the first parameter at [ebp+8].
Returning a value through eax works for me, reading the right parameter value from the stack doesn't.
Right now I'm just trying to write an assembly function, that can be called from C and returns the same value, that it is being passed.
When I run the following program, it prints number: 1 to the console, no matter what value is passed into myFunc. What am I doing wrong?
assembly.s
section .text
global _myFunc
_myFunc:
mov eax, [ebp+8]
ret
main.c
#include <stdio.h>
extern unsigned int myFunc(unsigned int somedata);
int main() {
unsigned int i = myFunc(6);
printf("number: %i\n",i);
return 0;
}
I'm using a Mac, nasm to assemble the code and gcc for C compilation.
Makefile
macho32:
nasm -f macho32 assembly.s
gcc -m32 -o macho32 assembly.o main.c
You need to setup to access the the parameters first by saving esp. This is explained in:
http://www.nasm.us/doc/nasmdoc9.html
in section "9.1.2 Function Definitions and Function Calls"
The following works for me
assembly.s
section .text
global myFunc:function
myFunc:
push ebp
mov ebp, esp
mov eax, [ebp+8]
mov esp, ebp
pop ebp
ret
main.c
#include <stdio.h>
extern unsigned int myFunc(unsigned int somedata);
int main() {
unsigned int i = myFunc(6);
printf("number: %i\n",i);
return 0;
}
Assembly & Compilation
ericu#eric-phenom-linux:~$ nasm -f elf32 assembly.s
ericu#eric-phenom-linux:~$ gcc -m32 assembly.o main.c
ericu#eric-phenom-linux:~$ ./a.out
number: 6
I am on a linux machine so I use elf32. The use of macho32 is correct on your Mac.
you refer to argument on stack, by reading from [EBP+offset] - has EBP been set up to actually point at stack? If no, you may have to do that first, conventionally done by:
push ebp
mov ebp,esp
Only then points EBP to its stacked previous contents, below stacked return address, and below passed arguments.
Your function should look like this,
_myFunc:
push ebp ; setup ebp as frame pointer
mov ebp, esp
mov eax, [ebp + 8]
leave ; mov esp,ebp / pop ebp
ret
The convention is to use ebp to access the parameters, to do so you need to save ebp on the stack and make it to point to the new top of the stack. At function exit you should restore ebp and esp, as the leave instruction does.
In nasm there is a macro package, c32.mak, that can help in supporting the C calling convention, these macros are arg, proc and endproc.
Using these macros your code should look like,
proc _myfunc
%$i arg
mov eax, [ebp + %$i]
endproc
I am using NASM on linux to write a basic assembly program that calls a function from the C libraries (printf). Unfortunately, I am incurring a segmentation fault while doing so. Commenting out the call to printf allows the program to run without error.
; Build using these commands:
; nasm -f elf64 -g -F stabs <filename>.asm
; gcc <filename>.o -o <filename>
;
SECTION .bss ; Section containing uninitialized data
SECTION .data ; Section containing initialized data
text db "hello world",10 ;
SECTION .text ; Section containing code
global main
extern printf
;-------------
;MAIN PROGRAM BEGINS HERE
;-------------
main:
push rbp
mov rbp,rsp
push rbx
push rsi
push rdi ;preserve registers
****************
;code i wish to execute
push text ;pushing address of text on to the stack
;x86-64 uses registers for first 6 args, thus should have been:
;mov rdi,text (place address of text in rdi)
;mov rax,0 (place a terminating byte at end of rdi)
call printf ;calling printf from c-libraries
add rsp,8 ;reseting the stack to pre "push text"
**************
pop rdi ;preserve registers
pop rsi
pop rbx
mov rsp,rbp
pop rbp
ret
x86_64 does not use the stack for the first 6 args. You need to load them in the proper registers. Those are:
rdi, rsi, rdx, rcx, r8, r9
The trick I use to remember the first two is to imagine the function is memcpy implemented as rep movsb,
You're calling a varargs function -- printf expects a variable number of arguments and you have to account for that in the argument stack. See here: http://www.csee.umbc.edu/portal/help/nasm/sample.shtml#printf1
I have some assembly code that uses scanf and printf and I'm running into some problems. When both of these functions are used in the same code, the values in the registers seem to be lost. The program basically loads a number and prints it out. We run it using
nasm -f elf64 file.asm && gcc -o file file.o && ./file
on linux
Here's our code:
extern printf
extern scanf
section .data
a db "set: ", 0
b db "not set: ", 0
reading db "Please enter a number: ", 0
message db "\n", 0
printsent db "%s", 10, 0
printint db "%d", 10, 0
printchar db "%c", 10, 0
readInt db "%d", 0
input db "%d", 0
section .text
global main
main:
hatta:
push rbp,
mov rbp, rsp,
push rbx,
xor rax, rax,
mov rdi, printsent,
mov rsi, reading
call printf,
pop rbx,
xor rax, rax,
mov rdi, readInt,
call scanf,
mov rbx, rdi
push rbx,
xor rax, rax,
mov rdi, printint,
mov rsi, rbx,
call printf,
pop rbx,
pop rbp,
ret
The odd thing is that if the line mov rdi, printint, is removed, we obtain the correct values. However, if we do the same thing with printsentence, we get a segmentation fault. Could anyone tell us the reason for this?
Thanks!
There are two errors in your scanf usage, possibly based on one false assumption: You seem to mean that scanf returns the loaded number in rdi and that no further argument is needed with format "%d". In truth the number (if scanned successfully) is returned in the memory pointed to by the second argument. Thus, the following changes make the code work.
pop rbx, | ;delete
=
xor rax, rax, = xor rax, rax,
mov rdi, readInt, = mov rdi, readInt,
> mov rsi, rsp
call scanf, = call scanf,
mov rbx, rdi | pop rbx,
Concerning if the line mov rdi, printint, is removed, we obtain the correct values - I doubt that.
I don't understand why you have the C flag here, there is no C code involved, but to your question:
As far as I remember the calling convention in Linux glibc x64 for printf(format, argument) is format in rdi, argument in rsi.
If you remove mov rdi, printsent, then you are calling printf(undefined,"Please enter a number: "). You did not provide a format argument in rdi, but printf
doesn't know that and uses whatever is in rdi at that moment. Most likely an invalid memory address which thus invokes a SIGSEGV.
By default function calls in x86 are supposed to be non-destructive on the arguments, though this is not a requirement. Standard library functions generally are. They achieve this by pushing the arguments on to the stack and reload them when done.
As such when you call scanf(readInt, ...) it will restore the pointer to readInt which has the same contents as printint in rdi when it returns. As such removing the line mov rdi, printint, has no effect because rdi contains a valid pointer to the format you need.