Working Components

Conditional Execution

条件执行允许我们通过达到不同的条件来控制脚本的流程。这一功能是必不可少的组成部分之一。否则,我们只能一个接一个地执行命令。

在定义各种条件时,我们指定应该为特定值执行哪些函数或代码段。如果我们达到了一个特定的条件,那么只执行该条件的代码,而跳过其他代码。一旦代码部分完成,以下命令将在条件执行之外执行。让我们再看一下脚本的第一部分并分析它。

Script.sh

Code:

#!/bin/bash

# Check for given argument
if [ $# -eq 0 ]
then
echo -e "You need to specify the target domain.\n"
echo -e "Usage:"
echo -e "\t$0 <domain>"
exit 1
else
domain=$1
fi

<SNIP>

总而言之,此代码段使用以下组件:

  • #!/bin/bash - Shebang.
  • if-else-fi - Conditional execution.
  • echo - Prints specific output.
  • $# / $0 / $1 - Special variables.
  • domain - Variables.

条件执行的条件可以使用变量($#$0$1domain)、值(0)和字符串来定义,我们将在下面的示例中看到。这些值将与我们将在下一节中查看的comparison operators-eq)进行比较。

Shebang

shebang行始终位于每个脚本的顶部,并且始终以“#!“开头。这一行包含执行脚本的指定解释器(/bin/bash)的路径。我们还可以使用Shebang来定义其他解释器,如Python,Perl等。

Code:

#!/usr/bin/env python

Code:

#!/usr/bin/env perl

If-Else-Fi

最基本的编程任务之一是检查不同的条件来处理这些条件。在编程和脚本语言中,条件检查通常有两种不同的形式,if-else conditioncase statements。在伪代码中,if条件的含义如下:

Pseudo-Code 伪代码

Code:

if [ the number of given arguments equals 0 ]
then
Print: "You need to specify the target domain."
Print: "<empty line>"
Print: "Usage:"
Print: " <name of the script> <domain>"
Exit the script with an error
else
The "domain" variable serves as the alias for the given argument
finish the if-condition

默认情况下,一个If-Else条件只能包含一个“If“,如下例所示。

If-Only.sh

Code: 验证码: bash

#!/bin/bash

value=$1

if [ $value -gt "10" ]
then
echo "Given argument is greater than 10."
fi

If-Only.sh - Execution

mikannse7@htb[/htb]$ bash if-only.sh 5

​ If-Only.sh - ExecutionIf-Only.sh执行

mikannse7@htb[/htb]$ bash if-only.sh 12

Given argument is greater than 10.

当添加ElifElse时,我们添加替代项来处理特定的值或状态。如果一个特定的值不适用于第一种情况,它将被其他人捕获。

If-Elif-Else.sh

Code:

#!/bin/bash

value=$1

if [ $value -gt "10" ]
then
echo "Given argument is greater than 10."
elif [ $value -lt "10" ]
then
echo "Given argument is less than 10."
else
echo "Given argument is not a number."
fi

If-Elif-Else.sh - Execution

mikannse7@htb[/htb]$ bash if-elif-else.sh 5

Given argument is less than 10.

​ If-Elif-Else.sh - ExecutionIf-Elif-Else.sh执行

mikannse7@htb[/htb]$ bash if-elif-else.sh 12

Given argument is greater than 10.

​ If-Elif-Else.sh - ExecutionIf-Elif-Else.sh执行

mikannse7@htb[/htb]$ bash if-elif-else.sh HTB

if-elif-else.sh: line 5: [: HTB: integer expression expected
if-elif-else.sh: line 8: [: HTB: integer expression expected
Given argument is not a number.

我们可以扩展脚本并指定几个条件。这可能看起来像这样:

Several Conditions - Script.sh 几个条件-Script.sh

Code:

#!/bin/bash

# Check for given argument
if [ $# -eq 0 ]
then
echo -e "You need to specify the target domain.\n"
echo -e "Usage:"
echo -e "\t$0 <domain>"
exit 1
elif [ $# -eq 1 ]
then
domain=$1
else
echo -e "Too many arguments given."
exit 1
fi

<SNIP>

这里我们定义了另一个条件(elif [<condition>];then),它打印一行,告诉我们(echo -e "...")我们已经给出了多个参数,并以错误(exit 1)退出程序。

Exercise Script

Code:

#!/bin/bash
# Count number of characters in a variable:
# echo $variable | wc -c

# Variable to encode
var="nef892na9s1p9asn2aJs71nIsm"

for counter in {1..40}
do
var=$(echo $var | base64)
done

Arguments, Variables, and Arrays

Arguments

bash脚本的优点是,我们总是可以传递多达9个参数($0-$9)给脚本,而无需将它们分配给变量或为这些变量设置相应的要求。9 arguments因为第一个参数$0是为脚本保留的。正如我们在这里看到的,我们需要在变量名之前使用美元符号($),以便在指定的位置使用它。相比之下,赋值看起来像这样:

mikannse7@htb[/htb]$ ./script.sh ARG1 ARG2 ARG3 ... ARG9
ASSIGNMENTS: $0 $1 $2 $3 ... $9

这意味着我们已经自动将相应的参数分配给了这个地方的预定义变量。这些变量称为特殊变量。这些特殊变量充当占位符。如果我们现在再次查看代码部分,我们将看到在何处使用了哪些参数。

CIDR.sh

Code:

#!/bin/bash

# Check for given argument
if [ $# -eq 0 ]
then
echo -e "You need to specify the target domain.\n"
echo -e "Usage:"
echo -e "\t$0 <domain>"
exit 1
else
domain=$1
fi

<SNIP>

有几种方法可以执行我们的脚本。但是,在使用脚本中定义的解释器执行脚本之前,我们必须首先设置脚本的执行特权。

CIDR.sh - Set Execution Privileges

mikannse7@htb[/htb]$ chmod +x cidr.sh

CIDR.sh - Execution without Arguments

mikannse7@htb[/htb]$ ./cidr.sh

You need to specify the target domain.

Usage:
cidr.sh <domain>

CIDR.sh - Execution without Execution Permissions

mikannse7@htb[/htb]$ bash cidr.sh

You need to specify the target domain.

Usage:
cidr.sh <domain>

Special Variables

特殊变量使用内部字段分隔符IFS)来标识参数结束和下一个参数开始的时间。Bash提供了各种特殊的变量来帮助编写脚本。其中一些变量是:

IFS Description
$# 此变量保存传递给脚本的参数的数量。
$@ 此变量可用于检索命令行参数列表。
$n 每个命令行参数都可以使用其位置有选择地检索。例如,第一个参数位于$1
$$ 当前正在执行的进程的进程ID。
$? $n 脚本的退出状态。此变量对于确定命令是否成功很有用。值0表示成功执行,而1表示失败的结果。

在上面显示的那些中,我们在if-else条件中有3个这样的特殊变量。

IFS Description
$# $n 在这种情况下,我们只需要一个变量,需要分配给domain变量。此变量用于指定我们要使用的目标。如果我们只提供一个参数,那么$#变量的值将为1
$0 $n 这个特殊的变量被分配了执行脚本的名称,然后在“Usage:”示例中显示。
$1 $n 用空格分隔,第一个参数被分配给该特殊变量。

Variables

我们还看到在if-else循环的末尾,我们将第一个参数的值赋给了名为“domain“的变量。变量的赋值没有美元符号($)。美元符号仅用于允许此变量的对应值在其他代码部分中使用。在分配变量时,名称和值之间不能有空格。

Code:

<SNIP>
else
domain=$1
fi
<SNIP>

与其他编程语言相比,Bash中的变量类型(如“strings”、“integers”和“boolean”)之间没有直接的区别和识别。“变量的所有内容都被视为字符串字符。Bash根据是否只分配数字来启用算术函数。重要的是要注意,当声明变量时,它们确实包含not。否则,实际变量名将被解释为内部函数或命令。

Declaring a Variable - Error

mikannse7@htb[/htb]$ variable = "this will result with an error."

command not found: variable

Declaring a Variable - Without an Error

mikannse7@htb[/htb]$ variable="Declared without an error."
mikannse7@htb[/htb]$ echo $variable

Declared without an error.

Arrays

在Bash中,也可以为单个变量分配多个值。如果我们想扫描多个域或IP地址,这可能是有益的。这些变量被称为arrays,我们可以使用它们来存储和处理特定类型值的有序序列。Arrays用从index开始的0标识每个存储的条目。当我们想给数组组件赋值时,我们用与标准shell变量相同的方式来做。我们所做的就是指定用方括号括起来的字段索引。在Bash中,arrays的声明看起来像这样:

Arrays.sh

Code:

#!/bin/bash

domains=(www.inlanefreight.com ftp.inlanefreight.com vpn.inlanefreight.com www2.inlanefreight.com)

echo ${domains[0]}

我们也可以使用索引单独检索它们,使用变量和花括号中的相应索引。花括号用于变量展开。

mikannse7@htb[/htb]$ ./Arrays.sh

www.inlanefreight.com

值得注意的是,单引号('')和双引号(". ")防止数组中的各个值之间用空格分隔。这意味着单引号和双引号之间的所有空格都将被忽略,并作为分配给数组的单个值处理。

Arrays.sh

Code:

#!/bin/bash

domains=("www.inlanefreight.com ftp.inlanefreight.com vpn.inlanefreight.com" www2.inlanefreight.com)
echo ${domains[0]}
mikannse7@htb[/htb]$ ./Arrays.sh

www.inlanefreight.com ftp.inlanefreight.com vpn.inlanefreight.com

Comparison Operators

为了将特定的值相互比较,我们需要称为比较运算符的元素。comparison operators用于确定如何比较定义的值。对于这些运营商,我们区分:

  • string operators
  • integer operators
  • file operators
  • boolean operators

String Operators

如果我们比较字符串,那么我们就知道我们希望在相应的值中有什么。

Operator Description
== is equal to
!= is not equal to
< is less than in ASCII alphabetical order
> is greater than in ASCII alphabetical order
-z if the string is empty (null)
-n if the string is not null

这里需要注意的是,我们将给定参数($1)的变量放在双引号("$1")中。这告诉Bash变量的内容应该作为字符串处理。否则,我们会得到一个错误。

Code:

#!/bin/bash

# Check the given argument
if [ "$1" != "HackTheBox" ]
then
echo -e "You need to give 'HackTheBox' as argument."
exit 1

elif [ $# -gt 1 ]
then
echo -e "Too many arguments given."
exit 1

else
domain=$1
echo -e "Success!"
fi

字符串比较运算符“< / >”仅在双方括号[[ <condition> ]]中起作用。我们可以在互联网上找到ASCII表,或者在终端中使用以下命令。我们稍后来看一个例子。

mikannse7@htb[/htb]$ man ascii

ASCII Table

Decimal小数 Hexadecial十六进制的 Character字符 Description描述
0 00 NUL End of a string字符串末尾
65 41 A一 Capital A大写的A
66 42 B Capital B资本B
67 43 C Capital C资本C
68 44 D Capital D大写D
127 7F DEL Delete删除

ASCII代表American Standard Code for Information Interchange,表示7位字符编码。由于每个位可以取两个值,因此存在128不同的位模式,其也可以被解释为十进制整数0 - 127或十六进制值00 -7F。前32个ASCII字符代码被保留为所谓的控制字符

Integer Operators

如果我们知道要比较什么值,比较整数对我们来说非常有用。因此,我们定义了接下来的步骤和命令,脚本应该如何处理相应的值。

Operator Description
-eq -n is equal to
-ne -n is not equal to不
-lt -n is less than
-le -n is less than or equal to
-gt -n is greater than
-ge -n is greater than or equal to

Code:

#!/bin/bash

# Check the given argument
if [ $# -lt 1 ]
then
echo -e "Number of given arguments is less than 1"
exit 1

elif [ $# -gt 1 ]
then
echo -e "Number of given arguments is greater than 1"
exit 1

else
domain=$1
echo -e "Number of given arguments equals 1"
fi

File Operators

如果我们想找出特定的权限或它们是否存在,文件操作符是很有用的。

Operator Descriptio
-e -n if the file exist
-f -n tests if it is a file
-d -n tests if it is a directory
-L -n tests if it is if a symbolic link
-N -n checks if the file was modified after it was last read检查文件在上次读取后是否被修改
-O -n if the current user owns the file
-G -n if the file’s group id matches the current user’s
-s -n tests if the file has a size greater than 0
-r -n tests if the file has read permission
-w -n tests if the file has write permission
-x -n tests if the file has execute permission

Code:

#!/bin/bash

# Check if the specified file exists
if [ -e "$1" ]
then
echo -e "The file exists."
exit 0

else
echo -e "The file does not exist."
exit 2
fi

Boolean and Logical Operators

我们得到一个布尔值“false”或“true”作为逻辑运算符的结果。Bash让我们可以使用双方括号[[ <condition> ]]来比较字符串。为了得到这些布尔值,我们可以使用字符串运算符。无论比较是否匹配,我们都会得到布尔值“false”或“true“。

Code:

#!/bin/bash

# Check the boolean value
if [[ -z $1 ]]
then
echo -e "Boolean value: True (is null)"
exit 1

elif [[ $# > 1 ]]
then
echo -e "Boolean value: True (is greater than)"
exit 1

else
domain=$1
echo -e "Boolean value: False (is equal to)"
fi

Logical Operators

使用逻辑运算符,我们可以在一个条件中定义多个条件。这意味着我们定义的所有条件必须匹配,然后才能执行相应的代码。

Operator Description
! -n logical negotation NOT
&& -n logical AND
`

Code:

#!/bin/bash

# Check if the specified file exists and if we have read permissions
if [[ -e "$1" && -r "$1" ]]
then
echo -e "We can read the file that has been specified."
exit 0

elif [[ ! -e "$1" ]]
then
echo -e "The specified file does not exist."
exit 2

elif [[ -e "$1" && ! -r "$1" ]]
then
echo -e "We don't have read permission for this file."
exit 1

else
echo -e "Error occured."
exit 5
fi

Exercise Script

Code:

#!/bin/bash

var="8dm7KsjU28B7v621Jls"
value="ERmFRMVZ0U2paTlJYTkxDZz09Cg"

for i in {1..40}
do
var=$(echo $var | base64)

#<---- If condition here:
done

Arithmetic

在Bash中,我们有七个不同的arithmetic operators可以使用。这些用于执行不同的数学运算或修改某些整数。

Arithmetic Operators 算术运算符

Operator操作者 Description描述
+ Addition
- Substraction
* Multiplication
/ Division
% Modulus
variable++ Increase the value of the variable by 1
variable-- Decrease the value of the variable by 1

我们可以在一个小脚本中总结所有这些操作符:

Arithmetic.sh

Code:

#!/bin/bash

increase=1
decrease=1

echo "Addition: 10 + 10 = $((10 + 10))"
echo "Substraction: 10 - 10 = $((10 - 10))"
echo "Multiplication: 10 * 10 = $((10 * 10))"
echo "Division: 10 / 10 = $((10 / 10))"
echo "Modulus: 10 % 4 = $((10 % 4))"

((increase++))
echo "Increase Variable: $increase"

((decrease--))
echo "Decrease Variable: $decrease"

该脚本的输出如下所示:

Arithmetic.sh - Execution

mikannse7@htb[/htb]$ ./Arithmetic.sh

Addition: 10 + 10 = 20
Substraction: 10 - 10 = 0
Multiplication: 10 * 10 = 100
Division: 10 / 10 = 1
Modulus: 10 % 4 = 2
Increase Variable: 2
Decrease Variable: 0

我们还可以计算变量的长度。使用这个函数`$