Cannot print the string to which the stack address points using INT80 in Ubuntu system - nasm

I can print character in label that in section .data
But I can't print character use stack address
section .data
break db "a"
section .text
global _start
_start:
mov rax, qword 'a'
push rax
; push 'a' to stack
mov rax,4
mov rbx,1
; get stack top pointer and mov to rcx register
mov rcx,rsp
; If replace rsp with label <break> that can print newlines character
; mov rcx,break
mov rdx,1
int 80h
pop rax
call quit
quit:
mov rbx, 0
mov rax, 1
int 80h
ret
console>
not print anything
If replace rsp with label that can print newlines
; mov rcx, rsp
mov rcx, break
console>a#
print one character
Makefile
.PHONY: test
test:
nasm -f elf64 test.asm
ld -s -o test test.o
./test
.PHONY: test_debug
test_debug:
nasm -f elf64 -F dwarf -g test.asm
ld -g -o test test.o
gdb test

Related

Why do i need to call syscall write before syscall read to make it accept user input?

In the following x64 assembly program I am attempting to read a single character from the command line and then print it back. You will notice that I am performing what seems to be a useless write before actually reading the character.
This program compiles and when run and will halt, accept a character as input and after pressing return will write that character back and exit. Without the spurious write, it doesn't halt and accept user input and just exits. Why is that?
test.asm:
global _start
section .text
_start:
mov r8, stack
mov rax, 1 ; syscall write
mov rdi, 1 ;
mov rsi, r8 ;
mov rdx, 1 ; Why do I need to do this write
syscall ; to make the following read work?
mov rax, 0 ; syscall read
mov rdi, 0 ;
mov rsi, r8 ;
syscall ; Read a character from the cli.
mov rax, 1 ; syscall write
mov rdi, 1 ;
mov rsi, r8 ;
mov rdx, 1 ;
syscall ; Print the character back to the cli.
mov rax, 60 ;
mov rdi, 0 ;
syscall ; Exit nicely.
section .bss
stack: resb 131072
I'm using nasm on Ubuntu 16.04 to compile like this:
nasm -f elf64 -o test.o test.asm
ld -m elf_x86_64 -o test test.o
./test
The problem is that when you try without the first write, you do not set the rdx to 1 with mov rdx, 1.Therefore, you are not telling how much to read to your syscall.
Here you can have a look at the
syscall table

Gdb problem when debugging with breakpoints and symbols

I coding assembly with Nasm, i want debug the program using gdb, but it not works when i put a breakpoint and run the program.
The program compile fine and link too, the problem is gdb.
Here is the commands to compile:
nasm -f elf64 -F dwarf -g types.asm
nasm -f elf64 -F dwarf -g functions.asm
nasm -f elf64 -F dwarf -g Hello.asm
ld -g -o Hello Hello.o functions.o types.o
This is the file i want debug Hello.asm:
%include "functions.asm"
section .bss
res: resb 1
fout: resb 1
section .text
global _start: ;must be declared for linker (ld)
section .data
msg db 'Hello, world!', 0xa ;string to be printed
len equ $ - msg ;length of the string
filename db 'hello.txt'
_start: ;tells linker entry point
mov ecx,5
mov edx,4
call sum
mov [res],eax
mov edx,1 ;message length
mov ecx,res ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
write_string msg,len
create_file filename
mov [fout],eax
close_file [fout]
call print_msg
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
sum:
mov eax,ecx
add eax,edx
add eax,'0'
ret
Next i open gdb:
gdb Hello
(gdb) break _start
Function «_start» not defined
¿Compilación de breakpoint pendiente hasta futura cargada de biblioteca compartida? (y or [n]) y
Punto de interrupción 1 (_start) pendiente.
(gdb) run
Starting program: /asm/Hello
9Hello, world!
Hello, world!from another file
[Inferior 1 (process 5811) exited with code 01]
(gdb)
I solved it, i only change position section .data to section .text and the debugger works.I don't know why, but now the gdb take the .start.

Putting a static address into a register with GNU AS (GAS) .intel_syntax?

.intel_syntax noprefix
.global _start
.text
_start:
mov eax, 4
mov ebx, 1
mov ecx, msg
mov edx, 15
int 0x80
mov eax, 1
mov ebx, 14
int 0x80
.data
msg:
.ascii "Hello, World!\n"
I am trying to compile the above code via GNU AS using the following commands:
asad#Arcturus:~/Desktop/ZJNK$ as --32 -msyntax=intel code.S -o code.o
asad#Arcturus:~/Desktop/ZJNK$ ld -m elf_i386 code.o -o a.out
asad#Arcturus:~/Desktop/ZJNK$ ./a.out
asad#Arcturus:~/Desktop/ZJNK$
But I cannot get any output on the terminal. However, the exit code is still readable:
asad#Arcturus:~/Desktop/ZJNK$ echo $?
14
I am using 64-bit Linux and am able to run the above code via nasm after required changes.
What could have gone wrong?
To load the address of msg, use
mov ecx, offset msg

Printing `argv[]` with nasm

I'm trying to print the command line arguments given to my program, using nasm:
GLOBAL main
EXTERN printf
section .rodata
fmt db "Argument: %s", 10, 0
section .text
main:
push ebp ; push ebp0
mov ebp, esp ; [ebp1] == ebp0
push dword[ebp+8] ; push argc
call print_args
mov eax, 0 ; return(0)
mov esp, ebp ; pop
pop ebp ; stack frame
ret
print_args:
push ebp ; pusheo ebp1
mov ebp, esp ; [ebp2] == ebp1
mov edi, dword[ebp+8] ; [ebp+8] == argc
jmp lop
postlop:
mov esp, ebp
pop ebp
ret
lop:
sub edi, 1
cmp edi, 0
jz postlop
mov esi, [ebp] ; [esi] == ebp1
mov ebx, [esi + 12] ; [esi+12] = [ebp1+12] = argv[0]?
push ebx
push fmt
call printf
jmp lop
However, this prints only garbage (I believe this should print argv[0], argc-1 times.).
I'm compiling my code with:
nasm -f elf32 main.asm
gcc -m32 main.o -o main.out
What is wrong?
By the way, using dword[ebp+8] works correctly to pick up argc.
I'm running this on ubuntu. Program does output Argument: ... argc-1 times, but the ... is garbage.
Just like [epb+8]is argc, [esi + 12] is argv, i.e. the address of the array of argument adresses. Thus, in order to find argv[0], you have to dereference once more.
mov esi, [ebp] ; [esi] == ebp1
mov ebx, [esi + 12] ; [esi+12] = [ebp1+12] = argv
push dword [ebx] ; [ebx] = argv[0]
;^^^^^^^^^^^
push fmt
call printf
I worked on this and this is all you need
Assemble as so. On my 32-bit debian 9 VM:
$ nasm -felf32 -g args.s -o args.o
$ gcc -no-pie args.o -o args
segment .data
format db "%s",0x0a,0
segment .text
global main ; let the linker know about main
extern printf ; resolve printf from libc
main:
push ebp ; prepare stack frame for main
mov ebp, esp
sub esp, 8
mov edi, dword[ebp+8] ; get argc into edi
mov esi, dword[ebp+12] ; get first argv string into esi
start_loop:
xor eax, eax
push dword [esi] ; must dereference esi; points to argv
push format
call printf
add esi, 4 ; advance to the next pointer in argv
dec edi ; decrement edi from argc to 0
cmp edi, 0 ; when it hits 0, we're done
jnz start_loop ; end with NULL pointer
end_loop:
xor eax, eax
leave
ret

NASM getting args and calling sys_execve

I'm trying to write a program that takes two arguments : the path of an executable file and the parameter to launch that executable with.
Example:
$ ./program /bin/ping 127.0.0.1
But the code I wrote does not seem to do anything, can you please tell me what am I doing wrong?
global main
section .text
main:
push ebp
mov ebp, esp
check_argc:
mov eax, [ebp + 8] ; eax <- argc
cmp eax, 1
jg do_execve
jmp done
do_execve:
mov eax,11 ; linux system call number (11) - sys_execve
mov ebx,[ebp+12] ; ebx <- argv[1]
lea ecx,[ebp+12] ; ebx <- &argv[1]
mov edx,0
int 0x80
done:
leave
ret
EDIT:
For compilation I used:
$ nasm -f elf32 program.asm
$ gcc -lc -m32 program.o -o program.exe
The "check_argc" part seems to work, I checked it with puts.
You problem lies here:
mov ebx,[ebp+12] ; ebx <- argv[1]
lea ecx,[ebp+12] ; ebx <- &argv[1]
The C prototype of main is: int main(int argc, char** argv), so what you're doing is actually:
mov ebx,[ebp+12] ; ebx <- argv = &argv[0]
lea ecx,[ebp+12] ; ecx <- &argv
What you want to do is something like the following:
mov ecx, [ebp+12] ; ecx <- &argv[0]
add ecx, 4 ; ecx <- &argv[1]
mov ebx, [ecx] ; ebx <- argv[1]

Resources