0%

防范措施

  • 设计安全的验证码(安全的流程+复杂又可用的图形)
  • 对认证错误的提交进行计数并给出限制,比如连续多次错误,锁定IP或者账号
  • 必要的情况下,使用双因素认证

    token在防范爆破的意义

一个简单的token实例

图片

一般的做法:

  1. 将token以’type=’hidden’的形式输出在表单中
  2. 在提交的认证的时候一起提交,并在后台对其校验

但,****由于token输出在了前端源码,容易被获取,因此并不能防止爆破。一般token防止csrf上会好很多

环境:老三样

演示:

查看F12能找到隐藏的token

图片

token是由于页面被打开的同时,后端收到请求后会生成一个token放到session里并输出到表单里,目的是当你输入用户名和密码时,会连同用户名和密码以及token一起进行验证(每次刷新页面都会刷新token

源码分析:

图片

先判断是否提交用户名和密码,再去判断token是否和session中的一致,如果通过才会去验证用户名和密码

图片

每次的token就是由set_token函数生成的,查看函数内容

图片

先判断token是否存在,如果存在便销毁,然后再去生成一个新的token,然后从指定的范围里生成一个随机数再赋值给session中

图片

然后就可以就从后端输出到前端,这样就实现了每次提交用户名密码还验证token

但!这样并不能防止暴力破解,因为已经把token值放在前端代码供我们随意使用了

我们只需要每次都写一个脚本获取token的值,再进行暴力破解就行

over.

不安全的验证码-on server常见问题

  • 验证码在后台不过期,导致可以长期使用
  • 验证码校验不严格,逻辑出现问题
  • 验证码设计的太过简单和有规律,容易被猜解
    (12306验证码yyds)

环境:老三样

演示:

进入环境,随意输入用户名和密码,正确输入验证码

图片

提示用户名或者密码不存在,抓包查看

图片

这里首先尝试不提交验证码的情况

图片

提示不能为空,接着尝试随意输入验证码(不按照环境提供的)

图片

提示验证码错误,可以发现这里后端对验证码进行了验证,接着验证验证码是否存在过期问题

按照环境所给验证码输入

图片

提示用户名或密码不存在,这次更改一下随意填的用户名和密码

图片

仍然是提示不存在,说明验证码是有效重复利用的(至少是在一段时间内有效)

接下来就可以按照之前暴力破解的套路,对用户名和密码进行爆破

PS:环境已提示正确的用户名和密码图片

建议把这几个加入字典,跑一跑效果即可,不用全跑浪费时间

源码分析:

在前端能发现生成验证码的文件图片

每次点击就可以刷新一个验证码,或者刷新页面也可

图片

这里文件源码对用户名多个元素进行判断是否为空,如果都不为空会首先去鉴别前端输入的验证码是否与后端session的一致,一致才会去验证用户名和密码,那么问题出在哪里?

查看文件可知问题在session这里,在PHP中如果不对session进行相应的销毁配置,默认的存在时间是1440s,也就是24分钟之内都是可以用的,这里并没有对销毁进行配置,所以我们才可以进行重复利用

正确来说

图片

验证码在这里验证结束后就应该进行销毁,而不是随着默认时间销毁

over.

  • 爆破之不安全的验证码分析

–on client

–on server

验证码:

  1. 防止暴力破解
  2. 防止机器恶意注册
    验证码的认证流程:

客户端request登陆页面,后台生成验证码:

  • 后台使用算法生成图片,并将图片response给客户端

  • 同时将算法生成的值全局赋值存到session中
    校验验证码:

  • 客户端将认证信息和验证码一同提交

  • 后台对提交的验证码与session里面的进行比较
    客户端重新刷新页面,再次生成新的验证码:

  • 验证码算法中一般包含随机函数,所以每次刷新都会改变

  • 演示

  • 环境:buu中的Pikachu,burp*

图片

随意输入一个验证码尝试,提示错误,随后根据环境输入正确验证码,则会提示用户名或者密码不存在

图片

现在看来其实是不能对图片验证码进行暴力破解(除非你为了这个写一个深度学习,那你属实牛逼)

随后看下页面的源码,这里可以看到验证码的生成是在前端JS脚本里进行的,每次点击下就能生成一个新的验证码

图片

代码如下

这里就不对具体的原理进行剖析,可自行解读

随后对一次登陆请求进行抓包,查看详情

图片

随后发送至repeater,并go

然后写一个随机的验证码提交查看返回信息

图片

提示用户名或者密码不存在,说明其并没有在后台进行验证(这玩意对于懂原理的人没鸟用)

随后按照上一期的暴力破解直接载入字典跑就行了

  • on client常见问题
  • 使用前端JS实现验证码(鸟用)
  • 将验证码在cookie中泄露,容易被获取
  • 将验证码在前端代码中泄露,容易被获取

准备工作:

工具:buu上的pikachu或者自己搭建的dvwa

burpsuite(其他抓包工具)

burp相关模块的介绍

图片

proxy:通过设置代理,拦截浏览器对网站发送的请求抓包

图片

Intruder:通过对抓包的数据包以变量的方式自定义参数,根据相应策略进行自动化的重放

在这个模块中比较重要的是Pasitions选项卡:

指定需要暴力破解的参数,并设置成变量,同时选择攻击模式

  • Sniper:设置一个payload,先将第一个变量使用字典进行测试,然后在将第二个变量使用字典进行测试
  • Battering ram:设置一个payload,所有的变量一起用字典内容被替换,然后一起尝试
  • Ptichfork:每个变量设置一个payload,分别使用对应的字典对变量进行同时替换
  • Cluster bomb:需要为每一个变量设置一个payload,分别使用字典内容组合对变量进行替换
    以上就是我们的准备工作

正文:

先看下提示,可获知正确的三个用户名和密码组合

图片

首先对网站做一个尝试性的登陆,用户名和密码随意输入

图片

提示我们用户名或者密码不存在,然后我们在burp里查看抓包

图片

将其发送至Instruder模块,对username以及password这两个变量设置参数,并载入相关的字典或者我们自己输入的一些密码用户名

图片

图片

如果说Burp是专业版的话,还可以对并发数进行设置(免费版不能),适当提升并发数可以增加我们爆破的效率(当然有些网站会对高并发进行限制)

图片

然后开始爆破

图片

一般来说可以根据返回的数据包长度来确认是否爆破成功,因为大多数攻击是失败的,数据包长度是一样的,而成功的数据包长度就会与之不同

图片

over.

暴力破解=连续性尝试+字典+自动化

其实就是瞎猜,但是一个有效的字典会大大提高破解的效率

  • 常用的账号密码(弱口令),比如常见的用户名/密码top100
  • 互联网上被脱裤的账号密码
  • 使用指定的字符使用工具按照指定的规则进行排列组合算法生成的密码

    Burte Force(暴力破解)概述

“暴力破解”是一攻击具手段,在web攻击中,一般会使用这种手段对应用系统的认证信息进行获取. 其过程就是使用大量的认证信息在认证接口进行尝试登录,直到得到正确的结果.为了提高效率,暴力破解一般会使用带有字典的工具来进行自动化操作。

理论上来说,大多数系统都是可以被暴力破解的,只要攻击者有足够强大的计算能力和时间,所以断定一个系统是否存在暴力破解漏洞,其条件也不是绝对的.我们说一个web应用系统存在暴力破解漏洞,一般是指该web应用系统没有采用或者采用了比较弱的认证安全策略,导致其被暴力破解的“可能性”变的比较高。 这里的认证安全策略, 包括:

1.是否要求用户设置复杂的密码;

2.是否每次认证都使用安全的验证码或者手机otp;

3.是否对尝试登录的行为进行判断和限制(如:连续5次错误登录,进行账号锁定或IP地址锁定等);

4.是否采用了双因素认证;…等等。

如果一个网站没有对登陆接口实施了防暴力破解的措施,或者实施了不合理的措施,就可以称该网站存在暴力破解的相关漏洞,但暴力破解的成功率并不是百分之一百(你的计算机是天河一号当我没说,你牛逼),所以有些网站管理员会忽视其网站的暴力破解漏洞,因为经过各种限制后,通过爆破所花费的时间成本已经远远大于了我们所能承受的

爆破的测试流程

  1. 确认登陆接口的脆弱性:
    确认目标是否存在漏洞(即存在的可能性)比如:尝试登陆—抓包,观察相关验证元素和response信息,判断是否存在可能

  2. 对字典进行优化:
    根据实际情况对字典进行优化,提高爆破的效率

  3. 工具自动化操作

配置相关的自动化工具(比如线程,超时时间,重试次数)

字典的优化过程

  • 技巧一:

    对目标站点进行注册,获取账号密码的一些限制,比如该站点要求密码必须6位以上,字母数字组合,则有根据要求优化字典
    
  • 技巧二:
    如果爆破的是后台,往往管理员账号比较具有特殊性,比如admin/administrator/root,可以使用这三个账号+任意密码尝试登陆,查看返回的结果,确认用户名

比如:

  • 输入xxx/aaa返回“用户名或密码错误”
  • 输入admin/bbb返回“密码错误”,则可以确认用户名为admin
    根据以上流程就可以只对密码进行爆破,提高效率。

熟悉的HGAME,花了几天把web.misc.crypto,还有几道签到题做了,这里做个记录

MISC

欢迎欢迎!热烈欢迎!

签到题,公众号发个消息就有

图片

这个压缩包有点麻烦

图片

拿到后是一个压缩包图片

告诉我们纯数字的6位密码是不安全的这里尝试直接暴力破解得到密码

图片

获得密码后打开readme获得如下提示

图片

再查看另外一个可知是一个密码本即字典,采用字典破解图片

获得如下密码&-`;qpCKliw2yTR\

打开后又有一个readme,打开

图片

而且发现这两者的crc是相同的,

图片

可以尝试采取明文攻击,注意这里提示了要以store模式进行

图片

这里压缩等级选择仅存储,然后进行明文攻击,慢慢等待就可以。然后获得一张图片

图片

拉进010发现里面有压缩包,binwalk分离出来,结果还是有密码的,把压缩包拉进010,发现存在伪加密,改一下就结束了,然后获得flag

图片

好康的流量

下载获得一个流量,拉进wireshark,发现存在base64

图片

加上题目名字是涩图,且下面的url解码出来是涩图.png,采取base64转图片

获得一张图片,用stegslove打开,发现一半flag

图片

接着查看lsb,这次是竖着的所以有点小坑,发现另一半

图片

组合在一起就行

群青(其实是幽灵东京)

打开网址是一首歌,另存到桌面上,用au打开,发现是这首歌的作者Yoasobi

再把这首歌拉进010看,发现有个silenteye提示,用silenteye解密,并用刚才获得的组合名密码解密

图片

获得另外一个音频,不过这个很刺耳,有点类似无线电,网络查询资料知道有道sctf2020的无线电考点基本一样,用安卓软件robot36直接一把梭了

图片

扫出来就是flag

CRYPTO

Easy RSA

图片

打开附件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from math import gcd
from random import randint
from gmpy2 import next_prime
from Crypto.Util.number import getPrime
from secret import flag

def encrypt(c):
    p = getPrime(8)
    q = getPrime(8)
    e = randint(0, p * q)
    while gcd(e, (p - 1) * (q - 1)) != 1:
        e = int(next_prime(e))
    return e, p, q, pow(ord(c), e, p * q)

if __name__ == '__main__':
    print(list(map(encrypt, flag)))
    # [(12433, 149, 197, 104), (8147, 131, 167, 6633), (10687, 211, 197, 35594), (19681, 131, 211, 15710), (33577, 251, 211, 38798), (30241, 157, 251, 35973), (293, 211, 157, 31548), (26459, 179, 149, 4778), (27479, 149, 223, 32728), (9029, 223, 137, 20696), (4649, 149, 151, 13418), (11783, 223, 251, 14239), (13537, 179, 137, 11702), (3835, 167, 139, 20051), (30983, 149, 227, 23928), (17581, 157, 131, 5855), (35381, 223, 179, 37774), (2357, 151, 223, 1849), (22649, 211, 229, 7348), (1151, 179, 223, 17982), (8431, 251, 163, 30226), (38501, 193, 211, 30559), (14549, 211, 151, 21143), (24781, 239, 241, 45604), (8051, 179, 131, 7994), (863, 181, 131, 11493), (1117, 239, 157, 12579), (7561, 149, 199, 8960), (19813, 239, 229, 53463), (4943, 131, 157, 14606), (29077, 191, 181, 33446), (18583, 211, 163, 31800), (30643, 173, 191, 27293), (11617, 223, 251, 13448), (19051, 191, 151, 21676), (18367, 179, 157, 14139), (18861, 149, 191, 5139), (9581, 211, 193, 25595)]

这个RSA也确实简单,大致来看这道题可以不看成rsa就看成是到别的题实际上就是求每组的chr(C),c是个ASCII    从可以显示的ASCII(32,127)中一个一个匹配过去,暴力   只要匹配上就输出
图片

写个jio本就可以了

import gmpy2

secret = [(12433, 149, 197, 104), (8147, 131, 167, 6633), (10687, 211, 197, 35594), (19681, 131, 211, 15710), (33577, 251, 211, 38798), (30241, 157, 251, 35973), (293, 211, 157, 31548), (26459, 179, 149, 4778), (27479, 149, 223, 32728), (9029, 223, 137, 20696), (4649, 149, 151, 13418), (11783, 223, 251, 14239), (13537, 179, 137, 11702), (3835, 167, 139, 20051), (30983, 149, 227, 23928), (17581, 157, 131, 5855), (35381, 223, 179, 37774), (2357, 151, 223, 1849), (22649, 211, 229, 7348), (1151, 179, 223, 17982), (8431, 251, 163, 30226), (38501, 193, 211, 30559), (14549, 211, 151, 21143), (24781, 239, 241, 45604), (8051, 179, 131, 7994), (863, 181, 131, 11493), (1117, 239, 157, 12579), (7561, 149, 199, 8960), (19813, 239, 229, 53463), (4943, 131, 157, 14606), (29077, 191, 181, 33446), (18583, 211, 163, 31800), (30643, 173, 191, 27293), (11617, 223, 251, 13448), (19051, 191, 151, 21676), (18367, 179, 157, 14139), (18861, 149, 191, 5139), (9581, 211, 193, 25595)]

1
2
3
4
5
6
7
8
9
10
11
12
13
flag = ""
for m in range(38):
#if 8 == 8 :
    e = secret[m][0]
    p = secret[m][1]
    q = secret[m][2]
    i = secret[m][3]
    lam = p*q
    for c in range(32,127):
            if i == gmpy2.powmod(c, e, lam):
                flag += chr(c)
print(flag)
print(len(flag))

Matryoshka

图片

1
⠨⠨⠤⠌⠤⠤⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠤⠤⠤⠌⠤⠤⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠤⠨⠨⠌⠨⠨⠨⠤⠤⠌⠤⠤⠨⠨⠤⠤⠌⠨⠤⠨⠨⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠤⠤⠤⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠤⠤⠤⠌⠤⠤⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠨⠤⠨⠤⠌⠤⠨⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠨⠤⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠤⠨⠨⠌⠨⠨⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠤⠨⠨⠌⠤⠤⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠨⠤⠌⠤⠨⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠤⠨⠨⠌⠨⠨⠨⠤⠤⠌⠤⠤⠨⠨⠤⠤⠌⠨⠤⠤⠤⠤⠌⠤⠤⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠨⠨⠨⠌⠨⠨⠨⠤⠤⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠨⠤⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠤⠤⠌⠤⠨⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠤⠤⠨⠌⠤⠤⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠨⠨⠨⠌⠨⠨⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠤⠌⠤⠨⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠨⠤⠨⠨⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠤⠤⠌⠨⠤⠤⠤⠤⠌⠤⠤⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠨⠌⠤⠨⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠤⠤⠨⠌⠨⠨⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠤⠨⠨⠌⠨⠨⠨⠤⠤⠌⠤⠤⠨⠨⠤⠤⠌⠨⠤⠤⠤⠤⠌⠤⠤⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠤⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠨⠤⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠤⠤⠌⠨⠤⠤⠤⠤⠌⠨⠨⠨⠤⠤⠌⠤⠤⠨⠨⠤⠤⠌⠨⠤⠨⠤⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠨⠨⠨⠌⠨⠨⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠤⠨⠨⠨⠨⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠨⠨⠨⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠤⠤⠤⠌⠤⠤⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠨⠌⠤⠨⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠨⠤⠤⠤⠤⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠤⠤⠌⠤⠨⠨⠨⠨⠌⠤⠤⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠤⠤⠤⠌⠨⠨⠨⠤⠤⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠤⠨⠨⠌⠤⠤⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠤⠤⠤⠌⠨⠨⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠨⠤⠨⠤⠌⠤⠨⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠤⠨⠨⠨⠨⠌⠨⠨⠨⠤⠤⠌⠤⠤⠨⠨⠤⠤⠌⠨⠤⠤⠤⠤⠌⠨⠨⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠨⠤⠤⠤⠤⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠨⠨⠨⠌⠨⠨⠨⠤⠤⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠨⠨⠨⠌⠤⠤⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠤⠨⠨⠨⠨⠌⠤⠨⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠨⠨⠨⠌⠨⠨⠨⠤⠤⠌⠤⠤⠨⠨⠤⠤⠌⠨⠤⠨⠤⠌⠤⠨⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠤⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠤⠤⠌⠨⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠨⠨⠤⠌⠤⠨⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠨⠨⠨⠌⠤⠨⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠨⠨⠤⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠨⠨⠨⠌⠨⠨⠨⠤⠤⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠤⠨⠨⠌⠤⠨⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠨⠨⠤⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠨⠨⠤⠌⠤⠨⠨⠨⠨

打开给了一串很像盲文的东西,直接拿去解码没用,仔细观察只有三种图案组成,考虑为摩斯,解码有点迹象,但依旧不像有用的信息,查看提示,纸条背面,考虑是先逆序再摩斯
得到一串ascii(十六进制)

1
46,66,42,75,66,45,46,6e,6d,4c,73,36,44,33,73,69,59,74,4c,36,58,32,70,34,69,4e,30,63,64,53,6c,79,6b,6d,39,72,51,4e,39,6f,4d,53,31,6a,6b,73,39,72,4b,32,52,36,6b,4c,38,68,6f,72,30,3d

接下来就直接用工具一把梭了
图片

English Novel

下载后得明文和密文以及加密脚本

1
2
3
4
5
6
7
8
9
10
11
def encrypt(data, key):
    assert len(data) <= len(key)
    result = ""
    for i in range(len(data)):
        if data[i].isupper():
            result += chr((ord(data[i]) - ord('A') + key[i]) % 26 + ord('A'))
        elif data[i].islower():
            result += chr((ord(data[i]) - ord('a') + key[i]) % 26 + ord('a'))
        else:
            result += data[i]
    return result

很明显的维吉尼亚加密,去看明文和密文已经打乱顺序,并未按照他给的顺序排列,虽然通过大小排序或者其他方法也能匹配到,理论上是可以找一对不是特别短的明文的和密文手算获得密钥然后去用在线解密就行。但是这里我还是请教了其他师傅,采取了脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
keylis = [-1] * 44
flag_cip = "klsyf{W0_j0v_ca0z_'Ks0ao-bln1qstxp_juqfqy'?}"
cip_list = [open('./encrypt/part'+str(i)+'.txt', 'r').read(44) for i in range(409)]
msg_list = [open('./original/part'+str(i)+'.txt', 'r').read(44) for i in range(409)]

while -1 in keylis:
    for cip in cip_list:
        for msg in msg_list:
            flag = True
            for i in range(44):
                if (cip[i].islower() ^ msg[i].islower()) or \
                    (cip[i].isupper() ^ msg[i].isupper()) or \
                        ((cip[i].isupper() or cip[i].islower()) ^ (msg[i].isupper() or msg[i].islower())):
                    flag = False
                    break
            if flag:
                for i in range(44):
                    if cip[i].isupper() or cip[i].islower():
                        keylis[i] = (ord(cip[i]) - ord(msg[i])) % 26

print(keylis)
result = ""
for i in range(44):
    if flag_cip[i].isupper():
        result += chr((ord(flag_cip[i]) - ord('A') - keylis[i]) % 26 + ord('A'))
    elif flag_cip[i].islower():
        result += chr((ord(flag_cip[i]) - ord('a') - keylis[i]) % 26 + ord('a'))
    else:
        result += flag_cip[i]
print(result)

Dancing Line

给了一张图片

图片

转向处当1不转当0,左上走到右下,碰见黑的就截断,ascii就是flag

类似摩斯,只不过是图片形式。可以自己记录下转向与否再解密,或者直接写个脚本,这里用的其他师傅的脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from PIL import Image
import numpy as np
ppp = Image.open('Dancing Line.bmp')
mmm = np.asarray(ppp)
m = mmm.shape[0]
n = mmm.shape[1]
pos = []
for i in range(m):
    for j in range(n):
        if mmm[i][j][0] != 255:
            pos.append((i, j))
typ = 1
liss = []
tmp = 0
for i in range(1, len(pos)):
    tmp_typ = (pos[i - 1][0] == pos[i][0])
    tmp = 2 * tmp + (typ ^ tmp_typ)
    if i % 8 == 0:
        liss.append(tmp)
        tmp = 0
for x in liss:
    print(chr(x), end = '')

IOT

饭卡的uno

图片

直接把附件扔进ida,加个H就是flag

接上文

PWN

test_your_nc

nc一下,直接ls就是flag

WEB

蜘蛛

每个网页都有进入下一关的url,大概到了100关找一下flag,写一个脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import requests
from bs4 import BeautifulSoup

payload='?key=waIhAPv5m%2FNnK8InBODSntbsBfxO0q5vPSQsMdFbo6lmSt1UNIAAAhoj%2FNP38yVBeU%2BUYKJQOG0k0HMjfeihTA%3D%3D'
def html(payload):
    url='https://hgame-spider.vidar.club/450bc23c34'
    html_text=requests.get(url=url+payload).text
    soup = BeautifulSoup(html_text,'lxml')
    tag=soup.find_all('a')
    for i in tag:
        if i.attrs['href'] != '':
            real_payload=i.attrs['href']
            print('[*]'+real_payload)
            html(real_payload)
html(payload)

Tetris plus

翻看js文件

图片

发现jsfuck

放到控制台运行

图片

Fujiwara Tofu Shop

一步一步按照提示构造数据包就行,主要考察http的知识

1
2
3
4
5
6
7
8
GET / HTTP/1.1
Host: shop.summ3r.top
User-Agent: Hachi-Roku
referer:qiumingshan.net
Cookie: flavor=Raspberry
gasoline:100
x-real-ip:127.0.0.1
Connection: close

easy_auth

http://adminisdoingwhat.mjclouds.com/

先注册一个账号

admin admin

然后登录查看返回包

图片

发现token为jwt

放到https://jwt.io/#debugger-io解密

发现有密钥 爆破一下

发现为空

图片

修改字段进行加密

图片

发现泄露app.js

进行查看

关键位置代码

图片

图片

访问http://whatadminisdoingwhat.mjclouds.com/v1/todo/list

带上我们之前的加密出来的token发送

图片

A+B这种题目,这道题目就是让我们输出 A + B 的值,但是这道题目呢?大整数加法同样是计算两个数的和,但是这两种题目的解法是完全不同的。如果我们还像之前一样这样写那么题目肯定会 WA 

1
2
3
4
5
6
7
8
9
#include<iostream>
using namespace std;

int main() {
    int A, B;
    cin >> A >> B;
    cout << A + B << endl;
    return 0;
}

因为后者的数据范围大大超过了int以及double等数据类型,会导致数据溢出,为了解决这种问题,就需要采用了高精度算法。

高精度算法简介

高精度算法,属于处理大数字的数学计算方法。在一般的科学计算中,会经常算到小数点后几百位或者更多,当然也可能是几千亿几百亿的大数字。一般这类数字我们统称为高精度数,高精度算法是用计算机对于超大数据的一种模拟加,减,乘,除,乘方,阶乘,开方等运算。对于非常庞大的数字无法在计算机中正常存储,于是,将这个数字拆开,拆成一位一位的,或者是四位四位的存储到一个数组中, 用一个数组去表示一个数字,这样这个数字就被称为是高精度数。

在C/C++的计算中如果处理不好很容易出现数据溢出的情况。比如 int 型数据的范围为 -2147483648 ~ +2147483647 (4 Bytes)如果一个比这个数据范围还要大的数,那么我们就不能直接存储在 int 变量中,否则会出现数据溢出的问题。一般我们做题目的时候题目都会提供数据范围,当给定的数据范围很大的时候我们一定要注意这个题目是不是高精度问题。

大数的存储方式

对于数字习惯先写高位再写低位,但是在计算机中计算的时候如果我们也按照从高位到低位存储数字,对我们写程序造成了不必要的麻烦。所以在数组中我们按照从低位到高位存储大数,即先存个位,再存十位,再存百位……。比如我们有一个数组 A ,那么A[0]存个位,A[1]存十位,A[2]存百位……以此类推。

 由于高精度数都比较大,所以在存储的过程中我们一般先以将数字存到一个 string 类型的字符串中,然后将其每一位减去 ‘0’ 再存入到数组中(因为在计算机中每一个字符都有它的ASCII码,字符’0’ - ‘9’ 的 ASCII码的范围为 48 - 57,用字符串中每一个字符的ASCII码减去 ‘0’ 的ASCII码正好对应相应的数字)。

图片

高精度加法详解

 其实高精度加法并没有我们想象中的那么难,实现的过程就是模拟了我们笔算加法的过程。首先从个位开始相加,先将两个数组的第一位A[0]、B[0]相加即两个数的个位相加。使用一个变量 t 来存储相加的结果,将想相加之后的结果对 10 取模然后存到结果数组的个位上即C[0]上。然后再使 t 除以 10 如果两个个位相加超过了 10 那么除以 10 之后的到的就是进位的结果,然后依次相加十位百位等等,直到两个数组的数字都加完。这里我们需要设置一个 变量 i = 0 来记录遍历数组的下标,如果 i 还没有超过数组最大的下标那么就相加,否则就不想加。

 比如 1234 + 56 我们会将其存储为 4321 + 65,4 + 6 = 10 ,10 % 10 = 0,10 / 10 = 1,所以我们将 0 存储在C[0]上,t = 1,然后再将 t + 3 = 4 , t + 5 = 9,此时9 % 10 = 9,9 / 10 = 0 , t = 0,这时56已经加完了,所以我们直接计算 t + 2 = 2, t = 0,t + 1 = 1,t = 0。所以最终 C[0] = 0,C[1] = 9,C[2] = 2,C[3] = 1,倒着输出数组C中的数字,即 1290 就是我们的答案了。

 这里要特别注意:我们在 for 循环的结束条件还需要判断一下 t 是否为 0 因为即使最后将两个数加完了还可能存在进位的可能,如果不加这个条件那么最高位就会少个 1。

大整数加法题目详解

题目描述

 求两个不超过 200200 位的非负整数的和。

输入格式

 有两行,每行是一个不超过 200200 位的非负整数,可能有多余的前导 00。

输出格式

 一行,即相加后的结果。结果里不能有多余的前导 00,即如果结果是 342342,那么就不能输出为 03420342。

 输出时每行末尾的多余空格,不影响答案正确性

样例输入

22222222222222222222

33333333333333333333

样例输出

55555555555555555555

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include<stdio.h>
#include<string.h>
#define max 300
int main()
{
    char a[max] = {0},b[max] = {0};
    int a1[max] = {0},b1[max] = {0},c1[max] ={0};
    int a_len,b_len,i;
    scanf("%s",&a);
    scanf("%s",&b);
    a_len = strlen(a);
    b_len = strlen(b);
    for(i = 0;i < a_len;i++)
        a1[i] = a[a_len - i - 1] - '0';
    for(i = 0;i < b_len;i++)
        b1[i] = b[b_len - i - 1] - '0';
    int t = 0,x = 0;
    while(t < a_len || t < b_len)
    {
        c1[t] = a1[t] - b1[t] + x;
        x = c1[t] / 10 ;
        c1[t] %= 10;
        t++;
    }
    while(!c1[t] && t)
    {
        t--;
    }
    for(;t >= 0;t--)
        printf("%d",c1[t]);
    return 0;
}

高精度减法详解

大整数减法又叫高精度减法,对于该问题首先我们要考虑如何在计算机中存储大整数

判断两个数的大小

做大整数减法首先我们需要判断一下 减数 和 被减数 哪一个更大。比如大整数 a - b,如果 a > b,那么结果为正数,在输出时我们就不用考虑输出负号;如果 a < b,那么结果为负数,我们需要将 a - b 改为 - (b - a) 来计算,我们只需要计算 b - a,最后在输出时先输出一个负号即可。因为在该题题目中保证了 被减数 a 大于减数 b (a>b) 所以我们就可以省略这一步直接进行相减即可

大整数减法实现

定义一个变量 int t = 0 作为借位的标记。因为在主函数传参时我们保证了 a 一定是大于 b 的,所以我们循环遍历 a,从个位开始逐位相减。这里的 t 是实现大整数减法的关键,首先我们计算一下当前位的值为多少比如我们开始计算两个数的个位相减,我们使用之前定义的变量 t 来存储结果,即 t = A[0] - B[0] - t,这里后面的 t 即为借位,如果 t 的结果大于 等于0 ,说明在两个数的个位 A[0] >= B[0] 那么就不需要借位那么我们将 t 设置为 0 下一次计算十位的时候依旧是 t = A[1] - B[1] - t ,之后我们将这个结果存储在C[0]上,即结果的个位。如果 t 的结果小于 0 ,那么说明需要借位,那么我们就将结果 +10 。然后将 t 设置为 1,证明我们借位了,在下一次t = A[1] - B[1] - t 时需要多减去一个 1。这里还要注意在相减的过程中我们要判断一下B的该位是否存在,存在我们才相减,不存在就不进行相减,所以在我们分开来算t = A[1] - B[1] - t

题目详解

求两个大的正整数相减的差。

输入格式

 共 2 行,第 1 行是被减数 a,第 2 行是减数 b(a > b)。每个大整数不超过 200 位,不会有多余的前导零。

输出格式

一行,即所求的差。

输出时每行末尾的多余空格,不影响答案正确性

样例输入

9999999999999999999999999999999999999

9999999999999

样例输出

9999999999999999999999990000000000000

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <stdio.h>
#include <string.h>
int main() {
char a[202] = {0}, b[202] = {0};//输入
int a1[202] = {0}, b1[202] = {0};//计算
int a_len, b_len, t = 0, i;
scanf("%s%s", a, b);
a_len = strlen(a);
b_len = strlen(b);

for (i = 0; i < a_len; i++)
a1[i] = a[a_len - 1 - i] - '0';
for (i = 0; i < b_len; i++)
b1[i] = b[b_len - 1 - i] - '0';



a_len = (a_len > b_len) ? a_len : b_len;//找两个数里面长的
for (i = 0; i <= a_len; i++) {//正常的进位算法
t = a1[i] - b1[i];
if (t<0){
t+=10;
a1[i+1]--;
}
a1[i] = t;

}
while (!a1[i] && i)//找起始位(避坑n+0)
i--;
for (; i >= 0; i--)
printf("%d", a1[i]);
return 0;
}

高精度乘法详解

 高精度算法简介已经在上文中详细的介绍过了,这里就不再赘述了

大数的存储方式

 大数的存储方式也在上文中详细的介绍过了,这里也不再赘述了。这里主要介绍一下高精度乘法的实现方式。

精度乘法实现

 这里主要介绍一下一个大整数 A 乘以一个比较小的数 b 的实现方法,两个大整数相乘的实现方法是一样的,不同之处在于两个大数相乘需要将第二个数也拆开分别进行相乘。首先我们定义一个vector数组 ans 来存储相乘之后的结果,定义一个整型变量 t 来存储每次的进位的值。因为是倒着存储的大数,所以在相乘的时候我们从下标为 0 的数字开始相乘依次向后遍历,并且将每次的相应数位相乘的结果放到数组 ans 中。

 每次相乘之前我们都需要先判断一下数组是否越界了,如果没有越界就使 t 加上当前位乘以较小的数字 b(注意:因为第二个数字 b 比较小,所以我们直接使 A[i] * b,即大数 A 的每一位数字 直接与 b 相乘,而不需要将 b 拆开,因为 b 比较小,所以我们不需要像大数 A 那样将 A 的每一位拆开进行相乘。 )。然后将 t % 10 即结果的个位放在当前位置上,然后使 t /= 10 算出进位的值,在下一次循环直接加上该进位的值即可。重复进行这一操作直到将数组 A 中的所有数位乘完,并且检查一下 t 是否进完位,如果相乘结束之后 t 不为 0 ,说明最后一个数位与 b 相乘还是需要进位,那么就继续执行 t % 10,t /= 10 的操作,直到 t = 0为止。

题目详解

题目描述

 任意给定一个正整数 N (N≤100),计算 2 的 N 次方的值。

输入格式

 输入一个正整数 N。

提示

高精度计算。

 输出时每行末尾的多余空格,不影响答案正确性

样例输入

5

样例输入

5

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include<stdio.h>
#include<string.h>
void timesTwo(char ans[])
{
    int len = strlen(ans);
    int tmp[1005] = {0};
    int sum[1005] = {0};
    for(int i = 0;i < len;i++)
        tmp[i] = ans[len - i - 1] -'0';
    for(int i = 0;i < len;i++)
    {
        sum[i] += tmp[i] * 2;
        sum[i + 1] += (sum[i] / 10);
        sum[i] %= 10;
    }
    int flag = 0;
    for(int i = len,j = 0;i >= 0;i--)
    {
        if(sum[i] != 0 || i == 0)
        {
            flag = 1;
        }
        if(flag)
        {
            ans[j++] = sum[i] + '0';
        }
    }
}
int main()
{
    char ans[1005] = {'1'};
    int n;
    scanf("%d",&n);
    for(int i = 0;i < n;i++)
    {
        timesTwo(ans);
    }
    printf("%s",ans);
    return 0;
}

高精度除法详解

高精度算法简介

 高精度算法简介已经在上文中详细的介绍过了,这里就不再赘述了

大数的存储方式

大数的存储方式也在上文,这里也不再赘述了。但是我们要注意的是在除法的过程中我们是从最高位开始计算的,而不是像加减乘法一样从最低位开始计算,但是我们在除法的大整数存储中依旧是按照先存最低位再存高位。因为往往在一个高精度问题中不单单会涉及到除法,可能还会有加减乘法运算,所以为了方便我们在存储大整数的时候都是按照由低位到高位存储,即倒着存储。下面来详细的介绍一下如何实现大整数除法。

高精度除法实现

首先我们想一下我们在笔算除法的时候的计算步骤,在大整数 A1A2A3A4A5A6 ÷ b 先判断一下最高位的数字A1能不能除开 b,除不开就落下来然后再计算A1A2 是否能够除开 b;如果能够除开那么就将商写在上面然后求出余数 r ;再计算下一位,将余数 r * 10 + A3,然后再计算商余数知道将所有的数位都除完,最后就剩下了最终的商和余数。

计算机中的大整数除法和我们笔算的时候思路是一样的,首先我们定义一个余数 r = 0,先使 r = r * 10 + A1,然后计算 r / b 的结果,然后使 r %= b,求出当前的余数再进行下一位的运算即使 r = r * 10 + A2,将 r / 10 ,然后再计算余数 r %= b;一直循环往复下去直到算完所有的数位。

题目详解

题目描述

 已知正整数 k 满足 2 ≤ k ≤ 9,现给出长度最大为 30 位的十进制非负整数 c,求所有能整除 c 的 k。

输入格式

 一个非负整数 c,c 的位数 ≤ 30。

输出格式

若存在满足 c % k = 0 的 k,从小到大输出所有这样的 k,相邻两个数之间用单个空格隔开;若没有这样的 k,则输出”none”。

 输出时每行末尾的多余空格,不影响答案正确性

样例输入

30

样例输出

2 3 5 6

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include<stdio.h>
#include<string.h>
int numMod(char s[],int k)
{
    int c[35] = {0};
    int len = strlen(s);
    for(int i = 0;i < len;i++)
        c[i] = s[i] - '0';
    int res = 0;
    int newNum = 0;
    for(int i = 0;i < len;i++)
    {
        newNum = res * 10 + c[i];
        res = newNum % k;
    }
    return res;
}
int main()
{
    char C[35] = {0};
    int flag = 0;
    scanf("%s",C);
    for(int k = 2;k <= 9;k++)
    {
        if(numMod(C,k) == 0)
        {
            flag = 1;
            printf("%d ",k);
        }
    }
    if(!flag)
    {
        printf("none");
    }
    return 0;
}

高精度阶乘例题

题目描述

求10000以内n的阶乘。

输入格式

只有一行输入,整数n(0≤n≤10000)

输出格式

一行,即n!的值。

样例输入

4

样例输出

24

分析

首先n的阶乘是从1开始相乘,乘到n为止的总乘积。定义很简单,但是要注意下数据范围,本题的n最大到达了10000。而13的阶乘就已经解决int范围的极限了,更别提10000了。这道题的答案很大,所以要用大数的方式来进行处理。

另外,n!=(n−1)!×n

n!=(n−1)!×n而n的范围又在10000以内,所以可以看作是一个大数乘一个int范围内数字的问题,就不用使用高精乘高精的方法了。

乘法计算时也是类似竖式计算的过程。将小的数字i与大数的每一位相乘,且从低位开始相乘。过程中进行进位操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include<stdio.h>
int ans[100005]={1,1};//存放阶乘 ans[0]是位数 倒序存放数字 
int jw[100005];//进位的值 
int n;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){//遍历1~n
//求出i的阶乘
// i!= (i-1)! * i 
for(int j=1;j<=ans[0];j++){
//ans[0]中存放阶乘的位数   
ans[j]=ans[j]*i+jw[j];//将i与每一位进行相乘 
jw[j]=0;//重置进位值 

if(ans[j]>=10){//超过10要进位 
jw[j+1]+=ans[j]/10;//记录进位值 
ans[j]%=10;//保留个位 

if(j==ans[0]) ans[0]++;//如果到了位数又发生进位,那么位数要发生变化 
}
}
}

for(int i=ans[0];i>=1;i--){//从高位开始倒序输出结果 
printf("%d",ans[i]);
}
return 0;
}

其实很简单,但是不知道为啥卡了我思维半天,想通了就豁然开朗(状态不太行

小蒜想让你根据参数,画出一个他想要的矩形。

输入格式

输入一行,包括四个参数:前两个参数为整数,依次代表矩形的高和宽(高不少于 3

3 行不多于 10

10 行,宽不少于 5

5 列不多于 10

10 列);第三个参数是一个字符,表示用来画图的矩形符号;第四个参数为 1

1 或 0

0,0

0 代表空心,1

1 代表实心。

输出格式

输出画出的图形。

小蒜想让你根据参数,画出一个他想要的矩形。

样例输入

1
7 7 @ 0

样例输出

1
2
3
4
5
6
7
@@@@@@@
@ @
@ @
@ @
@ @
@ @
@@@@@@@

【解题思路】

思路1:按行输出

输入高h,宽w,字符c,是否实心x

内部字符c_in有两种,若是实心图形,内部字符是c,若是空心图形,内部字符是’ ‘(空格)

上下两行,需要输出w个c,再输出换行。

中间的h - 2行,需要先输出一个c,再输出w - 2个c_in,再输出一个c,再输出换行。

思路2:遍历矩阵

循环嵌套输出整个矩阵

针对每个位置进行判断,如果符合条件,则输出*,否则输出’ ‘。

条件为:

如果是外圈,即行号为1或h,或列号为1或w,那么输出*

如果不是外圈,是内部位置,那么判断是否是实心,是实心输出*,否则输出’ ’

1.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include<stdio.h>
int main()
{
    int h,w,x;
    char  c;
    scanf("%d %d %c %d",&h,&w,&c,&x);
    char c_in = x == 1 ? c : ' ';
   for(int i = 0;i < w;i++)
        printf("%c",c);
    printf("\n");
    for(int i = 0;i < h - 2;i++)
    {
    printf("%c",c);
    for(int j = 0;j < w - 2;j++)
        printf("%c",c_in);
    printf("%c\n",c);
    }
    for(int i = 0;i < w;i++)
    {
        printf("%c",c);
    }
    printf("\n");
    return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2.#include<stdio.h>
int main()
{
    int h,w,x;
    char c;
    scanf("%d %d %c %d",&h,&w,&c,&x);
    for(int i = 1;i <= h;i++)
    {
        for(int j = 1;j <= w;j++)
        {
            if(i == 1 || i == h || j == 1 || j == w)
                printf("%c",c);
            else
            {
                if( x == 1)
                    printf("%c",c);
                else
                    printf(" ");
            }
        }
        printf("\n");
    }
    return 0;
}

【题目描述】

蒜头君有一个正整数 n,他想求第 n小的质数。

【输入格式】

一个不超过 10000的正整数 n。

【输出格式】

第 n 小的质数。

输出时每行末尾的多余空格,不影响答案正确性

【样例输入】

1
10

【样例输出】

1
29
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include<stdio.h>
#include<math.h>
int isprime(int m) { //判断一个数是不是质数 
    int i;
    for(i=2; i<=sqrt(m); i++) 
        if(m%i==0)
                return 0;
    return 1;
}
int main() 
{
    int n,sum=0;//定义第n小,质数累加 
    scanf("%d",&n); 
    for(int i=2;;i++)
    {
        if( isprime(i)==1)
            sum++;
        if(sum==n)  //等于第n小的时候输出 
        {
            printf("%d\n",i); 
            break;
        }       
    }
    return 0;
}

一、常用Window+R键命令

cmd         //命令窗口

mspaint     //打开画板

calc        //打开计算器

msconfig    //打开系统启动配置窗口

services.msc//启动本地服务操作窗口

control     //打开控制面板

notepad     //打开记事本

regedit     //注册表

二、常用CMD命令

shutdown -s -t 30    //30秒后关机

d:                   //切换盘符

dir                  // 查看当前路径内的内容

cd d:/test           //绝对路径,从盘符开始的路径

cd ./test            //相对路径,从当前目录开始(.为当前路径,..为上一级目录)

cd \                 //直接退回到盘符 

cls                  //清屏

exit                 //退出CMD窗口   

md 名称              //创建文件夹

rename 旧名 新名     //重命名文件夹

xcopy 源文件夹 目的文件夹  /s/d/e   

 //复制文件(夹)  /s复制文件夹下所有子文件夹和文件  /e即使有空文件夹也会复制   /d复制过程显示

rd 文件夹  /s       //删除文件(夹)/s删除文件夹下所有子文件夹和文件

type nul>文件名     //创建空文件

echo a>文件名       //创建指定内容的文件

rename 旧名 新名    //重命名文件

copy 源路径 目的路径   //路径要么都是相对路径,要么都是绝对路径

del 文件名          //删除文件   (如del *.txt 会删除所有扩展名为txt的文件)

ipconfig   //查看网卡信息

、环境变量:

1.定义:

例如Windows操作系统中的path环境变量,当要求系统运行一一个程序而没有告诉它程序所在的完整路径时,系统除了在当前目录下面寻找此程序外,还应到path中指定的路径去找。用户通过设置环境变量来更好的运行进程。

即如果想让一个程序不管是在哪一个目录下都能运行,就需要配置一个环境变量。

2.配置方法:

我的电脑右键属性->高级系统设置->高级->环境变量->系统变量->path双击->新建->输入路径->确定

但是这样有一个缺陷,即如果在一个目录下存在多层嵌套的子目录中有很多的路径需要设置,必须每一个路径都分别配置,这样会显得路径特别长。因此可以直接设置一个系统变量来解决,即将一部分相同的路径作为一个变量名使用。

1.我的电脑右键属性->高级系统设置->高级->环境变量->系统变量->新建->输入变量名(例如:Text),变量值(即路径,不要用中文的字符)->确定

2.path双击->新建->%Text%\hello\1->确定(用%%把变量名括起来,如果是变量名对应变量值的子目录,那么在后面跟上相应的路径)

3.(代替2的操作,是俩种编辑方式,看打开以后出现的是啥来判断)可以直接在path的变量值后面以‘;’分割,添加想要添加的路径名

3.注意事项:

路径必须是.bat文件所在目录的的绝对路径

在path中将路径上移或下移可以改变环境变量搜索顺序,提高搜索效率。