iOS逆向?qū)崙?zhàn)--018:HOOK原理

HOOK概述

HOOK,中文譯為“掛鉤”或“鉤子”涌穆。在iOS逆向中是指改變程序運行流程的一種技術(shù)。通過HOOK可以讓別人的程序執(zhí)行自己所寫的代碼雀久。在逆向中經(jīng)常使用這種技術(shù)宿稀。所以在學(xué)習(xí)過程中,我們重點要了解其原理赖捌,這樣能夠?qū)阂獯a進行有效的防護

HOOK示意圖

iOSHOOK技術(shù)的幾種方式:

  • Method Swizzle:主要用于OC方法祝沸,利用OCRuntime特性,動態(tài)改變SEL(方法編號)和IMP(方法實現(xiàn))的對應(yīng)關(guān)系越庇,達到OC方法調(diào)用流程改變的目的
  • fishhookFacebook提供的一個動態(tài)修改鏈接MachO文件的工具罩锐。利用MachO文件加載原理,通過修改懶加載和非懶加載兩個表的指針卤唉,達到對C函數(shù)進行HOOK的目的
  • Cydia Substrate:原名為Mobile Substrate涩惑,它的主要作用是針對OC方法、C函數(shù)以及函數(shù)地址進行HOOK操作桑驱。當(dāng)然它并不是僅僅針對iOS而設(shè)計的竭恬,安卓一樣可以使用。官方地址
Method Swizzle

利用OCRuntime特性熬的,動態(tài)改變SEL(方法編號)和IMP(方法實現(xiàn))的對應(yīng)關(guān)系痊硕,達到OC方法調(diào)用流程改變的目的。主要用于OC方法押框。

OC中岔绸,SELIMP之間的關(guān)系,就好像一本書的“目錄

  • SEL是方法編號橡伞,就像“標(biāo)題”一樣
  • IMP是方法實現(xiàn)的真實地址盒揉,就像“頁碼”一樣
  • 它們是一一對應(yīng)的關(guān)系

Runtime提供了交換兩個SELIMP對應(yīng)關(guān)系的函數(shù)

OBJC_EXPORT void
method_exchangeImplementations(Method _Nonnull m1, Method _Nonnull m2) 
   OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);

通過這個函數(shù)交換兩個SELIMP對應(yīng)關(guān)系的技術(shù),我們稱之為Method Swizzle(方法欺騙)

多種HOOK方式

  • class_addMethod方式:讓原始方法可以被調(diào)用骑歹,不至于因為找不到SEL而崩潰
  • class_replaceMethod方式:直接給原始的方法替換IMP
  • method_setImplementation方式:直接重新賦值新的IMP
Cydia Substrate

MobileHooker

顧名思義用于HOOK预烙。它定義一系列的宏和函數(shù)墨微,底層調(diào)用objcruntimefishhook來替換系統(tǒng)或者目標(biāo)應(yīng)用的函數(shù)

其中有兩個函數(shù):

  • MSHookMessageEx:主要作用于Objective-C方法
void MSHookMessageEx(Class class, SEL selector, IMP replacement, IMP result) 
  • MSHookFunction:主要作用于CC++函數(shù)道媚,Logos語法的%hook就是對以下函數(shù)做了一層封裝
void MSHookFunction(void function, void* replacement, void** p_original)

MobileLoader

MobileLoader用于加載第三方dylib在運行的應(yīng)用程序中。啟動時MobileLoader會根據(jù)規(guī)則把指定目錄的第三方的動態(tài)庫加載進去翘县,第三方的動態(tài)庫也就是我們寫的破解程序

safe mode

破解程序本質(zhì)是dylib最域,寄生在別人進程里。 系統(tǒng)進程一旦出錯锈麸,可能導(dǎo)致整個進程崩潰镀脂,崩潰后就會造成iOS癱瘓。所以Cydia Substrate引入了安全模式忘伞,在安全模式下所有基于Cydia Substratede的三方dylib都會被禁用薄翅,便于查錯與修復(fù)

fishHook

獲取代碼

git clone https://github.com/facebook/fishhook.git

關(guān)鍵函數(shù)

FISHHOOK_VISIBILITY
int rebind_symbols(struct rebinding rebindings[], size_t rebindings_nel);
  • rebindings:存放rebinding結(jié)構(gòu)體的數(shù)組沙兰,可以同時交換多個函數(shù)
  • rebindings_nel:數(shù)組的長度

rebinding結(jié)構(gòu)體

struct rebinding {
 const char *name;
 void *replacement;
 void **replaced;
};
  • name:需要HOOK的函數(shù)名稱,C字符串
  • replacement:新函數(shù)的地址
  • replaced:原始函數(shù)地址的指針

案例1:

HOOK系統(tǒng)NSLog函數(shù)

打開ViewController.m文件翘魄,定義新函數(shù)

void my_NSLog(NSString *format, ...) {    
   format = [format stringByAppendingString:@"~~~??????????"];
   sys_NSLog(format);
}

定義函數(shù)指針鼎天,用于保存NSLog系統(tǒng)函數(shù)地址

static void (*sys_NSLog)(NSString *format, ...);

viewDidLoad方法中,寫入以下代碼:

- (void)viewDidLoad {
   [super viewDidLoad];

   struct rebinding reb;
   reb.name="NSLog";
   reb.replacement=my_NSLog;
   reb.replaced=(void *)&sys_NSLog;
   
   struct rebinding rebs[] = { reb };
   rebind_symbols(rebs, 1);
}

添加touchesBegan方法

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
   NSLog(@"hahaha");
}

真機運行項目暑竟,點擊屏幕斋射,輸出以下內(nèi)容:

fishhookDemo[2072:399007] hahaha~~~??????????

fishHook可以HOOK我們的C函數(shù),但是我們知道函數(shù)是靜態(tài)的但荤,也就是說在編譯的時候罗岖,編譯器就知道了它的實現(xiàn)地址,這也是為什么C函數(shù)只寫函數(shù)聲明調(diào)用時會報錯腹躁。那么為什么fishHook還能夠改變C函數(shù)的調(diào)用呢桑包?難道函數(shù)也有動態(tài)的特性存在?

案例2:

HOOK自定義函數(shù)

打開ViewController.m文件纺非,定義自定義函數(shù)

void test(NSString *format, ...){
   NSLog(@"hahaha");
}

定義新函數(shù)

void my_test(NSString *format, ...){
   format = [format stringByAppendingString:@"~~~??????????"];
   sys_test(format);
}

定義函數(shù)指針捡多,用于保存test自定義函數(shù)地址

static void (*sys_test)(NSString *format, ...);

viewDidLoad方法中,寫入以下代碼:

- (void)viewDidLoad {
   [super viewDidLoad];

   struct rebinding reb;
   reb.name="test";
   reb.replacement=my_test;
   reb.replaced=(void *)&sys_test;
   
   struct rebinding rebs[] = { reb };
   rebind_symbols(rebs, 1);
}

添加touchesBegan方法

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
   test(@"hahaha");
}

真機運行項目铐炫,點擊屏幕垒手,輸出以下內(nèi)容:

fishhookDemo[2117:410009] hahaha

案例2中,HOOK自定義test函數(shù)并沒有效果倒信。NSLog是系統(tǒng)函數(shù)科贬,而test是當(dāng)前MachO中的函數(shù),它們之間有什么區(qū)別鳖悠?

fishHook原理探究

一般來說榜掌,靜態(tài)語言通過地址直接訪問,例如案例2中的test函數(shù)乘综。但對于NSLog系統(tǒng)函數(shù)來說憎账,它屬于外部調(diào)用函數(shù),編譯時并不能找到它的真實地址

NSLog存儲在Fundation框架中卡辰,App運行在不同系統(tǒng)版本的不同設(shè)備上胞皱,每個設(shè)備中NSLog的函數(shù)地址都各不相同

再有,當(dāng)App啟動時九妈,會涉及ASLR(地址空間配置隨機加載)反砌,導(dǎo)致程序運行它的虛擬內(nèi)存地址都不一樣

這些原因,都會造成外部函數(shù)的真實地址萌朱,在編譯時期是無法確定的

那外部函數(shù)是如何被調(diào)用的宴树?

當(dāng)App啟動時,dyld讀取主程序MachO文件晶疼,會加載共享緩存中的系統(tǒng)庫酒贬,將用到的函數(shù)真實地址告訴MachO

對于MachO中的代碼段來說又憨,它是只讀的。在運行時锭吨,無法直接修改外部函數(shù)的真實地址

對于上述情況竟块,蘋果采用PIC技術(shù)(位置獨立代碼),在MachO調(diào)用外部函數(shù)時耐齐,在可讀可寫的數(shù)據(jù)段浪秘,定義符號,占8字節(jié)埠况,用來存放外部函數(shù)的地址耸携。編譯時,暫存占位地址辕翰。運行時夺衍,dyld將符號綁定真實函數(shù)地址。對于代碼段來說喜命,并沒有任何改變

故此沟沙,外部調(diào)用函數(shù),并不是直接地址訪問壁榕,而是通過符號找到地址矛紫。這跟OCSELIMP的對應(yīng)關(guān)系非常相似。這種機制牌里,可以讓開發(fā)者動態(tài)HOOK外部調(diào)用函數(shù)

OC中動態(tài)改變SELIMP的對應(yīng)關(guān)系颊咬,對于外部調(diào)用函數(shù),動態(tài)改變的是符號和地址的對應(yīng)關(guān)系牡辽,上述操作稱為:符號表重綁定

案例1

查看NSLog加載前的占位地址

查看MachO文件

  • NSLog函數(shù)喳篇,存儲在懶加載符號表中。dyld加載MachO時态辛,綁定非懶加載符號和弱引用符號麸澜,而懶加載符號,則是在首次使用時動態(tài)綁定

打開ViewController.m文件奏黑,修改viewDidLoad代碼

- (void)viewDidLoad {
   [super viewDidLoad];
   
   NSLog(@"begin");

   struct rebinding reb;
   reb.name="NSLog";
   reb.replacement=my_NSLog;
   reb.replaced=(void *)&sys_NSLog;

   struct rebinding rebs[] = { reb };
   rebind_symbols(rebs, 1);
   
   NSLog(@"end");
}

beginend設(shè)置兩處斷點炊邦,真機運行項目

使用image list命令,找到程序虛擬內(nèi)存的首地址

  • 首地址:0x102c48000
  • ASLR0x2c48000

查看NSLogMachO中的偏移地址和占位地址

  • 偏移地址:0xC000
  • 占位地址:0x1000064C0

lldb中攀涵,使用程序首地址 + 偏移地址铣耘,找到NSLog加載前的占位地址

  • lldb中洽沟,獲取的NSLog占位地址為0x102c4e4c0以故,和MachO中看到的0x1000064C0并不一樣

因為MachO中的占位地址,還要加上程序啟動時的ASLR隨機偏移地址

  • 占位地址 + ASLR = 0x102c4e4c0裆操,和lldb中讀取出的地址一致

案例2

查看NSLog加載后的真實地址

承接案例1怒详,斷點向下執(zhí)行

lldb中炉媒,使用程序首地址 + 偏移地址,找到NSLog加載后的真實地址

  • 之前的占位地址0x102c4e4c0昆烁,被真實地址0x19d9327f0替換

使用dis -s 0x19d9327f0命令吊骤,讀取地址中的代碼

dis -s 0x000000019d9327f0
-------------------------
Foundation`NSLog:
   0x19d9327f0 <+0>:  sub    sp, sp, #0x20             ; =0x20 
   0x19d9327f4 <+4>:  stp    x29, x30, [sp, #0x10]
   0x19d9327f8 <+8>:  add    x29, sp, #0x10            ; =0x10 
   0x19d9327fc <+12>: adrp   x8, 311278
   0x19d932800 <+16>: ldr    x8, [x8, #0xb70]
   0x19d932804 <+20>: ldr    x8, [x8]
   0x19d932808 <+24>: str    x8, [sp, #0x8]
   0x19d93280c <+28>: add    x8, x29, #0x10            ; =0x10 
  • 指向NSLog代碼

案例3

查看交換后的函數(shù)地址

承接案例2,斷點向下執(zhí)行

lldb中静尼,使用程序首地址 + 偏移地址白粉,找到NSLog交換后的函數(shù)地址

  • 原本NSLog的真實地址為0x19d9327f0,交換后變?yōu)?code>0x102c4d57c

使用dis -s 0x102c4d57c命令鼠渺,讀取地址中的代碼

dis -s 0x102c4d57c
-------------------------
fishhookDemo`my_NSLog:
   0x102c4d57c <+0>:  sub    sp, sp, #0x30             ; =0x30 
   0x102c4d580 <+4>:  stp    x29, x30, [sp, #0x20]
   0x102c4d584 <+8>:  add    x29, sp, #0x20            ; =0x20 
   0x102c4d588 <+12>: sub    x8, x29, #0x8             ; =0x8 
   0x102c4d58c <+16>: mov    x9, #0x0
   0x102c4d590 <+20>: stur   x9, [x29, #-0x8]
   0x102c4d594 <+24>: str    x0, [sp, #0x10]
   0x102c4d598 <+28>: mov    x0, x8

指向my_NSLog代碼

由此可見鸭巴,HOOK外部的C函數(shù),本質(zhì)就是在修改符號和地址的對應(yīng)關(guān)系

符號綁定的過程
  • Symbol Table:符號表拦盹,?來保存符號
  • String Table:字符串表鹃祖,?來保存符號的名稱
  • Indirect Symbol Table:間接符號表,保存使?的外部符號普舆。更準(zhǔn)確?點就是使?的外部動態(tài)庫的符號恬口。是Symbol Table的子集

代碼中的函數(shù)名、變量名沼侣、方法名祖能,在項目編譯后,都會生成一張符號表蛾洛。符號之間也有差別芯杀,分為內(nèi)部符號和外部符號

內(nèi)部符號是當(dāng)前MachO中的符號,而外部符號又稱為間接符號雅潭,例如:系統(tǒng)庫揭厚、動態(tài)庫中的符號

符號按可見性劃分,分為全局符號和本地符號

  • 全局符號對整個項目可見
  • 本地符號僅對當(dāng)前文件可見

案例1:

符號綁定的過程

打開ViewController.m文件扶供,寫入以下代碼:

#import "ViewController.h"

@implementation ViewController

- (void)viewDidLoad {
   [super viewDidLoad];
   
   NSLog(@"第一次外部函數(shù)的調(diào)用!");
   NSLog(@"第二次外部函數(shù)的調(diào)用!");
}

@end

真機運行項目筛圆,來到viewDidLoad方法:

  • 兩次NSLog的指令都是bl 0x1022ba4d8

使用image list命令,找到程序虛擬內(nèi)存的首地址

  • 首地址:0x1022b4000

使用NSLog地址 - 首地址計算偏移地址

  • 偏移地址:0x64d8

打開MachO文件椿浓,找到偏移地址為0x64d8的位置

  • 處于__TEXT,__stubs
  • __stubs:符號樁太援,本質(zhì)上就是一段代碼,用于跳轉(zhuǎn)到懶加載符號表中扳碍,找到對應(yīng)符號的值
  • 0x64d8即是NSLog的樁

fishHook原理探究中提岔,多次提到跳轉(zhuǎn)到占位地址,這種說法并不準(zhǔn)確笋敞。真實的情況是碱蒙,會跳轉(zhuǎn)到外部符號的樁,本質(zhì)上就是一段代碼

案例2:

查看樁對應(yīng)的代碼

查看MachO文件,找到樁對應(yīng)的值

  • 1F2003D530D9025800021FD6:以二進制指令的形式存儲的代碼

單步調(diào)試赛惩,來到NSLog函數(shù)

使用x 0x1022ba4d8命令哀墓,讀取地址中的值,以二進制形式顯示

  • 1F2003D530D9025800021FD6喷兼,和MachO中對應(yīng)的指令一致

有此可見篮绰,1F2003D530D9025800021FD6對應(yīng)的就是上述三句匯編代碼

案例3:

三句匯編代碼的含義?

斷點執(zhí)行到br x16指令

  • br指令:跳轉(zhuǎn)到x16寄存器存儲的地址

查看x16寄存器存儲的地址季惯,再減去ASLR偏移地址

  • 得到地址:0x10000658c

查看MachO文件吠各,找到0x10000658c地址

  • 指向懶加載符號表中NSLog符號的值

三句匯編代碼的含義:找到懶加載符號表中的地址去執(zhí)行

案例4:

懶加載符號表中的地址,指向的代碼是什么勉抓?

MachO中走孽,找到偏移地址0x658c,指向__TEXT,__stubs_helper中的代碼

  • b指令琳状,跳轉(zhuǎn)到偏移地址為0x6574的位置執(zhí)行代碼

MachO中磕瓷,找到偏移地址為0x6574的位置

  • x16寄存器,偏移地址為0x8000
  • br指令念逞,跳轉(zhuǎn)到偏移地址為0x8000位置執(zhí)行代碼

MachO中困食,找到偏移地址為0x8000的位置

  • 處于非懶加載符號表中
  • 執(zhí)行dyld_stub_binder函數(shù),用于符號綁定

懶加載符號表中的地址翎承,指向?qū)ふ也?zhí)行dyld_stub_binder函數(shù)的代碼

案例5:

dyld_stub_binder也是外部函數(shù)硕盹,它的地址是如何找到的?

MachO中叨咖,可以看到dyld_stub_binder函數(shù)的偏移地址為0x8000瘩例,但全是0,說明此時還沒有值

dyld_stub_binder函數(shù)甸各,同樣是外部函數(shù)垛贤,存儲在非懶加載表中

當(dāng)dyld加載主程序時,會綁定非懶加載符號和弱引用符號趣倾,所以dyld_stub_binder函數(shù)的值聘惦,在程序啟動時被dyld直接綁定

真機運行項目,讀取首地址 + 0x8000地址中的值

使用dis -s 0x19c2e6f94命令儒恋,讀取地址中的代碼

libdyld.dylib`dyld_stub_binder:
   0x19c2e6f94 <+0>:  stp    x29, x30, [sp, #-0x10]!
   0x19c2e6f98 <+4>:  mov    x29, sp
   0x19c2e6f9c <+8>:  sub    sp, sp, #0xf0             ; =0xf0 
   0x19c2e6fa0 <+12>: stp    x0, x1, [x29, #-0x10]
   0x19c2e6fa4 <+16>: stp    x2, x3, [x29, #-0x20]
   0x19c2e6fa8 <+20>: stp    x4, x5, [x29, #-0x30]
   0x19c2e6fac <+24>: stp    x6, x7, [x29, #-0x40]
   0x19c2e6fb0 <+28>: stp    x8, x9, [x29, #-0x50]

案例6:

NSLog函數(shù)善绎,首次加載和非首次加載的區(qū)別

真機運行項目,首次加載NSLog函數(shù)

  • 先找到樁里面的代碼
  • 找到懶加載符號表中的地址去執(zhí)行
  • 指向__stubs_helper中的代碼
  • 尋找并執(zhí)行dyld_stub_binder函數(shù)
  • 符號表重綁定

再次加載NSLog函數(shù)

  • 找到樁里面的代碼
  • 找到懶加載符號表中的地址去執(zhí)行
  • 首次加載NSLog函數(shù)诫尽,懶加載符號表中的地址禀酱,因重綁定而修改
  • 修改后的值,直接指向NSLog函數(shù)的真實地址
通過符號找到字符串

fishHook提供的rebinding結(jié)構(gòu)體牧嫉,其中name為需要HOOK的函數(shù)名稱

作用:當(dāng)找到相應(yīng)的符號剂跟,再通過符號找到字符串,然后和name進行字符串比較,如果匹配成功浩聋,則替換函數(shù)指針

案例1:

通過懶加載符號表中的符號观蜗,找到間接符號表中的相同符號臊恋,再找到符號對應(yīng)的值

__la_symbol_ptr懶加載符號表中的符號和順序衣洁,跟間接符號表一致

Dynamic Symbol Table中,找到NSLog的值

案例2:

間接符號表中NSLog的值為0xB8抖仅,轉(zhuǎn)為10進制184

184對應(yīng)的是此符號在符號總表中的角標(biāo)

Symbol Table中坊夫,通過角標(biāo)找到符號凹髓,再找到String Table Index的值

案例3:

符號表中NSLogString Table Index值為0xCE廉丽,表示在字符串表中的偏移地址

String Table中,找到首地址

  • 首地址0x11230

通過首地址 + 偏移值 = 0x112FE萝挤,找到對應(yīng)字符串

  • _是函數(shù)的開始放吩,.是分隔符 智听。5F_開始,往后讀取_NSLog渡紫,遇到分隔符結(jié)束
總結(jié)

HOOK

  • 鉤子到推,改變程序執(zhí)行流程的一種技術(shù)

Method Swizzle
利用OC運行時的特性,修改SELIMP的對應(yīng)關(guān)系惕澎,達到對OC方法HOOK的目的

  • IMP莉测,本質(zhì)上是函數(shù)指針
  • method_exchangeImplementations:交互兩個IMP
  • class_replaceMethod:替換某個SELIMP,如果沒有該方法唧喉,使用class_addMethod添加
  • method_getImplementation捣卤、method_setImplementation:獲取和設(shè)置某個方法的IMP,很多三方框架都使用這種方式

fishHook

  • Facebook提供的一個工具八孝,利用MachO文件的加載原理董朝,動態(tài)修改懶加載和非懶加載兩張符號表
  • 可以HOOK系統(tǒng)函數(shù),但是無法HOOK自定義函數(shù)

fishHook原理解析

  • 共享緩存:iOS系統(tǒng)有一塊特殊的位置干跛,存放公用動態(tài)庫益涧。即:動態(tài)庫共享緩存(dyld shared cache
  • PIC技術(shù):由于外部函數(shù)調(diào)用,在編譯時期無法確定內(nèi)存地址驯鳖。蘋果采用PIC技術(shù)(位置獨立代碼)闲询,在MachO文件的DATA段,建立懶加載和非懶加載兩張符號表浅辙,里面存放執(zhí)行外部函數(shù)的指針

符號綁定過程

  • 外部函數(shù)調(diào)用扭弧,先找到樁里面的代碼,__TEXT,__stubs
  • 找到懶加載符號表中的地址去執(zhí)行

外部函數(shù)记舆,首次加載

  • 懶加載符號表中的地址鸽捻,指向__TEXT,__stubs_helper中的代碼
  • 通過代碼尋找并執(zhí)行dyld_stub_binder函數(shù)
  • 作用:符號表重綁定

外部函數(shù),非首次加載

  • 懶加載符號表中的地址,因重綁定而修改
  • 修改后的值御蒲,直接指向外部函數(shù)的真實地址

dyld_stub_binder函數(shù)

  • 存儲在非懶加載符號表中
  • 當(dāng)dyld加載主程序時衣赶,符號被dyld直接綁定

通過符號找到字符串

  • fishHook利用Lazy Symbol TableIndirect Symbol TableSymbol TableString Table,通過重綁定修改指針的值達到HOOK目的
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末厚满,一起剝皮案震驚了整個濱河市府瞄,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌碘箍,老刑警劉巖遵馆,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異丰榴,居然都是意外死亡货邓,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進店門四濒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來换况,“玉大人,你說我怎么就攤上這事盗蟆「甓” “怎么了?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵姆涩,是天一觀的道長挽拂。 經(jīng)常有香客問我,道長骨饿,這世上最難降的妖魔是什么亏栈? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮宏赘,結(jié)果婚禮上绒北,老公的妹妹穿的比我還像新娘。我一直安慰自己察署,他們只是感情好闷游,可當(dāng)我...
    茶點故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著贴汪,像睡著了一般脐往。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上扳埂,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天业簿,我揣著相機與錄音,去河邊找鬼阳懂。 笑死梅尤,一個胖子當(dāng)著我的面吹牛柜思,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播巷燥,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼赡盘,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了缰揪?” 一聲冷哼從身側(cè)響起陨享,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎邀跃,沒想到半個月后霉咨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蛙紫,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡拍屑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了坑傅。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片僵驰。...
    茶點故事閱讀 39,703評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖唁毒,靈堂內(nèi)的尸體忽然破棺而出蒜茴,到底是詐尸還是另有隱情,我是刑警寧澤浆西,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布粉私,位于F島的核電站,受9級特大地震影響近零,放射性物質(zhì)發(fā)生泄漏诺核。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一久信、第九天 我趴在偏房一處隱蔽的房頂上張望窖杀。 院中可真熱鬧,春花似錦裙士、人聲如沸入客。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽桌硫。三九已至,卻和暖如春啃炸,著一層夾襖步出監(jiān)牢的瞬間铆隘,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工肮帐, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留咖驮,地道東北人边器。 一個月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像托修,于是被迫代替她去往敵國和親忘巧。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,601評論 2 353

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