iOS逆向(5)-不知MachO怎敢說(shuō)自己懂DYLD

轉(zhuǎn)載:原文地址

在上篇文章代碼注入狰腌,竊取微信密碼中咱們已經(jīng)簡(jiǎn)單的提到了MachO,在用Framework做代碼注入的時(shí)候轮听,必須先向MachO的Load Commons中插入該Framework的的相對(duì)路徑笋鄙,讓我們的iPhone在執(zhí)行MachO的時(shí)候能夠識(shí)別并加載Framework!

窺一斑而知全豹互拾,從這些許內(nèi)容其實(shí)已經(jīng)可以了解到MachO在我們APP中的地位是多么的重要歪今。同樣,在咱們逆向的實(shí)踐中颜矿,MachO也是一道繞不過(guò)去門檻!

老規(guī)矩,片頭先上福利:點(diǎn)擊下載demo
這篇文章會(huì)用到的工具有:

廢話不多說(shuō)余掖,本篇文章將會(huì)從以下幾點(diǎn)細(xì)說(shuō)到底什么是MachO许布!

  • 什么是MachO
  • MachO的文件結(jié)構(gòu)
  • 從DYLD源碼的角度看APP啟動(dòng)流程 (重點(diǎn)!9棵泊柬!)

一、什么是MachO

Mach-O其實(shí)是Mach Object文件格式的縮寫诈火,是mac以及iOS上可執(zhí)行文件的格式兽赁, 類似于windows上的PE格式 (Portable Executable ), linux上的elf格式 (Executable and Linking Format)

1、常見的MachO文件

a冷守、目標(biāo)文件:.o
b刀崖、庫(kù)文件:.a .dylib Framework
c、可執(zhí)行文件:dyld .dsym

2拍摇、如何查看文件格式

我們可以通過(guò)file指令查看文件的具體格式

file指令

目前已知的架構(gòu)分為armv7,armv7s,arm64,i386,x86_64等等亮钦,MachO中其實(shí)也是這些架構(gòu)的集合〕浠睿可以隨意建立一個(gè)空工程:Dome1(空工程就不給Demo了)

查看Build出的Dome1.ipa中的MachO

x86架構(gòu)MachO

將最低版本設(shè)置為iOS 12或悲,用release打包出的Dome1.ipa中的MachO

arm64架構(gòu)MachO

將最低版本設(shè)置為iOS 8,用release打包出的Dome1.ipa中的MachO

多架構(gòu)MachO

從上面三張圖就可以確定MachO可以是多架構(gòu)的二進(jìn)制文件堪唐,稱之為「通用二進(jìn)制文件」

通用二進(jìn)制文件是蘋果公司提出的一種程序代碼巡语。能同時(shí)適用多種架構(gòu)的二進(jìn)制文件
a. 同一個(gè)程序包中同時(shí)為多種架構(gòu)提供最理想的性能。
b. 因?yàn)樾枰獌?chǔ)存多種代碼淮菠,通用二進(jìn)制應(yīng)用程序通常比單一平臺(tái)二進(jìn)制的程序要大男公。
c. 但是由于兩種架構(gòu)有共通的非執(zhí)行資源,所以并不會(huì)達(dá)到單一版本的兩倍之多。
d. 而且由于執(zhí)行中只調(diào)用一部分代碼枢赔,運(yùn)行起來(lái)也不需要額外的內(nèi)存澄阳。

注:其實(shí)除了更改最低版本號(hào)可以改變MachO的架構(gòu),在XCode的中也可以主動(dòng)設(shè)置

主動(dòng)修改架構(gòu)

3踏拜、拆分碎赢、重組MachO

// 使用lipo -info 可以查看MachO文件包含的架構(gòu)
$ lipo -info MachO文件
// 使用lipo –thin 拆分某種架構(gòu)
$ lipo MachO文件 –thin 架構(gòu) –output 輸出文件路徑
// 使用lipo -create  合并多種架構(gòu)
$ lipo -create MachO1  MachO2  -output 輸出文件路徑

拆分,重組MachO

二速梗、MachO的文件結(jié)構(gòu)

先上一張官網(wǎng)圖:

MachO的文件結(jié)構(gòu)

MachO分為三部分結(jié)構(gòu):Header肮塞、Load Commons、Data

1姻锁、Header

Header 包含該二進(jìn)制文件的一般信息
字節(jié)順序枕赵、架構(gòu)類型、加載指令的數(shù)量等位隶。
使得可以快速確認(rèn)一些信息拷窜,比如當(dāng)前文件用于32位還是64位,對(duì)應(yīng)的處理器是什么涧黄、文件類型是什么

本文從兩個(gè)視角分析Header篮昧,分別是「用MachOView可視化后直觀的查看」和「系統(tǒng)源碼解析」

  • 用MachOView可視化后直觀的查看
    上篇文章已經(jīng)講過(guò)使用MacOView可以直接查看一個(gè)MachO文件,如下圖

    MachO-Header
  • 系統(tǒng)源碼解析
    在MachO的源碼文件中同樣有對(duì)應(yīng)的字段笋妥。如下圖:

    MachO-Header源碼

2懊昨、Load Commons

Load commands是一張包含很多內(nèi)容的表。
內(nèi)容包括區(qū)域的位置挽鞠、符號(hào)表疚颊、動(dòng)態(tài)符號(hào)表等。

MachO-LoadCommons

上圖Load Commons中的大部分字段在下表中可以找到相關(guān)的含義信认。

名稱 含義
LC_SEGMENT_64 將文件中(32位或64位)的段映射到進(jìn)程地址空間中
LC_DYLD_INFO_ONLY 動(dòng)態(tài)鏈接相關(guān)信息
LC_SYMTAB 符號(hào)地址
LC_DYSYMTAB 動(dòng)態(tài)符號(hào)表地址
LC_LOAD_DYLINKER 使用誰(shuí)加載材义,我們使用dyld
LC_UUID 文件的UUID
LC_VERSION_MIN_MACOSX 支持最低的操作系統(tǒng)版本
LC_SOURCE_VERSION 源代碼版本
LC_MAIN 設(shè)置程序主線程的入口地址和棧大小
LC_LOAD_DYLIB 依賴庫(kù)的路徑,包含三方庫(kù)
LC_FUNCTION_STARTS 函數(shù)起始地址表
LC_CODE_SIGNATURE 代碼簽名

其中LC_LOAD_DYLINKERLC_LOAD_DYLIB

  • LC_LOAD_DYLINKER
    該字段標(biāo)明我們的MachO是被誰(shuí)加載進(jìn)去的嫁赏。
    可以理解為L(zhǎng)C_LOAD_DYLINKER指向的地址是微信APP加載小程序的引擎其掂,而我們的MachO是小程序。在上圖中可以看到我們的Demo1的LC_LOAD_DYLINKER指向的地址就是dyld潦蝇。dyld確實(shí)是用來(lái)加載我們app的款熬,在下面一節(jié)將會(huì)對(duì)dyld的源碼進(jìn)行分析,講述dyld是如何對(duì)MachO進(jìn)行加載的攘乒。

  • LC_LOAD_DYLIB
    該字段標(biāo)記了所有動(dòng)態(tài)庫(kù)的地址贤牛,只有在LC_LOAD_DYLIB中有標(biāo)記,我們MachO外部的動(dòng)態(tài)庫(kù)(如:Framework)才能被dyld正確的引用则酝,否則dyld不會(huì)主動(dòng)加載殉簸,這也是上篇文章,代碼注入的關(guān)鍵所在!

3般卑、Data

Data 通常是對(duì)象文件中最大的部分武鲁,包含Segement的具體數(shù)據(jù),如靜態(tài)C字符串蝠检,帶參數(shù)/不帶參數(shù)的OC方法沐鼠,帶參數(shù)/不帶參數(shù)的C函數(shù)。

在Demo1中編寫一下代碼

  • 靜態(tài)C字符串

  • 靜態(tài)OC字符串

  • 帶參數(shù)的OC方法

  • 不帶參數(shù)的OC方法

  • 帶參數(shù)的C函數(shù)

  • 不帶參數(shù)的C函數(shù)
    如圖:

    代碼

查看MachO中對(duì)應(yīng)的Data段:cstring,methname,如下兩圖:

MachO-字符串
MachO-方法名

可以看到叹谁,全局靜態(tài)C字符(myCString)饲梭,方法里面的字符串(myCFuncAString:%d,myCFuncString,%s,myOCFuncAString:%s,myOCFuncString:%s)都被保存在data段的cstring里了,哪怕是%d,%s等等這樣的參數(shù)類型字符串也被保存在內(nèi)本慕。但所有同樣的字符串只會(huì)被保存一次排拷。
同樣所有的OC方法都被保存在methname里了侧漓。

這里有個(gè)問(wèn)題:
在這兩個(gè)表中并沒(méi)有看到全局的靜態(tài)OC字符串(myOCString)和C函數(shù)(myCFuncA(int a),myCFunc())這里為什么沒(méi)有锅尘?他們應(yīng)該會(huì)被以是形式保存在哪里?

上面用cstringmethname距離了data段的作用布蔗,同樣的所有類名藤违,協(xié)議名等也是以同樣形式存儲(chǔ)在這。

上面已經(jīng)對(duì)MachO有了一個(gè)大概的了解纵揍,接下來(lái)本文就對(duì)dyld這么一個(gè)重要的東西進(jìn)行一個(gè)初探顿乒。

三、從DYLD源碼的角度看APP啟動(dòng)流程

1泽谨、在main函數(shù)中斷點(diǎn)查看

首先思考璧榄,在main函數(shù)中掛斷點(diǎn)能不能查看到APP啟動(dòng)對(duì)應(yīng)的堆棧?
這部分其實(shí)靠想吧雹,靠猜測(cè)很難有答案骨杂,我們直接用XCode直接嘗試:

main斷點(diǎn)

可以看到在main函數(shù)斷點(diǎn)并不能看到啟動(dòng)的對(duì)應(yīng)堆棧,說(shuō)明main函數(shù)也是被別人調(diào)用的雄卷,而不是處于app啟動(dòng)的堆棧中搓蚪。
既然main查不到啟動(dòng)堆棧,那么比app更早執(zhí)行的load方式是否可以找得到呢丁鹉?

2妒潭、在load方法中斷點(diǎn)查看

同樣的,直接X(jué)Code調(diào)試:

load斷點(diǎn)

在這可以發(fā)現(xiàn)更多的信息揣钦,比如在堆棧底部的匯編(這里用的是手機(jī)調(diào)試雳灾,所以是arm64架構(gòu))可以很明顯的發(fā)現(xiàn),是調(diào)用了用dyld中的dyldbootstrap文件中的start方法冯凹。
馬不停蹄谎亩,打開dyld源碼,找到對(duì)應(yīng)的dyldbootstrap文件中的start函數(shù)。
點(diǎn)擊這里下載dyld源碼

3团驱、在dyldbootstrap中查看start函數(shù)

//
//  This is code to bootstrap dyld.  This work in normally done for a program by dyld and crt.
//  In dyld we have to do this manually.
//
uintptr_t start(const struct macho_header* appsMachHeader, int argc, const char* argv[], 
                intptr_t slide, const struct macho_header* dyldsMachHeader,
                uintptr_t* startGlue)
{
    // if kernel had to slide dyld, we need to fix up load sensitive locations
    // we have to do this before using any global variables
    // 滑塊摸吠,ASLR技術(shù),地址偏移嚎花,是MachO文件在內(nèi)存中的地址重定向
    slide = slideOfMainExecutable(dyldsMachHeader);
    bool shouldRebase = slide != 0;
#if __has_feature(ptrauth_calls)
    shouldRebase = true;
#endif
    if ( shouldRebase ) {
        // 重定向
        rebaseDyld(dyldsMachHeader, slide);
    }

    // allow dyld to use mach messaging
    // 消息初始化
    mach_init();

    // kernel sets up env pointer to be just past end of agv array
    const char** envp = &argv[argc+1];

    // kernel sets up apple pointer to be just past end of envp array
    const char** apple = envp;
    while(*apple != NULL) { ++apple; }
    ++apple;

    // set up random value for stack canary
    // 棧溢出保護(hù)
    __guard_setup(apple);

#if DYLD_INITIALIZER_SUPPORT
    // run all C++ initializers inside dyld
    runDyldInitializers(dyldsMachHeader, slide, argc, argv, envp, apple);
#endif

    // now that we are done bootstrapping dyld, call dyld's main
    // 正在的啟動(dòng)函數(shù)寸痢,在dyld中的_main函數(shù)中
    uintptr_t appsSlide = slideOfMainExecutable(appsMachHeader);
    return dyld::_main(appsMachHeader, appsSlide, argc, argv, envp, apple, startGlue);
}

從start函數(shù)的源碼可得知道:dlyd會(huì)內(nèi)存中找到一塊地址給MachO使用,也就是ASLR紊选,內(nèi)存偏移啼止。
最后start函數(shù)執(zhí)行了一個(gè)main函數(shù)(這個(gè)可以不是我們app中的main函數(shù),而是dyld的)并返回兵罢。同樣的献烦,我們不能只蹭一蹭,要進(jìn)去干卖词!

4巩那、在dlyd中查看main函數(shù)

這個(gè)函數(shù)厲害了,如下圖此蜈,足足快500行了即横!

dyld的main函數(shù)

我們抓住其中的關(guān)鍵代碼,足步分析在main函數(shù)之前dyld到底幫我們做了哪一些事情裆赵。

1东囚、配置環(huán)境變量

從main函數(shù)的初始,到函數(shù)getHostInfo()之前都是在配置一些環(huán)境變量战授,已經(jīng)一些線程相關(guān)的页藻,涉及內(nèi)容太過(guò)底層,這就不一一分析了(其實(shí)是能力不及??)

配置環(huán)境變量

在這一步中有很多if判斷植兰,其實(shí)里面都是對(duì)應(yīng)的環(huán)境變量份帐,這些都是可以在XCode進(jìn)行相關(guān)的配置,進(jìn)行對(duì)應(yīng)的操作(如Log相關(guān)信息)钉跷。

2弥鹦、加載共享緩存庫(kù)

在iOS系統(tǒng)中,每個(gè)程序依賴的動(dòng)態(tài)庫(kù)都需要通過(guò)dyld(位于/usr/lib/dyld)一個(gè)一個(gè)加載到內(nèi)存爷辙,然而如果在每個(gè)程序運(yùn)行的時(shí)候都重復(fù)的去加載一次彬坏,勢(shì)必造成運(yùn)行緩慢,為了優(yōu)化啟動(dòng)速度和提高程序性能膝晾,共享緩存機(jī)制就應(yīng)運(yùn)而生栓始。所有默認(rèn)的動(dòng)態(tài)鏈接庫(kù)被合并成一個(gè)大的緩存文件,放到/System/Library/Caches/com.apple.dyld/目錄下血当,按不同的架構(gòu)保存分別保存著幻赚。其中包括UIKit禀忆,F(xiàn)oundation等基礎(chǔ)庫(kù)。

加載共享緩存庫(kù)_1
加載共享緩存庫(kù)_2

在源碼中可以看到在我們iOS系統(tǒng)中落恼,共享緩存庫(kù)被明確一定會(huì)被加載箩退。
因?yàn)檫@種機(jī)制的存在,使得iOS在的對(duì)這些基礎(chǔ)庫(kù)的加載的時(shí)候時(shí)間和內(nèi)存都得到節(jié)約佳谦!
但是有時(shí)因?yàn)楣蚕砭彺鎺?kù)的機(jī)制的存在使得iOS在共享緩存庫(kù)里面的C函數(shù)戴涝,也就是系統(tǒng)C函數(shù)變的不是那么靜態(tài),有了些許OC運(yùn)行時(shí)的特性钻蔑!
這部分內(nèi)容將會(huì)在下一篇文章著重講解啥刻!從不一樣的角度看Runtime!

3咪笑、實(shí)例化主程序

加載主程序其實(shí)就是對(duì)MachO文件中LoadCommons段的一些列加載可帽!
我們繼續(xù)對(duì)代碼的跟進(jìn),如下6張圖:

加載主程序_1
加載主程序_2

補(bǔ)充:實(shí)例化完之后調(diào)用addImage(image)窗怒,將實(shí)例化出來(lái)的鏡像加入所有的鏡像列表sAllImages映跟,主程序永遠(yuǎn)是sAllImages的第一個(gè)對(duì)象!

加載主程序_3
加載主程序_LoadCommons_1
加載主程序_LoadCommons_2
加載主程序_LoadCommons_3

從源代碼可以看出兜粘,加載主程序這一步其實(shí)很簡(jiǎn)單申窘,就是將MachO文件中的部分信息一步一步的放入內(nèi)存弯蚜。
其中從最后一張圖可以了解到:

  • 最大的segment數(shù)量為256個(gè)孔轴!
  • 最大的動(dòng)態(tài)庫(kù)(包括系統(tǒng)的個(gè)自定義的)個(gè)數(shù)為4096個(gè)!
4碎捺、加載動(dòng)態(tài)鏈接庫(kù)

加載動(dòng)態(tài)鏈接庫(kù)路鹰,如XCode的ViewDebug、MainThreadChecker收厨,我們之后代碼注入的庫(kù)也是通過(guò)這種形式添加的晋柱!

插入動(dòng)態(tài)鏈接庫(kù)
5、鏈接主程序
鏈接主程序

link函數(shù)里面其實(shí)就是對(duì)之前的imges(不是圖片诵叁,這是鏡像)進(jìn)行一些內(nèi)核操作雁竞,這部分Apple沒(méi)有開源出來(lái),只能看到些許源碼拧额,有興許的同學(xué)可以自行查閱:

Link
6碑诉、加載Load和特定的C++的構(gòu)造函數(shù)方法

無(wú)論是從之前斷點(diǎn)load方法還是我們現(xiàn)在一步步對(duì)源碼的根據(jù),都能了解到侥锦,dyldinitializeMainExecutable就是就加載load的入口:

initializeMainExecutable_1
initializeMainExecutable_2

并且最后都能接到一個(gè)結(jié)論:
dyldnotifySingle函數(shù)經(jīng)過(guò)一系列的跳轉(zhuǎn)进栽,最終會(huì)跳轉(zhuǎn)到objc源碼中的call_load_methods函數(shù)!恭垦!

那么這中間的的過(guò)程到底是怎么樣的呢快毛?看下方的gif:過(guò)程

最后找到函數(shù)_dyld_objc_notify_register格嗅,就在全局都找不到一個(gè)調(diào)用的地方了,其實(shí)這個(gè)函數(shù)本身就不是給dyld調(diào)用的唠帝,而是提供給外部調(diào)用的屯掖。怎么找到是誰(shuí)調(diào)用了_dyld_objc_notify_register呢?
繼續(xù)打開之前的Demo1襟衰,在工程中加上_dyld_objc_notify_register的符號(hào)斷點(diǎn)看看懂扼。

符號(hào)斷點(diǎn)

運(yùn)行工程,斷住之后再次查看函數(shù)調(diào)用棧:

符號(hào)斷點(diǎn)后的調(diào)用堆棧

這就可以很清晰的看到右蒲,原來(lái)是objc_init調(diào)用了咱們的_dyld_objc_notify_register函數(shù)阀湿。

同樣打開objc的源碼(點(diǎn)擊下載objc源碼 )
快速定位_dyld_objc_notify_register的調(diào)用位置。如圖:

_objc_init
load_images

這樣dyld是如何加載咱們的load方法就被找到了瑰妄。
期間如果有細(xì)心的同學(xué)可能看到了在notifySingle后面緊跟著doInitialization這樣一個(gè)函數(shù)陷嘴,這是一個(gè)系統(tǒng)特定的C++構(gòu)造函數(shù)的調(diào)用方法。

doInitialization_1
doModInitFunctions
ImageLoaderMachO_2

這種C++構(gòu)造函數(shù)有特定的寫法间坐,如下:

__attribute__((constructor)) void CPFunc(){
    printf("C++Func1");
}

有興趣的同學(xué)可以嘗試實(shí)現(xiàn)一次灾挨,在MachO文件中找到對(duì)應(yīng)的方法!
當(dāng)然竹宋,這在Demo1也是有的劳澄。

7、尋找APP的main函數(shù)并調(diào)用

當(dāng)上面的load和C++方法加載完成之后就會(huì)回到dyld的main方法里面蜈七,尋找APP的main函數(shù)并調(diào)用秒拔。

尋找APP的main函數(shù)并調(diào)用

最終dyld的main函數(shù)中的主要流程就已經(jīng)走完了,當(dāng)然這7個(gè)步驟是一條主線飒硅,期間還會(huì)有很多其他的步驟砂缩,過(guò)程非常繁瑣,這就不一一舉例了三娩。大家可以通過(guò)閱讀dyld的源碼盡收眼底庵芭。

四、總結(jié)

本文講述了MachO的概述雀监,文件結(jié)構(gòu)双吆,在從其中Load Commons中的LC_LOAD_DYLINKER引出dyld,接下根據(jù)dyld源碼分析了APP的啟動(dòng)流程会前。分別是:
1好乐、配置環(huán)境變量
2、加載共享緩存庫(kù)
3回官、實(shí)例化主程序
4曹宴、加載動(dòng)態(tài)鏈接庫(kù)
5、鏈接主程序
6歉提、加載Load和特定的C++的構(gòu)造函數(shù)方法
7笛坦、尋找APP的main函數(shù)并調(diào)用
另外dyld中LC_LOAD_DYLIB的(加載動(dòng)態(tài)鏈接庫(kù))存在区转,為我們逆向注入代碼提供了無(wú)限可能。
MachO中其實(shí)還有一些符號(hào)表版扩,為系統(tǒng)提供查詢對(duì)應(yīng)的方法名稱提供了路徑废离,這些在下一張文章中將會(huì)更加詳細(xì)的講到。

五礁芦、參考

1蜻韭、Dynamic Linking of Imported Functions in Mach-O
2、《iOS應(yīng)用逆向工程》沙梓社柿扣,吳航 著 肖方,機(jī)械工業(yè)出版社

轉(zhuǎn)載:原文地址
經(jīng)原作者同意:想交流iOS開發(fā),逆向等技術(shù)未状,可加iOS技術(shù)交流群:624212887俯画,進(jìn)行交流!


推薦文集

* 抖音效果實(shí)現(xiàn)

* BAT—最新iOS面試題總結(jié)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末司草,一起剝皮案震驚了整個(gè)濱河市艰垂,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌埋虹,老刑警劉巖猜憎,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異搔课,居然都是意外死亡胰柑,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門辣辫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)旦事,“玉大人,你說(shuō)我怎么就攤上這事急灭。” “怎么了谷遂?”我有些...
    開封第一講書人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵葬馋,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我肾扰,道長(zhǎng)畴嘶,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任集晚,我火速辦了婚禮窗悯,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘偷拔。我一直安慰自己蒋院,他們只是感情好亏钩,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著欺旧,像睡著了一般姑丑。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上辞友,一...
    開封第一講書人閱讀 51,365評(píng)論 1 302
  • 那天栅哀,我揣著相機(jī)與錄音,去河邊找鬼称龙。 笑死留拾,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的鲫尊。 我是一名探鬼主播间驮,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼马昨!你這毒婦竟也來(lái)了竞帽?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤鸿捧,失蹤者是張志新(化名)和其女友劉穎屹篓,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體匙奴,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡堆巧,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了泼菌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谍肤。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖哗伯,靈堂內(nèi)的尸體忽然破棺而出荒揣,到底是詐尸還是另有隱情,我是刑警寧澤焊刹,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布系任,位于F島的核電站,受9級(jí)特大地震影響虐块,放射性物質(zhì)發(fā)生泄漏俩滥。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一贺奠、第九天 我趴在偏房一處隱蔽的房頂上張望霜旧。 院中可真熱鬧,春花似錦儡率、人聲如沸挂据。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)棱貌。三九已至玖媚,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間婚脱,已是汗流浹背今魔。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留障贸,地道東北人错森。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像篮洁,于是被迫代替她去往敵國(guó)和親涩维。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

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