Android 簽名機制 v1、v2、v3

轉載自:https://github.com/jeanboydev/Android-ReadTheFuckingSourceCode/blob/master/article/android/basic/09_signature.md

什么是簽名?

要想知道簽名是什么,先來看為什么需要簽名 ?

了解 HTTPS 通信的同學應該知道,在消息通信時,必須至少解決兩個問題:一是確保消息來源的真實性,二是確保消息不會被第三方篡改。

在安裝 APK 時,同樣需要確保 APK 來源的真實性,以及 APK 沒有被第三方篡改。如何解決這兩個問題呢?

方法就是開發者對 APK 進行簽名:在 APK 中寫入一個「指紋」。指紋寫入以后,APK 中有任何修改,都會導致這個指紋無效,Android 系統在安裝 APK 進行簽名校驗時就會不通過,從而保證了安全性。

要了解如何實現簽名,需要了解兩個基本概念:消息摘要、數字簽名和數字證書。

消息摘要(Message Digest)

消息摘要(Message Digest),又稱數字摘要(Digital Digest)或數字指紋(Finger Print)。簡單來說,消息摘要就是在消息數據上,執行一個單向的 Hash 函數,生成一個固定長度的Hash值,這個Hash值即是消息摘要。

上面提到的的加密 Hash 函數就是消息摘要算法。它有以下特征:

無論輸入的消息有多長,計算出來的消息摘要的長度總是固定的。

例如:應用 MD5 算法摘要的消息有128個比特位,用 SHA-1 算法摘要的消息最終有 160 比特位的輸出,SHA-1 的變體可以產生 192 比特位和 256 比特位的消息摘要。一般認為,摘要的最終輸出越長,該摘要算法就越安全。

消息摘要看起來是「隨機的」。

這些比特看上去是胡亂的雜湊在一起的。可以用大量的輸入來檢驗其輸出是否相同,一般,不同的輸入會有不同的輸出,而且輸出的摘要消息可以通過隨機性檢驗。但是,一個摘要并不是真正隨機的,因為用相同的算法對相同的消息求兩次摘要,其結果必然相同;而若是真正隨機的,則無論如何都是無法重現的。因此消息摘要是「偽隨機的」。

消息摘要函數是單向函數,即只能進行正向的信息摘要,而無法從摘要中恢復出任何的消息,甚至根本就找不到任何與原信息相關的信息。

當然,可以采用強力攻擊的方法,即嘗試每一個可能的信息,計算其摘要,看看是否與已有的摘要相同,如果這樣做,最終肯定會恢復出摘要的消息。但實際上,要得到的信息可能是無窮個消息之一,所以這種強力攻擊幾乎是無效的。

好的摘要算法,沒有人能從中找到「碰撞」。或者說,無法找到兩條消息,使它們的摘要相同。

雖然「碰撞」是肯定存在的(由于長明文生成短摘要的 Hash 必然會產生碰撞)。即對于給定的一個摘要,不可能找到一條信息使其摘要正好是給定的。

正是由于以上特點,消息摘要算法被廣泛應用在「數字簽名」領域,作為對明文的摘要算法。著名的消息摘要算法有 RSA 公司的 MD5 算法和 SHA-1 算法及其大量的變體。

SHA-256 是 SHA-1 的升級版,現在 Android 簽名使用的默認算法都已經升級到 SHA-256 了。

消息摘要的這種特性,很適合來驗證數據的完整性。比如:在網絡傳輸過程中下載一個大文件 BigFile,我們會同時從網絡下載 BigFile 和 BigFile.md5,BigFile.md5 保存 BigFile 的摘要,我們在本地生成 BigFile 的消息摘要和 BigFile.md5 比較,如果內容相同,則表示下載過程正確。

注意,消息摘要只能保證消息的完整性,并不能保證消息的不可篡改性。

數字簽名(Digital Signature)

數字簽名方案是一種以電子形式存儲消息簽名的方法。一個完整的數字簽名方案應該由兩部分組成:簽名算法和驗證算法。

在講數字簽名之前,我們先簡單介紹幾個相關知識點:「公鑰密碼體制」、「對稱加密算法」、「非對稱加密算法」。

公鑰密碼體制(public-key cryptography)

公鑰密碼體制分為三個部分,公鑰、私鑰、加密解密算法,它的加密解密過程如下:

加密:通過加密算法和公鑰對內容(或者說明文)進行加密,得到密文。加密過程需要用到公鑰。

解密:通過解密算法和私鑰對密文進行解密,得到明文。解密過程需要用到解密算法和私鑰。注意,由公鑰加密的內容,只能由私鑰進行解密,也就是說,由公鑰加密的內容,如果不知道私鑰,是無法解密的。

公鑰密碼體制的公鑰和算法都是公開的(這是為什么叫公鑰密碼體制的原因),私鑰是保密的。大家都以使用公鑰進行加密,但是只有私鑰的持有者才能解密。

在實際 的使用中,有需要的人會生成一對公鑰和私鑰,把公鑰發布出去給別人使用,自己保留私鑰。目前使用最廣泛的公鑰密碼體制是 RSA 密碼體制。

對稱加密算法(symmetric key algorithms)

在對稱加密算法中,加密和解密都是使用的同一個密鑰。因此對稱加密算法要保證安全性的話,密鑰要做好保密,只能讓使用的人知道,不能對外公開。

非對稱加密算法(asymmetric key algorithms)

在非對稱加密算法中,加密使用的密鑰和解密使用的密鑰是不相同的。前面所說的公鑰密碼體制就是一種非對稱加密算法,它的公鑰和是私鑰是不能相同的,也就是說加密使用的密鑰和解密使用的密鑰不同,因此它是一個非對稱加密算法。

RSA 簡介

RSA 密碼體制是一種公鑰密碼體制,公鑰公開,私鑰保密,它的加密解密算法是公開的。由公鑰加密的內容可以并且只能由私鑰進行解密,而由私鑰加密的內容可以并且只能由公鑰進行解密。也就是說,RSA 的這一對公鑰、私鑰都可以用來加密和解密,并且一方加密的內容可以由并且只能由對方進行解密。

加密:公鑰加密,私鑰解密的過程,稱為「加密」。

因為公鑰是公開的,任何公鑰持有者都可以將想要發送給私鑰持有者的信息進行加密后發送,而這個信息只有私鑰持有者才能解密。

簽名:私鑰加密,公鑰解密的過程,稱為「簽名」。

它和加密有什么區別呢?因為公鑰是公開的,所以任何持有公鑰的人都能解密私鑰加密過的密文,所以這個過程并不能保證消息的安全性,但是它卻能保證消息來源的準確性和不可否認性,也就是說,如果使用公鑰能正常解密某一個密文,那么就能證明這段密文一定是由私鑰持有者發布的,而不是其他第三方發布的,并且私鑰持有者不能否認他曾經發布過該消息。故此將該過程稱為「簽名」。

數字簽名

事實上,任何一個公鑰密碼體制都可以單獨地作為一種數字簽名方案使用。

如 RSA 作為數字簽名方案使用時,可以定義如下:

這種簽名實際上就是用信源的私鑰加密消息,加密后的消息即成了簽體;而用對應的公鑰進行驗證,若公鑰解密后的消息與原來的消息相同,則消息是完整的,否則消息不完整。

它正好和公鑰密碼用于消息保密是相反的過程。因為只有信源才擁有自己地私鑰,別人無法重新加密源消息,所以即使有人截獲且更改了源消息,也無法重新生成簽體,因為只有用信源的私鑰才能形成正確地簽體。

同樣信宿只要驗證用信源的公鑰解密的消息是否與明文消息相同,就可以知道消息是否被更改過,而且可以認證消息是否是確實來自意定的信源,還可以使信源不能否認曾經發送的消息。所以 這樣可以完成數字簽名的功能。

但這種方案過于單純,它僅可以保證消息的完整性,而無法確保消息的保密性。而且這種方案要對所有的消息進行加密操作,這在消息的長度比較大時,效率是非常低的,主要原因在于公鑰體制的加解密過程的低效性。所以這種方案一般不可取。

幾乎所有的數字簽名方案都要和快速高效的摘要算法(Hash 函數)一起使用,當公鑰算法與摘要算法結合起來使用時,便構成了一種有效地數字簽名方案。

這個過程是:

用摘要算法對消息進行摘要。

再把摘要值用信源的私鑰加密。

通過以上兩步得到的消息就是所謂的原始信息的數字簽名,發送者需要將原始信息和數字簽名一同發送給接收者。而接收者在接收到原始信息和數字簽名后,通過以下 3 步驗證消息的真偽:

先把接收到的原始消息用同樣的摘要算法摘要,形成「準簽體」。

對附加上的那段數字簽名,使用預先得到的公鑰解密。

比較前兩步所得到的兩段消息是否一致。如果一致,則表明消息確實是期望的發送者發的,且內容沒有被篡改過;相反,如果不一致,則表明傳送的過程中一定出了問題,消息不可信。

這種方法使公鑰加密只對消息摘要進行操作,因為一種摘要算法的摘要消息長度是固定的,而且都比較「短」(相對于消息而言),正好符合公鑰加密的要求。這樣效率得到了提高,而其安全性也并未因為使用摘要算法而減弱。

綜上所述,數字簽名是?非對稱加密技術?+?消息摘要?技術的結合。

數字證書(Digital Certificate)

通過數字簽名技術,確實可以解決可靠通信的問題。一旦驗簽通過,接收者就能確信該消息是期望的發送者發送的,而發送者也不能否認曾經發送過該消息。

大家有沒有注意到,前面講的數字簽名方法,有一個前提,就是消息的接收者必須事先得到正確的公鑰。如果一開始公鑰就被別人篡改了,那壞人就會被你當成好人,而真正的消息發送者給你發的消息會被你視作無效的。而且,很多時候根本就不具備事先溝通公鑰的信息通道。

那么如何保證公鑰的安全可信呢?這就要靠數字證書來解決了。

數字證書是一個經證書授權(Certificate Authentication)中心數字簽名的包含公鑰擁有者信息以及公鑰的文件。數字證書的格式普遍采用的是 X.509 V3 國際標準,一個標準的 X.509 數字證書通常包含以下內容:

證書的發布機構(Issuer)

該證書是由哪個機構(CA 中心)頒發的。

證書的有效期(Validity)

證書的有效期,或者說使用期限。過了該日期,證書就失效了。

證書所有人的公鑰(Public-Key)

該證書所有人想要公布出去的公鑰。

證書所有人的名稱(Subject)

這個證書是發給誰的,或者說證書的所有者,一般是某個人或者某個公司名稱、機構的名稱、公司網站的網址等。

證書所使用的簽名算法(Signature algorithm)

這個數字證書的數字簽名所使用的加密算法,這樣就可以使用證書發布機構的證書里面的公鑰,根據這個算法對指紋進行解密。

證書發行者對證書的數字簽名(Thumbprint)

也就是該數字證書的指紋,用于保證數字證書的完整性,確保證書沒有被修改過。

其原理就是在發布證書時,CA 機構會根據簽名算法(Signature algorithm)對整個證書計算其 hash 值(指紋)并和證書放在一起,使用者打開證書時,自己也根據簽名算法計算一下證書的 hash 值(指紋),如果和證書中記錄的指紋對的上,就說明證書沒有被修改過。

可以看出,數字證書本身也用到了數字簽名技術,只不過簽名的內容是整個證書(里面包含了證書所有者的公鑰以及其他一些內容)。與普通數字簽名不同的是,數字證書的簽名者不是隨隨便便一個普通機構,而是 CA 機構。這就好像你的大學畢業證書上簽名的一般都是德高望重的校長一樣。

一般來說,這些 CA 機構的根證書已經在設備出廠前預先安裝到了你的設備上了。所以,數字證書可以保證證書里的公鑰確實是這個證書所有者的,或者證書可以用來確認對方的身份。可見,數字證書主要是用來解決公鑰的安全發放問題。

綜上所述,總結一下,數字簽名和簽名驗證的大體流程如下圖所示:

Android 中的簽名方案

Android 的簽名方案,發展到現在,不是一蹴而就的。Android 現在已經支持三種應用簽名方案:

v1 方案:基于 JAR 簽名。

v2 方案:APK 簽名方案 v2,在 Android 7.0 引入。

v3 方案:APK 簽名方案v3,在 Android 9.0 引入。

v1 到 v2 是顛覆性的,為了解決 JAR 簽名方案的安全性問題,而到了 v3 方案,其實結構上并沒有太大的調整,可以理解為 v2 簽名方案的升級版,有一些資料也把它稱之為 v2+ 方案。

因為這種簽名方案的升級,就是向下兼容的,所以只要使用得當,這個過程對開發者是透明的。

v1 到 v2 方案的升級,對開發者影響最大的,就是渠道簽署的問題。在當下這個大環境下,我們想讓不同渠道、市場的安裝包有所區別,攜帶渠道的唯一標識,這就是我們俗稱的渠道包。好在各大廠都開源了自己的簽渠道方案,例如:Walle(美團)、VasDolly(騰訊)都是非常優秀的方案。

APK 簽名方案 v1

簽名工具

Android 應用的簽名工具有兩種:jarsigner?和?apksigner。它們的簽名算法沒什么區別,主要是簽名使用的文件不同。

jarsigner:jdk 自帶的簽名工具,可以對 jar 進行簽名。使用 keystore 文件進行簽名。生成的簽名文件默認使用 keystore 的別名命名。

apksigner:Android sdk 提供的專門用于 Android 應用的簽名工具。使用 pk8、x509.pem 文件進行簽名。其中 pk8 是私鑰文件,x509.pem 是含有公鑰的文件。生成的簽名文件統一使用“CERT”命名。

既然這兩個工具都是給 APK 簽名的,那么 keystore 文件和 pk8,x509.pem 他們之間是不是有什么聯系呢?答案是肯定的,他們之間是可以轉化的,這里就不再分析如何進行轉化,網上的例子很多。

還有一個需要注意的知識點,如果我們查看一個keystore 文件的內容,會發現里面包含有一個 MD5 和 SHA1 摘要,這個就是 keystore 文件中私鑰的數據摘要,這個信息也是我們在申請很多開發平臺賬號時需要填入的信息。

簽名過程

首先我們任意選取一個簽名后的 APK(Sample-release.APK)解壓:

在?META-INF?文件夾下有三個文件:MANIFEST.MF、CERT.SF、CERT.RSA。它們就是簽名過程中生成的文件,姑且叫他們「簽名三兄弟」吧,把它們搞清楚了,你就精通簽名了。

MANIFEST.MF

該文件中保存的內容其實就是逐一遍歷 APK 中的所有條目,如果是目錄就跳過,如果是一個文件,就用 SHA1(或者 SHA256)消息摘要算法提取出該文件的摘要然后進行 BASE64 編碼后,作為「SHA1-Digest」屬性的值寫入到 MANIFEST.MF 文件中的一個塊中。該塊有一個「Name」屬性, 其值就是該文件在 APK 包中的路徑。

CERT.SF

SHA1-Digest-Manifest-Main-Attributes:對 MANIFEST.MF 頭部的塊做 SHA1(或者SHA256)后再用 Base64 編碼

SHA1-Digest-Manifest:對整個 MANIFEST.MF 文件做 SHA1(或者 SHA256)后再用 Base64 編碼

SHA1-Digest:對 MANIFEST.MF 的各個條目做 SHA1(或者 SHA256)后再用 Base64 編碼

對于 SHA1-Digest 值的驗證可以手動進行,將 MANIFEST.MF 中任意一個塊的內容復制并保存在一個新的文檔中,注意文末需要加兩個換行(這是由 signAPK 的源碼決定的)

CERT.RSA

這里會把之前生成的 CERT.SF 文件,用私鑰計算出簽名, 然后將簽名以及包含公鑰信息的數字證書一同寫入 CERT.RSA 中保存。這里要注意的是,Android APK 中的 CERT.RSA 證書是自簽名的,并不需要這個證書是第三方權威機構發布或者認證的,用戶可以在本地機器自行生成這個自簽名證書。Android 目前不對應用證書進行 CA 認證。

什么是自簽名證書?

所謂自簽名證書是指自己給自己頒發的證書,即公鑰證書中 Issuer(發布者)和 Subject(所有者)是相同的。當然,APK 也可以采用由 CA 頒發私鑰證書進行簽名。采用非自簽名時,最終 APK 的公鑰證書中就會包含證書鏈,并且會存在多余一個證書,證書間通過 Issuer 與 Subject進行關聯,Issuer 負責對 Subject 進行認證。當安裝 APK 時,系統只會用位于證書鏈 中最底層的證書對 APK 進行校驗,但并不會驗證證書鏈的有效性。

在 HTTPS 通信中使用自簽名證書時瀏覽器的顯示效果:

CERT.RSA 文件中的內容:

這里我們看到的都是二進制文件,因為 RSA 文件加密了,所以我們需要用 openssl 命令才能查看其內容:

$ openssl pkcs7 -inform DER -in /<文件存放路徑>/Sample-release_new/original/META-INF/CERT.RSA -text -noout -print_certs

綜上所述,一個完整的簽名過程如下所示:

簽名校驗過程

簽名驗證是發生在 APK 的安裝過程中,一共分為三步:

檢查 APK 中包含的所有文件,對應的摘要值與 MANIFEST.MF 文件中記錄的值一致。

使用證書文件(RSA 文件)檢驗簽名文件(SF 文件)沒有被修改過。

使用簽名文件(SF 文件)檢驗 MF 文件沒有被修改過。

綜上所述,一個完整的簽名驗證過程如下所示:

為什么使用這樣的簽名流程呢?

我們假設一下,首先,如果你改變了 APK 包中的任何文件,那么在 APK 安裝校驗時,改變后的文件摘要信息與 MANIFEST.MF 的檢驗信息不同,于是驗證失敗,程序就不能成功安裝。

其次,如果你對更改過的文件相應的算出新的摘要值,然后更改 MANIFEST.MF 文件里面對應的屬性值,那么必定與 CERT.SF 文件中算出的摘要值不一樣,照樣驗證失敗。

最后,如果你還不死心,繼續計算 MANIFEST.MF 的摘要值,相應的更改 CERT.SF 里面的值,那么數字簽名值必定與 CERT.RSA 文件中記錄的不一樣,還是失敗。

那么能不能繼續偽造數字簽名呢?不可能,因為沒有數字證書對應的私鑰。

APK 簽名方案 v2

APK 簽名方案 v2 是一種全文件簽名方案,該方案能夠發現對 APK 的受保護部分進行的所有更改,從而有助于加快驗證速度并增強完整性保證。

v1 簽名機制的劣勢

從 Android 7.0 開始,Android 支持了一套全新的 V2 簽名機制,為什么要推出新的簽名機制呢?通過前面的分析,可以發現 v1 簽名有兩個地方可以改進:

簽名校驗速度慢

校驗過程中需要對apk中所有文件進行摘要計算,在 APK 資源很多、性能較差的機器上簽名校驗會花費較長時間,導致安裝速度慢。

完整性保障不夠

META-INF 目錄用來存放簽名,自然此目錄本身是不計入簽名校驗過程的,可以隨意在這個目錄中添加文件,比如一些快速批量打包方案就選擇在這個目錄中添加渠道文件。

為了解決這兩個問題,在 Android 7.0 Nougat 中引入了全新的 APK Signature Scheme v2。

v2 帶來了什么變化?

由于在 v1 僅針對單個 ZIP 條目進行驗證,因此,在 APK 簽署后可進行許多修改 — 可以移動甚至重新壓縮文件。事實上,編譯過程中要用到的 ZIPalign 工具就是這么做的,它用于根據正確的字節限制調整 ZIP 條目,以改進運行時性能。而且我們也可以利用這個東西,在打包之后修改 META-INF 目錄下面的內容,或者修改 ZIP 的注釋來實現多渠道的打包,在 v1 簽名中都可以校驗通過。

v2 簽名將驗證歸檔中的所有字節,而不是單個 ZIP 條目,因此,在簽署后無法再運行 ZIPalign(必須在簽名之前執行)。正因如此,現在,在編譯過程中,Google 將壓縮、調整和簽署合并成一步完成。

v2 簽名模式

簡單來說,v2 簽名模式在原先 APK 塊中增加了一個新的塊(簽名塊),新的塊存儲了簽名,摘要,簽名算法,證書鏈,額外屬性等信息,這個塊有特定的格式,具體格式分析見后文,先看下現在 APK 成什么樣子了。

為了保護 APK 內容,整個 APK(ZIP 文件格式)被分為以下 4 個區塊:

ZIP 條目的內容(從偏移量 0 處開始一直到“APK 簽名分塊”的起始位置)

APK 簽名分塊

ZIP 中央目錄

ZIP 中央目錄結尾

其中,應用簽名方案的簽名信息會被保存在 區塊 2(APK Signing Block)中,而區塊 1(Contents of ZIP entries)、區塊 3(ZIP Central Directory)、區塊 4(ZIP End of Central Directory)是受保護的,在簽名后任何對區塊 1、3、4 的修改都逃不過新的應用簽名方案的檢查。

簽名過程

從上面我們可以看到 v2 模式塊有點類似于我們?META-INF?文件夾下的信息內容。那么對于上述當中摘要的信息又是怎么計算出來的呢。

首先,說一下 APK 摘要計算規則,對于每個摘要算法,計算結果如下:

將 APK 中文件 ZIP 條目的內容、ZIP 中央目錄、ZIP 中央目錄結尾按照 1MB 大小分割成一些小塊。

計算每個小塊的數據摘要,數據內容是 0xa5 + 塊字節長度 + 塊內容。

計算整體的數據摘要,數據內容是 0x5a + 數據塊的數量 + 每個數據塊的摘要內容

總之,就是把 APK 按照 1M 大小分割,分別計算這些分段的摘要,最后把這些分段的摘要在進行計算得到最終的摘要也就是 APK 的摘要。然后將 APK 的摘要 + 數字證書 + 其他屬性生成簽名數據寫入到 APK Signing Block 區塊。

簽名校驗過程

接下來我們來看v2簽名的校驗過程,整體大概流程如下圖所示:

其中 v2 簽名機制是在 Android 7.0 以及以上版本才支持。因此對于 Android 7.0 以及以上版本,在安裝過程中,如果發現有 v2 簽名塊,則必須走 v2 簽名機制,不能繞過。否則降級走 v1 簽名機制。v1 和 v2 簽名機制是可以同時存在的,其中對于 v1 和 v2 版本同時存在的時候,v1 版本的 META_INF 的?.SF?文件屬性當中有一個?X-Android-APK-Signed?屬性:

X-Android-APK-Signed: 2

因此如果想繞過 v2 走 v1 校驗是不行的。

v2 對多渠道打包的影響

之前的渠道包生成方案是通過在 META-INF 目錄下添加空文件,用空文件的名稱來作為渠道的唯一標識。但在新的應用簽名方案下 META-INF 已經被列入了保護區了,向 META-INF 添加空文件的方案會對區塊 1、3、4 都會有影響。

可以參考:美團解決方案。

APK 簽名方案 v3

Android 9.0 中引入了新的簽名方式,它的格式大體和 v2 類似,在 v2 插入的簽名塊(Apk Signature Block v2)中,又添加了一個新快(Attr塊)。

在這個新塊中,會記錄我們之前的簽名信息以及新的簽名信息,以密鑰轉輪的方案,來做簽名的替換和升級。這意味著,只要舊簽名證書在手,我們就可以通過它在新的 APK 文件中,更改簽名。

v3 簽名新增的新塊(attr)存儲了所有的簽名信息,由更小的 Level 塊,以鏈表的形式存儲。

其中每個節點都包含用于為之前版本的應用簽名的簽名證書,最舊的簽名證書對應根節點,系統會讓每個節點中的證書為列表中下一個證書簽名,從而為每個新密鑰提供證據來證明它應該像舊密鑰一樣可信。

這個過程有點類似 CA 證書的證明過程,已安裝的 App 的舊簽名,確保覆蓋安裝的 APK 的新簽名正確,將信任傳遞下去。

簽名校驗過程

Android 的簽名方案,無論怎么升級,都是要確保向下兼容。

在引入 v3 方案后,Android 9.0 及更高版本中,可以根據 APK 簽名方案,v3 -> v2 -> v1 依次嘗試驗證 APK。而較舊的平臺會忽略 v3 簽名并嘗試 v2 簽名,最后才去驗證 v1 簽名。

整個驗證的過程,如下圖:

需要注意的是,對于覆蓋安裝的情況,簽名校驗只支持升級,而不支持降級。也就是說設備上安裝了一個使用 v1 簽名的 APK,可以使用 v2 簽名的 APK 進行覆蓋安裝,反之則不允許。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,283評論 6 530
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 97,947評論 3 413
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,094評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,485評論 1 308
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,268評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,817評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,906評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,039評論 0 285
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,551評論 1 331
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,502評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,662評論 1 366
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,188評論 5 356
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,907評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,304評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,563評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,255評論 3 389
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,637評論 2 370

推薦閱讀更多精彩內容