简体   繁体   中英

How to call a main function in a linked executable written in C from NASM with argc,argv,envp supplied correctly

I am linking a C program to a NASM executable. The assembly file invokes the main function in the linked C program

virus:  infect.c virus.o
    $(CC) $(LFLAGS) $^ -o $@

virus.o: virus.asm template.asm.inc
    $(ASM) $(AFLAGS) $< -o $@

What I tried:

The infect.c contains the main function in this manner:

int main(int argc, char *const argv[], char *const envp[]) {
    DIR *dir;
    struct dirent *ent;
    struct stat st;
    int vfd, xfd, magic;
    pid_t pid;
    off_t offset;
    ino_t inode;

    vfd = open(argv[0], O_RDONLY);
    ...

Since I want to call the main function in infect.c from virus.asm . The main function should infact be in the virus.asm and since there cannot be two main functions in a executable I changed the main function in infect.c to

int infect(int argc, char *const argv[], char *const envp[]) {
    DIR *dir;
    struct dirent *ent;
    struct stat st;
    int vfd, xfd, magic;
    pid_t pid;
    off_t offset;
    ino_t inode;

    vfd = open(argv[0], O_RDONLY);
    ...

1) I do not know how to call this infact function from the NASM assembly, this is what i tried in virus.asm file

extern infect
main:
    call infect

The program runs, however it doesn't produce the desired effect. The infect.c is an ELF virus that is supposed to look for files in CWD and infect them.

2) The issue seems to be the int argc, char *const argv[], char *const envp[] that i'm not handling properly while calling

How do i properly call the function in infect.c from virus.asm with the argc , argv and envp supplied in order for the program to work correctly?

You can provide a _start entry point in an asm file. Bellow an example code that set argc, argv and envp for elf abi on AMD64, and linux kernel. It will not work with real code because it does not perform usual initialization process like setting fs segment for tls, initializing static variables etc... but it gives you a first taste of what need to be done!

Memo [argc -> %rdi ; argv -> %rsi ; envp -> %rdx ]

.global _start
.type _start,@function
.align 16
_start:
    .cfi_startproc
    .cfi_undefined rip
/*nullify rbp as required by doc*/
    xor %rbp, %rbp
/*move argc to rdi and advance rsp*/
    popq %rdi
/*set argv*/
    movq %rsp, %rsi
/*now envp is at rsp+8*argc+8*/
    lea 8(%rsp, %rdi, 8), %rdx
/*realign stack*/
  push %rdi
/*push rsp to the stack*/
  callq main
/*call _exit at return*/
  movq %rax,%rdi
  mov $231, %rax
  syscall
  .cfi_endproc
_start:
    xor rbp, rbp
    pop rdi
    mov rsi, rsp
    lea rdx, [rsp+rdi+8*8]
    push rdi
    call main
    mov rdi, rax
    mov eax, 1
    int 80h

Execute this first thing in the _start function. If you need to execute later on ensure you save the following registers

; save initial program state
mov rbx, rsp 
mov r14, rdi
mov r15, rsi

then you can reload these registers and call the instruction above to call main

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM