JS逆向之紅薯中文網(wǎng)隱式CSS反爬

已經(jīng)很久沒有寫JS逆向相關(guān)的文章了串前,距離上一篇JS逆向文章的發(fā)布時(shí)間已經(jīng)過了大半年了荡碾,之前把紅薯中文網(wǎng)網(wǎng)頁版的反爬講完之后就說過有機(jī)會(huì)把紅薯中文網(wǎng)手機(jī)版隱式Style-CSS反爬給大家分析一下,今天我就把這篇久違的文章給大家奉上劳殖。

目標(biāo)分析

跟網(wǎng)頁版網(wǎng)站一樣哆姻,紅薯中文網(wǎng)手機(jī)版網(wǎng)站的反爬也主要在小說的正文內(nèi)容矛缨,只不過反爬的技術(shù)種類不一樣,我們隨便找一本小說然后進(jìn)行分析灵妨,值得我們注意的是手機(jī)版和網(wǎng)頁版網(wǎng)站一樣依舊對(duì)小說的正文頁禁用了鼠標(biāo)右鍵泌霍,要檢查網(wǎng)頁元素(Ctrl+Shift+I)或者查看網(wǎng)頁源代碼(Ctrl+U)我們可以使用Chrome瀏覽器的快捷鍵:

隨便選擇小說正文內(nèi)容的一行朱转,通過檢查網(wǎng)頁元素可以發(fā)現(xiàn)瀏覽器渲染后的Elements中小說內(nèi)容的某些字并沒有渲染出來而是一個(gè)span標(biāo)簽藤为,span標(biāo)簽的文本內(nèi)容是::before呀酸,CSS類名是context_kw18性誉,鼠標(biāo)點(diǎn)擊::before我們可以在后邊的Styles選項(xiàng)卡中看到相關(guān)的CSS信息错览,可以發(fā)現(xiàn)剛才我們選擇的那個(gè)沒有渲染的字居然出現(xiàn)在CSS樣式的content屬性中倾哺,我們還可以發(fā)現(xiàn)這個(gè)CSS的文件地址并不是一個(gè)CSS路徑地址,而是<style>忌愚,這說明這個(gè)CSS是動(dòng)態(tài)生成的硕糊,肯定是通過JS的DOM操作生成的简十。

我們還可以發(fā)現(xiàn)其他沒有渲染的字也是這樣,不過它們的CSS類名不一樣恢恼,但是CSS類名都是context_kw開頭场斑,只是后面接不一樣的數(shù)字編號(hào)和簸,context_kw18對(duì)應(yīng)的是"天"字以及context_kw10對(duì)應(yīng)的是"之"字等碟刺。

我們?cè)俨榭匆幌戮W(wǎng)頁源代碼:

我們可以發(fā)現(xiàn)網(wǎng)頁源代碼里<span class="context_kw18"></span>里并沒有什么東西,其實(shí)在前面看到CSS樣式中的::before的時(shí)候吴菠,如果CSS樣式學(xué)得好的話就知道這是CSS的隱式做葵,隱式Style-CSS也是目前比較流行的一種反爬手段酿矢。

隱式Style–CSS

先來說說什么是隱式Style–CSS

  • CSS中瘫筐,::before 創(chuàng)建一個(gè)偽元素,其將成為匹配選中的元素的第一個(gè)子元素肛捍。常通過content屬性來為一個(gè)元素添加修飾性的內(nèi)容拙毫。

    引用自:developer.mozilla.org/zh-CN/docs/…

上面的這段話對(duì)于沒做過前端開發(fā)的朋友而言缀蹄,看著可能會(huì)有點(diǎn)難懂,沒關(guān)系袍患,我用一個(gè)例子簡(jiǎn)單地演示一下诡延。

我們新建一個(gè) HTML 文件輸入下面這樣的內(nèi)容:

  <span>歡迎大家來到我的簡(jiǎn)書肆良,我是成長(zhǎng)之路丶</span>惹恃,<span>今天我們要說的是紅薯中文網(wǎng)隱式style-CSS反爬</span>

并在這個(gè) HTML 中引用下面這個(gè)CSS樣式文件:

  span::before { 
  content: "“";
  color: blue;
  }
  span::after { 
  context: "”";
  color: red;
  }

最后在瀏覽器中展示的內(nèi)容是這樣的:

可以看到在上面的例子里巫糙,我在HTML源碼里隱藏了文字前后的符號(hào)参淹,但是經(jīng)過瀏覽器渲染后浙值,文字前后的符號(hào)就出現(xiàn)了开呐,是不是很神奇?目前很多網(wǎng)站都使用了類似這樣的反爬蟲技術(shù)卵惦,用來保護(hù)自己的內(nèi)容不被爬蟲爬取鸵荠。

逆向過程

既然我們知道了紅薯中文網(wǎng)手機(jī)版網(wǎng)站的小說正文內(nèi)容是隱式Style-CSS反爬蛹找,并且CSS是通過JS的DOM操作動(dòng)態(tài)生成的庸疾,那么我們就需要逆向分析它是如何通過JS把一些文字放到CSS樣式中然后動(dòng)態(tài)生成該CSS当编。

找逆向入口

因?yàn)镴S動(dòng)態(tài)渲染的CSS類名相似,只是CSS類名后面的數(shù)字編號(hào)不一樣臊泌,所以我們可以在Chrome瀏覽器調(diào)試面板全局搜索".context_kw"

通過搜索發(fā)現(xiàn)符合條件的就一個(gè)請(qǐng)求渠概,并且這個(gè)請(qǐng)求就是小說正文內(nèi)容請(qǐng)求(網(wǎng)頁源代碼)播揪,點(diǎn)擊這個(gè)請(qǐng)求來到Sources調(diào)試面板猪狈,點(diǎn)擊左下角的大括號(hào)({})把代碼美化一下雇庙,然后再搜索一下".context_kw"
通過搜索我們?cè)诒姸嘟Y(jié)果中找到了關(guān)鍵代碼状共,如圖所示,可以發(fā)現(xiàn)這個(gè)DOM操作的JS被混淆加密了匈挖,但是通過混淆代碼中document字眼我們還是可以看出DOM操作的痕跡儡循,它是通過循環(huán)把循環(huán)的i變量拼接".context_kw"這樣通過DOM操作之后就會(huì)得到我們?cè)陧撁嫔峡吹降?code>".context_kw10"等加上了數(shù)字編號(hào)的CSS類名择膝,混淆代碼后面還加上了words[i]這個(gè)變量检激,看名字叔收、代碼的位置以及代碼邏輯饺律,我們可以推測(cè)這個(gè)words[i]很有可能是每個(gè)隱式Style-CSScontent屬性中的文字,也就是我們要逆向獲取的內(nèi)容乒省,我們可以在Console面板中把它輸出一下:
可以發(fā)現(xiàn)words這個(gè)變量確實(shí)是我們要的數(shù)據(jù)袖扛,并且我們發(fā)現(xiàn)words是一個(gè)數(shù)組攻锰,數(shù)組的索引都能跟渲染后的CSS類名編號(hào)對(duì)上妓雾,比如:數(shù)組第10個(gè)是"天"字械姻,頁面上".context_kw10"對(duì)應(yīng)的也是"天"字楷拳,所以現(xiàn)在我們要找到words是怎么生成的欢揖,繼續(xù)在該文件全局搜索words
找到words生成的地方我們可以發(fā)現(xiàn)她混,它是定義一個(gè)數(shù)組坤按,并且涉及到了secwords這個(gè)變量以及_0xa5c1這個(gè)變量臭脓,'0x18'是十六進(jìn)制轉(zhuǎn)換成十進(jìn)制是24来累,有圖可以看到secwords是通過CryptoJS這個(gè)庫decrypted(解密)得到

嘹锁,我們先找到_0xa5c1變量然后逐步分析:

在Console面板中把輸出_0xa5c1變量:
找到_0xa5c1變量以及十六進(jìn)制索引后然后還原一下關(guān)鍵的代碼:

原代碼:

    var data = 'oJ3emFyc2SlOa4rTzCDYmjWmNjE8moH9tMXjvt0bFSa3TPymTswvxwRG65UthgN1IMjSK9TI81tBckTSfMh0zB24WvumsfvuiULCzO1DTOc/vWmvBHJG8BztW3X7lbB7KOrUzlbvtjGQKBkRRYkvDxva7PaCKQrbJk454/9/zkslehlXnUl+SGWXesXWkTVE';
    var keywords = CryptoJS['enc'][_0x1a5c('0xb')][_0x1a5c('0xc')](_0x1a5c('0xd'));
    var decrypted = CryptoJS[_0x1a5c('0x13')][_0x1a5c('0x14')](data, keywords, {
        'iv': iv,
        'padding': CryptoJS[_0x1a5c('0x0')][_0x1a5c('0x15')]
    });
    var secWords = decrypted['toString'](CryptoJS[_0x1a5c('0x16')][_0x1a5c('0x17')])['split'](',');
    var words = new Array(secWords[_0x1a5c('0x18')]);

還原之后代碼:

    var data = 'oJ3emFyc2SlOa4rTzCDYmjWmNjE8moH9tMXjvt0bFSa3TPymTswvxwRG65UthgN1IMjSK9TI81tBckTSfMh0zB24WvumsfvuiULCzO1DTOc/vWmvBHJG8BztW3X7lbB7KOrUzlbvtjGQKBkRRYkvDxva7PaCKQrbJk454/9/zkslehlXnUl+SGWXesXWkTVE';
    var keywords = CryptoJS.enc.Latin1.parse.("DC3A49D549646237");
    var decrypted = CryptoJS.AES.decrypt(data, keywords, {
        'iv': iv,
        'padding': CryptoJS.pad.ZeroPadding
    });
    var secWords = decrypted.toString(CryptoJS.enc.Utf8).spilt(',');
    var words = new Array(secWords.length);

可以發(fā)現(xiàn)words初始定義為一個(gè)secWords長(zhǎng)度的數(shù)組求冷,secWordsdecrypted解密然后按照','切割出來的數(shù)組匠题,decryptedAES解密韭山,解密需要data冷溃、keywords似枕,iv

AES加密解密

AES是一種加密方式凿歼,它有多種加密模式: ECB答憔、CBC虐拓、 OFB等,它加密解密需要key另凌,model(也就是加密模式,如:CBC)诗茎,iv(偏移向量)敢订,在JS中通過CryptoJS庫可以實(shí)現(xiàn)加密解密楚午,舉個(gè)列子:

//這是http://www.hongweipeng.com/index.php/archives/1936/頁面中的一個(gè)AES解密JS
function crypto_decode(encode_text) {
            let decode = CryptoJS.AES.decrypt(encode_text, CryptoJS.enc.Utf8.parse('lXMdrvEz90yXdVo7'), {
                iv: CryptoJS.enc.Utf8.parse('DkebZOLIhUKizj2L'),
                mode: CryptoJS.mode.CBC,
                padding: CryptoJS.pad.Pkcs7
            }).toString(CryptoJS.enc.Utf8);
            return decode;
        }

現(xiàn)在有好多網(wǎng)站在前端都使用了AES加密解密矾柜。

Python也有AES的加密解密庫pycryptodome(這個(gè)庫不止封裝了AES加密的相關(guān)還有其他加密算法怪蔑,具體自己去看文檔)缆瓣,根據(jù)AES加密結(jié)果輸出密文形式不同弓坞,它的加密解密稍微有些差異渡冻,比如加密輸出hash密文Base64密文的加密解密方法就有點(diǎn)不一樣:
CBC模式hash密文的加密解密:

from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hex


class AesCrypt(object):
    def __init__(self, key):
        self.key = key.encode('utf-8')
        self.model = AES.MODE_CBC
        
    # 加密方法  
    def encrypt(self, text):
        text = text.encode('utf-8')
        # key菩帝,model呼奢,iv
        cryptor = AES.new(self.key, self.model, b'DkebZOLIhUKizj2L')
        lenght = 16
        count = len(text)
        if count < lenght:
            add = (lenght - count)
            text = text + ('\0' * add).encode('utf-8')
        elif count > lenght:
            add = (lenght - (count % lenght))
            text = text + ('\0' * add).encode('utf-8')
        self.ciphertext = cryptor.encrypt(text)
        return b2a_hex(self.ciphertext)
    
    # 解密方法
    def decrpt(self, text):
        # key握础,model,iv
        cryptor = AES.new(self.key, self.model, b'DkebZOLIhUKizj2L')
        plain_text = cryptor.decrypt(a2b_hex(text))
        return bytes.decode(plain_text).rstrip('\0')

CBC模式Base64密文的加密解密:

import base64

from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hex

class AesCrypt(object):
    def __init__(self, key):
        self.key = key.encode('utf-8')
        self.model = AES.MODE_CBC
        
    # 加密方法    
    def encrypt(self, text):
        text = text.encode('utf-8')
        # key禀综,model简烘,iv
        cryptor = AES.new(self.key, self.model, b'DkebZOLIhUKizj2L')
        lenght = 16
        count = len(text)
        if count < lenght:
            add = (lenght - count)
            text = text + ('\0' * add).encode('utf-8')
        elif count > lenght:
            add = (lenght - (count % lenght))
            text = text + ('\0' * add).encode('utf-8')
        self.ciphertext = cryptor.encrypt(text)
        # 將加密后的數(shù)據(jù)base64編碼返回base64格式數(shù)據(jù)
        return base64.b64encode(self.ciphertext)
    
    # 解密方法
    def decrypt(self, text):
        # key,model定枷,iv
        cryptor = AES.new(self.key, self.model, b'146385F634C9CB00')
        # 將密文base64解碼
        decryptBytes = base64.b64decode(text)
        plain_text = cryptor.decrypt(decryptBytes)
        return bytes.decode(plain_text).rstrip('\0')

進(jìn)一步分析

既然我們知道secwordsAES逆向解密孤澎,并且我們了解了AES的基礎(chǔ)原理,那么我們就需要在JS中找到AES密文欠窒、key覆旭、model以及iv岖妄。

  1. iv型将,全局搜索iv找到相關(guān)代碼。
    • iv原始混淆代碼
var iv = '';
    try {
        if (top[_0x1a5c('0xe')][_0x1a5c('0xf')][_0x1a5c('0x10')] != window[_0x1a5c('0xf')][_0x1a5c('0x10')]) {
            top[_0x1a5c('0xe')][_0x1a5c('0xf')][_0x1a5c('0x10')] = window[_0x1a5c('0xf')][_0x1a5c('0x10')];
        }
        iv = CryptoJS['enc'][_0x1a5c('0xb')][_0x1a5c('0xc')](_0x1a5c('0x11'));
    } catch (_0x249434) {
        iv = CryptoJS['enc'][_0x1a5c('0xb')][_0x1a5c('0xc')](_0x1a5c('0x12'));
    }
  • iv還原后的代碼
var iv = '';
    try {
        if (top.window.location.href != window.location.href) {
            top.window.location.href = window.location.href;
        }
        iv = CryptoJS.enc.Latin1.parse("A61BFB423D6C6EB8");
    } catch (_0x249434) {
        iv = CryptoJS.enc.Latin1.parse("146385F634C9CB00");
    }

所以iv就是在_0x1a5c數(shù)組變量的第11個(gè)索引數(shù)據(jù)荐虐,也就是"A61BFB423D6C6EB8"

  1. model七兜,你把加密的CryptoJS代碼看一遍,你會(huì)發(fā)現(xiàn)這個(gè)AES加密用的modelCBC(搜索出現(xiàn)了CBC字眼)福扬,并且發(fā)現(xiàn)它使用的Base64密文加密解密
  2. key腕铸,其實(shí)key就是上面的keywords變量"DC3A49D549646237"(分析方法在上面惜犀,其實(shí)ivkey恬惯、密文都是一樣的分析方法)
  3. AES密文向拆,其實(shí)密文就是上面的data變量的值"oJ3emFyc2SlOa4rTzCDYmjWmNjE8moH9tMXjvt0bFSa3TPymTswvxwRG65UthgN1IMjSK9TI81tBckTSfMh0zB24WvumsfvuiULCzO1DTOc/vWmvBHJG8BztW3X7lbB7KOrUzlbvtjGQKBkRRYkvDxva7PaCKQrbJk454/9/zkslehlXnUl+SGWXesXWkTVE"
    找齊這寫需要的值之后就可以解密得到secword
import base64

from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hex

class AesCrypt(object):
    def __init__(self, key):
        self.key = key.encode('utf-8')
        self.model = AES.MODE_CBC
        
    # 加密方法    
    def encrypt(self, text):
        text = text.encode('utf-8')
        # key,model酪耳,iv
        cryptor = AES.new(self.key, self.model, b'A61BFB423D6C6EB8')
        lenght = 16
        count = len(text)
        if count < lenght:
            add = (lenght - count)
            text = text + ('\0' * add).encode('utf-8')
        elif count > lenght:
            add = (lenght - (count % lenght))
            text = text + ('\0' * add).encode('utf-8')
        self.ciphertext = cryptor.encrypt(text)
        # 將加密后的數(shù)據(jù)base64編碼返回base64格式數(shù)據(jù)
        return base64.b64encode(self.ciphertext)
    
    # 解密方法
    def decrypt(self, text):
        # key浓恳,model,iv
        cryptor = AES.new(self.key, self.model, b'A61BFB423D6C6EB8')
        # 將密文base64解碼
        decryptBytes = base64.b64decode(text)
        plain_text = cryptor.decrypt(decryptBytes)
        return bytes.decode(plain_text).rstrip('\0')
 if __name__ == '__main__':
    # 傳入key
    pc = AesCrypt("DC3A49D549646237")
    # 傳入需要解密的密文
    d = pc.decrypt('oJ3emFyc2SlOa4rTzCDYmjWmNjE8moH9tMXjvt0bFSa3TPymTswvxwRG65UthgN1IMjSK9TI81tBckTSfMh0zB24WvumsfvuiULCzO1DTOc/vWmvBHJG8BztW3X7lbB7KOrUzlbvtjGQKBkRRYkvDxva7PaCKQrbJk454/9/zkslehlXnUl+SGWXesXWkTVE')
    print(d)

解密出來的結(jié)果如下:

"65291, 30339, 65282, 26160, 26471, 21074, 19967, 19982, 36826, 20101, 20044, 8222, 8219, 22660, 23477, 20181, 20203, 22311, 22826, 20009, 20461"

可以發(fā)現(xiàn)是一組數(shù)字?jǐn)?shù)據(jù)碗暗,但是這些數(shù)據(jù)是一個(gè)整體颈将,是一個(gè)字符串,我們?cè)诳刂婆_(tái)輸出一下secword對(duì)比一下我們解密的結(jié)果:

我們發(fā)現(xiàn)結(jié)果是一樣的言疗,那么var words = new Array(secWords.length);就說明words是一個(gè)長(zhǎng)度為21的空數(shù)組晴圾,那么JS是如何把words和那些字產(chǎn)生關(guān)系的呢?

我們接著在跟words相關(guān)的代碼噪奄,全局搜索words[i](搜索words[i]不搜索words是因?yàn)?code>words搜出的結(jié)果太多死姚,并且words是跟i有關(guān)系):

我們發(fā)現(xiàn)這個(gè)循環(huán)里有words[i],我們分析這個(gè)循環(huán)(這里就全部還原這個(gè)循環(huán)了勤篮,有空可以自己還原一下都毒,這里只還原部分關(guān)鍵代碼):

  1. 定義一個(gè)循環(huán),i起始為0碰缔,i<secwords.lenght; i++账劲,也就是說i<21后停止循環(huán)
  2. 定義了一個(gè)變量_0x475a5f(這個(gè)一個(gè)混淆后的代碼,其實(shí)你為了好讀把它叫a變量也是可以)金抡,它的值是var _0x475a5f = '0|4|1|3|5|2'.split('|')瀑焦,也就是這個(gè)字符串按照"|"切割,所以_0x475a5f的值其實(shí)等于[0,4,1,3,5,2]梗肝,還定義一個(gè)_0xbddd40變量初始值為0
  3. 再定義一個(gè)whie循環(huán)榛瓮,因?yàn)闂l件"!![]"一直為true,所以這是一個(gè)死循環(huán)
  4. 定義一個(gè)swith循環(huán)巫击,循環(huán)的條件是_0x475a5f[_0xbddd40++]禀晓,這也說明switch會(huì)依次執(zhí)行case0、case4喘鸟、case1、case3驻右、case5什黑、case2
  5. 分別看每個(gè)case都做什么:
    • case0:將secwords的第i個(gè)值賦值給一個(gè)變量_0x2e1b2c
    • case1:定義一個(gè)變量把一個(gè)函數(shù)賦值給這個(gè)變量,這個(gè)函數(shù)里有定義了三個(gè)函數(shù)堪夭,經(jīng)過還原其實(shí)可以發(fā)現(xiàn)就是傳遞兩個(gè)數(shù)字到函數(shù)愕把,一個(gè)是secwords的第i個(gè)值拣凹,另一個(gè)是3,返回兩個(gè)數(shù)相加
    • case2:調(diào)用Sting.fromCharCode()方法恨豁,然后傳遞數(shù)字嚣镜,這個(gè)方法就是將 Unicode 編碼轉(zhuǎn)為一個(gè)字符 ,如: var n = String.fromCharCode(65); 結(jié)果是:A
    • case3:將變量_0x2e1b2c重新賦值橘蜜,調(diào)用_0x15d2ab然后把_0x2e1b2c傳遞給這個(gè)方法菊匿,_0x15d2ab這個(gè)方法其實(shí)在case4
    • case4:case4跟case1差不多,只不過它的返回值是一個(gè)三元運(yùn)算符计福,如果_0x2e1b2c偶數(shù)就返回這個(gè)數(shù)減2跌捆,奇數(shù)就返回這個(gè)數(shù)減4
    • case5:將變量_0x2e1b2c重新賦值,調(diào)用_0x5bb6ca然后把_0x2e1b2c傳遞給這個(gè)方法象颖,_0x15d2ab這個(gè)方法其實(shí)在case1
  6. 明白了每個(gè)case在做什么佩厚,然后按照case順序執(zhí)行,就能得出結(jié)論:把secword的各項(xiàng)如果是偶數(shù)減一说订,奇數(shù)加一然后使用fromCharCode方法將數(shù)字轉(zhuǎn)換成字符串

這樣就能得到我們要的數(shù)據(jù)抄瓦,比如"天"字倒數(shù)第三個(gè),secwords倒數(shù)第三個(gè)數(shù)字是" 22826" 陶冷,是偶數(shù)钙姊,減一然后使用fromCharCode方法將數(shù)字轉(zhuǎn)換成字符串,結(jié)果為"天"

總結(jié)

通過上面的分析我們可以得出結(jié)論:

  • 紅薯中文網(wǎng)手機(jī)版網(wǎng)站是隱式Style-CSS反爬埃叭,反爬的CSS是通過JS的DOM操作動(dòng)態(tài)生成的
  • 它操作DOM的JS代碼進(jìn)行了混淆摸恍,隱式Style-CSS中的content屬性中的值是AES解密后數(shù)據(jù)
    偶數(shù)減一,奇數(shù)加一然后將數(shù)字Unicode 轉(zhuǎn)換成字符串
    注意:
    我嘗試過很多小說赤屋,發(fā)現(xiàn)它們上面的case順序可能會(huì)不一樣(上面數(shù)字字符串切割出來的數(shù)字順序相對(duì)不一樣)立镶,AES的key、iv类早、data等都可能不一樣媚媒,如:放的位置也可能不一樣(如data可能放在數(shù)組變量里),表現(xiàn)形式也不一樣(如有的iv是直接給出涩僻,有的是需要從變量還原出來)缭召,但是結(jié)論都是先AES解密(自己提取data,key逆日,iv等數(shù)據(jù))再偶數(shù)減一嵌巷,奇數(shù)加一將數(shù)字Unicode 轉(zhuǎn)換成字符串

解密

我們可以使用Python的AES的Base64解密方法解密,然后對(duì)2求余判斷奇偶室抽,偶數(shù)減一搪哪,奇數(shù)加一,再使用Python數(shù)字Unicode 轉(zhuǎn)換字符串的函數(shù)(Python3內(nèi)置函數(shù)chr())轉(zhuǎn)成目標(biāo)字符坪圾,其次建立CSS類名索引和目標(biāo)字符的映射(CSS類名索引和結(jié)果的字典)晓折,最后源代碼中替換每個(gè)span標(biāo)簽再提取數(shù)據(jù)惑朦。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市漓概,隨后出現(xiàn)的幾起案子漾月,更是在濱河造成了極大的恐慌,老刑警劉巖胃珍,帶你破解...
    沈念sama閱讀 212,542評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件梁肿,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡堂鲜,警方通過查閱死者的電腦和手機(jī)栈雳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來缔莲,“玉大人哥纫,你說我怎么就攤上這事〕兆啵” “怎么了蛀骇?”我有些...
    開封第一講書人閱讀 158,021評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)读拆。 經(jīng)常有香客問我擅憔,道長(zhǎng),這世上最難降的妖魔是什么檐晕? 我笑而不...
    開封第一講書人閱讀 56,682評(píng)論 1 284
  • 正文 為了忘掉前任暑诸,我火速辦了婚禮,結(jié)果婚禮上辟灰,老公的妹妹穿的比我還像新娘个榕。我一直安慰自己,他們只是感情好芥喇,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,792評(píng)論 6 386
  • 文/花漫 我一把揭開白布西采。 她就那樣靜靜地躺著,像睡著了一般继控。 火紅的嫁衣襯著肌膚如雪械馆。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,985評(píng)論 1 291
  • 那天武通,我揣著相機(jī)與錄音霹崎,去河邊找鬼。 笑死冶忱,一個(gè)胖子當(dāng)著我的面吹牛尾菇,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 39,107評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼错沽,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了眶拉?” 一聲冷哼從身側(cè)響起千埃,我...
    開封第一講書人閱讀 37,845評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎忆植,沒想到半個(gè)月后放可,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,299評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡朝刊,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,612評(píng)論 2 327
  • 正文 我和宋清朗相戀三年耀里,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拾氓。...
    茶點(diǎn)故事閱讀 38,747評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡冯挎,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出咙鞍,到底是詐尸還是另有隱情房官,我是刑警寧澤,帶...
    沈念sama閱讀 34,441評(píng)論 4 333
  • 正文 年R本政府宣布续滋,位于F島的核電站翰守,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏疲酌。R本人自食惡果不足惜蜡峰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,072評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望朗恳。 院中可真熱鬧湿颅,春花似錦、人聲如沸僻肖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽臀脏。三九已至劝堪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間揉稚,已是汗流浹背秒啦。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評(píng)論 1 267
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留搀玖,地道東北人余境。 一個(gè)月前我還...
    沈念sama閱讀 46,545評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親芳来。 傳聞我的和親對(duì)象是個(gè)殘疾皇子含末,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,658評(píng)論 2 350