Как вызвать основную функцию в связанном исполняемом файле, написанном на C из NASM, с правильным указанием argc, argv, envp - PullRequest
1 голос
/ 12 мая 2019

Я связываю программу на C с исполняемым файлом NASM. Файл сборки вызывает основную функцию в связанной программе на C

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

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

Что я пробовал:

infect.c содержит главную функцию следующим образом:

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);
    ...

Так как я хочу вызвать функцию main в infect.c из virus.asm. Основная функция должна infact находиться в virus.asm, и поскольку в исполняемом файле не может быть двух основных функций, я изменил функцию main в infect.c на

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) Я не знаю, как вызвать эту функцию заражения из сборки NASM, это то, что я пробовал в virus.asm файле

extern infect
main:
    call infect

Программа работает, но не дает желаемого эффекта. infect.c - это вирус ELF, который должен искать файлы в CWD и заражать их.

2) Кажется, проблема в int argc, char *const argv[], char *const envp[], которую я не обрабатываю должным образом во время вызова

Как правильно вызвать функцию в infect.c из virus.asm с argc, argv и envp, предоставленными для корректной работы программы?

Ответы [ 2 ]

2 голосов
/ 17 мая 2019
_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

Выполните это первым делом в функции _start. Если вам нужно выполнить позже, убедитесь, что вы сохранили следующие регистры

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

тогда вы можете перезагрузить эти регистры и вызвать указанную выше инструкцию для вызова main

2 голосов
/ 12 мая 2019

Вы можете указать точку входа _start в asm-файле. Ниже приведен пример кода, который устанавливает argc, argv и envp для elf abi на AMD64 и ядра Linux. Он не будет работать с реальным кодом, потому что он не выполняет обычный процесс инициализации, такой как установка сегмента fs для tls, инициализация статических переменных и т. Д ..., но он дает вам первый вкус того, что нужно сделать!

Заметка [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
...