Hi i have a very difficult question. I wrote a function in x64 assembly and then i wanted to use it in my main.c. I included the assembly function via header file.
main.c:
#include <stdio.h>
#include "myunistd.h"
#include "mystddef.h"
int main(){
mywrite(1, "Test", 4);
}
myunistd.h:
#ifndef MYUNISTD_H
#define MYUNISTD_H
struct myrusage {};
ssize_t spastwrite(int fd, const void *buf, size_t count);
#endif
myunistd.s:
global mywrite
section .text
mywrite:
mov r8, rdi ; parameters in registers only for testing
mov r9, rsi
mov r10, rdx
mov rax, 1 ; write(
mov rdi, r8 ; STDOUT_FILENO,
mov rsi, r9 ; String,
mov rdx, r10 ; sizeof String
syscall ; );
mov rax, 60 ; exit(
mov rdi, 0 ; EXIT_SUCCESS
syscall ; );
The function works but i have no return argument like in the original write syscall. Also have the warning "implicit declaration of function 'mywrite' is invalid in C99".
Also good to know for you i defined size_t as unsigned long in mystddef.h.
I dont know. Hope you can help :)
Compiled with:nasm -f elf64 myunistd.s -o myunistd.o
clang main.c myunistd.o -o exe
Thx
Instead of using the exit syscall, use ret:
global mywrite
section .text
mywrite:
mov r8, rdi ; parameters in registers only for testing
mov r9, rsi
mov r10, rdx
mov rax, 1 ; write(
mov rdi, r8 ; STDOUT_FILENO,
mov rsi, r9 ; String,
mov rdx, r10 ; sizeof String
syscall ; );
ret
In your myunistd.h, you're declaring spastwrite and not mywrite. Change this:
ssize_t spastwrite(int fd, const void *buf, size_t count);
to this:
ssize_t mywrite(int fd, const void *buf, size_t count);
and it will work.
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
I have a problem with function pointers in assembly, even when my function returns a negative number it always sets rax to a positive number, I did a minimal reproductible example with a function that compares two integers and it does the same thing:
ASM Function code [EDIT]:
global foo
section .data
msg: db `superior\n`
msg_len: equ $-msg
section .text
foo:
push rbx
mov rbx, rdi
mov rdi, 2
mov rsi, 1
sub rsp, 8 ; align the stack frame
call rbx
add rsp, 8
test rax, rax ;[EDIT] correct: test eax, eax
js bar
mov rax, 1
mov rdi, 1
mov rsi, msg
mov rdx, msg_len
syscall
bar:
mov rdi, 1
mov rsi, 2
sub rsp, 8 ; same here
call rbx
add rsp, 8
test rax, rax ;[EDIT] correct: test eax, eax
js exit
mov rax, 1
mov rdi, 1
mov rsi, msg
mov rdx, msg_len
syscall
exit:
pop rbx ;restoring initial data of rbx
ret
main.c code:
#include <stdio.h>
int foo(int (*f)()); //my asm function prototype
int cmp(int i, int j)
{
printf("%d - %d\n", i, j);
return(i - j);
}
int main(void)
{
foo(&cmp);
return (0);
}
The output is:
2 - 1
superior
1 - 2
superior
But it should be just:
2 - 1
superior
Compilation:
nasm -f elf64 foo.s
gcc -c main.c -o main.o
gcc main.o foo.o
Thanks for the help
[EDIT] It didn't work because I checked rax instead of eax, now it works. Thanks for your help
An int is 32 bits, but rax is a 64-bit register. A function that returns int will place its return value in eax, which will typically zero out the high half of rax. So if cmp returns -1, which is the 32-bit number 0xffffffff, then rax will contain 0x00000000ffffffff. This is not a negative 64-bit number, so test rax, rax will not set the sign flag.
Try using test eax, eax as your test instead.
Your code seems too complicated.
Firstly, let's write the thing to do in language like C:
int foo(int (*f)()) {
if (cmp(2, 1) > 0) {
PRINT;
}
if (cmp(1, 2) > 0) {
PRINT;
}
}
Then, let's write assembly code according to this:
global foo
section .data
msg: db `superior\n`
msg_len: equ $-msg
section .text
; int foo(int (*f)()) {
foo:
mov rbx, rdi ; function pointer stored in rbx
; if (cmp(2, 1) > 0) {
mov rdi, 2 ; first integer
mov rsi, 1 ; second integer
call rbx ; call function pointer
cmp rax, 0
jle bar ; jump if rdi <= rsi (signed)
; PRINT;
mov rax, 1
mov rdi, 1
mov rsi, msg
mov rdx, msg_len
syscall ; write "superior\n"
; }
bar:
; if (cmp(1, 2) > 0) {
mov rdi, 1
mov rsi, 2
call rbx
cmp rax, 0
jle bar2
; PRINT;
mov rax, 1
mov rdi, 1
mov rsi, msg
mov rdx, msg_len
syscall ; write "superior\n"
; }
bar2:
; }
ret
To retain your code, points to fix are:
ja is for unsigned comparision. jg should be used to signed comparision instead.
There are code to print after bar2, but there also are code to print after the jump ja bar2 is not taken. You should add ret before bar: to prevent this from being executed.
the following code tries to read the command line arguments and then scans them with sscanf() and use the result to emit utf8 text.
I'm failing to call sscanf() and getting segfault error at the line where I call this function
I have already debugged this and I know where is the problem but not how to solve it.
global main
extern puts
extern sscanf
extern printf
extern emit_utf_8
section .text
main:
cmp rdi, 2
jl argumentsError
add rsi, 8 ; skip the name of the program
forloop:
mov r12, rsi
push rdi
push rsi
push r12
sub rsp, 8 ; must align stack before call
; start of for bloc
xor rax, rax
mov rdi, qword [r12]
mov rsi, codePointFormat
mov rdx, qword [codePoint]
call sscanf
cmp rax, 1
je ifthen
jmp else
ifthen:
mov rdi, codePoint
call emit_utf_8
jmp endif
else:
mov rdi, incorrectFormat
mov rsi, r12
call printf
endif:
; end of for bloc
add rsp, 8 ; restore %rsp to pre-aligned value
pop r12
pop rsi
pop rdi
add rsi, 8 ; point to next argument
dec rdi ; count down
jnz forloop ; if not done counting keep going
ret
argumentsError: mov rdi, argumentsRequiredMessage
call puts
mov rdi, argumentDescription
call puts
xor rax, rax
inc rax
ret
section .data
argumentsRequiredMessage:
db "This program requires one or more command line arguments,", 0
argumentDescription: db "one for each code point to encode as UTF-8.", 0
incorrectFormat: db "(%s incorrect format)", 0
codePointFormat: db "U+%6X", 0
section .bss
codePoint: resb 8 ; The code point from sscanf should go here.
Is there a way to pass that third argument?
sscanf() signature.
in __cdecl sscanf(const char *const _buffer, const char *const _Format, ...)
I'm using ubuntu 19.04 64 bit
I want to call a ASM function in a c code, How do I pass the parameters to the ASM code?
#include <stdio.h>
extern int * asm_mod_array(int *ptr,int size);
int main()
{
int fren[5]={1,2,3,4,5};
/*Call ASM func*/
int a=asm_mod_array(fren,5);
printf(u,a);
return 0;
}
now, i want to use this parameters in my ASM function.
;asm_mod_array(int ptr,int size)
global asm_mod_array
asm_mod_array:
push r12
mov rdi, 0
mov rsi, 0
mov r12,0
mov rax,0
sumLoop:
add rax, [rdi+r12]
inc r12
cmp r12, rsi
jl sumLoop
mov [rdx], rax
pop r12
ret
NOTE: in the ASM code the 0, have to be changed with the parameters passed by c.
You can access the arguments according to the AA64 calling conventions for your platform. On most systems, except Windows, this is defined by the System V AMD64 ABI.
By these calling conventions, ptr will be in rdi and size will be in rsi. The return value is placed in rax.
See X86 calling conventions.
For a security class I am supposed to write self-modifying code for a program which finds its own executable on the disk, reads the binary data, and encrypts part of it before writing it back out to the disk. This is supposed to be like a polymorphic virus which changes itself to fool antivirus scanners which detect known signatures.
I have all the pieces pretty much in place:
I am finding the executable using /proc/self/exe.
I am using a simple AES implementation to encrypt 16 byte string in some dummy code in the executable.
I am able to read the binary data in and locate the part I need to encrypt.
My problem is that the only way I have been able to open the executable is in read-only mode "rb". If I try to open the file for writing in mode "wb" or "r+b" I get back the error "Text file busy". Is there anyway for me to write to a process's own executable in C? Can I do this by changing the permissions somehow?
EDIT: What I am trying to accomplish is to have an executable which will encrypt part of itself each time that it runs so that it will have a new checksum after every time it runs.
After reading data from the executable binary, how can I either write back to it or remove it and replace it with a new file with the same filename?
You cannot write to a file that is currently mapped as an executable. However, you can write to a file that has the same path as the current executable, so long as it isn't actually the same file — try unlinking the file you're being executed from and creating a new file in its place, for instance.
In order to do self modification too, I wrote a small code in nasm (which can be used as a stub), which opens itself and at the middle of the code (right after the mmap), we have a pointer which points to the bytes of the executable that we can modify.
The code looks like this:
BITS 64
section .text
global _start
_start:
call _main__
mov rax, 60
mov rdi, 0x0
syscall ; exit(0);
_main__:
push rbp
mov rbp, rsp
sub rsp, 144 ; stat_file
mov rdi, [rbp+0x18]
lea rsi, [rsp]
call _open_self ; open self
push r12 ; len file
push rax ; addr
mov r14, rsi
mov rdi, [rbp+0x18] ; pathname
pop rsi ; addr
pop rdx ; len
push rdx
push rsi
call __create
mov r13, rax ; second fd
mov rdi, r14 ; fd
pop rsi ; addr -> mmap
pop rdx ; len_file
call __close_unmap
mov rax, 87
mov rdi, [rbp+0x18]
syscall
mov rax, 0x3 ; close(scnd_fd);
mov rdi, r13
syscall
mov rax, 86
push 'nasm'
lea rdi, [rsp]
mov rsi, [rbp+0x18]
syscall ; link tmp name to original name
mov rax, 87
lea rdi, [rsp]
syscall ; delete old tmp file
leave
ret
; ===============================
; Open himself
_open_self:
push rbp
mov rbp, rsp
mov r15, rsi ; &stat_file
mov r12, rdi ; *pathname
mov rax, 0x2
mov rsi, 0x0 ; 0_RD
mov rdx, 509
syscall
push rax ; fd
mov rdi, rax ; fd
mov rsi, r15 ; struct stat
mov rax, 5 ; fstat
syscall
xor rdi, rdi
mov rsi, qword [r15+48]
mov rdx, 0x4
mov r10, 0x2
pop r8
push r8
mov r9, 0x0
mov rax, 9
syscall ; mmap
; rax -> byte of the executable that we gonna dump
mov r12, qword [r15+48]
pop rsi ; fd
leave
ret
; ===============================
; int __create(const char *pathname, void *addr, ssize_t len_bytes_mapped);
__create:
push rbp
mov rbp, rsp
push rsi ; addr
push rcx ; len
push 'nasm'
lea rdi, [rsp]
mov rax, 0x2
mov rsi, 0x42 ; 0_CREAT | O_RDWR
mov rdx, 509
syscall ; sys_open
add rsp, 0x8 ; 'nasm'
mov r9, rax ; fd
mov rdi, rax ; fd
mov rax, 0x1
pop rdx
pop rsi
syscall ; sys_write
mov rax, r9 ; fd final
leave
ret
; int __close_unmap(int fd, unsigned lon addr, ssize_t len_file);
__close_unmap:
push rbp
mov rbp, rsp
push rdi
mov rdi, rsi
mov rsi, rdx
mov rax, 11
syscall ; munmap(addr, len_file)
pop rdi
mov rax, 3
syscall ; close(fd);
leave
ret
It is a bit long but it makes just :
-Open it self in read mode (O_RD == 0x0)
-Do a stat(*pathname, &buffer_struct_stat);
-And then a mmap(0, buffer_struct_stat.st_size, 0x4, MAP_PRIVATE, fd_read_only, 0);
-Here you can edit your executable by editing the bytes at the address returned by mmap
-Create a tmp file named "nasm"
-Do a write(fd_tmp, address_of_mmap, buffer_struct_stat.st_size)
-Close the two file descriptors and munmap the mmap
-Now it's cool : unlink(pathname) and link("nasm", "pathname")