assembly, how to use mprotect? - linux

I am trying to make self modifying code in Linux. I thought it would works but didn't.
section .data
section .text
global _start
_start:
mov eax, 125 ;mprotect syscall number
mov ebx, _start ; *addr
mov ecx, 0x10000 ;page interval.
mov edx, 7 ; rwx permission
int 0x80
jmp modify
target:
mov eax, edx
halt:
mov ebx, 1
mov eax, 1
int 0x80
modify:
mov ebx, [new]
mov [target], ebx
jmp target
new:
mov ebx, 0
I used nasm on ubuntu 18.04.
INT 0x80 return value is -22 0xffffffea
I don't know what is wrong.

Run your program under strace, like strace ./a.out to decode system call args and return values.
Probably your base address isn't page-aligned, or the range includes some unmapped pages. You could round down to a page boundary with and ebx, -4096, or you could align _start by putting align 4096 before it.
Or instead of calling mprotect yourself, you could link your program with ld --omagic to make the text segment read+write+exec.

Related

Assembly NASM - AND Mask

When I run this program it says:
jdoodle.asm:9: error: invalid combination of opcode and operands
The problem is the AND al, ah. The rest of the code should be correct, I just need to know how to solve this problem because as it seems I can't do an AND between 2 registers.
section .text
global _start
_start:
call _input
mov al, input
mov ah, maschera
and al, ah
mov input, al
call _output
jmp _exit
_input:
mov eax, 3
mov ebx, 0
mov ecx, input
mov edx, 1
int 80h
ret
_output:
mov eax, 4
mov ebx, 1
mov ecx, input
mov edx, 1
int 80h
ret
_exit:
mov eax, 1
int 80h
section .data
maschera: db 11111111b
segment .bss
input resb 1
MASM/TASM/JWASM syntax is different from NASM. If you want to load/store data at an address you need to explicitly use square brackets. If you want to use the MOV instruction to place the address of a label in a variable you do not use square brackets. Square brackets are like a de-reference operator.
In 32-bit code you will want to ensure addresses are loaded into 32-bit registers. Any address above 255 won't fit in an 8 byte register, any address above 65535 won't fit in a 16-bit register.
The code you were probably looking for is:
section .text
global _start
_start:
call _input
mov al, [input]
mov ah, [maschera]
and al, ah
mov [input], al
call _output
jmp _exit
_input:
mov eax, 3
mov ebx, 0
mov ecx, input
mov edx, 1
int 80h
ret
_output:
mov eax, 4
mov ebx, 1
mov ecx, input
mov edx, 1
int 80h
ret
_exit:
mov eax, 1
int 80h
section .data
maschera: db 11111111b
segment .bss
input resb 1

how to call lseek and _llseek syscall from assembly [duplicate]

I was experimenting and have the following assembly code, which works very well, except that I get a "Segmentation fault (core dumped)" message right before my program ends:
GLOBAL _start
%define ___STDIN 0
%define ___STDOUT 1
%define ___SYSCALL_WRITE 0x04
segment .data
segment .rodata
L1 db "hello World", 10, 0
segment .bss
segment .text
_start:
mov eax, ___SYSCALL_WRITE
mov ebx, ___STDOUT
mov ecx, L1
mov edx, 13
int 0x80
It doesn't matter whether or not I have ret at the end; I still get the message.
What's the problem?
I'm using x86 and nasm.
You can't ret from start; it isn't a function and there's no return address on the stack. The stack pointer points at argc on process entry.
As n.m. said in the comments, the issue is that you aren't exiting the program, so execution runs off into garbage code and you get a segfault.
What you need is:
;; Linux 32-bit x86
%define ___SYSCALL_EXIT 1
// ... at the end of _start:
mov eax, ___SYSCALL_EXIT
mov ebx, 0
int 0x80
(The above is 32-bit code. In 64-bit code you want mov eax, 231 (exit_group) / syscall, with the exit status in EDI. For example:
;; Linux x86-64
xor edi, edi ; or mov edi, eax if you have a ret val in EAX
mov eax, 231 ; __NR_exit_group
syscall

Linux Assembly segmentation fault print using loop

I'm writing an assembly program that would print even numbers between 0-9 using a loop. I encountered this problem, segmentation fault while running the code. I check other answers on the site but couldn't find an answer that satisfies my issue.
I suspect that the function nwLine might be the source of the problem.
;;this program prints even numbers from 0-8 using loop function
section .text
global _start
cr db 10
_start: ;tell linker entry point
mov ecx, 5
mov eax, '0'
evenLoop:
mov [evnum], eax ;add eax to evnum
mov eax, 4
mov ebx, 1
push ecx
mov ecx, evnum
mov edx, 1
int 80h
call nwLine
mov eax, [evnum]
sub eax, '1'
inc eax
add eax, '2'
pop ecx
loop evenLoop
nwLine: ;function to move pointer to next line
mov eax,4 ; System call number(sys_write)
mov ebx,1 ; File descriptor 1 - standard output
mov ecx, cr
mov edx, 1
int 80h ; Call the kernel
ret
mov eax,1 ;system call number (sys_exit)
int 80h ;call kernel
section .bss
evnum resb 1
if anyone knows how to solve the problem with the nwLine function, please tell me.

linux assembly: how to call syscall?

I want to call a syscall in assembly. The problem is I can't mov ecx,rsp. rsp is 64-bit register, ecx is a 32-bit register. I want to pass the buffer addr as a parameter of this syscall. What can I do? Thanks.
section .data
s0: db "Largest basic function number supported:%s\n",0
s0len: equ $-s0
section .text
global main
extern write
main:
sub rsp, 16
xor eax, eax
cpuid
mov [rsp], ebx
mov [rsp+4], edx
mov [rsp+8], ecx
mov [rsp+12], word 0x0
mov eax, 4
mov ebx, 1
mov ecx, rsp
mov edx, 4
int 80h
mov eax, 4
mov ebx, 1
mov ecx, s0
mov edx, s0len
int 80h
mov eax, 1
int 80h
To make a system call in 64-bit Linux, place the system call number in rax, and its arguments, in order, in rdi, rsi, rdx, r10, r8, and r9, then invoke syscall.
Note that 64-bit call numbers are different from 32-bit call numbers.
Here is an example in GAS syntax. NASM syntax for putting an address in a register is lea rsi, [rel message] using a RIP-relative LEA.
.global _start
.text
_start:
# write(1, message, 13)
mov $1, %rax # system call 1 is write
mov $1, %rdi # file handle 1 is stdout
lea message(%rip), %rsi # address of string to output
mov $13, %rdx # number of bytes
syscall
# exit(0)
mov $60, %rax # system call 60 is exit
xor %rdi, %rdi # return code 0
syscall
.section .rodata # read-only data section
message:
.ascii "Hello, World\n"
See also What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code?

Linked assembly subroutine doesn't work as expected

I'm writing a simple subroutine in FASM to print 32-bit unsigned integers to STDOUT. This is what I came up with:
format elf
public uprint
section ".text" executable
uprint:
push ebx
push ecx
push edx
push esi
mov ebx, 10
mov ecx, buf + 11
xor esi, esi
do:
dec ecx
xor edx, edx
div ebx
add dl, 0x30
mov [ecx], dl
inc esi
test eax, 0
jnz do
mov eax, 4
mov ebx, 1
mov edx, esi
int 0x80
pop esi
pop edx
pop ecx
pop ebx
ret
section ".data" writeable
buf rb 11
Then I wrote another program to test whether the above subroutine works properly:
format elf
extrn uprint
public _start
section ".text" executable
_start:
mov eax, 1337
call uprint
mov eax, 4
mov ebx, 1
mov ecx, newline
mov edx, 1
int 0x80
mov eax, 1
xor ebx, ebx
int 0x80
section ".data"
newline db 0x0A
I compiled both these programs to their corresponding object files and linked them to create the executable.
On executing the program however it only displayed 7 instead of 1337. As it turns out only the last digit of the number is display regardless of the number itself.
This is strange because my uprint subroutine is correct. In fact if I combine both these programs into a single program then it displays 1337 correctly.
What am I doing wrong?
I gain the distinct impression that your LINK operation is building the uprint before the _start and you're in fact entering UPRINT, not at _start as you expect.
I found out my mistake. I'm using test eax, 0 which always sets the zero flag. Hence only the first digit is processed. Intead I need to use either test eax, eax or cmp eax, 0.

Resources