【问题标题】:Execute system command in x64 bit assembly?在 x64 位程序集中执行系统命令?
【发布时间】:2020-02-19 19:39:15
【问题描述】:

我最近一直在尝试使用纯汇编执行系统命令。我设法在 x32 位二进制文​​件中实现它,如下所示:execute system command (bash) using assembly?

但现在我正在尝试将相同的过程集成到 x64 位二进制文​​件中。我可能不擅长谷歌搜索,但我找不到任何展示如何在 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 位弧,那么假设我们可能也必须在每个参数之后推入 64 位 NULL,对吗? 我玩了一点,推送一个 32 位 NULL 来分隔堆栈中的参数,但效果不佳。

不知道我犯了什么错误,脚本不工作:(

非常感谢任何指导。

我在x64 bit kali linux 中使用nasm

【问题讨论】:

  • rax=0x0b=11 / 系统调用是 munmap。使用strace 调试进行系统调用的程序。
  • @PeterCordes 系统调用 0x0b 是否应该是别的东西?我明白 64 位系统调用是不同的,例如 0x04 是 32 位写入的,但 0x01 是 64 位的。
  • eax=0x0b / int 0x80 是 execve,所以显然这就是您在该代码的 64 位端口中想要的。 (显然,这是您调用可执行文件而不是 munmap 所需的系统调用)。检查文档和/或asm/unistd_32.hasm/unistd_64.h。当然调用约定也不同,不同的寄存器。阅读有关 64 位系统调用的教程。
  • @PeterCordes, ty unistd_64.h 真的很有帮助。所以,59 假设系统调用execve 很好,更新我的脚本。但仍然无法正常工作,还将 strace 输出添加到我的问题中。我想问题出在execve(0x2f, [0x2f], NULL) = -1 EFAULT (Bad address),对吧?

标签: linux assembly x86-64 nasm


【解决方案1】:

非常感谢@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

【讨论】:

  • 第三个参数 (RDX) 是 envp,并且必须为 NULL,或指向以 NULL 结尾的指针数组的指针。您已经这样做了,但您提到了其他 2 个参数。
  • 在 asm 中仍然没有 cmets 的情况下将其归零两次会使答案变得更糟,而不是更好。
猜你喜欢
  • 2011-03-12
  • 2011-03-29
  • 1970-01-01
  • 2010-09-10
  • 2020-09-24
相关资源
最近更新 更多