How to patch assembly code to the end of exe file - linux

I'm trying to patch code written in x86 Assembly to an end of the file given as a parameter.
specific in my code:
the function code_start prints a message to stdout.
the function code_end purpose is to patch the code from code_start to the end of a file name given as a parameter from the C program.
My question is:
What should I fill (where I put the question marks) or change in the function code_end in the order it to work as I wish.
My idea was to open the file by an append system call, write the function code_start, close the file.
important note: without using any imported functions, only by using system calls
Code snippet:
code_start:
pushad
mov eax,4 ;system call number (sys_write)
mov ebx,1 ;file descriptor (stdout)
mov ecx, msg ;message to write
mov edx, len ;message length
int 0x80 ;call kernel
popad
ret
code_end:
push ebp ; Save caller state
mov ebp, esp
sub esp, 4 ; Leave space for local var on stack
pushad ; Save some more caller state
mov eax,4 ;system call number (sys_write)
mov ebx, [ebp+8] ; Copy function args to registers: leftmost -> fileName
mov ecx, 1024 ;system call number O_APPEND
int 0x80 ;call kernel
;eax has the pointer to end of file
mov ebx, eax ;move the file pointer to second argument
mov eax, 4 ;move the code of SYS_WRITE
mov ecx, ?? ;from where to write
mov edx, ?? ;how much to write
int 0x80 ;call kernel
mov eax,6 ;system call number (SYS_CLOSE)
mov ebx, [ebp+8] ; Copy function args to registers: leftmost -> fileName
int 0x80 ;call kernel
popad
add esp, 4
pop ebp ; Restore caller state
ret

First of all instead of: mov ecx 1024 it should be mov ecx, 1025 in order to open it for write and appeand.
Second instead of the question marks it should be:
mov ecx, code_start
mov edx code_end
sub edx, code_start

Related

Appending Two Strings in Assembly

We've learned only a touch (by touch I mean nothing in class, only theoretical talk of how registers work) of assembly in school and my professor wants us to do something in assembly a little harder than adding two integers. I've been doing a bunch of research and have come up with some code. I am using Microsoft Visual Code on a Linux VM. From my understanding, the code puts input1 into ECX, then puts input2 into ECX, then this essentially appends IF the length of input1 is at least 10 bytes. Not entirely sure how this is working. If I use less than 10 bytes for the first input I get the next input printed on a new line.
I've been trying to understand how [variable] and variable, value vs. address if I understand correctly, fit into this and have played around with reserved byte variables. I'm not asking for my project to be done, but I feel like I'm blindly trying this as opposed to without direction. Thanks in advance guys!
section .text
global main ;must be declared for using gcc
extern printf ;C library used to print
extern exit ;C library used to exit
extern scanf ;C library used to input user entry
main: ;tell linker entry point, called main due to C library usage
;Reads prompt message
mov eax, 4 ;system call number (sys_write)
mov ebx, 1 ;file descriptor (stdout)
mov ecx, prompt1 ;message to write called prompt
mov edx, len1 ;message length
int 0x80 ;call kernel
;Accept user input
mov eax, 3 ;system call number (sys_read)
mov ebx, 0 ;file descriptor (stdin)
mov ecx, input1 ;variable to read into, i.e. input
mov edx, 25 ;input length
int 0x80 ;call kernel
;Reads prompt message
mov eax, 4 ;system call number (sys_write)
mov ebx, 1 ;file descriptor (stdout)
mov ecx, prompt2 ;message to write called prompt
mov edx, len2 ;message length
int 0x80 ;call kernel
;Accept user input
mov eax, 3 ;system call number (sys_read)
mov ebx, 0 ;file descriptor (stdin)
mov ecx, input2 ;variable to read into, i.e. input
mov edx, 25 ;input length
int 0x80 ;call kernel
;cld
mov al, 0
mov ecx, 50
mov edi, input3
repne scasb
dec edi
mov ecx, 2
mov esi, input4
rep movsb
int 0x80
;Display user input
mov eax, 4 ;system call number (sys_write)
mov ebx, 1 ;file descriptor (stdout)
mov ecx, input1 ;message to write
mov edx, 50 ;message length
int 0x80 ;call kernel
call exit
section .data
prompt1 db 'Please enter your first string: ', 0xa ;string to print for user input
len1 equ $ - prompt1 ;length of string prompt
prompt2 db 'Please enter your second string: ',0xa ;string to print for user input
len2 equ $ - prompt2 ;length of string prompt
input3: times 10 db 0 ;variable input is of 10 bytes, null string terminated
input4: times 1 db 0
section .bss
input1 resb 50
input2 resb 25

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.

How to read and write a byte from and to stdin/stdout using Syscall in x86 with NASM assembler?

I am trying to read a string from stdin and print it back out using x86, NASM, and Syscalls. Reading in a byte will be a function, and writing out a byte will be a function. I am reading the string from stdin and putting each char into an array. Here is my initial idea:
;read_writer.asm
section .data
arr times 100 db 0 ; array of 100 elements initialzed to 0
ptr dd 0
section .text
global _start
_start:
push ebp ; setup stack
mov ebp, esp ; setup stack
push, 0x10 ; allocate space for potential local variables
call readin: ;call read in func
push eax ;return char from readin will be in eax, push it for writeout
call writeout:
leave
mov eax, 1 ;exit
mov ebx, 0
int 0x80
readin:
push ebp
mov ebp, esp ; setup stack
mov eax, 3 ;read
mov ebx, 1 ;stdin
; i feel like i am missing code here bit not sure what
leave ;reset stack
ret ;return eax
writeout:
push ebp
mov ebp, esp ; setup stack
push eax ;push eax since it was pushed earlier
mov eax, 4 ;write
mov ebx, 1 ;stdout
; i feel like i am missing code here bit not sure what
leave ;reset stack
ret ;return eax
Sample input:
Hello World
Sample output:
Hello World
The functions should be used with cdecl, which I dont think I am doing correctly. I also realised I am not putting the chars into arr.
For starters, you're missing the int 0x80 in both readin and writeout.
And, as you can see here, both sys_read and sys_write expect a (const) char* in ecx. That address should point to the buffer where the bytes to write are stored / the read bytes should be stored.The value of edx should be set to the number of bytes to read / write.
So in the readin example you want something like:
mov eax, 3 ;read
mov ebx, 0 ;stdin. NOTE: stdin is 0, not 1
sub esp,4 ; Allocate some space on the stack
mov ecx,esp ; Read characters to the stack
mov edx,1
int 0x80
movzx eax,byte [esp] ; Place the character in eax, which is used for function return values
add esp,4
And similarly for writeout.

add two digit numbers in NASM(Linux)

I want to add two-digit numbers in NASM(Linux). To add two simple numbers, I use the following code:
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov eax,'3'
sub eax, '0'
mov ebx, '4'
sub ebx, '0'
add eax, ebx
add eax, '0'
mov [sum], eax
mov ecx,msg
mov edx, len
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov ecx,sum
mov edx, 1
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
msg db "The sum is:", 0xA,0xD
len equ $ - msg
segment .bss
sum resb 1
The result of the code is 7.But when I carry number 17 in register eax forexample the result is not correct.In this case 5.Tell me please what is the problem? Thank you!
Here's your example with a little bit of cleaning up to help make it easier to read.
Suggestion: this kind of consistency will greatly improve your public image.
But hey; nice commenting, I could read your code and understand it (which is why I decided to answer you)
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov eax, '3'
sub eax, '0'
mov ebx, '4'
sub ebx, '0'
add eax, ebx
add eax, '0'
mov [sum], eax
mov ecx, msg
mov edx, len
mov ebx, 1 ;file descriptor (stdout)
mov eax, 4 ;system call number (sys_write)
int 0x80 ;call kernel
mov ecx, sum
mov edx, 1
mov ebx, 1 ;file descriptor (stdout)
mov eax, 4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax, 1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
msg db "The sum is:", 0xA,0xD
len equ $ - msg
segment .bss
sum resb 1
Okay now, as for your comment, "...But when I carry number 17 in register eax forexample the result is not correct."
I can imagine !
Question, when you "...carry number 17 in register eax..." are you doing it like this ?...
Mov Eax,"17"
If so, slow down and take a look at your code one step at a time via debug.
I believe that what you'll see is that you are actually doing this...
Mov Eax, 3137h
Although it might be
Mov Eax, 3731h
Interesting concept. I've never done anything like that. Whatever.
What's more, if you are using this place to store that same number...
sum resb 1
You only have one byte.
Best I can tell, your example code is limited to single digit numbers.
Now then, since your label sum has reserved only one byte; 8 bits, you can see the problem as you are storing 32 bits there. (Well, you're trying to; it won't work.) No clue what happens when you do that. You probably want to rethink that structure.
As for why 17 becomes 5, no clue here.
Let us know if any of this helps you. Assembly is great stuff. As you are personally experiencing, the initial thought adjustment can be strange for the brain, can't it !

How to save a file in assembly language with nasm in Linux x86?

I'm just wondering how I can throw a buffer to a file. I know I can set up the registers like:
mov eax, 4
mov ebx, (file descriptor here)
mov ecx, myBuffer
mov edx, myBufferLen
int 80h
and then close the file with:
mov eax, 6
int 80h
but I'm not sure how to get the file descriptor. Someone told me that whenever you open a file, after calling the service dispatcher, the eax has the file descriptor. Whatever I try, it doesn't create a new file or save the current one.
mov eax, 5 ; __NR_open
mov ebx, filename ; zero terminated!
mov ecx, 2 ; O_WRITE? Check me on this!
mov edx, 777q ; permissions - Check me on this, too!
int 80h
; did we succeed?
cmp eax, -4096
ja exit
mov [descriptor], eax
; and so on...
;...
xor eax, eax ; claim no error
exit:
mov ebx, eax
neg ebx
mov eax, 1 ; __NR_exit
int 80h
I'm uncertain on the "magic numbers" for open flags and permissions, and too lazy to look them up right now (fs.h?). You may need to "or" the open flags with O_CREATE to create a new file(?). The trick at "exit:" negates the (negative) ERRNO (if any) so you can read it easily with "echo $?". Something like that...
Thanks to #gnometorule for the solution. So this is how you store a buffer into file:
in this case you are receiving the file name as a first parameter when you run the program.
section .text
global _start
_start:
pop ebx ; this is the amount of parameter received (in this case 2)
pop ebx ; this is the direction of our program
pop ebx ; this is the first parameter (our file name eg. "text.txt")
so we open it and move it to a buffer to edit or whatever we want with it.
textEdit:
;we open the file
mov eax, 5
push ebx ; we save the file name in the stack for later use
mov ecx,0
int 80h
; and then we move the information read to buffer
mov eax, 3
mov ebx, eax ; really dont know how this works, but it does.
mov ecx, fileBuffer
mov edx, fileBufferSize
int 80h
now fileBuffer (wich is a buffer defined in section .bss) has what we had in the file we opened. Here you can edit the information. When we want to save it back to the file it goes like this:
saveFile:
;open the file
mov eax, 5
pop ebx ; the file name was stored in the stack,
push ebx ; so we retrieve it and save it back for later use
mov ecx, 2 ; ecx has the access mode ("2"aloud us to read/write)
mov edx, $0666
int 80h
;now we are going to write to the file
mov ebx, eax ; eax has the file descriptor we opened. so we move it to ebx.
mov eax, 4 ; we are going to use the write service (#4)
mov ecx, fileBuffer ; ecx has the adress of what we want to write
mov edx, fileBufferSize ; edx has the amount of bytes we want to write
int 80h
; close the file
mov eax, 6
int 80h
jmp exit ; jump wherever you want, or end your program... etc.
This worked for me.

Resources