Android 代碼混淆Proguard

混淆概念
Android代碼混淆,又稱Android混淆蔬蕊,是伴隨著Android系統(tǒng)的流行而產(chǎn)生的一種APP保護技術(shù)拌滋,用于保護APP不被破解和逆向分析。
在Android的具體表現(xiàn)就是打包時雌芽,將項目里的包名授艰、類名、變量名根據(jù)混淆規(guī)則進行更改膘怕,使反編譯工具反編譯出來的代碼人難以閱讀想诅,從而達到防止被逆向破解的目的。

在Android里面,由于AndroidStudio集成了ProGuard来破,因此我們最常用篮灼,最簡單的混淆是ProGuard混淆。
ProGuard混淆主要包括有四個功能:

壓縮(Shrink):用于檢測和刪除沒有使用的類徘禁、字段诅诱、方法和屬性。
優(yōu)化(Optimize):對于字節(jié)碼進行優(yōu)化送朱,并且移除無用指令娘荡。
混淆(Obfuscate):使用a,b,c等名稱對類,字段和方法進行重命名驶沼。
預(yù)檢(Preverify):主要是在Java平臺上對處理后的代碼進行預(yù)檢炮沐。
綜上我們可以總結(jié)出混淆的兩大作用:

安全,提高了反編譯&逆向破解的難度回怜。
壓縮代碼大年,刪除無用的代碼,簡單的代碼重命名玉雾,都可以減少Apk體積翔试。
其實混淆還有另一個妙用,也是今天我們重點要說的:
不同的混淆規(guī)則可以編譯完全不同的代碼复旬,降低代碼重復(fù)率垦缅,用于制作馬甲包。

開啟混淆
在主模塊的build.gradle中添加如下代碼驹碍,即可開啟混淆壁涎。

android{
//...
buildTypes {
release {
debuggable false //是否debug
jniDebuggable false // 是否打開jniDebuggable開關(guān)
minifyEnabled true //代碼壓縮,混淆
shrinkResources true //資源壓縮
zipAlignEnabled true //壓縮優(yōu)化
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release //簽名
}
debug {
signingConfig signingConfigs.release //簽名
}
}
//...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
配置混淆開關(guān)的是minifyEnabled志秃。
proguardFiles用于指定混淆規(guī)則粹庞,自動使用默認(rèn)的混淆規(guī)則,而我們可以在proguard-rules.pro中自定義自己的混淆規(guī)則洽损。

混淆規(guī)則
常見的混淆規(guī)則應(yīng)該主要包含如下四個部分:

基本配置,設(shè)定混淆的規(guī)則等革半,基本配置是每個混淆文件必須存在的碑定。
基本的keep項,多數(shù)Android工程都需要非混淆的內(nèi)容又官,包括有四大組件延刘,AndroidX等內(nèi)容。
第三方庫sdk的混淆白名單六敬,根據(jù)對應(yīng)文檔添加即可(新版本構(gòu)建工具可以在sdk內(nèi)部添加碘赖,因此大部分sdk新版本都無須再添加)。
其他需要不混淆的內(nèi)容,包括:實體類普泡,json解析類播掷,WebView及js的調(diào)用模塊,與反射相關(guān)的類和方法撼班。
混淆的詳細規(guī)則可以參考:ProGuard的官方文檔
混淆指令的詳細解釋可以參考:混淆必知必會

混淆白名單
指定一些包名歧匈、類名、變量等不可以被混淆砰嘁。假設(shè)沒指定白名單就進行混淆打包件炉,而某某類的類名被混淆了(假設(shè)變成了a),那么可能其他引用或使用該類的類就找不到該類矮湘,說不定應(yīng)用就會因此崩潰或是導(dǎo)致相應(yīng)的功能無法使用斟冕。
比如我們通過反射調(diào)用了一個類,如果該類打包時被混淆缅阳,那么運行時必定會找不到該類i磕蛇,進而導(dǎo)致App異常。

打包效果

proguard-rules.pro中配置完常用混淆后券时,我們可以打一個release包孤里。(每次混淆修改后,打包前注意clean)
打包成功后在AndroidStudio中雙擊打開apk橘洞,點擊classes.dex就可以看到混淆后的代碼捌袜,包名,類名炸枣,方法都變成了近似于“亂碼”虏等。

打印混淆信息
混淆后雖然增強了App的安全性,上線后同時也會導(dǎo)致一些“副作用”:

日志打印信息不準(zhǔn)確
報錯信息無法定位具體位置
我們可以在proguard-rules.pro中添加如下代碼适肠,混淆后霍衫,就會在指定文件中輸入混淆信息。
這對于我們排查線上問題有很大幫助侯养,諸如bugly等異常上報平臺敦跌,都可以上傳mapping.txt幫助在錯誤信息中定位代碼。

-printseeds proguardbuild/print_seeds.txt #未混淆的類和成員
-printusage proguardbuild/print_unused.txt #列出從 apk 中刪除的代碼
-printmapping proguardbuild/print_mapping.txt #混淆前后的映射逛揩,生成映射文件
1
2
3
混淆出不同的代碼
實際上基本混淆配置完只要不去修改柠傍,相同代碼每次打包得到的代碼都是一樣的。
對于單包常規(guī)開發(fā)來說辩稽,這是沒有問題的惧笛。
但是實際上絕大多數(shù)App都需要馬甲包去增加搜索關(guān)鍵字,進而達到引流效果逞泄。
然而馬甲包上架有一個始終無法回避問題:代碼相似度患整,在審核嚴(yán)格的平臺拜效,代碼相似度過高甚至?xí)?dǎo)致主包下架,造成無法挽回的損失各谚。

降低代碼相似度紧憾,常規(guī)來說有兩個方案:

成本高&低效率的一點點改代碼。
暴力的生成垃圾代碼嘲碧,增大分母稻励,降低百分比。
如何通過混淆來解決這個問題呢愈涩?核心混淆規(guī)則如下:

指定一個文本文件望抽,其中所有有效字詞都用作混淆字段和方法名稱。

默認(rèn)情況下履婉,諸如“a”煤篙,“b”等短名稱用作混淆名稱。

使用模糊字典毁腿,您可以指定保留關(guān)鍵字的列表辑奈,或具有外來字符的標(biāo)識符,

例如: 忽略空格已烤,標(biāo)點符號鸠窗,重復(fù)字和#符號后的注釋。

注意胯究,模糊字典幾乎不改善混淆稍计。 有些編譯器可以自動替換它們,并且通過使用更簡單的名稱再次混淆裕循,可以很簡單地撤消該效果臣嚣。

最有用的是指定類文件中通常已經(jīng)存在的字符串(例如'Code'),從而減少類文件的大小剥哑。 僅適用于混淆處理硅则。

-obfuscationdictionary proguardbuild/pro_package.txt

指定一個文本文件,其中所有有效詞都用作混淆類名株婴。 與-obfuscationdictionary類似怎虫。 僅適用于混淆處理。

-classobfuscationdictionary proguardbuild/pro_class.txt

指定一個文本文件困介,其中所有有效詞都用作混淆包名稱揪垄。與-obfuscationdictionary類似。 僅適用于混淆處理逻翁。

-packageobfuscationdictionary proguardbuild/pro_func.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
簡單來說我們可以指定一個txt文件作為混淆字典,混淆過程中修改的包名捡鱼,類八回,方法都取自于該字典。只要我們每個馬甲包的字典不一致,我們自然能得到代碼相似度低的馬甲包缠诅。

你可以簡單粗暴的Copy中的別人的混淆字典:喪心病狂的Android混淆文件生成器

打包出來的效果如下:

Tips:相同的混淆字典打包出來的代碼仍是一致的溶浴,因此你每個馬甲包都應(yīng)該使用不同的混淆字典。

腳本生成
如果你有幾百個馬甲包管引,Copy別人的遲早“山窮水盡”士败。
作為程序員,這些都不應(yīng)該難到我們褥伴。Python腳本隨機生成就是啦~

import random
import string
import os
'''
腳本生成混淆字典
'''

//生產(chǎn)8000個不重復(fù)的字符串
totalNum = 8000

def main():
dir = "../app/proguardbuild"
createProRules(dir+'/pro_package.txt')
createProRules(dir+'/pro_class.txt')
createProRules(dir+'/pro_func.txt')

def createProRules(fileName):
dirName = os.path.dirname(fileName)
if not os.path.exists(dirName):
os.mkdir(dirName)
'''
生成totalNum個隨機不重復(fù)的字符串
:return:
'''
new_list = []
while 1:
value = ''.join(random.sample(string.ascii_letters +
string.digits, random.randint(1, 8))) //生成1~8位數(shù)隨機字符串
if value not in new_list:
new_list.append(value)
if len(new_list) == totalNum:
break
else:
continue
result = '\n'.join(new_list)
file = open(fileName, 'w', encoding='UTF-8')
file.write(result)
file.close()

if name == 'main':
main()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
使用Python腳本生成混淆字典后谅将,打包效果如下:

至此,你再也不用效率低下的去改代碼重慢,也不用生成一堆垃圾代碼讓“強迫癥”難受饥臂。

混淆模板
我的混淆模板,僅供參考~

------------------------------基本指令區(qū)---------------------------------

-optimizationpasses 5 #指定壓縮級別
-optimizations !code/simplification/arithmetic,!field/,!class/merging/ #混淆時采用的算法
-verbose #打印混淆的詳細信息
-dontoptimize #關(guān)閉優(yōu)化
-keepattributes Annotation #保留注解中的參數(shù)
-keepattributes Annotation,InnerClasses # 保持注解
-keepattributes Signature # 避免混淆泛型, 這在JSON實體映射時非常重要
-ignorewarnings # 屏蔽警告
-keepattributes SourceFile,LineNumberTable # 拋出異常時保留代碼行號

混淆時不使用大小寫混合似踱,混淆后的類名為小寫(大小寫混淆容易導(dǎo)致class文件相互覆蓋)

-dontusemixedcaseclassnames

未混淆的類和成員

-printseeds proguardbuild/print_seeds.txt

列出從 apk 中刪除的代碼

-printusage proguardbuild/print_unused.txt

混淆前后的映射隅熙,生成映射文件

-printmapping proguardbuild/print_mapping.txt

指定一個文本文件,其中所有有效字詞都用作混淆字段和方法名稱核芽。

默認(rèn)情況下囚戚,諸如“a”,“b”等短名稱用作混淆名稱轧简。

使用模糊字典驰坊,您可以指定保留關(guān)鍵字的列表,或具有外來字符的標(biāo)識符吉懊,

例如: 忽略空格庐橙,標(biāo)點符號,重復(fù)字和#符號后的注釋借嗽。

注意态鳖,模糊字典幾乎不改善混淆。 有些編譯器可以自動替換它們恶导,并且通過使用更簡單的名稱再次混淆浆竭,可以很簡單地撤消該效果。

最有用的是指定類文件中通常已經(jīng)存在的字符串(例如'Code')惨寿,從而減少類文件的大小邦泄。 僅適用于混淆處理。

-obfuscationdictionary proguardbuild/pro_package.txt

指定一個文本文件裂垦,其中所有有效詞都用作混淆類名顺囊。 與-obfuscationdictionary類似。 僅適用于混淆處理蕉拢。

-classobfuscationdictionary proguardbuild/pro_class.txt

指定一個文本文件特碳,其中所有有效詞都用作混淆包名稱诚亚。與-obfuscationdictionary類似。 僅適用于混淆處理午乓。

-packageobfuscationdictionary proguardbuild/pro_func.txt

-------------------------------基本指令區(qū)--------------------------------

---------------------------------默認(rèn)保留區(qū)---------------------------------

繼承activity,application,service,broadcastReceiver,contentprovider....不進行混淆

-keep public class * extends android.app.Activity
-keep public class * extends androidx.fragment.app.Fragment
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class * extends android.view.View
-keep class android.support.** {*;}

androidx 混淆

-keep class com.google.android.material.** {;}
-keep class androidx.
* {;}
-keep public class * extends androidx.
*
-keep interface androidx.** {;}
-keep class * implements androidx.
* {
;
}
-dontwarn com.google.android.material.
*
-dontnote com.google.android.material.**
-dontwarn androidx.**
-printconfiguration
-keep,allowobfuscation interface androidx.annotation.Keep
-keep @androidx.annotation.Keep class *
-keepclassmembers class * {
@androidx.annotation.Keep *;
}

不混淆View中的set() 和 get()方法 以保證屬性動畫正常工作 某個類中的某個方法不混淆

自定義View的set get方法 和 構(gòu)造方法不混淆

-keep public class * extends android.view.View{
*** get();
void set
(***);
public <init>(android.content.Context);
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
}

這個主要是在layout 中寫的onclick方法android:onclick="onClick"站宗,不進行混淆

-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}

保持 Serializable 不被混淆

-keepnames class * implements java.io.Serializable

實現(xiàn)Serializable接口的類重寫父類方法保留

-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}

保留R文件中所有靜態(tài)字段,以保證正確找到每個資源的ID

-keepclassmembers class *.R$ {
public static <fields>;
}

-keepclassmembers class * {
void (Event);
}

保留枚舉類中的values和valueOf方法

-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}

保留Parcelable實現(xiàn)類中的Creator字段益愈,以保證Parcelable機制正常工作

-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}

保持 Parcelable 不被混淆

-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}

不混淆包含native方法的類的類名以及native方法名

-keepclasseswithmembernames class * {
native<methods>;
}

避免log打印輸出

-assumenosideeffects class android.util.Log {
public static *** v(...);
public static *** d(...);
public static *** i(...);
public static *** w(...);
}

對含有反射類的處理

--------------------------------默認(rèn)保留區(qū)--------------------------------------------

----------------------------- WebView(項目中沒有可以忽略) -----------------------------

webView需要進行特殊處理

WebView

-dontwarn android.webkit.WebView
-dontwarn android.net.http.SslError
-dontwarn android.webkit.WebViewClient
-keep public class android.webkit.WebView
-keep public class android.net.http.SslError
-keep public class android.webkit.WebViewClient

在app中與HTML5的JavaScript的交互進行特殊處理

我們需要確保這些js要調(diào)用的原生方法不能夠被混淆梢灭,于是我們需要做如下處理:

-keepclassmembers class com.deepocean.tplh5.helper.JsInterfaceHelper {
<methods>;
}

----------------------------- WebView(項目中沒有可以忽略) -----------------------------

----------------------------- 實體類不可混淆 ------------------------------------------

添加實體類混淆規(guī)則

Application classes that will be serialized/deserialized over Gson

-keep class .entity. { *; }
-keep class .bean. { *; }

----------------------------- 實體類不可混淆 ------------------------------------------

----------------------------- 第三方類庫 ------------------------------------------

添加第三方類庫的混淆規(guī)則

Adjust sdk

-keep class com.adjust.sdk.*{ ; }
-keep class com.google.android.gms.common.ConnectionResult {
int SUCCESS;
}
-keep class com.google.android.gms.ads.identifier.AdvertisingIdClient {
com.google.android.gms.ads.identifier.AdvertisingIdClientInfo getAdvertisingIdInfo(android.content.Context); } -keep class com.google.android.gms.ads.identifier.AdvertisingIdClientInfo {
java.lang.String getId();
boolean isLimitAdTrackingEnabled();
}
-keep public class com.android.installreferrer.
{ *; }

OkHttp3 去掉缺失類警告

-dontwarn org.bouncycastle.**
-dontwarn org.conscrypt.**
-dontwarn org.openjsse.javax.net.ssl.**
-dontwarn org.openjsse.net.ssl.**

----------------------------- 第三方類庫 ------------------------------------------

————————————————
版權(quán)聲明:本文為CSDN博主「DeMonnnnnn」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議蒸其,轉(zhuǎn)載請附上原文出處鏈接及本聲明敏释。
原文鏈接:https://blog.csdn.net/DeMonliuhui/article/details/128295336


混淆語法主要用于定義不需要混淆的代碼。
1.
-keep class com.example.MyClass {
    public void myMethod1();
    public void myMethod2();
}
上述規(guī)則會保留 com.example.MyClass 類的類名和 myMethod1() 和 myMethod2() 方法不被混淆枣接。

2.
  -keep class com.thc.test.*
一顆星表示只是保持該包下的類名颂暇,而子包下的類名還是會被混淆;

3.
  -keep class com.thc.test.**
兩顆星表示把本包和所含子包下的類名都保持但惶;

4.
 -keep class com.thc.test.*{*;}
既可以保持該包下的類名耳鸯,又可以保持類里面的內(nèi)容不被混淆;

5.
  -keep class com.thc.test.**{*;}
既可以保持該包及子包下的類名,又可以保持類里面的內(nèi)容不被混淆;

6.
  -keep class com.thc.gradlestudy.MyProguardBean{
      <init>; #匹配所有構(gòu)造器
      <fields>;#匹配所有域
      <methods>;#匹配所有方法
  }
保持類中特定內(nèi)容膀曾,而不是所有的內(nèi)容

7.
-keep class com.xlpay.sqlite.cache.ProguardTest$MyClass{*;}
要保留一個類中的內(nèi)部類不被混淆需要用 $ 符號

8.
  -keep public class * extends android.app.Activity
  -keep public class * extends android.app.Application
  -keep public class * extends android.app.Service
  -keep public class * extends android.content.BroadcastReceiver
  -keep public class * extends android.content.ContentProvider
  -keep public class * extends android.view.View
使用Java的基本規(guī)則來保護特定類不被混淆县爬,比如用extends,implement等這些Java規(guī)則添谊,如下:保持Android底層組件和類不要混淆

9.
  #保持ProguardTest類下test(String)方法不被混淆
  -keepclassmembernames class com.xlpay.sqlite.cache.ProguardTest{
      public void test(java.lang.String);
  }
 如果不需要保持類名财喳,只需要保持該類下的特定方法保持不被混淆,需要使用keepclassmembers斩狱,而不是keep耳高,因為keep方法會保持類名。

10.
  #保持native方法不被混淆
  -keepclasseswithmembernames class * {    
      native <methods>; 
  }
jni方法不可混淆所踊,因為native方法是要完整的包名類名方法名來定義的泌枪,不能修改,否則找不到秕岛;

11.
  -keep class * implements Android.os.Parcelable { 
      # 保持Parcelable不被混淆            
      public static final Android.os.Parcelable$Creator *;
  }
Parcelable的子類和Creator靜態(tài)成員變量不混淆碌燕,否則會產(chǎn)生Android.os.BadParcelableException異常

12.
  -keepclassmembers enum * {  
      public static **[] values();  
      public static ** valueOf(java.lang.String);  
  }
使用enum類型時需要注意避免以下兩個方法混淆,因為enum類的特殊性继薛,以下兩個方法會被反射調(diào)用修壕,見第二條規(guī)則
http://www.reibang.com/p/546733072d8d

其他常用混淆設(shè)置
通用設(shè)置
# 指定代碼的壓縮級別 0 - 7(指定代碼進行迭代優(yōu)化的次數(shù),在Android里面默認(rèn)是5遏考,這條指令也只有在可以優(yōu)化時起作用慈鸠。)
-optimizationpasses 5
# 混淆時不會產(chǎn)生形形色色的類名(混淆時不使用大小寫混合類名)
-dontusemixedcaseclassnames
# 指定不去忽略非公共的庫類(不跳過library中的非public的類)
-dontskipnonpubliclibraryclasses
# 指定不去忽略包可見的庫類的成員
-dontskipnonpubliclibraryclassmembers
#不進行優(yōu)化,建議使用此選項灌具,
-dontoptimize 
# 不進行預(yù)校驗,Android不需要,可加快混淆速度青团。
-dontpreverify
# 拋出異常時保留代碼行號
-keepattributes SourceFile,LineNumberTable
#打印混淆的詳細信息
-verbose






最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末像棘,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子壶冒,更是在濱河造成了極大的恐慌,老刑警劉巖截歉,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件胖腾,死亡現(xiàn)場離奇詭異,居然都是意外死亡瘪松,警方通過查閱死者的電腦和手機咸作,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來宵睦,“玉大人记罚,你說我怎么就攤上這事】呛浚” “怎么了桐智?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長烟馅。 經(jīng)常有香客問我说庭,道長,這世上最難降的妖魔是什么郑趁? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任刊驴,我火速辦了婚禮,結(jié)果婚禮上寡润,老公的妹妹穿的比我還像新娘捆憎。我一直安慰自己,他們只是感情好梭纹,可當(dāng)我...
    茶點故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布躲惰。 她就那樣靜靜地躺著,像睡著了一般栗柒。 火紅的嫁衣襯著肌膚如雪礁扮。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天瞬沦,我揣著相機與錄音太伊,去河邊找鬼。 笑死逛钻,一個胖子當(dāng)著我的面吹牛僚焦,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播曙痘,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼芳悲,長吁一口氣:“原來是場噩夢啊……” “哼立肘!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起名扛,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤谅年,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后肮韧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體融蹂,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年弄企,在試婚紗的時候發(fā)現(xiàn)自己被綠了超燃。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡拘领,死狀恐怖意乓,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情约素,我是刑警寧澤届良,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站业汰,受9級特大地震影響伙窃,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜样漆,卻給世界環(huán)境...
    茶點故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一为障、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧放祟,春花似錦鳍怨、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至眉撵,卻和暖如春侦香,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背纽疟。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工罐韩, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人污朽。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓奈附,卻偏偏與公主長得像每庆,于是被迫代替她去往敵國和親稠诲。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,077評論 2 355

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