尽可能详细的文件上传讲解

文章目录

  • 尽可能详细的文件上传讲解
  • 0x01 upload-labs master的安装
  • 0x02 前端JavaScript检测
  • 0x03 检测文件类型
  • 0x04 根据文件头检测文件类型
    • 根据文件内容类型
  • 0x04 检测文件名进行过滤
    • 黑名单绕过
    • 大小写绕过
    • 白名单绕过
    • 空字符绕过
    • deldot()绕过
    • 流特性绕过
    • 双写绕过
  • 0x05 检测文件内容进行过滤
    • 二次渲染绕过
    • upload其他优秀题目
  • 06 文件上传的危害
    • 文件上传绕waf

大部分看到这篇文章的人应该都明白什么是文件上传,文件上传是攻击非常常见的方式,网上也有非常多的优秀文章,不过还是想自己整理+归纳+总结+讲解一篇关于文件上传的文章
这里借助一个靶场总结了一下常见的文件上传漏洞类型,在平时的业务、实战或CTF中可能会遇到这个漏洞,在做靶场时应该抱着学习此类型及其相关技术为目的,不要单纯拿结果

因为lmn有做过几遍upload-labs master靶场的题目,而且靶场囊括的类型也比较全面,这里也就结合了靶场的题目

0x01 upload-labs master的安装

“upload-labs master”这个靶场在接触文件上传的人应该都听过,lmn也做了几遍整理过笔记,毕竟网上教程这么多这里就简单总结一下

下面借助了很多靶场中的题目,可以自行安装

下载地址:https://github.com/c0ny1/upload-labs

运行环境:
操作系统:windows、Linux
php版本:大部分都是推荐 5.2.17版本

别忘了新建一个upload

配置好就可以开始了!

0x02 前端JavaScript检测

这道题Pass-01就是利用前端校验,也属于客户端校验,经常碰到前端使用JS代码检测被上传文件的上传类型和文件大小,只有前端教研安全性很低,可以通过禁用JS来绕过

上传入口看到一个 onsubmit 参数,onsubmit是在表单提交之前调用,在我们点击提交之后,就会调用这个事件句柄函数,也就是 checkFile()

确定为js绕过代码

推荐一个很好用的禁止js的插件,叫NoScript,可以方便打开或禁止js

还有一种方法就是直接删掉checkFile()函数

0x03 检测文件类型

文件上传中文件类型的检测也比较常见比较好绕过,例如这么一段代码
$_FILES[‘upload_file’][‘type’] == ‘image/jpeg’
意思是判断文件类型是否等于image/jpeg,是的话提交成功,不是则通知用户提交失败

这里可以拓展一下php的$_FILES系统函数用法
$_FILES[‘myFile’][‘name’] 表示文件的名称
$_FILES[‘myFile’][‘type’] 表示文件的 MIME 类型
$_FILES[‘myFile’][‘size’] 已上传文件的大小(单位:字节)
$_FILES[‘myFile’][‘tmp_name’] 储存的临时文件名,一般是系统默认
$_FILES[‘myFile’][‘error’] 该文件上传相关的错误代码,PHP4.2版本后增加的

例如Pass-02(MIME 类型验证)这道题,尝试通过burp拦截包对Content-Type进行修改

MIME全名叫多用途互联网邮件扩展(Multipurpose Internet MailExtensions),现在被应用到多种协议里,MIME的常见形式是一个主类型加一个子类型,用斜线分隔
百科给出的比较全面的类型:
超文本标记语言文本 .html text/html
xml文档 .xml text/xml
XHTML文档 .xhtml application/xhtml+xml
普通文本 .txt text/plain
RTF文本 .rtf application/rtf
PDF文档 .pdf application/pdf
Microsoft Word文件 .word application/msword
PNG图像 .png image/png
GIF图形 .gif image/gif
JPEG图形 .jpeg,.jpg image/jpeg

Content-Type(内容类型):用于定义网络文件的类型和网页的编码,决定浏览器将以什么形式、什么编码读取这个文件

查看题目给出的源码进行分析,我添加上了一些注释,会的可以忽略,不会的可以参考

$is_upload = false;
$msg = null;
// isset()函数用于检测变量是否已设置并且非NULL
if (isset($_POST['submit'])) {// file_exists() 函数检查文件或目录是否存在// $UPLOAD_ADDR 为上传到哪个地址if (file_exists($UPLOAD_ADDR)) {// 必须满足 upload_file 的类型为'image/jpeg'或'image/png'或'image/gif'if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) {// move_uploaded_file() 函数将上传的文件移动到新位置if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {$img_path = $UPLOAD_ADDR . $_FILES['upload_file']['name'];$is_upload = true;}} else {$msg = '文件类型不正确,请重新上传!';}} else {$msg = $UPLOAD_ADDR.'文件夹不存在,请手工创建!';}
}

0x04 根据文件头检测文件类型

根据文件内容类型

与上一个类似,检查文件的类型,但这个是通过检查文件的内容,根据文件的内容判断文件类型,这里就不能直接burp抓包修改Content-Type了

upload-labs master中有几道关于此类型的题,我们先看 Pass-14(图片马字节)这道题

首先看一下题目给出的判断文件类型的源码:

function getReailFileType($filename){// 为移植性考虑,强烈建议在用 fopen() 打开文件时总是使用 'b' 标记。$file = fopen($filename, "rb");// 只读2字节,fread单位为字节$bin = fread($file, 2); fclose($file);// unpack() 函数从二进制字符串对数据进行解包// 前面的参数表示在解包数据时所使用的格式$strInfo = @unpack("C2chars", $bin);// intval() 函数用于获取变量的整数值$typeCode = intval($strInfo['chars1'].$strInfo['chars2']);    $fileType = '';    switch($typeCode){      case 255216:            $fileType = 'jpg';break;case 13780:            $fileType = 'png';break;        case 7173:            $fileType = 'gif';break;default:            $fileType = 'unknown';}    return $fileType;
}

其中最关键的读取代码为

$bin = fread($file, 2); //只读2字节fclose($file);

根据源码知道只对文件的头2个字节做检测
这里就需要制作木马图片,然后上传即可。
copy 1.jpg /b + 1l.php /a 1.jpg

/be为二进制,表示以二进制格式合并1.jpg和1l.php

也可以用winhex、010editor等工具在图片添加上图片的文件头

而Pass-15(图片马getimagesize)这题添加了getimagesize()函数,getimagesize()对目标文件的16进制去进行一个读取,可以伪造假图片,上传同14

Pass-16(图片马php_exif)

$image_type = exif_imagetype($filename);

exif_imagetype()函数是PHP中的内置函数,用于确定图像的类型(读取一个图像的第一个字节并检查其签名。如果发现了恰当的签名则返回一个对应的常量,否则返回 FALSE。)
上传同14

常见的头部对应关系比如(可以多总结一下)
.JPEG;.JPE;.JPG,”JPGGraphic File”
.gif,”GIF 89A”
.zip,”Zip Compressed”
.doc;.xls;.xlt;.ppt;.apr,”MS Compound Document v1 or Lotus Approach APRfile”

0x04 检测文件名进行过滤

黑名单绕过

黑名单校验就很不安全,很多网站会采用黑名单过滤的方法,但是又很容易就被绕过,例如用一些常见的扩展名就可以轻而易举绕过。

例如Pass-03(黑名单验证)这道题,首先分析源码

$is_upload = false;
$msg = null;
// isset() 用于检测变量是否已设置并且非NULL
// 判断是否存在通过POST方式提交过来的变量
if (isset($_POST['submit'])) {// file_exists() 检查文件或目录是否存在if (file_exists($UPLOAD_ADDR)) {$deny_ext = array('.asp','.aspx','.php','.jsp');// trim() 函数移除字符串两侧的空白字符或其他预定义字符// 空格、制表符 tab、换行符等等$file_name = trim($_FILES['upload_file']['name']);// 删除文件名末尾的点$file_name = deldot($file_name);// 搜索 "." 在字符串中的位置并返回从该位置到字符串结尾的所有字符$file_ext = strrchr($file_name, '.');// 转换为小写$file_ext = strtolower($file_ext); // 去除字符串::$DATA$file_ext = str_ireplace('::$DATA', '', $file_ext);// 收尾去空$file_ext = trim($file_ext);

该代码是对上传后的文件后缀进行检测,我们可以上传不在黑名单的文件后缀,.php3可以被解析成.php,前提是Apache的httpd.conf中配置有如下代码:
AddType application/x-httpd-php .php .php3 .phtml

常见的可执行文件的后缀:
PHP: php2、php3、php5、phtml、pht
ASP: aspx、ascx、ashx、cer、asa
JSP: jspx

换后缀名上传成功

当然,针对这道题有一种非常巧妙的解题方法,也适用于一些其他道题,仔细分析中间那段代码
上传XXX.php. .
先将文件名最后的点删掉,再通过 strrchr() 函数返回最右边“.”的后面饿字符

strrchr() 函数查找字符串在另一个字符串中最后一次出现的位置,并返回从该位置到字符串结尾的所有字符
这样上传的文件名就为 XXX.php. 因为在存储时会默认删掉这个点,也就可以上传成功

这里有个Tips:Apache的解析顺序是从右到左开始解析文件后缀的,如果最右侧扩展名不可识别,就继续往左判断。直到遇到可以解析的文件后缀为止

利用上面的方法可以解一下这道题:Pass-05

$deny_ext = array(".php",".php5",".php4",...".htaccess");
$file_name = trim($_FILES['upload_file']['name']);
$file_name = deldot($file_name);//删除文件名末尾的点
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //转换为小写
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //首尾去空

XXX.php. .
相同原理,听说为新加题目,查看几年前笔记确实没有此题

大小写绕过

根据Pass-06(大小写过滤)这个题,我们清楚看到是函数并没有对大小写进行检查,即使是列了黑名单,也会因为这个问题而绕过

直接分析源码

// 缩写为减少文章篇幅,实际看 Pass-04
$deny_ext = array(".php",".php5",".php4",...".htaccess");
$file_name = trim($_FILES['upload_file']['name']);
$file_name = deldot($file_name);//删除文件名末尾的点
$file_ext = strrchr($file_name, '.');
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //首尾去空

通过分析 Pass-04 我们一定记着但是当时有一句
f i l e e x t = s t r t o l o w e r ( file_ext = strtolower( filee​xt=strtolower(file_ext); //转换为小写
既然不再转换大小写,那就直接大小写绕过

白名单绕过

白名单绕过虽然相比于黑名单更加安全,但是还是会存在其他问题,在upload-labs master中,给出一个%00截断与0x00阶段的题目

Pass-12(%00截断)

$ext_arr = array('jpg','png','gif');
// substr — 返回字符串的子串
// strrpos - 查找在字符串中最后一次出现的位置
$file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);if(in_array($file_ext,$ext_arr)){$temp_file = $_FILES['upload_file']['tmp_name'];$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;

当网站上传XXX.php%00.jpg时,通过白名单绕过,保存文件时,遇到%00字符就会截断后面的.jpg,文件最终保存为XXX.php

Pass-13(0x00截断)
查看源代码发现 此题在上题将GET换为POST,利用Pass-11的方法 ,但在url解码中%00不会被解析,但是我们可以使用0x00进行截断

空字符绕过

参考:Pass-07
分析源码

$deny_ext = array(".php",".php5",".php4",...".htaccess");
$file_name = $_FILES['upload_file']['name'];
$file_name = deldot($file_name);//删除文件名末尾的点
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //转换为小写
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA

先删掉最后的“.”,再返回“.”后面的字符,之后是大小写处理,直接上传“.php ”(php后面有个空格)即可绕过

deldot()绕过

参考:Pass-08(deldot())
分析源码

$deny_ext = array(".php",".php5",".php4",...".htaccess");
$file_name = trim($_FILES['upload_file']['name']);
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //转换为小写
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //首尾去空

先去空,然后返回“.”后面的字符,之后转换大小写,这里也有一个逻辑错误,直接返回最后一个点之后的消息,那直接后缀名改为“.php.”即可绕过

流特性绕过

参考:Pass-09
还是分析源码

$deny_ext = array(".php",".php5",".php4",...".htaccess");
$file_name = trim($_FILES['upload_file']['name']);
$file_name = deldot($file_name);//删除文件名末尾的点
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //转换为小写
$file_ext = trim($file_ext); //首尾去空

这次没有这一句

$file_ext = str_ireplace('::$DATA', '', $file_ext);
//去除字符串::$DATA

这个关于windows下文件的流特性
:: D A T A 会 把 之 后 的 数 据 当 成 文 件 流 处 理 , 不 会 检 测 后 缀 名 , 保 持 “ : : DATA 会把 之后的数据当成文件流处理,不会检测后缀名,保持“:: DATA会把之后的数据当成文件流处理,不会检测后缀名,保持“::DATA”之前的文件名

双写绕过

参考:Pass-11

$file_name = trim($_FILES['upload_file']['name']);
$file_name = str_ireplace($deny_ext,"", $file_name);
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH.'/'.$file_name;

str_ireplace() 函数替换字符串中的一些字符(不区分大小写)
既然替换一次,可采用双写绕过
XXX.pphphp

注意⚠️:XXX.phphpp这样就是不行的,因为他会去掉从前面来说的第一个php,去掉后会成为XXX.hpp

除这些之外upload labs还有一道Pass-10(过滤)
直接分析源码

$deny_ext = array(".php",".php5",".php4",...".htaccess");
$file_name = trim($_FILES['upload_file']['name']);
$file_name = deldot($file_name);//删除文件名末尾的点
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //转换为小写
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //首尾去空

采用抓包添加后缀 .php. .

0x05 检测文件内容进行过滤

例如 Pass-04这道题,这道题除了可以采用 Pass-03 中的一种读源码的方法,更主要的是学习使用 .htaccess文件
分析源码,是在基础上添加了更多的后缀过滤

$file_name = trim($_FILES['upload_file']['name']);
$file_name = deldot($file_name);//删除文件名末尾的点
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //转换为小写
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //收尾去空

htaccess文件能够更改服务器的设置,全称为Hypertext Access,称为超文本入口,提供了针对目录改变配置的方法,可在一个特定的文档目录中放置一个包含一个或多个指令的文件。
如果想详看可以参考或自行搜索:https://www.cnblogs.com/adforce/archive/2012/11/23/2784664.html

对于这道题,我们可以上传一个.htaccess 文件重写服务器的文件解析

开启htaccess的方法:
打开apache的httpd.conf设置文件
查找到的AllowOverride None,将其改为AllowOverride All

创建一个.htaccess文件
内容写成:
AddType application/x-httpd-php .jpg,可将jpg文件解析为php文件
SetHandler application/x-httpd-php,可将其他所有文件解析为php文件

之后上传文件就可以了

二次渲染绕过

二次渲染指的是提取了文件中的图片数据,然后再对图片重新渲染,这样加在其中的恶意代码就不见了
例如Pass-17(二次渲染绕过)这个题
采用的二次渲染技术,就是根据用户上传的图片,新生成一个图片,将原始图片删除,将新图片添加到数据库中。

关于这道题,lmn写多少都不如这篇文章详细,所以干脆不写了,可以参考参考
https://xz.aliyun.com/t/2657#toc-13

处这两个以外也可以学习一下文件包含漏洞,例如,如果网站对jsp,php等文件内容进行校验,可以通过上传(无限制)的文件例如.txt文件,并通过例如php语句<?php Include(“上传的txt文件路径”);?>进行文件包含,从而达到目的
常见的文件包含例如:
include()
require()
include_once()
require_once()
include(),只生成警告(E_WARNING),并且脚本会继续
require(),会生成致命错误(E_COMPILE_ERROR)并停止脚本
include_once()与require_once(),如果文件已包含,则不会包含,其他特性如上

upload其他优秀题目

Pass-18 19(条件竞争)
竞争条件:多个线程或者进程在读写一个共享数据时结果依赖于它们执行的相对时间的情形
先将文件上传到服务器,然后判断文件后缀是否在白名单里,如果在则重命名,否则删除
这里的原理就是上传info.php,边上传边访问,保证在上传之前访问到,利用burp的intruder模块不断上传

这里需要借助一段代码

<?php fputs(fopen('info.php','w'),'<?php phpinfo();?>');?>

因为在没有文件时,w写参数会自动创建文件,并将后面的字放到前面的文件中,所以用burp的intruder连续访问,因为是多个进程或者线程在读写数据,其最终的的结果依赖于多个进程的指令执行顺序,也就是可能在被删除前访问到文件

Pass-20(/.绕过)
查看源码

save_name为页面上我们提交的文件名,因此抓包修改为upload-19.php/.
upload-19是因为上传处默认文件名就是这个

06 文件上传的危害

文件上传漏洞很容易带来严重的安全问题,可以利用文件上传漏洞上传Webshell

webshell,web指的是在web服务器上,shell是用脚本语言编写的脚本程序,通常黑会自己编写webshell,并上传到目标web服务器的页面的目录下,然后通过目标系统进行入侵

根据不同的分类可以分为很多类,比如根据功能可以分为大马和小马,小马通常指一句话木马,例如将<%eval request(“pass”)%>这句话写入一个后缀为.asp的文件中,然后传到服务器上面。eval方法将request(“pass”)转换成代码执行,request函数的作用是应用外部文件。
根据脚本的类型可以分为jsp、asp、aspx、php等

现在对于不同的web服务器系统对应的有不同的web服务端程序,windows端主流的有iis,linux端主流的有Nginx。这些服务对服务器会带来一些隐患,这些服务器上都存在一些漏洞,很容易被黑客利用

利用上面提到的文件上传绕过方法,可以将恶意文件传入服务器中

文件上传绕waf

通过绕过waf达到防止恶意文件被拦截的效果,这里给出几种大家屡试不爽的方法

  1. 有时候可以通过之前给出的替换不常见的但可达到相同解析效果的文件名
  2. 制造一些“垃圾数据”,可以降低waf的检测
  3. 例如早期的安全狗就可以通过多加几个filename绕过
  4. (看到有人说有些waf会检测是否为POST,如果为POST则会校验数据包内容,这里更改POST为GET)
  5. 删除Conten-Type字段
  6. 删除Content-Disposition字段里的空格
  7. 修改Content-Disposition字段值的大小写
  8. (文件名处回车)

参考文章:
https://blog.csdn.net/skynet_x/article/details/109285482?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2aggregatepagefirst_rank_ecpm_v1~rank_v31_ecpm-10-109285482.pc_agg_new_rank&utm_term=upload-labs-master&spm=1000.2123.3001.4430
https://blog.csdn.net/qq_42357070/article/details/82881393?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164543284216780255288719%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=164543284216780255288719&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2alltop_positive~default-1-82881393.pc_search_insert_ulrmf&utm_term=webshell&spm=1018.2226.3001.4187
https://blog.csdn.net/qq_42181428/article/details/87090539

尽可能详细的文件上传讲解相关推荐

  1. 超详细的文件上传和下载(Spring Boot)

    超详细的文件上传和下载 前言Ⅰ:@RequestParam和@RequestPart的区别 @RequestPart @RequestPart这个注解用在multipart/form-data表单提交 ...

  2. layui多文件上传讲解_Laravel 使用 layui 文件上传组件批量上传图片

    摘要 Laravel 使用 layui 文件上传组件批量上传图片. layui是一款经典国产模块化前端UI框架,首先看看官方的介绍: layui(谐音:类UI) 是一款采用自身模块规范编写的前端 UI ...

  3. layui多文件上传讲解_Layui 多文件上传 SSH

    jsp 页面 pageEncoding="UTF-8"%> Insert title here 选择多文件 文件名大小状态操作 开始上传 layui.use('upload' ...

  4. layui多文件上传讲解_layui d多文件上传(示例代码)

    借阅 前端代码 选择多文件 图片大小状态操作 不计在线 删除 开始上传 JS 代码 layui.use('upload', function(){ var upload = layui.upload; ...

  5. 使用WinHttp接口实现HTTP协议Get、Post和文件上传功能

    我实现了一个最新版本的接口,详见<实现HTTP协议Get.Post和文件上传功能--使用WinHttp接口实现>.还有基于libcurl实现的版本<实现HTTP协议Get.Post和 ...

  6. [网络安全自学篇] 八十一.WHUCTF之WEB类解题思路WP(文件上传漏洞、冰蝎蚁剑、反序列化phar)

    这是作者网络安全自学教程系列,主要是关于安全工具和实践操作的在线笔记,特分享出来与博友们学习,希望您喜欢,一起进步.前文分享了WHUCTF部分题目,包括代码审计.文件包含.过滤绕过.SQL注入.这篇文 ...

  7. php 函数封装上传,PHP(多)文件上传实现和函数封装

    一.PHP 文件上传的相关知识 对 PHP 文件上传的相关知识总结主要是参考老师演示的代码和 drawer.php(某大神写的 PHP 单文件版的服务器文件管理端) 1. php 关于文件上传的配置文 ...

  8. 文件上传下载注意事项

    目录 一.文件上传注意事项 二.文件下载注意事项(我这里只单文件下载) 三.友情链接 四.最后非常感谢网上的原意分享的人儿^_^ 一.文件上传注意事项 文件格式是否符合要求 文件名称是否有特殊符号,比 ...

  9. 实例讲解ThinkPHP的UploadFile文件上传类的详细用法

    ThinkPHP文件上传自带了上传类,使用起来非常方便,我们将以一个文件上传实例来讲解ThinkPHP上传类的实际用法,上传类使用时有详细的中文注释,可以非常方便的告诉你类的一些方法或变量的使用方法. ...

最新文章

  1. 30年间,软件开发行业为何Bug纷飞?
  2. Altium Protel PCB Layer
  3. 改改Python代码,运行速度还能提升6万倍
  4. win32开发(添加菜单)
  5. Linux操作命令(二)
  6. 中文文本纠错工具推荐:pycorrector
  7. Ubuntu类似与xshell 和crt的软件 pac- Ásbrú Connection Manager
  8. Go基础:延迟调用defer、异常处理
  9. Linux 简单的聊天室
  10. 优秀logo设计解析_国外30个优秀的logo的设计思维分析
  11. Tangle:不同于区块链的分布式账本
  12. 3大奇葩排序之猴子算法
  13. 用NDK交叉编译pixman-0.34
  14. 性能调优(一)----Amdahl定律及木桶原理
  15. 【SpringMVC】拦截器和过滤器
  16. Drools 7 用OOPath遍历嵌套类型的实体对象
  17. 微服务架构设计实践系列之五:架构准备阶段
  18. 域渗透基础之NTLM认证协议
  19. windows7 图形界面远程 centos6.5
  20. 【水声自适应通信】基于OFDM的水声自适应调制通信系统性能matlab仿真

热门文章

  1. 层出不穷的终端设备适配需求下 未来的响应式Web设计长什么样?
  2. 太陽花的伤感空间日志分享:最后哭的人,还是自己
  3. 计算机的图标怎么会恢复,桌面图标变成未知图标了怎么恢复?
  4. RevitAPI: Revit 2016新功能和API介绍视频
  5. shell中source命令与sh命令的区别
  6. 【苹果推信】苹果推imessage群发开发真实机器调试的测试证书
  7. 智能电销机器人解决了传统电销行业哪些问题?
  8. php重定向页面的三种方式
  9. 微信公众号开发系统入门教程(公众号注册、开发环境搭建、access_token管理、Demo实现、natapp外网穿透)
  10. iOS开发——网络请求数据处理