ios 逆向 -- 反調(diào)試 和 反反調(diào)試

一: ptrace 作用

ptrace系統(tǒng)調(diào)從名字上看是用于進(jìn)程跟蹤的体谒,它提供了父進(jìn)程可以觀察和控制其子進(jìn)程執(zhí)行的能力骂远,并允許父進(jìn)程檢查和替換子進(jìn)程的內(nèi)核鏡像(包 括寄存器)的值趣避。其基本原理是: 當(dāng)使用了ptrace跟蹤后尸执,所有發(fā)送給被跟蹤的子進(jìn)程的信號(除了SIGKILL)婚夫,都會(huì)被轉(zhuǎn)發(fā)給父進(jìn)程,而子進(jìn)程則會(huì)被阻塞署鸡,這時(shí)子進(jìn)程的狀態(tài)就會(huì)被 系統(tǒng)標(biāo)注為TASK_TRACED案糙。而父進(jìn)程收到信號后,就可以對停止下來的子進(jìn)程進(jìn)行檢查和修改靴庆,然后讓子進(jìn)程繼續(xù)運(yùn)行 时捌,因而可以實(shí)現(xiàn)斷點(diǎn)調(diào)試和系統(tǒng)調(diào)用的跟蹤

使用ptrace,你可以在用戶層 【攔截和修改】系統(tǒng)調(diào)用(sys call)

注意:

被跟蹤的程序在進(jìn)入或者退出某次系統(tǒng)調(diào)用的時(shí)候都會(huì)觸發(fā)一個(gè)SIGTRAP信號炉抒,而被父進(jìn)程捕獲

Ptrace其原型為:

include <sys/ptrace.h>

long ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data);

ptrace有四個(gè)參數(shù):

1). enum __ptrace_request request:指示了ptrace要執(zhí)行的命令奢讨。

2). pid_t pid: 指示ptrace要跟蹤的進(jìn)程。

3). void *addr: 指示要監(jiān)控的內(nèi)存地址焰薄。

4). void *data: 存放讀取出的或者要寫入的數(shù)據(jù)拿诸。

ptrace是如此的強(qiáng)大,以至于有很多大家所常用的工具都基于ptrace來實(shí)現(xiàn)塞茅,如strace和gdb

反調(diào)試舉例說明:

比如: ptrace的命令PT_DENY_ATTACH 是蘋果增加的一個(gè) ptrace 選項(xiàng)亩码,用于阻止 GDB 等調(diào)試器依附到某進(jìn)程,用法如下:

ptrace(PT_DENY_ATTACH, 0, 0, 0);

void anti_gdb_debug() {

    void *handle = dlopen(0, RTLD_GLOBAL | RTLD_NOW);

    ptrace_ptr_t ptrace_ptr = dlsym(handle, "ptrace");

    ptrace_ptr(PT_DENY_ATTACH, 0, 0, 0);

    dlclose(handle);

}

總結(jié)一下:ptrace被廣泛用于反調(diào)試,因?yàn)橐粋€(gè)進(jìn)程只能被ptrace一次,如果事先調(diào)用了ptrace方法,那就可以防止別人調(diào)試我們的程序.

也就是說誰先調(diào)用ptrace 誰說了算野瘦,如果我們直接在app 中寫ptrace 描沟, 那么調(diào)試的時(shí)候肯定就無法調(diào)試,因?yàn)楸粦?yīng)用內(nèi)的ptrace 搶占了

反反調(diào)試: 如果別人的的app進(jìn)行了ptrace防護(hù)鞭光,那么你怎么讓他的ptrace不起作用吏廉,進(jìn)而調(diào)試其他的app。由于ptrace是系統(tǒng)函數(shù)惰许,那么我們可以用fishhook來hook住ptrace函數(shù)席覆,然后讓他的app調(diào)用我們自己的ptrace函數(shù),即寫動(dòng)態(tài)庫啡省,如果多個(gè)動(dòng)態(tài)庫hook 了ptrace ,我們可以調(diào)整 Link Binary Libraries的順序加載娜睛,假設(shè)人家應(yīng)用自己寫的hook ptrace動(dòng)態(tài)庫肯定會(huì)在自己前面髓霞,最后的方式我們可以通過修改macho的二進(jìn)制讓他的ptrace失效【不去執(zhí)行ptrace】,然后進(jìn)行調(diào)試.
最后:在給一種反調(diào)試的方案畦戒,這種也只能無法斷點(diǎn)調(diào)試ptrace 函數(shù)

我不想暴露自己的ptrace等系統(tǒng)方法方库,不想被符號斷點(diǎn)斷住,可以采用匯編進(jìn)行調(diào)用ptrace

image.png

這樣人家就很難通過斷點(diǎn)的方式去調(diào)試

調(diào)試器建立調(diào)試關(guān)系的兩種方式:

用gdb調(diào)試程序[調(diào)試程序也在一個(gè)進(jìn)程里]障斋,可以直接gdb ./test,也可以gdb (test的進(jìn)程號)纵潦。這對應(yīng)著使用ptrace建立跟蹤關(guān)系的兩種方式:

  • fork:利用fork+execve執(zhí)行被測試的程序,子進(jìn)程在執(zhí)行execve之前調(diào)用ptrace(PTRACE_TRACEME)垃环,建立了與父進(jìn)程(debugger 調(diào)試程序進(jìn)程)的跟蹤關(guān)系邀层。

  • attach: debugger可以調(diào)用ptrace(PTRACE_ATTACH闲坎,pid,…)颅眶,建立自己與進(jìn)程號為pid的進(jìn)程間的跟蹤關(guān)系。即利用PTRACE_ATTACH鼠证,使自己變成被調(diào)試程序的父進(jìn)程(用ps可以看到)涛目。用attach建立起來的跟蹤關(guān)系秸谢,可以調(diào)用ptrace(PTRACE_DETACH,pid,…)來解除霹肝。注意attach進(jìn)程時(shí)的權(quán)限問題估蹄,如一個(gè)非root權(quán)限的進(jìn)程是不能attach到一個(gè)root進(jìn)程上的。

第一種方式的例子:

ptrace提供了對子進(jìn)程進(jìn)行單步的功能沫换,ptrace(PTRACE_SINGLESTEP, …) 會(huì)使內(nèi)核在子進(jìn)程的每一條指令執(zhí)行前先將其阻塞臭蚁,然后將控制權(quán)交給父進(jìn)程

而父進(jìn)程此時(shí)會(huì)使用 wait函數(shù)等待阻塞信號,然后判斷status變量來檢查子進(jìn)程是被ptrace暫停掉還是已經(jīng)運(yùn)行結(jié)束并退出讯赏,如果狀態(tài)是ptrace暫停的垮兑,則可以獲取子進(jìn)程的寄存器器狀態(tài),

ptrace(PTRACE_GETREGS,child, NULL, ?s)待逞,獲取當(dāng)前指令等甥角,在讓ptrace控制單步執(zhí)行
ptrace(PTRACE_SINGLESTEP, child,NULL, NULL);

每一步都去喚醒子進(jìn)程繼續(xù)執(zhí)行,并告訴內(nèi)核在執(zhí)行一條指令后就將其阻塞

最后讓子進(jìn)程恢復(fù)

PTRACE_SYSCALL:繼續(xù)识樱,但在下一個(gè)系統(tǒng)調(diào)用入口或出口處停止嗤无。

二: sysctl 作用

sysctl命令被用于在內(nèi)核運(yùn)行時(shí)動(dòng)態(tài)地修改內(nèi)核的運(yùn)行參數(shù)

函數(shù)原型

int sysctl (int *name, int nlen, void *oldval, size_t *oldlenp, void *newval, size_t newlen);

Name /* 整形數(shù)組,每個(gè)數(shù)組元素代表系統(tǒng)參數(shù)存取路徑上的一個(gè)文件或目錄名怜庸,例如/proc/sys/kernel用CTL_KERN表示*/

oldval /* 當(dāng)讀取系統(tǒng)參數(shù)時(shí)当犯,用于存取系統(tǒng)參數(shù)值,也就是/proc/sys/下的某個(gè)文件內(nèi)容*/

Newval /* 當(dāng)寫系統(tǒng)參數(shù)時(shí)割疾,記錄所要寫入的新值*/

反調(diào)試舉例:

當(dāng)一個(gè)進(jìn)程被調(diào)試的時(shí)候嚎卫,該進(jìn)程會(huì)有一個(gè)標(biāo)記來標(biāo)記自己正在被調(diào)試,所以可以通過sysctl去查看當(dāng)前進(jìn)程的信息,看有沒有這個(gè)標(biāo)記位即可檢查當(dāng)前調(diào)試狀態(tài)拓诸。

image.png

檢測到調(diào)試器就退出侵佃,或者制造崩潰,或者隱藏工程啥的奠支,當(dāng)然也可以定時(shí)去查看有沒有這個(gè)標(biāo)記

三: syscall 作用

為從實(shí)現(xiàn)從用戶態(tài)切換到內(nèi)核態(tài)馋辈,系統(tǒng)提供了一個(gè)系統(tǒng)調(diào)用函數(shù)syscall ,所有的系統(tǒng)調(diào)用都可以通過syscall 去實(shí)現(xiàn)

比如: syscall (26,31,0,0) 來調(diào)用系統(tǒng)函數(shù)ptrace倍谜,ptrace的系統(tǒng)調(diào)用函數(shù)號是26

syscall是通過軟中斷來實(shí)現(xiàn)從用戶態(tài)到內(nèi)核態(tài)迈螟,也可以通過匯編svc調(diào)用來實(shí)現(xiàn)。

image.png

比如:arm 32位 #80 就是軟中斷值尔崔,r12 存放系統(tǒng)函數(shù)編號答毫,arm 64位 #128 是系統(tǒng)中斷碼,x0存放系統(tǒng)函數(shù)編號

四: 重簽名防護(hù)

想自己的app不被重簽名季春,可以在代碼中檢測簽名信息

查看證書的application-identifier 查看embedded.mobileprovision信息security cms -D -i embedded.mobileprovision 找到<key>application-identifier</key>的value的第一部分就是

在執(zhí)行代碼的時(shí)候檢查簽名是否和我們已知的簽名對比

void checkCodesign(NSString *id){
 // 描述文件路徑
 NSString *embeddedPath = [[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"];
 // 讀取application-identifier 注意描述文件的編碼要使用:NSASCIIStringEncoding
 NSString *embeddedProvisioning = [NSString stringWithContentsOfFile:embeddedPath encoding:NSASCIIStringEncoding error:nil];
 NSArray *embeddedProvisioningLines = [embeddedProvisioning componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
  
 for (int i = 0; i < embeddedProvisioningLines.count; i++) {
 if ([embeddedProvisioningLines[i] rangeOfString:@"application-identifier"].location != NSNotFound) {
   
  NSInteger fromPosition = [embeddedProvisioningLines[i+1] rangeOfString:@"<string>"].location+8;
   
  NSInteger toPosition = [embeddedProvisioningLines[i+1] rangeOfString:@"</string>"].location;
   
  NSRange range;
  range.location = fromPosition;
  range.length = toPosition - fromPosition;
   
  NSString *fullIdentifier = [embeddedProvisioningLines[i+1] substringWithRange:range];
  NSArray *identifierComponents = [fullIdentifier componentsSeparatedByString:@"."];
  NSString *appIdentifier = [identifierComponents firstObject];
  
  // 對比簽名ID
  if (![appIdentifier isEqual:id]) {
  //exit
  asm(
   "mov X0,#0\n"
   "mov w16,#1\n"
   "svc #0x80"
   );
  }
  break;
 }
 }
}

五:反反調(diào)試

這里主要針對ptrace洗搂、sysctl、syscall來反反調(diào)試载弄,做法就很簡單了蚕脏,hook函數(shù)

比如:

1: hook ptrace 函數(shù), 遇到request = 31, 就知道程序進(jìn)行了反調(diào)試侦锯,所以我們可以將request 改掉

image.png

2:hook sysctl , 看其是否在檢查進(jìn)程被追蹤的這個(gè)標(biāo)記TASK_TRACED,我們將其返回信息info_ptr -> kp_proc.p_flag 改掉,讓其檢查的結(jié)果是沒有設(shè)置追蹤標(biāo)識

image.png

3 hook syscall , 防止ptrace 是通過syscall 的方式去調(diào)用的秦驯,

image.png

4:hook dlsym 防止通過這種方式去調(diào)用ptrace 函數(shù)

image.png

5 初始化函數(shù)

image.png

或者使用fishhook

image.png

lldb 反反調(diào)試的

通過lldb下斷點(diǎn)尺碰,然后修改參數(shù),或者直接返回也可以達(dá)到反反調(diào)試的效果

為了方便直接使用facebook的chisel來增加腳本译隘。

image.png
image.png
image.png

當(dāng)遇到情況為$x0 == 31 時(shí)發(fā)生回掉亲桥,將x0 或者r0 的值改成0

image.png

六: App的防護(hù)

1:首先加強(qiáng)現(xiàn)有的密碼檢測機(jī)制的監(jiān)測力度,除了密碼長度,數(shù)字、字符甚至特殊符號的混雜程度,本文著重對易受攻擊的鍵盤上特定組合碼進(jìn)行檢測;

2:其次完善iOS內(nèi)存保護(hù)機(jī)制,利用Objective-C對象實(shí)現(xiàn)內(nèi)存安全擦除,保證及時(shí)對文件數(shù)據(jù)的每個(gè)字節(jié)都做到全覆蓋,防止對象被跟蹤后信息遭到泄露;

3:再次在維護(hù)程序在運(yùn)行時(shí)的安全性上提出了一種貫穿程序被調(diào)試的三個(gè)階段的反調(diào)試機(jī)制:從程序開始被調(diào)試固耘、繼續(xù)被跟蹤到最終被惡意修改均進(jìn)行跟蹤測試,最終阻止被惡意修改的目標(biāo)繼續(xù)的執(zhí)行

針對上述安全隱患题篷,我們的iOS應(yīng)用安全防護(hù)框架需實(shí)現(xiàn)的任務(wù)大致如下:

  • 防護(hù)

    • ObjC類名方法名等重命名為難以理解的字符

    • 加密靜態(tài)字符串運(yùn)行時(shí)解密

    • 混淆代碼使其難于反匯編

    • 本地存儲文件防篡改

  • 檢測

    • 調(diào)試狀態(tài)檢測 : 反調(diào)試 ptrace . sysctl

    • 越獄環(huán)境檢測

    • ObjC的Swizzle檢測

    • 任意函數(shù)的hook檢測

    • 指定區(qū)域或數(shù)據(jù)段的校驗(yàn)和檢測

  • 自修復(fù)

    • 自修復(fù)被篡改的數(shù)據(jù)和代碼段

此外,還需要多層的防護(hù)厅目,通過高層保護(hù)低層的方式來保證整個(gè)防護(hù)機(jī)制不失效番枚。 參考IBM移動(dòng)終端安全防護(hù)框架解決方案:

1:越獄檢測的方法:

   1》使用NSFileManager判斷設(shè)備是否安裝了如下越獄常用工具

       /Applications/Cydia.app

       /Library/MobileSubstrate/MobileSubstrate.dylib

       /bin/bash

        /usr/sbin/sshd

        /etc/apt

      這種方式不要寫成Bool 方式去檢查 ,容易被攻擊者h(yuǎn)ook

        ![image.png](https://upload-images.jianshu.io/upload_images/1974361-6b0840859fa3ba63.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

       注意: 攻擊者可能會(huì)改變這些工具的安裝路徑损敷,躲過你的判斷葫笼。

   2》可以嘗試打開cydia應(yīng)用注冊的URL scheme,后面應(yīng)該是你知道某個(gè)應(yīng)用URL scheme

        if([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"[cydia://package/com.example.package](cydia://package/com.example.package)"]]){

             NSLog(@"Device is jailbroken");

        }

       但是不是所有的工具都會(huì)注冊URL scheme拗馒,而且攻擊者可以修改任何應(yīng)用的URL scheme路星。

   3》你可以嘗試讀取下應(yīng)用列表,看看有無權(quán)限獲扔展稹:
image.png
   攻擊者可能會(huì)hook NSFileManager 的方法洋丐,讓你的想法不能如愿

     4》你可以回避 NSFileManager呈昔,使用stat系列函數(shù)檢測Cydia等工具:

        ![image.png](https://upload-images.jianshu.io/upload_images/1974361-cfbf09cba56d9648.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

攻擊者可能會(huì)利用 Fishhook原理 hook了stat

   5》你可以看看stat是不是出自系統(tǒng)庫,有沒有被攻擊者換掉
image.png

使用dladdr方法可以獲得一個(gè)函數(shù)所在的模塊.從而判斷該函數(shù)是否被替換掉

如果結(jié)果不是 /usr/lib/system/libsystem_kernel.dylib 的話友绝,那就100%被攻擊了堤尾。

如果 libsystem_kernel.dylib 都是被攻擊者替換掉的…

也可以判斷ios 的方法在什么庫中,通過該方法驗(yàn)證指定類的方法是否都來自指定模塊

image.png

建議使用inline方式編譯,像這樣以內(nèi)聯(lián)函數(shù)的形式編譯,攻擊者必須修改每一處調(diào)用該函數(shù)的的地方

檢查所有方法判斷是否來之某個(gè)模塊

image.png
    6》檢索一下自己的應(yīng)用程序是否被鏈接了異常動(dòng)態(tài)庫九榔,列出所有已鏈接的動(dòng)態(tài)庫:
image.png

通常情況下哀峻,會(huì)包含越獄機(jī)的輸出結(jié)果會(huì)包含字符串: Library/MobileSubstrate/MobileSubstrate.dylib

攻擊者可能會(huì)給MobileSubstrate改名,但是原理都是通過DYLD_INSERT_LIBRARIES注入動(dòng)態(tài)庫

       7》可以通過檢測當(dāng)前程序運(yùn)行的環(huán)境變量:
image.png

未越獄設(shè)備返回結(jié)果是null哲泊,越獄設(shè)備就各有各的精彩了剩蟀,尤其是老一點(diǎn)的iOS版本越獄環(huán)境

上述越獄檢查總結(jié)如下:

  • 不要用NSFileManager,這是最容易被hook掉的切威。

  • 檢測方法中所用到的函數(shù)盡可能用底層的C育特,如文件檢測用stat函數(shù)(iPod7.0,越獄機(jī)檢測越獄常見的會(huì)安裝的文件只能檢測到此步驟先朦,下面的檢測不出來)

  • 再進(jìn)一步缰冤,就是檢測stat是否出自系統(tǒng)庫

  • 再進(jìn)一步,就是檢測鏈接動(dòng)態(tài)庫(盡量不要喳魏,appStore可能審核不過)

  • 再進(jìn)一步棉浸,檢測程序運(yùn)行的環(huán)境變量

即使這樣還是不能完全檢查

比如: 用戶可能安裝越獄檢測繞過插件(xCon),對于越獄檢測刺彩,很大程度上都還是針對某些目錄下某個(gè)文件名字是否換了或者文件被替換了等等去檢測迷郑;

檢測代碼
- (BOOL)mgjpf_isJailbroken

{

    //以下檢測的過程是越往下,越獄越高級
   // /Applications/Cydia.app, /privte/var/stash

    BOOL jailbroken = NO;

    NSString *cydiaPath = @"/Applications/Cydia.app";

    NSString *aptPath = @"/private/var/lib/apt/";

    if ([[NSFileManager defaultManager] fileExistsAtPath:cydiaPath]) {

        jailbroken = YES;

    }

    if ([[NSFileManager defaultManager] fileExistsAtPath:aptPath]) {

        jailbroken = YES;

    }

    //可能存在hook了NSFileManager方法创倔,此處用底層C stat去檢測

    struct stat stat_info;

    if (0 == stat("/Library/MobileSubstrate/MobileSubstrate.dylib", &stat_info)) {

        jailbroken = YES;

    }

    if (0 == stat("/Applications/Cydia.app", &stat_info)) {

        jailbroken = YES;

    }

    if (0 == stat("/var/lib/cydia/", &stat_info)) {

        jailbroken = YES;

    }

    if (0 == stat("/var/cache/apt", &stat_info)) {

        jailbroken = YES;

    }

//    /Library/MobileSubstrate/MobileSubstrate.dylib 最重要的越獄文件嗡害,幾乎所有的越獄機(jī)都會(huì)安裝MobileSubstrate

//    /Applications/Cydia.app/ /var/lib/cydia/絕大多數(shù)越獄機(jī)都會(huì)安裝

//    /var/cache/apt /var/lib/apt /etc/apt

//    /bin/bash /bin/sh

//    /usr/sbin/sshd /usr/libexec/ssh-keysign /etc/ssh/sshd_config

    //可能存在stat也被hook了,可以看stat是不是出自系統(tǒng)庫畦攘,有沒有被攻擊者換掉

    //這種情況出現(xiàn)的可能性很小

    int ret;

    Dl_info dylib_info;

    int (*func_stat)(const char *,struct stat *) = stat;

    if ((ret = dladdr(func_stat, &dylib_info))) {

        NSLog(@"lib:%s",dylib_info.dli_fname);      //如果不是系統(tǒng)庫霸妹,肯定被攻擊了

        if (strcmp(dylib_info.dli_fname, "/usr/lib/system/libsystem_kernel.dylib")) {   //不相等,肯定被攻擊了知押,相等為0

            jailbroken = YES;

        }

    }

    //還可以檢測鏈接動(dòng)態(tài)庫叹螟,看下是否被鏈接了異常動(dòng)態(tài)庫,但是此方法存在appStore審核不通過的情況台盯,這里不作羅列

    //通常首妖,越獄機(jī)的輸出結(jié)果會(huì)包含字符串: Library/MobileSubstrate/MobileSubstrate.dylib——之所以用檢測鏈接動(dòng)態(tài)庫的方法,是可能存在前面的方法被hook的情況爷恳。這個(gè)字符串有缆,前面的stat已經(jīng)做了

    //如果攻擊者給MobileSubstrate改名,但是原理都是通過DYLD_INSERT_LIBRARIES注入動(dòng)態(tài)庫

    //那么可以,檢測當(dāng)前程序運(yùn)行的環(huán)境變量

    char *env = getenv("DYLD_INSERT_LIBRARIES");

    if (env != NULL) {

        jailbroken = YES;

    }

    return jailbroken;

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末棚壁,一起剝皮案震驚了整個(gè)濱河市杯矩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌袖外,老刑警劉巖史隆,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異曼验,居然都是意外死亡泌射,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進(jìn)店門鬓照,熙熙樓的掌柜王于貴愁眉苦臉地迎上來熔酷,“玉大人,你說我怎么就攤上這事豺裆【苊兀” “怎么了?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵臭猜,是天一觀的道長躺酒。 經(jīng)常有香客問我,道長蔑歌,這世上最難降的妖魔是什么羹应? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮次屠,結(jié)果婚禮上量愧,老公的妹妹穿的比我還像新娘。我一直安慰自己帅矗,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布煞烫。 她就那樣靜靜地躺著浑此,像睡著了一般。 火紅的嫁衣襯著肌膚如雪滞详。 梳的紋絲不亂的頭發(fā)上凛俱,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天,我揣著相機(jī)與錄音料饥,去河邊找鬼蒲犬。 笑死,一個(gè)胖子當(dāng)著我的面吹牛岸啡,可吹牛的內(nèi)容都是我干的原叮。 我是一名探鬼主播,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼奋隶!你這毒婦竟也來了擂送?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤唯欣,失蹤者是張志新(化名)和其女友劉穎嘹吨,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體境氢,經(jīng)...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蟀拷,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了萍聊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片问芬。...
    茶點(diǎn)故事閱讀 40,872評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖脐区,靈堂內(nèi)的尸體忽然破棺而出愈诚,到底是詐尸還是另有隱情,我是刑警寧澤牛隅,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布炕柔,位于F島的核電站,受9級特大地震影響媒佣,放射性物質(zhì)發(fā)生泄漏匕累。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一默伍、第九天 我趴在偏房一處隱蔽的房頂上張望欢嘿。 院中可真熱鬧,春花似錦也糊、人聲如沸炼蹦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽掐隐。三九已至,卻和暖如春钞馁,著一層夾襖步出監(jiān)牢的瞬間虑省,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工僧凰, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留探颈,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓训措,卻偏偏與公主長得像伪节,于是被迫代替她去往敵國和親光羞。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,876評論 2 361

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