Выполнить системную команду в 64-битной сборке? - PullRequest
2 голосов
/ 19 февраля 2020

Недавно я пытался выполнить системные команды, используя чистую сборку. Мне удалось добиться этого в x32-битном двоичном файле, как указано здесь: выполнить системную команду (bash), используя сборку?

Но сейчас я пытаюсь интегрировать эту же процедуру в x64 бит двоичный Возможно, я очень плохо разбираюсь в искусстве поиска в Google, но я не смог найти ни одной статьи, показывающей, как выполнять системные команды в битах x64.

В точности сказано, что я сделал ниже:

SECTION .data
SECTION .text
global main
main:
xor rax, rax
xor rdx, rdx

push rdx

mov rdi, 0x736c2f2f6369622f    ; "sl/nib/"
push rdi
mov rbx, rsp

push rdx

mov rdi, 0x2f
push rdi
mov rsi, rsp

push rax
push rsi
push rbx

mov rcx, rsp

mov rax, 59
syscall

mov rax, 60
syscall

точка останова при первом системном вызове:

(gdb) x/20x $rsp
0x7fffffffe140: 0xffffe168      0x00007fff      0xffffe158      0x00007fff
0x7fffffffe150: 0x00000000      0x00000000      0x0000002f      0x00000000
0x7fffffffe160: 0x00000000      0x00000000      0x6369622f      0x736c2f2f
0x7fffffffe170: 0x00000000      0x00000000      0xf7e1bbbb      0x00007fff
0x7fffffffe180: 0x00000000      0x00000000      0xffffe258      0x00007fff
(gdb) x/20x $rcx
0x7fffffffe140: 0xffffe168      0x00007fff      0xffffe158      0x00007fff
0x7fffffffe150: 0x00000000      0x00000000      0x0000002f      0x00000000
0x7fffffffe160: 0x00000000      0x00000000      0x6369622f      0x736c2f2f
0x7fffffffe170: 0x00000000      0x00000000      0xf7e1bbbb      0x00007fff
0x7fffffffe180: 0x00000000      0x00000000      0xffffe258      0x00007fff
(gdb) x/20x $rsi
0x7fffffffe158: 0x0000002f      0x00000000      0x00000000      0x00000000
0x7fffffffe168: 0x6369622f      0x736c2f2f      0x00000000      0x00000000

Вывод Strace:

execve("./system", ["./system"], 0x7ffd27c17790 /* 45 vars */) = 0
brk(NULL)                               = 0x5642527c2000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or     directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=104798, ...}) = 0
mmap(NULL, 104798, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fc05fca4000
close(3)                                = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) =     3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\320l\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1820104, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc05fca2000
mmap(NULL, 1832568, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fc05fae2000
mprotect(0x7fc05fb07000, 1642496, PROT_NONE) = 0
mmap(0x7fc05fb07000, 1339392, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x25000) = 0x7fc05fb07000
mmap(0x7fc05fc4e000, 299008, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x16c000) = 0x7fc05fc4e000
mmap(0x7fc05fc98000, 24576, PROT_READ|PROT_WRITE,     MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b5000) = 0x7fc05fc98000
mmap(0x7fc05fc9e000, 13944, PROT_READ|PROT_WRITE,     MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fc05fc9e000
close(3)                                = 0
arch_prctl(ARCH_SET_FS, 0x7fc05fca3500) = 0
mprotect(0x7fc05fc98000, 12288, PROT_READ) = 0
mprotect(0x564250be4000, 4096, PROT_READ) = 0
mprotect(0x7fc05fce5000, 4096, PROT_READ) = 0
munmap(0x7fc05fca4000, 104798)          = 0
execve(0x2f, [0x2f], NULL)              = -1 EFAULT (Bad address)
exit(47)                                = ?
+++ exited with 47 +++

Поскольку мы имеем дело с 64-битным ar c, то предположим, что нам может потребоваться pu sh 64-битный NULL после каждого аргумента тоже, верно? Я немного поигрался с pu sh 32-битным NULL, чтобы отделить аргументы в стеке, но это не сработало.

Не уверен, какую ошибку я допускаю, что скрипт не работает : (

Любое руководство очень ценится.

Я использую nasm в x64 bit kali linux

1 Ответ

1 голос
/ 19 февраля 2020

Огромное спасибо @ PeterCordes.

  1. В 64-битной архитектуре вы можете посетить unistd_64.h, чтобы найти коды для системных вызовов. которые в этом случае для execve системного вызова были 59.

  2. strace очень помогли. с небольшой отладкой обнаружил, что местоположение исполняемого файла /bin//ls должно храниться в rdi, а аргументы /bin//ls ./ должны храниться в rsi.

полный рабочий код ниже:

SECTION .data
SECTION .text
global main
main:
xor rax, rax
xor rdx, rdx

push rdx

mov rcx, 0x736c2f2f6e69622f    ; "sl/nib/"
push rcx
mov rdi, rsp

;push rdx

mov rcx, 0x2f2e 
push rcx
mov rsi, rsp

push rax
push rsi
push rdi

mov rsi, rsp
mov rax, 59
syscall

mov rax, 60
syscall
...