深入解析Windows操作系统---第一章

第一章 概念和工具

本章将介绍Microsoft Windows操作系统的关键概念和术语,比如Windows API,进程,线程,虚拟内存,内核模式和用户模式,对象,句柄,安全性和注册表等,这些概念和术语将贯穿全书。同时也会介绍一些可以用来探查Windows内部的工具,比如内核调试器,性能监视器,以及来自Windows Sysinternals的一些关键工具。此外,还将说明如何以WDK(Windows Driver Kit)和SDK(Platform Software Development Kit)作为资源,来找到关于Windows内部机制的进一步信息。

请一定要理解本章中讲述的所有内容,本书其余章节将以此为基础

1.1 Windows操作系统的版本

本书涵盖了Microsoft Windows客户机和服务器操作系统的最新版本:Windows 7(32位和64位)和Windows Server 2008 R2(64位)。除非特别声明,否则本书中的讲解适合用于所有版本。

1.2 基础概念和术语

在本书讲解过程中,我们会提到一些对于某些读者来说可能并不熟悉的结构和概念。在这一节中,我们将界定贯穿全书的术语。在阅读后续章节前,你应该熟悉这些术语。

Windows API

Windows应用编程接口(API)是针对Windows操作系统家族的用户模式系统编程接口。在64位版本的Windows推广以前,32位版本Windows操作系统的编程接口被称为Win32 API,以区别于原来的16位版本Windows的编程接口,即16位Windows API。在本书中,术语Windows API兼指Windows的32位和64位编程接口。



Windows软件开发工具(SDK)文档描述了Windows API。这份文档可以在www.msdn.microsoft.com在线免费查阅。关于如何在Windows基础API上编写程序,有一份极好的资料---Jeffrey Richter和Christophe Nasarre所写的Windows via C/C++ 一书。


Windows API包含数千个可调用的函数,它们可以被分成以下一些大类:

  • 基本服务
  • 组件服务
  • 用户界面服务
  • 图形和多媒体服务
  • 消息和协作
  • 网络
  • Web服务

本书主要关注关键基本服务(比如进程和线程,内存管理,I/O和安全性)的内部机理。


关于.NET
Microsoft.NET框架是由一个被称为框架类库(FCL,Framework Class Library)的类库和一个提供了托管代码执行环境的公共语言运行库(CLR,Common Language Runtime)组成的,后者提供的代码执行环境包含以下一些特征:

  • 即时编译
  • 类型检验
  • 垃圾回收
  • 代码访问安全性

由于CLR具有这些特性,因此它所提供的开发环境能够提高开发人员的生产效率,减少常见的编程错误。
关于.NET框架及其核心架构的精彩描述,参见Jeffrey Richter的CLR via C#



Win32 API的历史
有意思的是,Win32并不是Windows NT最初预定的编程接口。因为Windows NT项目在启动之初,目的是代替OS/2第2版,所以,它的主要编程接口是32位OS/2 Presentation Manager API。
然而,项目进行了一年后,Microsoft Windows 3.0 进入市场,并且呈现出很好的发展势头。于是,Microsoft转变了方向,使Windows NT成为未来Windows产品家族的替代品,而不是用来替代OS/2。也正是这个时候,才真正有必要定制Windows API---在此之前,在Windows 3.0 中,只有16位接口的API。
尽管当时在Windows API中将引入很多在Windows 3.1 上还无法使用的新函数,但是,Microsoft还是决定让新的API与16位Windows API在函数名称,语义和数据类型用法上尽可能兼容,以便减轻将已有的的16位Windows应用程序移植到Windows NT上的负担。这也是许多函数名称和接口看起来并不一致的原因:为了确保当时新的Windows API与老的16位Windows API保持兼容,这是必须的。


服务,函数和例程

在Windows的用户文档和程序设计文档中,有几个术语在不同的上下文环境中有着不同的含义。例如,服务可以指操作系统中可以被调用的例程,设备驱动程序或者服务器进程。下面的列表描述了一些特定的术语在本书中的含义:

  • Windows API函数 指Windows API中已被文档化的,可以被调用的子例程,例如*CreateProcess,CreateFileGetMessage
  • 原生的系统服务(或者系统调用) 指操作系统中为文档化的,可在用户模式下调用的底层服务。例如,NtCreateUserProcess 是一个内部系统服务,Windows的CreateProcess函数调用该服务来创建新的进程。
  • 内核支持函数(或例程) 指位于Windows操作系统内部且只能在内核模式下调用的子例程。例如,ExAllocatePoolWithTag就是一个这样的例程,设备驱动程序调用该例程可以向Windows系统堆(称为内存池)申请内存。
  • Windows服务 指由Windows服务控制管理器启动的进程。例如,Task Scheduler服务运行在用户模式进程中,它支持at命令。
  • DLL(动态链接库) 指一组可调用的子例程,合起来被链接成一个二进制文件,使用这些子例程的应用程序可以动态地加载此二进制文件。例如Msvcrt.dll(C运行库)和Kernel32.dll(一个Windows API子系统库)。Windows的用户模式组件和应用程序大量使用了DLL。DLL比静态库的优势在于,应用程序可以共享DLL,Windows保证在内存中只有一份DLL代码,供所有引用该DLL的应用程序共享。注意,非可执行的.NET程序集也被编译成DLL,但是,它们没有任何子例程,而是由CLR解析出编译的元数据,以便访问对应的数据类型和成员。

进程,线程和作业

尽管表面上看起来程序和进程非常相似,但本质上它们却是截然不同的。程序是一个静态的指令序列,而进程是一个容器,其中包含了执行程序的特定实例所需的各种资源。从最高层次的抽象来看,Windows进程是由以下元素构成的:

  • 私有的虚拟地址空间,这是指该进程可以使用的一组虚拟内存地址。
  • 可执行的程序,它定义了初始化的代码和数据,并且被映射到该进程的虚拟地址空间中。
  • 已打开句柄列表,这些句柄指向各种系统资源,比如信号量,通信端口和文件,该进程内所有的线程都可以访问这些系统资源。
  • 被称为访问令牌的安全环境,它标识了与该进程关联的用户,安全组,特权,UAC虚拟化状态,会话,以及有限的用户账户状态。
  • 被称为进程ID的唯一标识符
  • 至少一个执行线程

每个进程也指向它的父进程或者创建者进程。如果父进程不再存在,子进程中的这一信息并不会被更新。

关于进程和线程的信息,Sysinternals出品的Process Explorer提供了比其他任何工具都要多的细节,正因为如此,你将会在本书的许多实验中看到这个工具的运用。


线程是一个进程内部的实体,也是Windows执行此进程时的调度实体。如果没有线程,进程的程序将不可能运行起来。线程包括以下一些最基本的部件:

  • 一组代表处理器状态的CPU寄存器中的内容。
  • 两个栈---一个是用于线程在内核模式下执行时,另一个用于线程在用户模式下执行时。
  • 一个被称为线程ID的唯一标识符的一部分。
  • 有时候线程也有它们自己的安全环境,或者令牌,多线程服务器应用程序要模仿其客户的安全环境时,常常会使用线程自己的安全环境。

易失的寄存器,栈和私有存储区域结合起来被称为线程的环境(context)。因为这些信息随着Windows所在机器架构的不同而有所不同,所以,此架构必须是与底层架构相关的。Windows的GetThreadContext函数允许程序访问这一与架构相关的信息(称为CONTEXT块)。


纤程与用户模式调度器线程

因为将CPU的执行从一个线程切换到另一个线程,将不可避免地涉及内核调度器,所以,这可能是一个开销昂贵的操作,如果两个线程经常频繁来回切换则尤为如此。Windows实现了两种机制来降低这种开销:纤程(fiber)和用户模式调度(UMS)

纤程使得一个应用程序可以调度它自己的"线程"的执行过程,而不必依赖Windows内置的基于优先级的调度机制。纤程也常被称为"轻量"线程:从调度的角度来看,它们对于内核是不可见的,因为它们是在用户模式下在Kernel32.dll中实现的。使用方法参考Windows SDK文档。

UMS线程仅在64位Windows长可用,它基本上提供了与纤程同样的好处,没有更多的坏处。UMS线程有它们自己的内核线程状态,因此对于内核是可见的,这使得多个UMS线程都可以发出阻塞的系统调用,对资源进行共享或竞争,并且有每个线程特有的状态(per-thread state)


虽然线程有自己的执行环境,但是,同一个进程内部的所有线程共享该进程的虚拟地址空间(以及同属于该进程的其他资源),这意味着,一个进程内的所有线程都可以完全地读或写该进程的虚拟地址空间。然而,一个进程中的线程不可能无意识地引用另一个进程的地址空间,除非两种情况:第二个进程将它的一部分私有地址空间变成共享内存区(shared memory section)(在Windows API中称为文件映射对象(file mapping object));或者,第一个进程有权打开第二个进程,从而可以使用诸如ReadProcessMemoryWriteProcessMemory 等跨进程的内存函数。

除了私有地址空间和一个或者多个线程以外,每个进程还有一个安全环境和一个已打开句柄的列表,这些句柄指向诸如文件,共享内存区,或者像互斥体,事件或者信号量等某个同步对象

每个进程都有一个安全环境,存储在一个称为访问令牌(access token)的对象中。进程的访问令牌包含了该进程的安全标识和凭证。在默认情况下,线程没有自己的访问令牌,但是他们也可以获得一个访问令牌,因此单独的线程可以模仿另一个进程的安全环境。

虚拟地址描述符(AVD)是指一些数据结构,内存管理器利用这些数据结构来记录进程正在使用的虚拟地址。

Windows在进程模型上提供了一个拓展,称为作业(job)。作业对象的主要功能是,使一组进程被当做一个整体来管理和维护。通过作业对象,可以对特定属性进行控制,也可以对一个进程,或者所有与作业相关联的进程进行限制。作业对象也可以为所有与该作业相关联的进程记录下基本审计信息,其中也包括曾经与改作业关联但是已经终止了的进程的审计信息。在某种程度上,作业对象弥补了Windows平台上缺乏结构化的进程树的不足,而且,它的功能。

虚拟内存

Windows实现了一个基于平面(线性)地址空间的虚拟内存系统,使每个进程感觉自己独立拥有一个很大的私有地址空间。虚拟内存提供了一个内存逻辑视图,它可能并不对应于内存的物理布局。在运行的时候,内存管理器借助于硬件的支持,将虚拟地址转译或者映射(map)成真正存放数据的物理地址。操作系统通过控制这一保护和映射机制,可以确保一个进程不会闯入到另一个进程中,也不会改写操作系统的数据。
因为大多数系统所拥有的物理内存,比当前正在运行的进程所用到的虚拟内存总量要少得多,所以,内存管理器会将内存中的有些内容转移或者(page)到磁盘上。将数据翻译到磁盘上以后,就可以释放这部分物理内存,因此,这些物理内存可以被别的进程所使用,或者用于操作系统本身。当线程访问一个已被翻到磁盘上的虚拟地址时,虚拟内存管理器会将磁盘上的信息装回内存中。应用程序无须任何改变就可以利用这种分页(paging)功能,因为在硬件的支持下,内存管理器无须任何关于进程和线程的知识,也无须进程或线程的协助,就可以实现分页。
虚拟地址空间的大小随着硬件平台而有所不同。在32位x86系统中,总的虚拟地址空间有一个理论上的最大值4GB。在默认情况下,Windows将这一部分地址空间的一半(4GB虚拟地址空间中较低的一半,x00000000x7FFFFFFF)分配给进程,作为它们独有的私有存储空间,而另一半(地址空间中较高的一半,x80000000xFFFFFFFF)则用于它自己的被保护的操作系统内存。低一半地址空间的映射关系会发生变化,以便总是反应出当前正在执行的进程的虚拟地址空间,而高一半地址空间的映射关系总是由操作系统的虚拟内存构成。Windows支持一些引导选项,可以使那些运行带有特殊标记的程序(在可执行映像文件头部设置了大地址空间感知标志)的进程能够使用多达3GB的私有空间(给操作系统留下1GB)。这一选项使得像数据库服务器这样的应用程序的更多内容保留在进程的地址空间中,从而减少映射该数据库的子集视图的需求。
虽然3GB比2GB更好,但是,对于映射非常大的数据库(许多个GB)而言,虚拟地址空间任然不足。针对在32位系统上的这种需求,Windows提供了一个被称为地址窗口扩展(AWE,Addres Windowing Extension)的机制,使得32位应用程序可以申请多达64GB物理内存,然后将内存视图或者窗口映射到它的2GB虚拟地址空间中。虽然AWE将管理"虚拟内存-物理内存"映射关系的负担放到了程序员的身上,但是,它确实解决了问题,使得进程能够直接访问更多的物理内存。超过了它的32位进程地址空间一次能够映射的数量。
64位Windows为进程提供了更大的地址空间:在IA-64系统上位7152GB,x64系统上为8192GB。注意,这些大小值并不代表这些平台上的架构限制。64位地址空间的大小超过了170亿GB,但当前的64位硬件限制了地址空间比该值要小,而在当前的64位Windows中,由于Windows的实现机制,此地址空间又被降低到8192GB(8TB)。

内核模式和用户模式

为了避免用户应用程序访问和/或修改关键的操作系统数据,Windows使用了两种处理器访问模式(即使运行Windows的底层处理器支持多余两种模式):用户模式内核模式。用户程序运行在用户模式下,而操作系统代码(比如系统服务和设备驱动程序)运行在内核模式下。内核模式是指这样一种处理器执行模式:它允许访问所有的系统内存和所有的CPU指令。通过让操作系统软件比应用软件有更高的特权级,处理器位操作系统设计者提供了必要的保护,可以确保行为不正常的应用程序不会破环系统整体的稳定性。


注:
x86和x64处理器架构定义了四种特权级,或者称为四个环(ring),来保护系统代码和数据不会被低级别的代码恶意地或无意地改写。Windows使用特权级0(或称为0环)作为内核模式,特权级3(或称3环)作为用户模式。Windows之所以只使用两级,是因为它过去支持的一些硬件架构(比如Compaq Alpha和Silicon Graphics MIPS)只实现了两个特权级。


虽然每个Windows进程都有自己私有的内存空间,但是内核模式的操作系统和设备驱动程序代码共享一个虚拟地址空间。虚拟内存中的内一个页面都被标记了处理器必须在什么访问模式下才可以读和/或写该页面。系统空间中的页面只有在内核模式下才可以访问,而用户地址空间的所有页面都可以在用户模式下访问。只读页面(比如包含静态数据的页面)在任何模式下都是不可写的。此外,在支持不可执行(no-execute)内存保护的处理器上,Windows将包含数据的页面标记为不可执行,从而防止数据区域被无意或恶意地当作代码来执行。

对于在内核模式下运行的组件,32位Windows对它们所使用的私有系统内存并不提供读写保护。换句话说,一旦进入内核模式,操作系统和设备驱动程序的代码可以完全访问系统空间的内存,也可以绕过Windows的安全机制直接访问对象。因为有大量的Windows操作系统代码运行在内核模式下,所以很关键的一点是,对在内核模式下运行的组件必须要谨慎地设计和测试,以确保它们不会破坏系统的安全性,也不会造成系统不稳定。

由于缺乏保护,因此,再加载第三方设备驱动程序时更需要加倍小心,因为一旦进入内核模式,这些软件就可以完全访问所有的操作系统数据。这一弱点也正是Windows要引入驱动程序签名机制的原因之一。引入驱动程序签名机制以后,当未签名的即插即用驱动程序企图加入系统中时,Windows会警告用户,并且阻止其加入系统(如果做了这样的配置)。还有一种被称为驱动程序检验器(Driver Verifier)的机制,可以帮助设备驱动程序的编写者找到驱动程序中引发安全性或可靠性问题的缺陷(比如缓存区溢出或者内存泄漏)。

在64位版本的Windows中,内核模式代码签名(KMCS,Kernel Mode Code Signing)策略规定,64位设备驱动程序(不仅仅是即插即用程序)必须要经过某个主码认证权威机构发放的密钥来签名。用户不能明确地强制安装未经签名的驱动程序,即使管理员也不行,但有一个一次性的例外,这一限制可以在系统引导时手工禁止,即,在引导时按下F8键,选择高级引导选项"禁用驱动程序强制签名(Disable Driver Signature Enforcement)"。这会导致在桌面壁纸上出现一个水印,同时特定的数字版权保护(DRM)特性被关闭。

在第2章"系统架构"中将看到,用户应用程序将在进行系统服务调用时,会从用户模式切换到内核模式下。例如,WIndows的ReadFile函数最终要调用Windows内部的一个例程,由该例程真正完成从一个文件中读取数据的任务。由于该例程需要访问内部的系统数据结构,所以,它必须运行在内核模式下。从用户模式切换到内核模式,可以通过专门的处理器指令来完成,该指令会将处理器切换到内核模式下,并进入内核模式中的系统服务分发代码,进一步调用Ntostrnl.exe或Win32k.sys中适当的内部函数。在将控制权返回用户线程之前,处理器的模式被切换回用户模式。通过这种方法,操作系统将自身和它的数据保护起来,使它们不会被用户进程看到或者修改。
因此,很自然地,对于一个用户线程来说,它的一部分时间运行在用户模式下,另一部时间运行在内核模式下。实际上,因为图形和窗口系统的大部分时间也运行在内核模式下,所以,图形密集的应用程序花在内模式下的时间比在用户模式下的时间多得多。这一点很容易测试,一种简单的办法是,运行一个图形密集的应用程序,比如"画图"或者Chess Tians,然后使用性能监视器(具体方法百度)

终端服务及多个会话

终端服务指的是在单个系统中,Windows对于多个可交互用户会话的支持。利用Windows的终端服务,一个远程用户可以在另一台机器上建立一个会话,并且登陆进去,在该服务器上运行应用程序。服务器把图形用户界面(以及其他可配置的资源,比如音频和剪切板)传送到客户机,客户机把用户的输入传回服务器。(与X窗口系统类似,Windows允许在一个服务器系统运行独立的应用程序,其显示部分远程传送到客户机,而非将整个桌面远程到客户机)。
第一个会话被认为是服务会话,或者零号会话,它包含了宿纳系统服务的进程。在机器的物理控制台上的第一个登陆会话位一号会话,而其他会话可以通过远程桌面连接程序(Mstsc.exe)来建立,或者通过使用快速用户切换来建立。

Windows的客户机版本允许单个远程用户连接到及其上,但如果有人已经在控制台上登陆了,则工作站会被锁住(也就是说,一个人可以利用本地或者远程方式使用Windows客户机系统,但不能同时以这两种方式来使用系统)。

Windows服务器系统支持两个并发的远程连接(这是为了方便远程管理,例如,有些管理工具要求登录到被管理的机器中才可以使用),以及两个以上的远程会话。

所有Windows客户机版本都支持通过使用一个被称为快速用户切换(fast user switching)的特性,在本地创建多个会话。当用户选择断开其会话,而不是注销其登录时,当前会话仍然保留在系统中,而系统返回到主屏幕。如果一个新的用户登陆进来,则新建一个会话。

对象和句柄

在Windows操作系统中,内核对象是指某个静态定义的对象类型的单个运行时实例。对象类型由系统定义的的数据类型,在该数据类型的实例上进行操作的一组函数,以及一组对象属性构成。如果你编写Windows应用程序,那么,你可能会遇到进程,线程,文件和事件对象,这只是对象的一些例子而已。这些对象都是以Windows创建和管理的底层对象为基础的。在Windows中,任何进程都是进程对象类型的实例,文件是文件对象类型的实例,如此等等。

对象属性是对象中的数据域,每个对象属性定义了对象的一部分状态。例如,类型为进程的对象,其属性包括进程ID,基本调度优先级和一个指向访问令牌对象的指针。对象方法,即操纵对象的手段,通常用于读取或者改变对象的属性。例如,进程的open方法接受一个进程标识符作为输入,返回一个指向该进程对象的指针作为输出。

对象和普通数据结构之间的最根本区别是,对象的内部结构是不透明的。你必须调用一个对象服务才可以获得对象内部的数据,或者把数据放入对象内部。你不能直接读取或者改变一个对象内部的数据。这一区别将对象的底层实现与那些仅仅使用该对象的代码隔离开来,此技术使得对象的实现可以随着时间而容易地改变。

借助一个被称为对象管理器的内核组件,Windows中的对象提供一种便捷的途径来实现下列四个重要的操作系统任务:

  • 为系统资源提供可供人读的名称。
  • 进程之间共享资源和数据。
  • 保护资源,避免未授权的访问。
  • 引用跟踪,这使得系统能够知道一个对象何时不再有用,从而可以被自动释放。

并非Windows操作系统中的所有数据结构都是对象。只有确实需要被共享,保护,命名或者让用户模式程序看得到(通过系统服务)的数据才被放入到对象中。仅仅被操作系统的某一个组件用来实现其内部函数的数据结构并不是对象。

安全性

Windows从一开始就被要求是安全的,能够满足政府和工业界各种正式的安全评级的需求

Windows的核心安全功能包括:针对所有可共享系统对象(比如文件,目录,进程,线程等等)的自主保护(need-to-know)和强制完整性保护,安全审计(针对主体或者用户和他们发起的动作的记录),登陆时候的用户认证,以及禁止用户通过访问未初始化资源的做法来访问其他用户已释放的资源(比如空闲内存或磁盘空间)。

Windows有三种对对象的访问控制形式。第一种控制形式称为自主访问控制,大多数人一想到操作系统安全性,自然就会想到这种保护机制。其做法是,由对象(比如文件或者打印机)的所有者授权或者拒绝其他人访问这些对象。当用户登陆系统中时,他们会得到一组安全凭证,或者一个安全环境。当他们试图访问对象时,系统会将他们的安全环境与他们要访问的对象的访问控制列表进行比较,以确定他们是否可以执行所请求的操作。

当自主访问控制不能满足需要时,应该使用特权访问控制。这种方法可以确保:即使对象的所有者当前无法联系到,也有人可以访问被保护的对象。例如,如果一个员工离开了公司,则管理员必须有办法访问那些本该只有该员工才可以访问的文件。在这种情况下,在Windows中,管理员能够接管这些文件的所有权,从而可以根据需要管理它们的权限。

最后,当需要额外的一层安全控制以实现在同一个账户内部的对象访问保护时,需要使用强制完整性控制。它既被用于将Internet Explorer的保护模式与用户的配置隔离开,也被用于保护那些由提升了特权的管理员所创建的对象,避免被未被提升特权的管理员账户所访问。

注册表

如果你与Windows操作系统打过交道,那么,你可能听说过或者看到过注册表。探讨Windows内部机理,就不能不提到注册表,因为注册表是系统数据库,它包含了引导和配置系统所必需的消息,全系统范围内控制Windows操作的软件设置,安全数据库,以及针对每个用户配置设置(比如使用哪个屏幕保护程序)。

同时,注册表也是一个反映内存中易失数据的窗口,比如系统的当前硬件状态(哪些设备驱动程序已经加载,它们用到了哪些资源,等等)以及Windows的性能计数器。

虽然许多Windows用户和管理员从来不需要直接查看注册表(因为你可以通过标准的管理工具来查看或者改变大多数配置设置),但是,注册表仍然是一个非常有用的Windows内部信息来源,因为它包含了许多会影响系统性能和行为的设置。在本书中你将会看到许多注册表键,当介绍某些组件时,将会提及相应的注册表键。本书中提到的绝大多数注册表键位于全系统范围的配置(即HKEY_LOCAL_MACHINE)下面,我们将其缩写位HKLM。

Unicode

Windows区别于大多数其他操作系统的一个方面是,它的大多数内部文本串是以16位宽度的Unicode字符来存储和处理的。

因为许多应用程序只处理8位(单字节)ANS字符串,所以,接受字符串参数的Windows函数有两个入口点:一个Unicode(宽字符,16位)版本和一个ANSI(窄字符,8位)版本。

无论哪个语言版本的Windows,它们都包含同样的函数。Windows不再使用多种不同的语言版本,而是使用一份全球同一的二进制代码,这样,同一份安装可以支持多种语言(只需导入各种语言包即可)。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容