iOS逆向06 -- Mach-O

Mach-O文件
  • Mach-O是Mach Object文件格式的縮寫,是mac以及iOS上可執(zhí)行文件的格式妖异,例如當(dāng)Xcode App工程編譯完成之后就會生成一個可執(zhí)行文件吵护,其格式就是Mach-O文件焦读;
Mach-O的相關(guān)名詞
  • Executable 可執(zhí)行文件;
  • Dylib 動態(tài)庫睁冬;
  • Bundle 無法被連接的動態(tài)庫,只能通過dlopen()加載;
  • Image 指的是Executable豆拨,Dylib或者Bundle的一種直奋,文中會多次使用Image這個名詞;
  • Framework 動態(tài)庫(可以是靜態(tài)庫)和對應(yīng)的頭文件和資源文件的集合施禾;
Mach-O文件的常見類型
#define MH_OBJECT   0x1     /* relocatable object file */
#define MH_EXECUTE  0x2     /* demand paged executable file */
#define MH_FVMLIB   0x3     /* fixed VM shared library file */
#define MH_CORE     0x4     /* core file */
#define MH_PRELOAD  0x5     /* preloaded executable file */
#define MH_DYLIB    0x6     /* dynamically bound shared library */
#define MH_DYLINKER 0x7     /* dynamic link editor */
#define MH_BUNDLE   0x8     /* dynamically bound bundle file */
#define MH_DYLIB_STUB   0x9     /* shared library stub for static */
                    /*  linking only, no section contents */
#define MH_DSYM     0xa     /* companion file with only debug */
                    /*  sections */
#define MH_KEXT_BUNDLE  0xb     /* x86_64 kexts */
  • MH_OBJECT:目標(biāo)文件即 .o 文件 以及靜態(tài)庫文件即 .a 文件(多個.o文件合并在一起)脚线;
  • MH_EXECUTE:可執(zhí)行文件,即App編譯運行后生成的可執(zhí)行文件弥搞,在/Products路徑下邮绿;
  • MH_DYLIB:動態(tài)庫文件,即.dylib文件 或者 .framework文件攀例;
  • MH_DYLINKER:/usr/lib/dyld路徑下的dyld文件船逮;
  • MH_DSYM:Xcode打包后生成的符號表文件,即.dSYM文件粤铭;

查看文件的格式類型

  • 使用命令行 file 文件名

  • 查看自定義的目標(biāo).o文件

    • 終端輸入:file YYPerson.o
    • 終端輸出:YYPerson.o: Mach-O 64-bit object x86_64
  • 查看Xcode編譯運行后生成的可執(zhí)行文件

    • 終端輸入:file SuningWeiDian
    • 終端輸出:Mach-O 64-bit executable x86_64
  • 終端cd /usr/lib 然后 ls 列出所有l(wèi)ib文件挖胃;然后查看ACIPCBTLib.dylib文件

    • 終端輸入:file ACIPCBTLib.dylib
    • 終端輸出:ACIPCBTLib.dylib: Mach-O 64-bit dynamically linked shared library x86_64
  • 同上 查看 dyld文件

    • 終端輸入:file dyld
    • 終端輸出:dyld: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit dynamic linker x86_64] [i386:Mach-O dynamic linker i386]
      dyld (for architecture x86_64): Mach-O 64-bit dynamic linker x86_64
      dyld (for architecture i386):Mach-O dynamic linker i386
    • 可以看出 dyld 這個文件有點特殊;能同時支持x86_64與i386兩種架構(gòu)承耿;
  • 查看打包之后生成的dSYM文件

    • 終端輸入:file SuningWeiDian
    • 終端輸出:Mach-O universal binary with 2 architectures: [arm_v7:Mach-O dSYM companion file arm_v7] [arm64] SuningWeiDian (for architecture armv7): Mach-O dSYM companion file arm_v7 SuningWeiDian (for architecture arm64): Mach-O 64-bit dSYM companion file arm64

通用二進制文件(Universal binary)

  • 在iOS中不同手機對應(yīng)著可能不同的架構(gòu)冠骄,如arm64、armv7加袋、armv7s凛辣,為了兼容不同架構(gòu)的手機,蘋果推出了通用二進制文件职烧,其能同時支持多個不同架構(gòu)扁誓,因此通用二進制文件,比單一架構(gòu)二進制文件要大很多蚀之,因此也稱之為胖二進制文件蝗敢;
  • 當(dāng)一個文件同時支持多個架構(gòu)平臺,比如同時支持 ARMV7足删、ARM64寿谴,就相當(dāng)是兩個 Mach-O 文件,編譯器會編譯兩個Mach-O文件失受,然后合成一個Fat文件讶泰;
  • 例如上面的dSYM文件,就是通用二進制文件拂到,支持兩種架構(gòu)痪署;
  • 在Xcode工程中有配置支持不同架構(gòu)的選項,如下圖所示:
Snip20210616_14.png

Mach-O文件的基本結(jié)構(gòu)

  • 先上一個官方截圖兄旬,如下所示:
Snip20210119_19.png
  • 可以看出Mach-O文件主要包含三個部分:
    • Header:包含Mach-O文件的基本信息狼犯,例如文件類型,支持的CPU架構(gòu)類型,加載指令的數(shù)量悯森,所占內(nèi)存大小等等宋舷;
    • Load Commands:不同數(shù)據(jù)段segment的加載命令,指導(dǎo)加載器加載數(shù)據(jù)瓢姻;
    • Data:指數(shù)據(jù)段Segment肥缔,其有不同的Section組成;

otool工具

  • otool是Mac系統(tǒng)自帶的汹来,可以查看Mach-O文件特定部分和段的內(nèi)容的工具续膳;
  • 下面使用的資源是自己本地工程Mach-O文件結(jié)構(gòu)生成一個Mach-O文件結(jié)構(gòu).app文件,其包內(nèi)容中有一個Mach-O目標(biāo)文件:Mach-O文件結(jié)構(gòu)收班,下面利用otool的常見命令行操作Mach-O文件結(jié)構(gòu)
  • otool -h Mach-O文件結(jié)構(gòu)獲取Mach-O文件的Header頭信息坟岔,輸出結(jié)果如下:
Mach header
magic     cputype    cpusubtype  caps   filetype  ncmds sizeofcmds  flags
0xfeedfacf 16777223   3           0x00      2       75    8304       0x00218085
  • otool -L Mach-O文件結(jié)構(gòu)查看Mach-O文件所使用的動態(tài)庫,會打印出App中所有的動態(tài)庫如下所示:
Snip20210111_37.png
  • objdump --macho --private-headers Mach-O文件結(jié)構(gòu)摔桦,輸出結(jié)果如下:
image.png

MachOView圖形化界面工具

  • otool是通過命令行來查看Mach-O文件的結(jié)構(gòu)社付,但是不夠直觀,而MachOView是一款圖形化的查看Mach-O文件結(jié)構(gòu)的工具軟件邻耕,更加直觀鸥咖;
  • 點擊這里 進行下載兄世;
  • Mach-O文件結(jié)構(gòu)這個Mach-O文件直接拖入MachOView中啼辣,如下所示:
    image.png

Mach-O文件三部分的詳細分析

  • 源碼查看 在Xcode中按下Command+Shift+O 然后輸入loader.h 可以定位到系統(tǒng)關(guān)于Mach-O文件的定義;
第一部分:Mach_Header
  • 定義如下所示:
struct mach_header {
    uint32_t    magic;         /* mach magic number identifier */
    cpu_type_t   cputype;      /* cpu specifier */
    cpu_subtype_t   cpusubtype;  /* machine specifier */
    uint32_t    filetype;              /* type of file */
    uint32_t    ncmds;         /* number of load commands */
    uint32_t    sizeofcmds;    /* the size of all the load commands */
    uint32_t    flags;         /* flags */
};
  • magic:提供給系統(tǒng)內(nèi)核御滩,用來判斷文件是否是Mach-O的文件格式鸥拧;
  • cputype:表示支持的CPU類型,一般有armv7, armv64, x86, x86_64 這幾種類型削解;
  • filetype:表示Mach-O的具體文件類型富弦,如果是可執(zhí)行文件就是 MH_EXECUTE,如果是動態(tài)庫就是 MH_DYLIB氛驮,詳情見文章頂部腕柜;
  • ncmds:表示Mach-O文件中所有Load Commands(加載命令)的總個數(shù);
  • sizeofcmds:表示Load Commands所有(加載命令)占用的字節(jié)總大薪梅稀盏缤;
  • flags:表示文件的標(biāo)志信息;
第二部分:Load Commands
  • Load Commands緊跟在Mach_Header之后磷脯,這些加載指令告訴loader加載器如何加載二進制數(shù)據(jù)蛾找,本質(zhì)就是確定如何加載段segment數(shù)據(jù)娩脾,其定義如下所示:
struct load_command {
    uint32_t cmd;       /* type of load command */
    uint32_t cmdsize;   /* total size of command in bytes */
};
  • 屬性cmd:表示Load Commands(加載命令)的類型赵誓;
  • 屬性cmdsize:表示當(dāng)前的加載命令所占內(nèi)存大小;
  • 使用MachOView工具查看Mach-O文件的Load Commands部分可以看到:
image.png
  • 常見的加載命令的簡介如下所示:
    • LC_SEGMENT_64:將該段(64位)映射到進程地址空間中俩功;
    • LC_DYLD_INF0_0NLY:加載動態(tài)鏈接庫信息(重定向地址幻枉、弱引用綁定、懶加載綁定诡蜓、開放函數(shù)等的偏移值等信息)熬甫;
    • LC_SYMTAB:加載符號表;
    • LC_DYSYMTAB:加載動態(tài)符號表蔓罚;
    • LC_LOAD_DYLINKER:加載動態(tài)加載庫椿肩,可以看出示例使用的是/usr/lib/dyld;
    • LC.UUID: 確定文件的唯一標(biāo)識豺谈,crash解析中也會有這個郑象,去檢測dysm文件crash文件是否匹配;
    • LC_VERSION_MIN_IPHONEOS:確定二進制文件要求的最低操作系統(tǒng)版本茬末;
    • LC.SOURCE.VERSION:構(gòu)建二進制文件的源代碼版本號厂榛;
    • LC.MAIN:主程序的入口,dyld獲取該地址丽惭,然后跳轉(zhuǎn)到該處執(zhí)行击奶;
    • LC_ENCRYPTION_INFO_64:加載加密信息;
    • LC_LOADJDYLIB:加載額外的動態(tài)庫责掏;
    • LC_FUNCTION_STARTS:定義一個函數(shù)起始地址表,使調(diào)試器和其他程序易于看到一個地址是否在函數(shù)內(nèi)柜砾;
    • LC_DATA_IN_CODE:定義在代碼段內(nèi)的非指令的表;
    • LC_CODE_SIGNATURE:獲取應(yīng)用簽名信息换衬;
  • 下面以加載指令LC_SEGMENT_64為例局义,此加載指令的結(jié)構(gòu)如下所示:
image.png
  • LC_SEGMENT_64此加載指令屬于segment段加載指令,其結(jié)構(gòu)體源碼如下所示:
struct segment_command { /* for 32-bit architectures */
    uint32_t    cmd;        /* LC_SEGMENT */
    uint32_t    cmdsize;    /* includes sizeof section structs */
    char        segname[16];    /* segment name */
    uint32_t    vmaddr;     /* memory address of this segment */
    uint32_t    vmsize;     /* memory size of this segment */
    uint32_t    fileoff;    /* file offset of this segment */
    uint32_t    filesize;   /* amount to map from the file */
    vm_prot_t   maxprot;    /* maximum VM protection */
    vm_prot_t   initprot;   /* initial VM protection */
    uint32_t    nsects;     /* number of sections in segment */
    uint32_t    flags;      /* flags */
}
  • cmd:加載命令的類型冗疮;
  • cmdsize:加載命令的所占內(nèi)存大刑汛健;
  • segname: 加載目標(biāo)段Segment的名稱术幔,常見的段segment有 __PAGEZERO另萤、__LINKEDIT__TEXT诅挑、__DATA四敞;
    • __PAGEZERO 在可執(zhí)行文件有的,動態(tài)庫里沒有拔妥,這個段開始地址為0(NULL指針指向的位置)忿危,是一個不可讀、不可寫没龙、不可執(zhí)行的空間铺厨,能夠在空指針訪問時拋出異常缎玫;
    • __TEXT代碼段,里面主要是存放代碼的解滓,該段是可讀可執(zhí)行赃磨,但是不可寫;
    • __DATA數(shù)據(jù)段洼裤,里面主要是存放數(shù)據(jù)邻辉,該段是可讀可寫,但不可執(zhí)行腮鞍;
    • __LINKEDIT:用于存放簽名信息值骇,該段是只可讀,不可寫不可執(zhí)行移国;
  • 段Segment類型的截圖如下:
image.png
  • vmaddr:段Segment的虛擬內(nèi)存地址雷客;
  • vmsize:段Segment的虛擬內(nèi)存大小桥狡;
  • fileoff:段Segment的在文件中的偏移量搅裙;
  • filesize:段Segment在文件中所占的內(nèi)存大小裹芝;
  • nsects:段Segment包含節(jié)區(qū)sections的數(shù)量部逮;
  • maxprot:表示頁面所需要的最高內(nèi)存保護;
  • initprot:表示頁面初始的內(nèi)存保護嫂易;
  • flags:表示段的標(biāo)志信息兄朋;

第三部分:Data數(shù)據(jù)部分

  • Data數(shù)據(jù)部分,就是指段Segment的數(shù)據(jù)怜械,而Segment段是由多個Section組成的颅和,所以其主體部分為Section,而Section的頭部信息Section Header是存放在段的加載命令中缕允,其結(jié)構(gòu)如下所示:
image.png
  • 首先來介紹一下Section Header峡扩,當(dāng)一個段segmemt包含多個節(jié)區(qū)Section,節(jié)區(qū)頭Section Header會以數(shù)組的形式存儲在段加載命令中障本,如上截圖所示教届,毋庸置疑其是描述Section的結(jié)構(gòu)信息的;
  • Section的源碼如下所示:
struct section_64 { /* for 64-bit architectures */
    char        sectname[16];   /* name of this section */
    char        segname[16];    /* segment this section goes in */
    uint64_t    addr;       /* memory address of this section */
    uint64_t    size;       /* size in bytes of this section */
    uint32_t    offset;     /* file offset of this section */
    uint32_t    align;      /* section alignment (power of 2) */
    uint32_t    reloff;     /* file offset of relocation entries */
    uint32_t    nreloc;     /* number of relocation entries */
    uint32_t    flags;      /* flags (section type and attributes)*/
    uint32_t    reserved1;  /* reserved (for offset or index) */
    uint32_t    reserved2;  /* reserved (for count or sizeof) */
    uint32_t    reserved3;  /* reserved */
};
  • sectname:section的名稱驾霜,常見的section有_text案训、stubs等等;
  • segname :當(dāng)前section所隸屬的Segment粪糙,例如__TEXT(代碼段)强霎;
  • addr : section在內(nèi)存的起始位置;
  • size: section所占內(nèi)存大腥馗浴城舞;
  • offset: section在文件中的偏移量轩触;
  • align:字節(jié)大小對齊,2的align次方椿争;
  • reloff:重定位入口的文件偏移;
  • nreloc: 需要重定位的入口數(shù)量熟嫩;
  • flags:包含section的type和attributes秦踪;
__TEXT段中的Section組成如下所示:
  • __text:代碼節(jié),存放機器編譯后的代碼掸茅;
  • __stubs:用于輔助做動態(tài)鏈接代碼(dyld)椅邓;
  • __stub_helper:用于輔助做動態(tài)鏈接(dyld);
  • __objc_methname:objc的方法名稱昧狮;
  • __cstring:代碼運行中包含的字符串常量景馁,比如代碼中定義#define kGeTuiPushAESKey "DWE2#@e2!",那DWE2#@e2!會存在這個區(qū)里逗鸣;
  • __objc_classname: objc類名合住;
  • __objc_methtype: objc方法類型;
  • __ustring
  • __gcc_except_tab
  • __const:存儲const修飾的常量撒璧;
  • __dof_RACSignal
  • __dof_RACCompou
  • __unwind_info
__DATA段中的Section組成如下所示:
  • __got:存儲引用符號的實際地址透葛,類似于動態(tài)符號表;
  • __la_symbol_ptr:lazy symbol pointers卿樱,懶加載的函數(shù)指針地址僚害,和__stubs和stub_helper配合使用,具體原理暫留繁调;
  • __mod_init_func:模塊初始化的方法萨蚕;
  • __const:存儲constant常量的數(shù)據(jù),比如使用extern導(dǎo)出的const修飾的常量蹄胰;
  • __cfstring:使用Core Foundation字符串岳遥;
  • __objc_classlist:objc類列表,保存類信息,映射了__objc_data的地址裕寨;
  • __objc_nlclslist:Objective-C 的 +load 函數(shù)列表寒随,比 __mod_init_func 更早執(zhí)行;
  • __objc_catlist:categories分類帮坚;
  • __objc_nlcatlist:Objective-C 的categories的 +load函數(shù)列表妻往;
  • __objc_protolist:objc協(xié)議列表;
  • __objc_imageinfo:objc鏡像信息试和;
  • __objc_const:objc常量讯泣,保存objc_classdata結(jié)構(gòu)體數(shù)據(jù),用于映射類相關(guān)數(shù)據(jù)的地址阅悍,比如類名好渠,方法名等昨稼;
  • __objc_selrefs:引用到的objc方法;
  • __objc_protorefs:引用到的objc協(xié)議拳锚;
  • __objc_classrefs:引用到的objc類假栓;
  • __objc_superrefs:objc超類引用;
  • __objc_ivar:objc ivar指針霍掺,存儲屬性匾荆;
  • __objc_data:objc的數(shù)據(jù),用于保存類需要的數(shù)據(jù)杆烁,最主要的內(nèi)容是映射牙丽,__objc_const地址,用于找到類的相關(guān)數(shù)據(jù)兔魂;
  • __data:暫時沒理解烤芦,從日志看存放了協(xié)議和一些固定了地址已經(jīng)初始化的靜態(tài)量;
  • __bss:存儲未初始化的靜態(tài)量析校,比如:static NSThread *_networkRequestThread = nil构罗,其中這里面的size表示應(yīng)用運行占用的內(nèi)存,不是實際的占用空間智玻,所以計算大小的時候應(yīng)該去掉這部分數(shù)據(jù)绰播;
  • __common:存儲導(dǎo)出的全局的數(shù)據(jù),類似于static尚困,但是沒有用static修飾蠢箩,比如KSCrash里面NSDictionary* g_registerOrders,g_registerOrders就存儲在__common里面事甜;
image.png
Mach-O文件的結(jié)構(gòu)分析
  • 首先創(chuàng)建兩個.c文件分別為a.cb.c谬泌,代碼如下:
//a.c文件
#include <stdio.h>

//顯式的說明了a的存儲空間是在程序的其他地方分配的,在文件中其他位置或者其他文件中尋找a這個變量
extern int global_var;

void func(int a);

int main(int argc, const char * argv[]) {
    int a = 100;
    func(a + global_var);
    return 0;
}
//b.c文件
#include <stdio.h>

int global_var = 1;

void func(int a) {
    global_var = a;
}
  • 在進行代碼分析之前逻谦,首先介紹兩個概念模塊符號掌实;

  • 模塊:我們可以理解一個源代碼文件為一個模塊。比如上面a模塊和b模塊邦马。我們現(xiàn)在寫一個程序贱鼻,不可能所有代碼都在一個源代碼文件上,都是分模塊的滋将,一般一個類在一個源文件上邻悬,就成為一個模塊,模塊化好處就是復(fù)用随闽、維護父丰,還有編譯時候,未改動的模塊掘宪,不用重新編譯蛾扇,直接用之前編譯好的緩存攘烛;

  • 符號:簡單理解就是函數(shù)名和變量名,比如上面總共有三個符號:global_var镀首、main坟漱、func

  • 將a.c與b.c文件分別編譯生成目標(biāo)文件a.ob.o文件更哄,可通過終端命令來實現(xiàn)芋齿,輸入:xcrun -sdk iphoneos clang -c a.c b.c -target arm64-apple-ios12.2

  • 將生成的a.o與b.o目標(biāo)文件,進行靜態(tài)鏈接竖瘾,生成一個最終的目標(biāo)文件沟突,命名為ab花颗,可通過終端命令來實現(xiàn)捕传,輸入:xcrun -sdk iphoneos clang a.o b.o -o ab -target arm64-apple-ios12.2,最終的所有文件如下所示:

    image.png

  • 可使用file 文件名扩劝,查看文件類型庸论,如下所示:

    image.png

  • a.ob.oab均屬于Mach-O文件棒呛,可使用MachOView打開進行查看聂示;

  • 使用MachOView打開a.o文件,內(nèi)容如下所示:

    Snip20220104_121.png

  • adrp x10 #0:其中#0是全局變量global_var的臨時內(nèi)存地址簇秒,是編譯器暫時用#0代替的鱼喉;

  • ldr w11 [x10]:將x10寄存器中的內(nèi)存地址中的數(shù)值,也就是全局變量global_var趋观,寫入w11寄存器中扛禽;

  • add w0 w9 w11:將w9與w11中的數(shù)值相加,即100+1計算結(jié)果賦值給w0皱坛,w0寄存器中存儲著func函數(shù)的參數(shù)编曼;

  • bl #0x3c:其中#0x3c是func函數(shù)的臨時地址,是編譯器暫時用#0x3c代替的剩辟;

  • 使用MachOView打開ab文件掐场,內(nèi)容如下所示:

    Snip20220104_118.png

  • a.ob.o在經(jīng)過鏈接器進行靜態(tài)鏈接之后,生成ab文件贩猎,在ab文件中的全局變量global_var與函數(shù)func的內(nèi)存地址是真正的內(nèi)存地址熊户,那么鏈接器是怎么進行調(diào)整的;

  • 全局變量global_var與函數(shù)func的內(nèi)存地址從a.oab經(jīng)過了鏈接器的靜態(tài)鏈接吭服,這兩個符號的內(nèi)存地址在前后發(fā)生了變化敏弃,現(xiàn)在我們來探索其中的工作原理;

  • 首先在a.o文件中包含了一個重定位表噪馏,其專門保存了所有需要進行重定位的符號麦到,根據(jù)符號信息可以在當(dāng)前文件的符號表中查看符號的詳細信息绿饵;

  • 在進行a.ob.o文件鏈接時,會將a.o里面有這兩符號的引用瓶颠,然后b.o里面有這兩符號的定義拟赊,一起合并到全局符號表里,最后在全局符號表中粹淋,對符號進行重定位吸祟,修正符號的正確地址;

    Snip20220104_130.png

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末桃移,一起剝皮案震驚了整個濱河市屋匕,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌借杰,老刑警劉巖过吻,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蔗衡,居然都是意外死亡纤虽,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門绞惦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來逼纸,“玉大人,你說我怎么就攤上這事济蝉〗芄簦” “怎么了?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵王滤,是天一觀的道長贺嫂。 經(jīng)常有香客問我,道長淑仆,這世上最難降的妖魔是什么涝婉? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮蔗怠,結(jié)果婚禮上墩弯,老公的妹妹穿的比我還像新娘。我一直安慰自己寞射,他們只是感情好渔工,可當(dāng)我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著桥温,像睡著了一般引矩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天旺韭,我揣著相機與錄音氛谜,去河邊找鬼。 笑死区端,一個胖子當(dāng)著我的面吹牛值漫,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播织盼,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼杨何,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了沥邻?” 一聲冷哼從身側(cè)響起危虱,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎唐全,沒想到半個月后埃跷,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡芦瘾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年捌蚊,在試婚紗的時候發(fā)現(xiàn)自己被綠了集畅。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片近弟。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖挺智,靈堂內(nèi)的尸體忽然破棺而出祷愉,到底是詐尸還是另有隱情,我是刑警寧澤赦颇,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響愉镰,放射性物質(zhì)發(fā)生泄漏纵装。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一扇苞、第九天 我趴在偏房一處隱蔽的房頂上張望欺殿。 院中可真熱鬧,春花似錦鳖敷、人聲如沸脖苏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽棍潘。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間亦歉,已是汗流浹背恤浪。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留肴楷,地道東北人资锰。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像阶祭,于是被迫代替她去往敵國和親绷杜。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,976評論 2 355

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