內(nèi)核的基本操作,多線程和數(shù)據(jù)結(jié)構(gòu)2022-02-24

image

內(nèi)核的基本操作厂庇,多線程和數(shù)據(jù)結(jié)構(gòu)

內(nèi)核的基本操作

UNICODE_STRING

為什么字符串很重要

  • 大型工程中10%~20%的代碼都與字符串操作有關(guān)
  • 面試里面也有很多字符串相關(guān)問題
  • 字符串涉及到指針操作
  • 字符串是編程第二個重要關(guān)口

字符串分兩類:0結(jié)尾和非零結(jié)尾

char *

在c語言中使用繁堡,以‘\0'結(jié)尾

BSTR

在win32編程中使用,前4個字節(jié)表示字節(jié)長伯诬,后面以'\0'結(jié)尾,可以理解為是char*UNICODE_STRING的綜合

UNICODE STRING

內(nèi)核函數(shù)多以這種字符串作為輸入?yún)?shù)巫财,不是以'\0'結(jié)尾

定義:

/// unicode編碼字符
typedef struct UNICODE_STRING{
USHORT Length; ///< 字節(jié)數(shù)盗似,不是字符數(shù),而是數(shù)據(jù)的字節(jié)數(shù),字節(jié)數(shù) = 字符數(shù) *sizeof(WCHAR) 
USHORT MaximumLength; ///< 字節(jié)數(shù),告訴系統(tǒng)函數(shù)最多有多少內(nèi)存可用
PWSTR Buffer; ///< 只是一個指針平项,一旦定義之后并沒有內(nèi)存赫舒,需要正確初始化之后,讓Buffer含有真正的數(shù)據(jù)闽瓢,才擁有內(nèi)存.**非零結(jié)尾接癌,中間也可能含有0**,PWSTR等價于WCHAR
}UNICODE_STRING,*PUNICODE_STRING;
/// 多字節(jié)編碼字符
typedef struct _STRING{
USHORT Length; ///< 其他參數(shù)同上
USHORT MaximumLength; ///< 其他參數(shù)同上
PCHAR Buffer; ///< 其他參數(shù)同上
}ANSESTRING,*PANSI_STRING; 

/// Buffer不是以零結(jié)尾,中間也可能含有零扣讼,wcscpy/wcscmp等操作其中的Buffer不可靠缺猛,
///(如果中間UNICODE_STRING.Buffer或者_STRING.Buffer中間也可能含有零,則會提前截斷椭符,如果中間不含有零荔燎,則會溢出)

對比:

typedef struct XXX{
USHORT Leng;
...
WCHAR Buffer[MAX_PATH]; ///< 字符數(shù)組,一旦定義就擁有內(nèi)存
}XXX,*PXXX

初始化方式:

用字符串常量對其初始化
UNICODE_STRING uStr={0}销钝;///< 直接定義有咨,Buffer沒有內(nèi)存(Buffer = NULL),必須正確初始化,讓Buffer含有真正的數(shù)據(jù)蒸健。
/// 在棧上的局部變量未初始化摔吏,調(diào)試的時候內(nèi)存顯示的是"燙燙燙"
/// 在堆上的局部變量未初始化,調(diào)試的時候內(nèi)存顯示的是"屯屯屯"
/// L"Hello,world!"字符串常量存放在靜態(tài)區(qū)的.rdata
WCHAR *szHello = L"Hello,world!";
/// buffer是淺拷貝(只把常量字符串的地址拷貝到buffer中)纵装,buffer直接指向L"Hello,world!"
/// Length:wcslen(szHello)*sizeof(WCHAR)征讲;
/// MaximumLength:(wcslen(szHello)+1)*sizeof(WCHAR);

RtllnitUnicodeString(&ustrTest,szHello);
上面兩句等價于:DECLARE_CONST_UNICODE_STRING(ustrTest,L"Hello,world!);
/// buffer直接指向靜態(tài)常量L"Hello,world!"橡娄,常量區(qū)內(nèi)存不可被修改诗箍,下面的操作必然會出錯。
RtlCopyUnicodeString(&ustrTest,&uStr2);
RtlAppendUnicodeToString(&ustrTest,Str1);
RtlAppendUnicodeStringToString(&ustrTest挽唉,&uStr2);
RtlAnsiStringToUnicodeString(&ustrTest,&aStr1,FALSE);
用棧上的buffer或靜態(tài)區(qū)的內(nèi)存對其初始化
/// 定義并初始化一個UNICODE_STRING字符串
UNICODE_STRING ustrTest=(0};
/// 如果把SZHello定義在函數(shù)內(nèi)部就是在棧上
/// 如果把SZHello定義在全局變量就是在靜態(tài)區(qū).bss                  
WCHAR SZHello[512]=L"Hello,world!"
/// 用棧上的buffer或靜態(tài)區(qū)的內(nèi)存對其初始化滤祖,
ustrTest.Buffer = szHello;
ustrTest.Length = wcslen("Lhello,world")*sizeof(WCHAR);
ustrTest.MaximumLength*sizeof(szHello);
用從堆上分配一個內(nèi)存對其初始化
/// 定義并初始化一個UNICODE_STRING字符串
UNICODE_STRING ustrTest = {0};
/// 設(shè)置有效長度
ULONG ulLength =wcslen(L"Hello world")*sizeof(WCHAR);
/// @param MAX_PATH*sizeof(WCHAR)表示待分配的內(nèi)存的大小(是字節(jié)數(shù)瓶籽,在驅(qū)動中UNICODE_STRING一般用來表示設(shè)備對象名匠童,符號鏈接,文件路徑塑顺,所以**字符數(shù)**不會超過MAX_PATH)MAX_PATH宏是260(個)汤求,表示在windows系統(tǒng)中一個文件的路徑最大個**字符數(shù)**俏险。(除去一個盤符,一個':',一個'\',一個'\0',所以實際上文件路徑剩下可修改的是256)
/// 為Buffer分配一個堆上的內(nèi)存
ustrTest.Buffer = ExAllocatePooMWithTag(PagedPool,MAX_PATH*sizeof(WCHAR),'POCU');
/// 如果分配失敗扬绪,則return
if (ustrTest.Buffer ==NULL)
{
    return竖独;
}
/// 分配成,則對Buffer的指向的堆上內(nèi)存初始化為0
RtlZeroMemory(ustrTest.Buffer,MAX PATH*sizeof(WCHAR))挤牛;
/// 把L"Hello,world"拷貝到Buffer指向的內(nèi)存中去莹痢,是深拷貝
memcpy(ustrTest.Buffer,L"Hello,world",ulLength);
/// 設(shè)置有效長度
ustrTest.Length =ulLength;
/// 設(shè)置最大長度
ustrTest.MaximumLength MAX_PATH*sizeof(WCHAR);
DbgPrint("%wZ\n",&ustrTest);
/// 堆上分配的內(nèi)存需要手動把它釋放掉
ExFreePool(ustrTest.Buffer);
/// 如果下面還需要使用ustrTest墓赴,一定要把它設(shè)為NEULL
/// 如果執(zhí)行完ExFreePool(ustrTest.Buffer);函數(shù)返回了竞膳,就不需要設(shè)置為NULL
/// ustrTest.Buffer = NULL;

問題代碼:如果文件超過130個字符,就會出問題诫硕,文件路徑不全顶猜。

UNICODE STRING uPath={0};
uPath.Buffer=ExAllocatePooMWithTag(
    PagedPool,
    MAX_PATH,
    'MLFC'
);
uPath.Length=wcslen(L"c:\doc\1.txt")*sizeof(WCHAR);
uPath.MaximumLength=MAX_PATH;

常用對字符串處理的API

初始化
/// 是淺拷貝(只把字符串str1的地址拷貝到uStr1.buffer中),buffer直接指向字符串str1
RtlInitUnicodeString(&uStr1,str1);

淺拷貝只是拷貝的一個地址痘括。在用堆上的內(nèi)存對UNICODE_STRING初始化時长窄,應(yīng)該使用memcpy(ustrTest.Buffer,L"Hello,world",ulLength);``ustrTest.Length =ulLength;``ustrTest.MaximumLength MAX_PATH*sizeof(WCHAR);來賦值纲菌,要注意不要使用RtllnitunicodeString(ustrTest,L"Hello,world")來賦值(會有風險)

/// eg:UNICODE_STRING初始化不當導(dǎo)致的藍屏
UNICODE_STRING ustrTest = {0};
ustrTest.Buffer = ExAllocatePoolWithTag(PagedPool,
(wcslen(L"Hello,world"))*sizeof(WCHAR),'POCU');
if (ustrTest.Buffer == NULL)
{
    return;
}
RtlZeroMemory(ustrTest.Buffer,
(wcslen(L"Hello,world"))*sizeof(WCHAR));
/// Buffer原來執(zhí)行的堆上的內(nèi)存挠日,執(zhí)行完之后,Buffer指向了靜態(tài)區(qū)的常量字符串
RtllnitunicodeString(ustrTest,L"Hello,world");
DbgPrint("%wZIn"&ustrTest);
/// 這里釋放Buffer所指向的內(nèi)存翰舌,不是堆上內(nèi)存嚣潜,內(nèi)存泄漏了,同時釋放的是靜態(tài)區(qū)內(nèi)存椅贱,系統(tǒng)自我保護藍屏了
ExFreePool(ustrTest.Buffer);
拷貝
/// 深拷貝(copy值懂算,不是地址),很明顯名字中有copy字樣
RtlCopyUnicodeString(&uStr1,&uStr2); 
拼接
/// @param str2 是簡單以'\0'結(jié)尾的C語言中的字符串
RtlAppendUnicodeToString(&uStr1,str2);
/// @param ustr2 本身就是UNICODE_STRING的字符串
RtlAppendUnicodeStringToString(&uStr1,&uStr2);

/// eg:
/// 用棧上的buffer或靜態(tài)區(qū)的內(nèi)存對其初始化
UNICODE_STRING uStr1 = {0};
WCHAR buff[100] = "Hello";
uStr1.Length = 10;
uStr1.Buffer = buff;
/// str1是簡單以'\0'結(jié)尾的C語言中的字符串
WCHARstr *str1 = L"world";
/// 用str1對uStr2初始化
UNICODE_STRING uStr2 = {0};
uStr2.Length=10:
uStr2.Buffer=str1;

///如果直接拼接一個簡單以'\0'結(jié)尾的C語言中的字符串則使用下面這個函數(shù)
RtlAppendUnicodeToString(&uStr1,str1);
///如果直接拼接一個UNICODE_STRING字符串則使用下面這個和函數(shù)
RtlAppendUnicodeStringToString(&uStr1,&uStr2);
拆分
比較
/// @param TRUE/FALSE 是否忽略大小寫
/// @return 0表示相等庇麦,負數(shù)表示uStr1 < uStr1,正數(shù)則表示uStr1 > uStr1
RtlcompareUnicodeString(&uStr1,&uStr1
TRUE/FALSE);
編碼轉(zhuǎn)換
/// 把多字節(jié)字符串轉(zhuǎn)換成寬字節(jié)字符串
/// @param TRUE/FALSE 轉(zhuǎn)換的過程中內(nèi)存的大小會發(fā)生變化计技,涉及內(nèi)存分配和計算,TRUE表示交給系統(tǒng)去計算內(nèi)存的大小和分配內(nèi)存山橄,F(xiàn)ALSE則表示程序員自己去計算和分配內(nèi)存
RtlAnsiStringToUnicodeString(&uStr1,&aStr1,
TRUE/FALSE);
/// 如果前面設(shè)置為TRUE垮媒,系統(tǒng)幫忙計算和分配內(nèi)存,用完之后一定要釋放掉航棱,否則會造成內(nèi)存泄漏
/// 實際上很少會遇到字符串編碼的轉(zhuǎn)換睡雇,因為內(nèi)核中用的都是UNICODE_STRING
/// DbgPrint在打印unicode中文的話,在debug view里面是看不到的饮醇,這種情況下就需要把unicode中文轉(zhuǎn)化成多字節(jié)編碼才能看到
RtlFreeUnicodeString(&uStr1);

安全函數(shù)

/// unicode編碼字符
typedef struct UNICODE_STRING{
USHORT Length; ///< 字節(jié)數(shù)它抱,不是字符數(shù),而是有效數(shù)據(jù)的字節(jié)數(shù)
USHORT MaximumLength; ///< 字節(jié)數(shù),告訴系統(tǒng)函數(shù)最多有多少內(nèi)存可用
PWSTR Buffer; ///< 只是一個指針朴艰,一旦定義之后并沒有內(nèi)存观蓄,需要正確初始化之后混移,讓Buffer含有真正的數(shù)據(jù),才擁有內(nèi)存.**非零結(jié)尾蜘腌,中間也可能含有0**,PWSTR等價于WCHAR
}UNICODE_STRING,*PUNICODE_STRING;

在UNICODE_STRNG的類型定義中可以發(fā)現(xiàn),是存在UNICODE_STRING能存儲大字符長度是655(USHORT取值范圍是0-(2^16-1)),能表示65535/2 = 32,767個字符沫屡,而在上述的對字符串操作的函數(shù)中饵隙,都沒有溢出檢測的撮珠,存溢出風險

//安全函數(shù),溢出檢測
#include <ntstrsafe.h>
/// str1金矛,&uStr2超過了32767芯急,或者uStr1+uStr2超過了32767,函數(shù)就會返回失敗
RtlUnicodeStringInit(&uStr1,str1);
RtlUnicodeStringCopy(&uStr1,&uStr2);
RtlUnicodeStringCat(&uStr1,&uStr2);
/// 不能操作32767個字符
#define NTSTRSAFE UNICODE_STRING_MAX_CCH(Oxffff / sizeof((wchar t))

自己實現(xiàn)所有c語言中與字符串相關(guān)的庫函數(shù)驶俊,再與微軟的對比

初始化
拷貝
拼接
拆分
比較

文件

文件的表示

  • 應(yīng)用層:"c\\doc\\hi.txt"
  • 內(nèi)核:L"\\??\\c:\\hi.txt" --> "\\device\\harddiskvolume3\\hi.txt
    • "\\device\\harddiskvolume3\\hi.txt表示在設(shè)備對象上有hi.txt文件娶耍,設(shè)備對象名"\\device\\harddiskvolume3\\hi.txt是由內(nèi)核驅(qū)動創(chuàng)建的,然后在根據(jù)設(shè)備對象名創(chuàng)建符號鏈接饼酿。"\\device\\harddiskvolume3\\hi.txt
      • \\??\\c:代表卷設(shè)備對象的符號鏈接榕酒,也稱為盤符。

設(shè)備對象的表示

  • 應(yīng)用層:
    -設(shè)備名: L"\\\\.\\xxxDrv"其中xxxDrv代表符號鏈接名故俐,把設(shè)備對象當作一個特殊的文件打開想鹰,打開得到一個句柄。
  • 內(nèi)核層:
    • 設(shè)備名:`"\device\xxxDrv"``
    • 符號鏈接名:"dosdevices\\xxxDrv"等價于\\??\\xxxDrv"

文件操作

應(yīng)用層

打開文件獲得handle -> 基于handle讀寫刪除查詢 -> 關(guān)閉

創(chuàng)建文件/文件夾
讀/寫
拷貝
移動
刪除
屬性訪問與設(shè)置
內(nèi)核層

每個API都有對應(yīng)的Irp药版,但復(fù)制辑舷、粘貼、移動沒有對應(yīng)的Irp槽片,因為這三個動作本質(zhì)是讀和寫

ZwCreateFile
  • ZwCreateFile打開文件
  • 接口說明
/**
 *  @brief       DriverEntry NtCreateFile 例程創(chuàng)建一個新文件或打開一個現(xiàn)有文件何缓。
 *  @param[out]  FileHandle 指向接收文件句柄的 HANDLE 變量的指針。
 *  @param[in]   DesiredAccess 指定一個ACCESS_MASK值还栓,該值確定對對象的請求訪問權(quán)限碌廓。
 *  @param[in]   ObjectAttributes 文件路徑
 *  @param[out]  IoStatusBlock 操作的結(jié)果,指向IO_STATUS_BLOCK結(jié)構(gòu)的指針剩盒,該結(jié)構(gòu)接收最終完成狀態(tài)和有關(guān)所請求操作的其他信息
 *  @param[in]   AllocationSize 指向LARGE_INTEGER的指針氓皱,該LARGE_INTEGER包含創(chuàng)建或覆蓋的文件的初始分配大小(以字節(jié)為單位)勃刨。
 *                              如果"分配大小"為 NULL波材,則未指定分配大小。如果未創(chuàng)建或覆蓋任何文件身隐,則忽略分配大小廷区。
 *  @param[in]   FileAttributes 指定一個或多個FILE_ATTRIBUTE_XXX 標志,這些標志表示在創(chuàng)建或覆蓋文件時要設(shè)置的文件屬性贾铝。
 *                              調(diào)用方通常指定FILE_ATTRIBUTE_NORMAL隙轻,從而設(shè)置默認屬性埠帕。
 *  @param[in]   ShareAccess 創(chuàng)建/打開這個文件的共享訪問的類型,指定為零或以下標志的任意組合玖绿。共享讀|共享寫|共享刪除敛瓷,如果設(shè)為0,則進程以獨占的方式打開這個文件斑匪,
 *                           其他進程沒辦法再打開它呐籽,也就沒辦法刪除它,但還是有其他辦法強刪的
 *  @param[in]   CreateDisposition 指定在文件存在或不存在時要執(zhí)行的操作蚀瘸。FILE_OPEN_IF狡蝶,存在則打開這個文件屋确,不存在則創(chuàng)建這個文件
 *                                 360在處理文件創(chuàng)建攔截的時候舀患,曾經(jīng)在FILE_OPEN_IF出現(xiàn)過漏洞,流氓軟件生成仿造系統(tǒng)軟件的圖標誘導(dǎo)
 *                                 用戶點擊攻晒,給網(wǎng)站導(dǎo)流獲取收益寂嘉。因為當時360考慮到大部分文件都是以FILE_OPEN奏瞬、FILE_OPEN_IF方式打開的,
 *                                 如果監(jiān)控會拖慢系統(tǒng)性能泉孩,后來還是把這個標志加入到監(jiān)控中來了
 *  @param[in]   CreateOptions 指定驅(qū)動程序創(chuàng)建或打開文件時要應(yīng)用的選項硼端。同步操作的標志、普通文件標志棵譬、文件夾標志
 *  @param[in]   EaBuffer 對于設(shè)備和中間驅(qū)動程序显蝌,此參數(shù)必須是 NULL 指針。
 *  @param[in]   EaLength 對于設(shè)備和中間驅(qū)動程序订咸,此參數(shù)必須為零曼尊。
 *  @return      ntStatus NtCreateFile 在成功時返回 STATUS_SUCCESS,或在失敗時返回相應(yīng)的 NTSTATUS 錯誤代碼脏嚷。在后一種情況下骆撇,
 *                        調(diào)用方可以通過檢查 IoStatusBlock 參數(shù)來確定失敗的原因。
 *  @see         https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntifs/nf-ntifs-ntcreatefile
 *  @author      cisco(微信公眾號:堅毅猿)
 *  @date        2022-02-24 22:09
 */
ZwCreateFile(
_Out_ PHANDLE FileHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes,
_Out_ PIO_STATUS_BLOCK IoStatusBlock,
_In_opt_ PLARGE_INTEGER AllocationSize,
_In_ ULONG FileAttributes,
_In_ ULONG ShareAccess,
_In_ ULONG CreateDisposition,
_In_ ULONG CreateOptions,
_In_reads_bytes_opt_(EaLength) PVOID EaBuffer,
_In_ ULONG EaLength
);
ZwWriteFile
  • ZwWriteFile寫文件父叙,是相對于應(yīng)用層來說神郊,數(shù)據(jù)流向:r3->R0
ZwReadFile
  • ZwReadFile讀文件,是相對于應(yīng)用層來說趾唱,數(shù)據(jù)流向:r0->R3
ZwQuerylnformationFile
  • ZwQuerylnformationFile查詢文件信息
ZwQueryFullAttributesFile
  • ZwQueryFullAttributesFile查詢文件完整信息
ZwSetinformationFile
  • ZwSetinformationFile設(shè)置文件信息 -> irp_mj_set_information
    • 在這里還有兩個重要的Irp(重命名和刪除涌乳,Major)
ZwClose
  • ZwClose關(guān)閉文件
ZwQueryDirectoryFile
  • ZwQueryDirectoryFile遍歷文件夾
    • ./當前目錄
    • ..父目錄

注冊表

強制刪除文件,文件注冊表穿越

內(nèi)核的多線程

內(nèi)核中的數(shù)據(jù)結(jié)構(gòu)(代替遞歸)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末甜癞,一起剝皮案震驚了整個濱河市夕晓,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌悠咱,老刑警劉巖蒸辆,帶你破解...
    沈念sama閱讀 212,294評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件征炼,死亡現(xiàn)場離奇詭異,居然都是意外死亡躬贡,警方通過查閱死者的電腦和手機谆奥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,493評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拂玻,“玉大人酸些,你說我怎么就攤上這事》慕玻” “怎么了擂仍?”我有些...
    開封第一講書人閱讀 157,790評論 0 348
  • 文/不壞的土叔 我叫張陵囤屹,是天一觀的道長熬甚。 經(jīng)常有香客問我,道長肋坚,這世上最難降的妖魔是什么乡括? 我笑而不...
    開封第一講書人閱讀 56,595評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮智厌,結(jié)果婚禮上诲泌,老公的妹妹穿的比我還像新娘。我一直安慰自己铣鹏,他們只是感情好敷扫,可當我...
    茶點故事閱讀 65,718評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著诚卸,像睡著了一般葵第。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上合溺,一...
    開封第一講書人閱讀 49,906評論 1 290
  • 那天卒密,我揣著相機與錄音,去河邊找鬼棠赛。 笑死哮奇,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的睛约。 我是一名探鬼主播鼎俘,決...
    沈念sama閱讀 39,053評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼辩涝!你這毒婦竟也來了贸伐?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,797評論 0 268
  • 序言:老撾萬榮一對情侶失蹤膀值,失蹤者是張志新(化名)和其女友劉穎棍丐,沒想到半個月后误辑,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,250評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡歌逢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,570評論 2 327
  • 正文 我和宋清朗相戀三年巾钉,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片秘案。...
    茶點故事閱讀 38,711評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡砰苍,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出阱高,到底是詐尸還是另有隱情赚导,我是刑警寧澤,帶...
    沈念sama閱讀 34,388評論 4 332
  • 正文 年R本政府宣布赤惊,位于F島的核電站吼旧,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏未舟。R本人自食惡果不足惜圈暗,卻給世界環(huán)境...
    茶點故事閱讀 40,018評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望裕膀。 院中可真熱鬧员串,春花似錦、人聲如沸昼扛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,796評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽抄谐。三九已至渺鹦,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間斯稳,已是汗流浹背海铆。 一陣腳步聲響...
    開封第一講書人閱讀 32,023評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留挣惰,地道東北人卧斟。 一個月前我還...
    沈念sama閱讀 46,461評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像憎茂,于是被迫代替她去往敵國和親珍语。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,595評論 2 350