【JS 逆向百例】復(fù)雜的登錄過(guò)程报账,最新WB逆向

聲明

本文章中所有內(nèi)容僅供學(xué)習(xí)交流,抓包內(nèi)容琐凭、敏感網(wǎng)址统屈、數(shù)據(jù)接口均已做脫敏處理,嚴(yán)禁用于商業(yè)用途和非法用途吨掌,否則由此產(chǎn)生的一切后果均與作者無(wú)關(guān)窿侈,若有侵權(quán),請(qǐng)聯(lián)系我立即刪除肛著!

逆向目標(biāo)

本次的逆向目標(biāo)是WB的登錄殉农,雖然登錄的加密參數(shù)沒(méi)有太多超凳,但是登錄的流程稍微復(fù)雜一點(diǎn),經(jīng)歷了很多次中轉(zhuǎn)危队,細(xì)分下來(lái)大約要經(jīng)過(guò)九次處理才能成功登錄聪建。

在登錄過(guò)程中遇到的加密參數(shù)只有一個(gè)钙畔,即密碼加密茫陆,加密后的密碼在獲取 token 的時(shí)候會(huì)用到,獲取 token 是一個(gè) POST 請(qǐng)求擎析,其 Form Data 里的 sp 值就是加密后的密碼簿盅,類(lèi)似于:e23c5d62dbf9f8364005f331e487873c70d7ab0e8dd2057c3e66d1ae5d2837ef1dcf86......

登錄流程

首先來(lái)理清一下登錄流程,每一步特殊的參數(shù)進(jìn)都行了說(shuō)明,沒(méi)有提及的參數(shù)表示是定值,直接復(fù)制即可。

大致流程如下:

  1. 預(yù)登陸

  2. 獲取加密密碼

  3. 獲取 token

  4. 獲取加密后的賬號(hào)

  5. 發(fā)送驗(yàn)證碼

  6. 校驗(yàn)驗(yàn)證碼

  7. 訪(fǎng)問(wèn) redirect url

  8. 訪(fǎng)問(wèn) crossdomain2 url

  9. 通過(guò) passport url 登錄

1.預(yù)登陸

01.png

預(yù)登陸為 GET 請(qǐng)求粉铐,Query String Parameters 中主要包含兩個(gè)比較重要的參數(shù):su:用戶(hù)名經(jīng)過(guò) base64 編碼得到倡缠,_: 13 位時(shí)間戳盾饮,返回的數(shù)據(jù)包含一個(gè) JSON徘钥,可用正則提取出來(lái)而钞,JSON 里面包含 retcodeservertimepcid果元,nonce倡怎,pubkeyrsakvexectime 七個(gè)參數(shù)值吼句,其中大多數(shù)值都是后面的請(qǐng)求當(dāng)中要用到的尔艇,部分值是加密密碼要用到的,返回?cái)?shù)據(jù)數(shù)示例:

xxxxSSOController.preloginCallBack({
    "retcode": 0,
    "servertime": 1627461942,
    "pcid": "gz-1cd535198c0efe850b96944c7945e8fd514b",
    "nonce": "GWBOCL",
    "pubkey": "EB2A38568661887FA180BDDB5CABD5F21C7BFD59C090CB2D245......",
    "rsakv": 1330428213,
    "exectime": 16
})

2.獲取加密后的密碼

密碼的加密使用的是 RSA 加密恨憎,可以通過(guò) Python 或者 JS 來(lái)獲取加密后的密碼今瀑,JS 加密的逆向在后面拿出來(lái)單獨(dú)分析。

3.獲取 token

02.png

這個(gè) token 值在后面的獲取加密手機(jī)號(hào)影暴、發(fā)送驗(yàn)證碼魂拦、校驗(yàn)驗(yàn)證碼等步驟中都會(huì)用到安疗,獲取 token 值為 POST 請(qǐng)求,Query String Parameters 的值是固定的:client: ssologin.js(v1.4.19)璧亚,F(xiàn)orm Data 的值相對(duì)來(lái)說(shuō)比較多,但是除了加密的密碼以外觉义,其他參數(shù)其實(shí)都是可以在第1步預(yù)登陸返回的數(shù)據(jù)里找到,主要的參數(shù)如下:

  • su:用戶(hù)名經(jīng)過(guò) base64 加密得到
  • servertime:通過(guò)第1步預(yù)登陸返回的 JSON 里面獲取
  • nonce:通過(guò)第1步預(yù)登陸返回的 JSON 里面獲取
  • rsakv:通過(guò)第1步預(yù)登陸返回的 JSON 里面獲取
  • sp:加密后的密碼
  • prelt:隨機(jī)值

返回?cái)?shù)據(jù)為 HTML 源碼海洼,可以從里面提取 token 值龙优,類(lèi)似于:2NGFhARzFAFAIp_QwX70Npj8gw4lgj7RbCnByb3RlY3Rpb24.,如果返回的 token 不是這種陆淀,則說(shuō)明賬號(hào)或者密碼錯(cuò)誤。

4.獲取加密后的賬號(hào)

03.png

前面我們遇到的 su 是用戶(hù)名經(jīng)過(guò) base64 加密得到募闲,這里它對(duì)用戶(hù)名進(jìn)行了進(jìn)一步的加密處理,加密后的用戶(hù)名在發(fā)送驗(yàn)證碼和校驗(yàn)驗(yàn)證碼的時(shí)候會(huì)用到看铆,GET 請(qǐng)求,Query String Parameters 的參數(shù)也比較簡(jiǎn)單诫睬,token 就是第3步獲取的 token 值,callback_url 是網(wǎng)站的主頁(yè),返回?cái)?shù)據(jù)是 HTML 源碼,可以使用 xpath 語(yǔ)法://input[@name='encrypt_mobile']/@value 來(lái)提取加密后的賬號(hào),其值類(lèi)似于:f2de0b5e333a,這里需要注意的是,即便是同一個(gè)賬號(hào),每次加密的結(jié)果也是不一樣的。

5.發(fā)送驗(yàn)證碼

04.png

發(fā)送驗(yàn)證碼是一個(gè) POST 請(qǐng)求张抄,其參數(shù)也比較簡(jiǎn)單,Query String Parameters 里的 token 是第3步獲取的 token,F(xiàn)orm Data 里的 encrypt_mobile 是第4步獲取的加密后的賬號(hào)样眠,返回的數(shù)據(jù)是驗(yàn)證碼發(fā)送的狀態(tài)甥桂,例如:{'retcode': 20000000, 'msg': 'succ', 'data': []}

6.校驗(yàn)驗(yàn)證碼

05.png

校驗(yàn)驗(yàn)證碼是一個(gè) POST 請(qǐng)求完沪,其參數(shù)也非常簡(jiǎn)單,Query String Parameters 里的 token 是第3步獲取的 token嵌戈,F(xiàn)orm Data 里的 encrypt_mobile 是第4步獲取的加密后的賬號(hào)覆积,code 是第5步收到的驗(yàn)證碼,返回?cái)?shù)據(jù)是一個(gè) JSON熟呛,retcodemsg 代表校驗(yàn)的狀態(tài)宽档,redirect url 是校驗(yàn)步驟完成后接著要訪(fǎng)問(wèn)的頁(yè)面,在下一步中要用到庵朝,返回的數(shù)據(jù)示例:

{
  "retcode": 20000000,
  "msg": "succ",
  "data": {
    "redirect_url": "https://login.xxxx.com.cn/sso/login.php?entry=xxxxx&returntype=META&crossdomain=1&cdult=3&alt=ALT-NTcxNjMyMTA2OA==-1630292617-yf-78B1DDE6833847576B0DC4B77A6C77C4-1&savestate=30&url=https://xxxxx.com"
  }
}

7.訪(fǎng)問(wèn) redirect url

06.png

這一步的請(qǐng)求接口其實(shí)就是第6步返回的 redirect url吗冤,GET 請(qǐng)求,類(lèi)似于:https://login.xxxx.com.cn/sso/login.php?entry=xxxxx&returntype=META......

返回的數(shù)據(jù)是 HTML 源碼九府,我們要從中提取 crossdomain2 的 URL椎瘟,提取的結(jié)果類(lèi)似于:https://login.xxxx.com.cn/crossdomain2.php?action=login&entry=xxxxx......,同樣的侄旬,這個(gè) URL 也是接下來(lái)需要訪(fǎng)問(wèn)的頁(yè)面肺蔚。

8.訪(fǎng)問(wèn) crossdomain2 url

07.png

這一步的請(qǐng)求接口就是第7步提取的 crossdomain2 url,GET 請(qǐng)求儡羔,類(lèi)似于:https://login.xxxx.com.cn/crossdomain2.php?action=login&entry=xxxxx......

返回的數(shù)據(jù)同樣是 HTML 源碼宣羊,我們要從中提取真正的登錄的 URL,提取的結(jié)果類(lèi)似于:https://passport.xxxxx.com/wbsso/login?ssosavestate=1661828618&url=https......笔链,最后一步只需要訪(fǎng)問(wèn)這個(gè)真正的登錄 URL 就能實(shí)現(xiàn)登錄操作了段只。

9.通過(guò) passport url 登錄

08.png

這是最后一步,也是真正的登錄操作鉴扫,GET 請(qǐng)求赞枕,請(qǐng)求接口就是第8步提取的 passport url,類(lèi)似于:https://passport.xxxxx.com/wbsso/login?ssosavestate=1661828618&url=https......

返回的數(shù)據(jù)包含了登錄結(jié)果、用戶(hù) ID 和用戶(hù)名炕婶,類(lèi)似于:

({"result":true,"userinfo":{"uniqueid":"5712321368","displayname":"tomb"}});

自此姐赡,WB的完整登錄流程已完成,可以直接拿登錄成功后的 cookies 進(jìn)行其他操作了柠掂。

加密密碼逆向

在登錄流程中项滑,第2步是獲取加密后的密碼,在登錄的第3步獲取 token 里涯贞,請(qǐng)求的 Query String Parameters 包含了一個(gè)加密參數(shù) sp枪狂,這個(gè)就是加密后的密碼,接下來(lái)我們對(duì)密碼的加密進(jìn)行逆向分析宋渔。

直接全局搜索 sp 關(guān)鍵字州疾,發(fā)現(xiàn)有很多值,這里我們又用到了前面講過(guò)的技巧皇拣,嘗試搜索 sp=严蓖、sp: 或者 var sp 等來(lái)縮小范圍,在本案例中氧急,我們嘗試搜索 sp=颗胡,可以看到在 index.js 里面只有一個(gè)值,埋下斷點(diǎn)進(jìn)行調(diào)試吩坝,可以看到 sp 其實(shí)就是 b 的值:

PS:搜索時(shí)要注意毒姨,不能在登錄成功后的頁(yè)面進(jìn)行搜索,此時(shí)資源已刷新钾恢,重新加載了手素,加密的 JS 文件已經(jīng)沒(méi)有了,需要在登錄界面輸入錯(cuò)誤的賬號(hào)密碼來(lái)抓包瘩蚪、搜索泉懦、斷點(diǎn)。

09.png

繼續(xù)往上追蹤這個(gè) b 的值疹瘦,關(guān)鍵代碼有個(gè) if-else 語(yǔ)句崩哩,分別埋下斷點(diǎn),經(jīng)過(guò)調(diào)試可以看到 b 的值在 if 下面生成:

10.png

分析一下兩行關(guān)鍵代碼:

f.setPublic(me.rsaPubkey, "10001");
b = f.encrypt([me.servertime, me.nonce].join("\t") + "\n" + b)

me.rsaPubkey言沐、me.servertime邓嘹、me.nonce 都是第1步預(yù)登陸返回的數(shù)據(jù)。

把鼠標(biāo)移到 f.setPublicf.encrypt险胰,可以看到分別是 brbt 函數(shù):

11.png
12.png

分別跟進(jìn)這兩個(gè)函數(shù)汹押,可以看到都在一個(gè)匿名函數(shù)下面:

13.png

直接將整個(gè)匿名函數(shù)復(fù)制下來(lái),去掉最外面的匿名函數(shù)起便,進(jìn)行本地調(diào)試棚贾,調(diào)試過(guò)程中會(huì)提示 navigator 未定義窖维,查看復(fù)制的源碼,里面用到了 navigator.appNamenavigator.appVersion妙痹,直接定義即可铸史,或者置空都行。

navigator = {
    appName: "Netscape",
    appVersion: "5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
}

繼續(xù)調(diào)試會(huì)發(fā)現(xiàn)在 var c = this.doPublic(b); 提示對(duì)象不支持此屬性或方法怯伊,搜索 doPublic 發(fā)現(xiàn)有一句 bq.prototype.doPublic = bs;琳轿,這里直接將其改為 doPublic = bs; 即可。

分析整個(gè) RSA 加密邏輯耿芹,其實(shí)也可以通過(guò) Python 來(lái)實(shí)現(xiàn)崭篡,代碼示例(pubkey 需要補(bǔ)全):

import rsa
import binascii


pre_parameter = {
        "retcode": 0,
        "servertime": 1627461942,
        "pcid": "gz-1cd535198c0efe850b96944c7945e8fd514b",
        "nonce": "GWBOCL",
        "pubkey": "EB2A38568661887FA180BDDB5CABD5F21C7BFD59C090CB2D245......",
        "rsakv": 1330428213,
        "exectime": 16
}

password = '12345678'

public_key = rsa.PublicKey(int(pre_parameter['pubkey'], 16), int('10001', 16))
text = '%s\t%s\n%s' % (pre_parameter['servertime'], pre_parameter['nonce'], password)
encrypted_str = rsa.encrypt(text.encode(), public_key)
encrypted_password = binascii.b2a_hex(encrypted_str).decode()

print(encrypted_password)

完整代碼

GitHub 關(guān)注 K 哥爬蟲(chóng),持續(xù)分享爬蟲(chóng)相關(guān)代碼猩系!歡迎 star 媚送!https://github.com/kgepachong/

以下只演示部分關(guān)鍵代碼,不能直接運(yùn)行寇甸!完整代碼倉(cāng)庫(kù)地址:https://github.com/kgepachong/crawler/

關(guān)鍵 JS 加密代碼架構(gòu)

navigator = {
    appName: "Netscape",
    appVersion: "5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
}

function bt(a) {}

function bs(a) {}

function br(a, b) {}

// 此處省略 N 個(gè)函數(shù)

bl.prototype.nextBytes = bk;
doPublic = bs;
bq.prototype.setPublic = br;
bq.prototype.encrypt = bt;
this.RSAKey = bq


function getEncryptedPassword(me, b) {
    br(me.pubkey, "10001");
    b = bt([me.servertime, me.nonce].join("\t") + "\n" + b);
    return b
}

// 測(cè)試樣例
// var me = {
//     "retcode": 0,
//     "servertime": 1627283238,
//     "pcid": "gz-a9243276722ed6d4671f21310e2665c92ba4",
//     "nonce": "N0Y3SZ",
//     "pubkey": "EB2A38568661887FA180BDDB5CABD5F21C7BFD59C090CB2D245A87AC253062882729293E5506350508E7F9AA3BB77F4333231490F915F6D63C55FE2F08A49B353F444AD3993CACC02DB784ABBB8E42A9B1BBFFFB38BE18D78E87A0E41B9B8F73A928EE0CCEE1F6739884B9777E4FE9E88A1BBE495927AC4A799B3181D6442443",
//     "rsakv": "1330428213",
//     "exectime": 13
// }
// var b = '12312312312'  // 密碼
// console.log(getEncryptedPassword(me, b))

Python 登錄關(guān)鍵代碼

#!/usr/bin/env python3
# -*- coding: utf-8 -*-


import re
import json
import time
import base64
import binascii

import rsa
import execjs
import requests
from lxml import etree


# 判斷某些請(qǐng)求是否成功的標(biāo)志
response_success_str = 'succ'

pre_login_url = '脫敏處理,完整代碼關(guān)注 GitHub:https://github.com/kgepachong/crawler'
get_token_url = '脫敏處理疗涉,完整代碼關(guān)注 GitHub:https://github.com/kgepachong/crawler'
protection_url = '脫敏處理拿霉,完整代碼關(guān)注 GitHub:https://github.com/kgepachong/crawler'
send_code_url = '脫敏處理,完整代碼關(guān)注 GitHub:https://github.com/kgepachong/crawler'
confirm_url = '脫敏處理咱扣,完整代碼關(guān)注 GitHub:https://github.com/kgepachong/crawler'

headers = {
    'Host': '脫敏處理绽淘,完整代碼關(guān)注 GitHub:https://github.com/kgepachong/crawler',
    'Referer': '脫敏處理,完整代碼關(guān)注 GitHub:https://github.com/kgepachong/crawler',
    'sec-ch-ua': '" Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}
session = requests.session()


def get_pre_parameter(username: str) -> dict:
    su = base64.b64encode(username.encode())
    time_now = str(int(time.time() * 1000))
    params = {
        'entry': '脫敏處理闹伪,完整代碼關(guān)注 GitHub:https://github.com/kgepachong/crawler',
        'callback': '脫敏處理沪铭,完整代碼關(guān)注 GitHub:https://github.com/kgepachong/crawler',
        'su': su,
        'rsakt': 'mod',
        'checkpin': 1,
        'client': 'ssologin.js(v1.4.19)',
        '_': time_now,
    }
    response = session.get(url=pre_login_url, params=params, headers=headers).text
    parameter_dict = json.loads(re.findall(r'\((.*)\)', response)[0])
    # print('1.【pre parameter】: %s' % parameter_dict)
    return parameter_dict


def get_encrypted_password(pre_parameter: dict, password: str) -> str:
    # 通過(guò) JS 獲取加密后的密碼
    # with open('encrypt.js', 'r', encoding='utf-8') as f:
    #     js = f.read()
    # encrypted_password = execjs.compile(js).call('getEncryptedPassword', pre_parameter, password)
    # # print('2.【encrypted password】: %s' % encrypted_password)
    # return encrypted_password

    # 通過(guò) Python 的 rsa 模塊和 binascii 模塊獲取加密后的密碼
    public_key = rsa.PublicKey(int(pre_parameter['pubkey'], 16), int('10001', 16))
    text = '%s\t%s\n%s' % (pre_parameter['servertime'], pre_parameter['nonce'], password)
    encrypted_str = rsa.encrypt(text.encode(), public_key)
    encrypted_password = binascii.b2a_hex(encrypted_str).decode()
    # print('2.【encrypted password】: %s' % encrypted_password)
    return encrypted_password


def get_token(encrypted_password: str, pre_parameter: dict, username: str) -> str:
    su = base64.b64encode(username.encode())
    data = {
        'entry': '脫敏處理,完整代碼關(guān)注 GitHub:https://github.com/kgepachong/crawler',
        'gateway': 1,
        'from': '',
        'savestate': 7,
        'qrcode_flag': False,
        'useticket': 1,
        'pagerefer': '',
        'vsnf': 1,
        'su': su,
        'service': 'miniblog',
        'servertime': pre_parameter['servertime'],
        'nonce': pre_parameter['nonce'],
        'pwencode': 'rsa2',
        'rsakv': pre_parameter['rsakv'],
        'sp': encrypted_password,
        'sr': '1920*1080',
        'encoding': 'UTF-8',
        'prelt': 38,
        'url': '脫敏處理偏瓤,完整代碼關(guān)注 GitHub:https://github.com/kgepachong/crawler',
        'returntype': 'META'
    }
    response = session.post(url=get_token_url, headers=headers, data=data)
    # response.encoding = 'gbk'
    ajax_login_url = re.findall(r'replace\("(.*)"\)', response.text)[0]
    token = ajax_login_url.split('token%3D')[-1]
    if 'weibo' not in token:
        # print('3.【token】: %s' % token)
        return token
    else:
        raise Exception('登錄失敗! 用戶(hù)名或者密碼錯(cuò)誤!')


def get_encrypted_mobile(token: str) -> str:
    params = {
        'token': token,
        'callback_url': '脫敏處理杀怠,完整代碼關(guān)注 GitHub:https://github.com/kgepachong/crawler'
    }
    response = session.get(url=protection_url, params=params, headers=headers)
    tree = etree.HTML(response.text)
    encrypted_mobile = tree.xpath("http://input[@name='encrypt_mobile']/@value")[0]
    # print('4.【encrypted mobile】: %s' % encrypted_mobile)
    return encrypted_mobile


def send_code(token: str, encrypt_mobile: str) -> str:
    params = {'token': token}
    data = {'encrypt_mobile': encrypt_mobile}
    response = session.post(url=send_code_url, params=params, data=data, headers=headers).json()
    if response['msg'] == response_success_str:
        code = input('請(qǐng)輸入驗(yàn)證碼: ')
        # print('5.【code】: %s' % code)
        return code
    else:
        # print('5.【failed to send verification code】: %s' % response)
        raise Exception('驗(yàn)證碼發(fā)送失敗: %s' % response)


def confirm_code(encrypted_mobile: str, code: str, token: str) -> str:
    params = {'token': token}
    data = {
        'encrypt_mobile': encrypted_mobile,
        'code': code
    }
    response = session.post(url=confirm_url, params=params, data=data, headers=headers).json()
    if response['msg'] == response_success_str:
        redirect_url = response['data']['redirect_url']
        # print('6.【redirect url】: %s' % redirect_url)
        return redirect_url
    else:
        # print('6.【驗(yàn)證碼校驗(yàn)失敗】: %s' % response)
        raise Exception('驗(yàn)證碼校驗(yàn)失敗: %s' % response)


def get_cross_domain2_url(redirect_url: str) -> str:
    response = session.get(url=redirect_url, headers=headers).text
    cross_domain2_url = re.findall(r'replace\("(.*)"\)', response)[0]
    # print('7.【cross domain2 url】: %s' % cross_domain2_url)
    return cross_domain2_url


def get_passport_url(cross_domain2_url: str) -> str:
    response = session.get(url=cross_domain2_url, headers=headers).text
    passport_url_str = re.findall(r'setCrossDomainUrlList\((.*)\)', response)[0]
    passport_url = json.loads(passport_url_str)['arrURL'][0]
    # print('8.【passport url】: %s' % passport_url)
    return passport_url


def login(passport_url: str) -> None:
    response = session.get(url=passport_url, headers=headers).text
    login_result = json.loads(response.replace('(', '').replace(');', ''))
    if login_result['result']:
        user_unique_id = login_result['userinfo']['uniqueid']
        user_display_name = login_result['userinfo']['displayname']
        print('登錄成功!用戶(hù) ID:%s厅克,用戶(hù)名:%s' % (user_unique_id, user_display_name))
    else:
        raise Exception('登錄失斉馔恕:%s' % login_result)


def main():
    username = input('請(qǐng)輸入登錄賬號(hào): ')
    password = input('請(qǐng)輸入登錄密碼: ')

    # 1.預(yù)登陸,獲取一個(gè)字典參數(shù)证舟,包含后面要用的 servertime硕旗、nonce、pubkey女责、rsakv
    pre_parameter = get_pre_parameter(username)

    # 2.通過(guò) JS 或者 Python 獲取加密后的密碼
    encrypted_password = get_encrypted_password(pre_parameter, password)

    # 3.獲取 token
    token = get_token(encrypted_password, pre_parameter, username)

    # 4.通過(guò) protection url 獲取加密后的手機(jī)號(hào)
    encrypted_mobile = get_encrypted_mobile(token)

    # 5.發(fā)送手機(jī)驗(yàn)證碼
    code = send_code(token, encrypted_mobile)

    # 6.校驗(yàn)驗(yàn)證碼漆枚,校驗(yàn)成功則返回一個(gè)重定向的 URL
    redirect_url = confirm_code(encrypted_mobile, code, token)

    # 7.訪(fǎng)問(wèn)重定向的 URL,提取 crossdomain2 URL
    cross_domain2_url = get_cross_domain2_url(redirect_url)

    # 8.訪(fǎng)問(wèn) crossdomain2 URL抵知,提取 passport URL
    passport_url = get_passport_url(cross_domain2_url)

    # 9.訪(fǎng)問(wèn) passport URL 進(jìn)行登錄操作
    login(passport_url)


if __name__ == '__main__':
    main()
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末墙基,一起剝皮案震驚了整個(gè)濱河市昔榴,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌碘橘,老刑警劉巖互订,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異痘拆,居然都是意外死亡仰禽,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén)纺蛆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)吐葵,“玉大人,你說(shuō)我怎么就攤上這事桥氏∥虑停” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵字支,是天一觀的道長(zhǎng)凤藏。 經(jīng)常有香客問(wèn)我,道長(zhǎng)堕伪,這世上最難降的妖魔是什么揖庄? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮欠雌,結(jié)果婚禮上蹄梢,老公的妹妹穿的比我還像新娘。我一直安慰自己富俄,他們只是感情好禁炒,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著霍比,像睡著了一般幕袱。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上桂塞,一...
    開(kāi)封第一講書(shū)人閱讀 51,301評(píng)論 1 301
  • 那天凹蜂,我揣著相機(jī)與錄音,去河邊找鬼阁危。 笑死玛痊,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的狂打。 我是一名探鬼主播擂煞,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼趴乡!你這毒婦竟也來(lái)了对省?” 一聲冷哼從身側(cè)響起蝗拿,我...
    開(kāi)封第一講書(shū)人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蒿涎,沒(méi)想到半個(gè)月后哀托,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡劳秋,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年仓手,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片玻淑。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡嗽冒,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出补履,到底是詐尸還是另有隱情添坊,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布箫锤,位于F島的核電站贬蛙,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏麻汰。R本人自食惡果不足惜速客,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望五鲫。 院中可真熱鬧,春花似錦岔擂、人聲如沸位喂。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)塑崖。三九已至,卻和暖如春痛倚,著一層夾襖步出監(jiān)牢的瞬間规婆,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工蝉稳, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留抒蚜,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓耘戚,卻偏偏與公主長(zhǎng)得像嗡髓,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子收津,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容