我最近一直在尝试使用纯汇编来执行系统命令。我设法在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来分离堆栈中的参数,但是效果不佳。
不确定我犯了什么错误,该脚本不起作用:(
非常感谢任何指导。
我正在nasm
中使用x64 bit kali linux
非常感谢@PeterCordes。
在64位体系结构中,您可以访问unistd_64.h
查找系统调用的代码。在这种情况下,对于execve
,系统调用为59。
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