python编写命令行 python命令行写代码_开发语言


本篇文章记录的是Python命令行编程知识。

一、命令行编程

什么是命令行编程呢?
通过命令行的方式和用户交互,接收用户输入的数据,然后处理,结果再次通过命令行反馈给用户。
对于安全人员编写poc和exp,你会发现很多python工具都是命令行版本的。

1、input接收

在之前的函数中,已经介绍过input函数了,这里我们直接开始案例。
如果我们要编写一个RCE漏洞的exp,可以先构造我们的思路
示例:

url = input("请输入url: ").strip()
cmd = input("请输入你要执行的系统命令: ").strip()
# 简易模仿代码
print(f"正在对{url} 网站执行 {cmd} 这条系统命令")
print("命令执行完成 , 命令的回显: root")

稍微美化一下:

def main():
    banner = """cve-2022-4346-rce
使用方法 : 根据提示依次输入url和命令"""
    print(banner)
    url = input("请输入url: ").strip()
    cmd = input("请输入你要执行的系统命令: ").strip()
    # 简易模仿代码
    print(f"正在对{url} 网站执行 {cmd} 这条系统命令")
    print("命令执行完成,命令的回显: root")


if __name__ == '__main__':
    main()

2、sys模块

import sys

print(sys.argv)  # 接收py脚本传进来的参数 , 返回一个列表 , 一般用来获取命令行参数
# 我们编写poc可以通过它来获取用户传递过来的url , 要执行的命令等

使用sys模块优化一下,这个时候接收参数,就不需要input接收了,而是通过sys.argv
示例:

import sys
#
def main(url, cmd):
    # 简易模仿代码
    """真正具体对指定url执行命令的代码"""
    print(f"正在对{url} 网站执行{cmd} 这条系统命令")
    print("命令执行完成,命令的回显: root")


if __name__ == '__main__':
    banner = """welcome use cve-2022-4346-rce
使用方法 : python3 cve-2022-4346-rce.py http://www.mhx.com id\n"""
    print(banner)
    if len(sys.argv) == 3:
        url = sys.argv[1]
        cmd = sys.argv[2]
        main(url, cmd)
    else:
        print("输入参数有误,请按照提示输入")

退出函数

import sys

sys.exit(0)     # 一旦执行这行代码 , 程序会直接退出 , 安全退出
sys.exit(1)     # 一旦执行这行代码 , 程序会直接退出 , 报错退出

二、argparse模块

argparse模块是python标准库中推荐的命令行解析模块,也是一个内置模块。

命令行参数可以提升脚本的灵活性,更加通用。完成参数解析一般用到getopt, optparse和argparse,其中argparse 是基于 optparse , 在Python3.2新推出的命令行参数解析模块 , 比较主流

特点:

  • 支持可选参数
  • 支持子命令
  • 支持重复参数个数统计
  • 更加友好的使用提示
    该模块不但可以用来写poc/exp,还可以写一些命令行的渗透测试工具。
    初步:
# 导入模块
import argparse
# 实例化一个对象 , 并添加命令行的描述信息,一般在脚本中用来介绍脚本是干嘛的
parser = argparse.ArgumentParser(description="这是脚本的提示信息")
# 调用parse_args方法
parser.parse_args()

直接运行:

# 直接运行
D:\python3 argparse模块.py

# 使用-h参数
D:\python3 argparse模块.py -h
usage: argparse模块.py [-h]

这是脚本的提示信息

optional arguments:
  -h, --help  show this help message and exit

# 使用一个不存在的参数
D:\python3 argparse模块.py -a
usage: argparse模块.py [-h]
argparse模块.py: error: unrecognized arguments: -a
  • 在没有任何选项 (参数) 的情况下运行脚本不会在标准输出显示任何内容。这没有什么用处。
  • 第二次运行开始展现出 argparse 模块的作用。我们几乎什么也没有做,但已经得到一条很好的帮助信息。
  • --help 选项,也可缩写为 -h,是唯一 一个可以直接使用的选项(即不需要指定该选项的内容)。指定任何内容都会导致错误。即便如此,我们也能直接得到一条有用的用法信息

1、位置参数

示例:

import argparse
parser = argparse.ArgumentParser()
# 添加一个参数,参数名叫做url
parser.add_argument("url")
# 解析参数,得到一个args对象
args = parser.parse_args()
# 通过 对象.参数名 调用
print(args.url)

使用:

D:\python3 argparse模块.py  http://XXX.com
http://XXX.com

D:\python3 argparse模块.py  -h
usage: argparse模块.py [-h] url

positional arguments:
  url

optional arguments:
  -h, --help  show this help message and exit

虽然有个参数的传入 , 但是多多少少不是我们想要的 , 但是不要急 , 一般位置参数是用来做工具中必须传入的参数

一般都不是用来接收值的 , 而是指定工具如何运行的 , 比如
scan 位置参数 可以通过这个参数指定工具运行扫描功能
关于添加位置参数 , 可以给参数设置一些属性 , 比如

parser.add_argument("url", help="input a url",type=str)
# 默认参数接收的值都是字符串类型, 如果需要其他类型 , 需要使用type指定

使用-h参数 , 可以查看参数的help属性的值

2、可选参数

示例:

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("--url", help="input a url")
args = parser.parse_args()
# 输入args.url的值
print(args.url)  # 默认不指定值的时候为None

运行:

# 没有参数直接运行
D:\python3 argparse模块.py
None

# 设置参数值
D:\python3 argparse模块.py --url http://www.XXX.com
http://www.XXX.com

# 查看帮助信息
D:\python3 argparse模块.py -h
usage: argparse模块.py [-h] [--url URL]

optional arguments:
  -h, --help  show this help message and exit
  --url URL   input a url

3、短选项

示例:

import argparse
parser = argparse.ArgumentParser()

parser.add_argument("-u", "--url", help="input a url",)

args = parser.parse_args()

print(args.url)

运行:

# 直接运行
D:\>python3 argparse模块.py
None
# 使用短选项
D:\python3 argparse模块.py -u http://www.mhx.com
http://www.mhx.com
# 使用长选项
D:\python3 argparse模块.py --url  http://www.mhx.com
http://www.mhx.com
# 查看帮助信息
D:\python3 argparse模块.py -h
usage: argparse模块.py [-h] [-u URL]

optional arguments:
  -h, --help         show this help message and exit
  -u URL, --ver VER  increase output ver

有一些需要注意的属性:

`dest` 通常会作为 `add_argument()`的第一个参数 , 对于可选参数来说 , 默认属性名就是参数名 , 如果有`dest`指定则是`dest值`

如果你想给一个参数设置一个默认值 , 可以通过`default=1`关键字实现
当 `action="store"`也就是默认的 , 是接收参数存进来的值 , 并存储

示例:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-z","--zzz", dest="ggg",type=int, default=1,help="display a square of a given number",action="store")
args = parser.parse_args()

# print(args.zzz)  # 报错 , 因为指定了dest关键字 , 一般情况下参数名
print(args.ggg)

运行:

# 直接运行 , 打印默认值
D:\python3 argparse模块.py
1

# 使用短选项指定参数的值 , 注意使用依然是-z
D:\python3 argparse模块.py -z 1
1
# 查看帮助
D:\python3 argparse模块.py -h
usage: argparse模块.py [-h] [-z GGG]

optional arguments:
  -h, --help         show this help message and exit
  -z GGG, --zzz GGG  display a square of a given number

该模块完整手册请见 : https://docs.python.org/zh-cn/3.8/library/argparse.html

4、小模板

下面是一个小模板,编写的时候可以先套用,最好是有自己的风格

import argparse
import textwrap


def main(url, cmd):
    # 简易模仿代码
    """真正具体对指定url执行命令的代码"""
    print(f"正在对{url} 网站执行{cmd} 这条系统命令")
    print("命令执行完成,命令的回显: root")


if __name__ == '__main__':
    banner = """ 
 _   _     _       _          _          ____                 
| |_| |__ (_)_ __ | | ___ __ | |__  _ __| ___|   _ __ ___ ___ 
| __| '_ \| | '_ \| |/ / '_ \| '_ \| '_ \___ \  | '__/ __/ _ \\
| |_| | | | | | | |   <| |_) | | | | |_) |__) | | | | (_|  __/
 \__|_| |_|_|_| |_|_|\_\ .__/|_| |_| .__/____/  |_|  \___\___|
                       |_|         |_|  
"""
    print(banner)
    parser = argparse.ArgumentParser(description='thinkphp5 rce exp', formatter_class=argparse.RawDescriptionHelpFormatter,
                                     epilog=textwrap.dedent('''example:
        python3 cve-2022-4334-rce.py -u http://192.168.1.108 -c id
        '''))
    parser.add_argument("-u", "--url", dest="url", type=str, help=" example: http://www.xxx.com")
    parser.add_argument("-c", "--cmd", dest="cmd", type=str, default="whoami", help="default=whoami example: id")
    args = parser.parse_args()

    main(args.url, args.cmd)