工具使用手册
程序
gdb
[]表示直接输入
“”表示需由引号包裹
- {}表示键盘操作
基本
help [指令]
查看个指令的用法i
即info 查看信息i b
查看断点i r
查看寄存器i f
查看函数名
show
与info类似,但更多是调试信息stack [数]
查看栈backtrace
查看当前调试环境中所有栈帧的信息,栈回溯.vmmap
内存段基本信息frame
查看当前frame(函数,栈帧)里的变量值等信息display /[n]i $pc
查看当前往下n行代码disassemble *addr
反汇编某块内存,disassemble /r
带机器码distance
计算距离context(ctx)
再次打印当前状态
随机化信息
libc
打印libc基址ld
打印ld基址code
打印code基址tls
打印tls地址heapbase
打印heap基址
符号与源码
info sharedlibrary
查询符号表地址add-symbol-file /home/aichch/glibc-all-in-one/libs/2.31-0ubuntu9_amd64/.debug/libc-2.31.so
加载符号文件,调试会有一些问题dir
查看源码目录dir 指定目录
指定查找源码目录,例如调试malloc源码
最后还有一种最有效的加载符号表方式
利用gdb的python api导入调试文件,稳定性最高,调试不出错
借助其api写成的loadsym.py实现
1 | gdb.attach(sh,'''source ./libcdbg/loadsym.py |
在2.34以前可以直接加载.debug目录下的对应符号文件,如以上所示
不过从2.34开始,提供的glibc符号文件格式发生变化,loadsym的对象也有一些变化
现在我们需要先file查看下载的libc.so的build-id,例如2.36-0ubuntu4_amd64的build-id是d1704d25fbbb72fa95d517b883131828c0883fe9,那么就前往.built-id文件夹寻找d1文件夹,找到其中的704d25fbbb72fa95d517b883131828c0883fe9.debug文件,将其加载
1 | gdb.attach(sh,'''source ./libcdbg/loadsym.py |
一般来说,ubuntu的同一个glibc版本的各个小版本的libc.so的符号差距不会太大,因此每个glibc版本有一个调试文件即可
不过特殊情况可能会出现符号较大差异,依然要调试的话可以下载指定版本的libc
执行
start
开始或重新开始s [数]
单步步入,会进入子函数,数有填的话就是执行多少步,源码层面si [数]
同上,汇编层面
n [数]
单步步过,不会进入子函数,数有填的话就是执行多少步,源码层面ni [数]
同上,汇编层面
c
继续执行到断点,没断点就一直执行下去{ctrl+c}
程序输入时强行中断r
重新开始执行finish(fi)
结束当前正在执行的函数,并在跳出函数后暂停程序的执行return [值]
结束当前调用函数并返回指定值,到上一层函数调用处停止程序执行。jump(j) [地址]
使程序从当前要执行的代码处,直接跳转到指定位置处继续执行后续的代码。即跳过部分代码until(u)
单纯使用 until 命令,可以运行程序直到退出循环体。until n
命令中,n 为某一行代码的行号,该命令会使程序运行至第 n 行代码处停止。
断点
b *[地址]
b *$ rebase([相对偏移])
开启pie时可用
b [函数名]
b [数]
源码第几行断点b +[数]
当前往下多少停住,同样可以有-delete [数]
删除断点disable [数]
禁用断点enable [数]
启用断点clear
清楚下面所有断点watch [地址]
该地址数据改变时停下,例如watch * (long long int*)0xdeadbeef
或者watch {long long int}0xdeadbeef
watch [变量]
该变量改变的时候会断awatch [地址]
硬件断点,访问时便会中断info watchpoints
查看watch断点信息catch syscall
syscall系统调用的时候断住,后面可以跟指定的系统调用号tcatch syscall
syscall系统调用的时候断住,只断一次info break
catch的断点可以通过i b查看
查找数据
search [值(多是字面值,字符串之类)]
find "字符串"
pwndbg独有
查看内存
x /[nuf]
n代表几个单元
u代表每个单元几个字节(b—1|h—2|w—4|g—8)
f代表显示格式
1
2
3
4
5
6
7
8
9
10
11x 按十六进制格式显示变量。
d 按十进制格式显示变量。
u 按十六进制格式显示无符号整型。
o 按八进制格式显示变量。
t 按二进制格式显示变量。
a 按十六进制格式显示变量。
c 按字符格式显示变量。
f 按浮点数格式显示变量。
s 按字符串显示。
b 按字符显示。
i 显示汇编指令
print(p) (&)[符号]
打印符号的内容或查看符号的地址,支持进一步的指针调用,例如p _rtld_global->_dl_ns->_ns_loaded->l_info[26]
p (*(类型\*)内存地址)
,可以将某一块内存视为指定符号打印内容,例如p (*(struct _IO_FILE_plus*)0x603180)
telescope [内存|符号]
查看内容以更直观的方式ptype [符号]
打印符号定义例如ptype struct _IO_wide_data
ptype /o
额外显示内部成员偏移
hexdump
像debug那样显示内存dump memory bin start end
dump内存
修改数据
set $[寄存器]=[值]
把寄存器的值变为所更改的set *([地址])=[值]
地址的值更改,注意带星号,默认int位数,例如set * (long long int*)0xdeadbeef=0x123456789
set {数据类型}([地址])=[值]
地址的值修改(指定位数).不用星号.例如set {long long int}0xdeadbeef=0x123456789
set args "a1" "a2" "a3"
给参数123赋值set args "python3 -c 'print "1234\x7f\xde"'"'
使用python给参数赋值不可见字符
多线程
info threads
查看可切换调试的线程:thread
线程id切换调试的线程set scheduler-locking on
只运行当前线程set scheduler-locking off
运行全部的线程thread apply 线程id gdb_cmd
指定某线程执行某gdb命令thread apply all gdb_cmd
全部的线程执行某gdb命令
堆(pwndbg)独有
mp
查看mmap详细信息,包括临界信息等top_chunk
显示topchunk信息arena
显示当前arena的详细信息arenas
显示所有arena的基本信息arenainfo
好看的显示所有arena的信息
bins
常用,查看所有种类的堆块的链表情况
fastbins
单独查看fastbins的链表情况largebins
同上,单独查看largebins的链表情况smallbins
同上,单独查看smallbins的链表情况unsortedbin
同上,单独查看unsortedbin链表情况tcachebins
同上,单独查看tcachebins的链表情况tcache
查看tcache详细信息
heap
数据结构的形式显示所有堆块,会显示一大堆
heapbase
查看堆起始地址heapinfo
、heapinfoall
显示堆得信息,和bins的挺像的,没bins好用parseheap
显示堆结构,很好用
tracemalloc
好用,会跟提示所有操作堆的地方malloc_chunk [chunk符号或地址]
查看该chunk的信息find_fake_fast [地址] [大小]
查找一块可以在给定地址附近伪造fake_fast_chunk的内存vis
以数据块模式查看堆
其他(一些是pwndbg独有)
cyclic [数]
生成用来溢出的字符cyclic -l [ 地址]
搭配使用
$reabse
//开启PIE的情况的地址偏移b *$reabse(0x123456)
断住PIE状态下的二进制文件中0x123456的地方codebase
打印PIE偏移,与rebase不同,这是打印,rebase是使用
retaddr
打印包含返回地址的栈地址canary
直接看canary的值plt
查看plt表got
查看got表hexdump [地址] [数]
像IDA那样显示数据,带字符串magic
打印一些useful符号
python-API
文档Python API (Debugging with GDB)
在gdb命令行中,直接python $gdb-function
即可使用
善用help [命令]
gdb-multiarch
target remote : $port
连接调试端口
set architecture $arch
设置调试架构
set endian little/big
设置大小端
gdb-multiarch
启动的时候最好带上本地文件
调试异构时无法使用ctrl+c发送系统中断,因此只能打断点使程序停下
gdb-multiarch在程序崩溃时,偶尔会产生占用巨大空间的coredump文件
可以进入/var/lib/apport/coredump
文件夹将其删除
qemu
qemu-$arch -g $port -L $sharelib $file
qemu启动程序
one_gadget
one_gadget是libc中存在的一些执行execve("/bin/sh", NULL, NULL)
的片段,当可以泄露libc地址,并且可以知道libc版本的时候,可以使用此方法来快速控制指令寄存器开启shell。
相比于system("/bin/sh")
,这种方式更加方便,不用控制RDI、RSI、RDX等参数。运用于不利构造参数的情况。
1 | one_gadget <FILE|-b BuildID> [options] |
- 如果是使用_malloc_hook来调用one_gadget,那么需要配合realloc来构造所需参数,realloc在libc中的符号是__libc_realloc
- 如果是使用其他方式调用one_gadget,比如说修改GOT表,那么需要在栈上提前构造好参数,或者将rax寄存器清零
ROPgadget
ROPgadget --binary filename --only 'pop|ret'
搜索gadget
ROPgadget --binary filename --string '/bin/sh'
字符串
还有其他不少功能,详见help
ropper
可以先使用ropper
直接进入程序内部
再使用其他命令
gadget
亦或者直接
ropper --file filename --string '/bin/sh'
ropper --file filename --search 'asm_code'
指令可以指搜索部分例如mov rdx
,也可以搜索更全mov rdx, rdi
亦或者多条mov rdx, rdi; mov rdi, rax;
要注意空格,逗号,分号的位置,不然搜不到
?和%的用法:
1 | [Search] |
感觉比ROPgadget要好用一点
其他
ropper还附带许多功能,例如asm和disasm等,不过用得比较多的还是gadget
更多详见说明文档
binutils
1 | readelf 读取基本信息 |
工具 | 功能 |
---|---|
strace | 跟踪程序执行过程中产生的系统调用及接收到的信号 |
readelf | 用于查看ELF格式的文件信息 |
file | 用于辨识文件类型 |
objdump | 以一种可阅读的格式让你更多地了解二进制文件可能带有的附加信息 |
ldd | 列出一个程序所需要得动态链接库 |
hexdump | hexdump主要用来查看“二进制”文件的十六进制编码 |
ar | 创建静态库,插入/删除/列出/提取 成员函数 |
strings | 列出目标文件中所有可打印的字符串 |
nm | 列出目标文件中符号表所定义的符号 |
strip | 从目标文件中删除符号表的信息 |
size | 列出目标文件中各个段的大小 |
patchelf
ldd查看libc和ld路径(file和readelf指令也行)
1 | linux:~/pwn$ ldd elf |
patchelf使用
ld切换
1 | patchelf --set-interpreter /home/aichch/glibc-all-in-one/libs/2.31-0ubuntu9_amd64/ld-2.31.so[绝对路径] ./elf |
libc切换
1 | patchelf --replace-needed libc.so.6[符号] /home/aichch/glibc-all-in-one/libs/2.31-0ubuntu9_amd64/libc-2.31.so[绝对路径] ./elf |
也有这样修改libc的
1 | patchelf --set-rpath /home/aichch/glibc-all-in-one/libs/2.31-0ubuntu9_amd64/libc-2.31.so[绝对路径] ./elf |
patchelf --set-rpath
的作用是 在ELF文件的 Dynamic section 的中添加一个 RUNPATH 段里面储存着动态链接库的绝对路径,即设置程序的动态链接库
readelf -d ./elf 查看runpath和needed
ld版本与libc版本要对应
不过有时替换了之后,ldd会显示不是可执行文件,但却可以正常运行
glibc_all_one
更新
./update_list
下载
./download libc
_name
其他来源glibc安装
glibc-2.23为例
解压tar xvf glibc-2.23.tar.gz
进入解压目录
1 | cd glibc-2.23 |
选择带 debug symobl 以及配置好安装位置
CFLAGS="-g -g3 -ggdb -gdwarf-4 -Og -w" CXXFLAGS="-g -g3 -ggdb -gdwarf-4 -Og -w" ../configure --prefix=/home/aichch/glibc_all_one/libs/glibc-2.23/
CFLAGS、CXXFLAGS 与 debug symobl 有关
—prefix 是安装目录
编译安装
make && make install
若出现
1 | /tmp/ccPRCqlU.s: Error: `loc1@GLIBC_2.2.5' can't be versioned to common symbol 'loc1' |
解决方案就是在 /misc/regexp.c
中增改几行代码
做如下修改
1 | diff --git a/misc/regexp.c b/misc/regexp.c |
dd
dd 命令用于读取
、转换
并输出
数据。
- if=文件名:输入文件名,默认为标准输入。即指定源文件。
- of=文件名:输出文件名,默认为标准输出。即指定目的文件。
- ibs=bytes:一次读入bytes个字节,即指定一个块大小为bytes个字节。
obs=bytes:一次输出bytes个字节,即指定一个块大小为bytes个字节。
bs=bytes:同时设置读入/输出的块大小为bytes个字节。 - cbs=bytes:一次转换bytes个字节,即指定转换缓冲区大小。
- skip=blocks:从输入文件开头跳过blocks个块后再开始复制。
- seek=blocks:从输出文件开头跳过blocks个块后再开始复制。
- count=blocks:仅拷贝blocks个块,块大小等于ibs指定的字节数。
- conv=<关键字>,关键字可以有以下11种:
- conversion:用指定的参数转换文件。
- ascii:转换ebcdic为ascii
- ebcdic:转换ascii为ebcdic
- ibm:转换ascii为alternate ebcdic
- block:把每一行转换为长度为cbs,不足部分用空格填充
- unblock:使每一行的长度都为cbs,不足部分用空格填充
- lcase:把大写字符转换为小写字符
- ucase:把小写字符转换为大写字符
- swap:交换输入的每对字节
- noerror:出错时不停止
- notrunc:不截短输出文件
- sync:将每个输入块填充到ibs个字节,不足部分用空(NUL)字符补齐
xxd
对数据进行十六进制存储
参数
- -ps:以纯十六进制形式打印
- -c[]:显示多少列
- -s:start at \
bytes abs. (or +: rel.) infile offset.
diff
用于对比两个文件之间的差异
也可以用于对比两个文件夹,使用-r
进行递归
python包
pwntools
程序启动
process启动
强制使用给定的ld和libc启动进程
1 | p = process(argv=["/home/aichch/glibc-all-in-one/libs/2.31-0ubuntu9_amd64/ld-2.31.so", "./elf"],env={"LD_PRELOAD":"/home/aichch/pwn/libc-2.31.so"}) |
aslr等级设置
1 | p=process('./elf',aslr=0/1/2) |
带参数启动
1 | p=process(argv=['./elf',arguments]) |
debug启动
1 | io = gdb.debug("/bin/bash", gdbscript='continue') |
在这个例子中,传入了gdbscript='continue'
,以使调试器恢复执行,但是可以传入任何有效的 GDB 脚本命令,它们将在调试进程启动时被执行。
运行异构架构的进程必须用gdb.debug
启动,以便对其进行调试
以debug()启动的程序会停在start函数的起始,即程序的最开始
remote远程
1 | p=remote(ip,host,ssl=false) |
参数:
1 | Arguments: |
ssh连接
shell = ssh(user=user, host=host, port=port, password=password)
数据接收与发送
1 | sh.recv(numb = 2048, timeout = dufault) 接受数据,numb指定接收的字节,timeout指定超时 |
针对elf的处理
常用符号处理
1 | elf=ELF('libc.so.6') |
更多
1 | #read,write and patch |
context及log
1 | context.log_level = 'DEBUG' |
gdb
1 | gdb.attach() |
1 | Linux 系统有一个叫做trace_scope的设置,它可以阻止非子进程的进程被调试。Pwntools 对于它自己启动的任何进程都能解决这个问题,但是如果你必须在 Pwntools 之外启动一个进程,并试图通过 pid 附加到它(例如gdb.attach(1)),可能被阻止附加。 |
ROP
1 | rop=ROP('') 创建一个rop对象 |
pwntools comandline
1 | checksec 检查保护 |
qemu
需要用pwntools调试qemu启动的程序,首先需要设置context,不然很多设置会出错
对于动态链接的程序还需要
如果用process()启动异构elf,pwntools只会尝试盲目打开程序,如果失败则会使用qemu逐个尝试打开程序,当然也可以自己指定
例如
p=process(["qemu-arm", "-g", "1234", "-L", "/usr/arm-linux-gnueabihf", "./armup_buu"])
不过这样启动就是调试模式,程序完全由gdb-multiarch控制
p=process(["qemu-arm", "-L", "/usr/arm-linux-gnueabihf", "./armup_buu"])
这样启动程序就能正常向下执行了
只是这样打开的话gdb.attach(p)是附加不上去的,只能到另一个命令行使用gdb.multiarch调试
当然也可以通过gdb.debug()打开异构elf,pwntools会自动添加适合的命令行参数给qemu,并正确启动gdb
不过实际发现上面两种方式在调试时都不是很灵敏
constants
constants
可以返回诸多c源文件中定义的常量
LibcSearcher
1 | libc = LibcSearcher("函数名",函数真实地址) |
另外如果是pypi上下载的更新版本,还多了一些功能
1 | len(libc) # 返回在当前约束条件下,可能的 Libc 数量 |
struct
将字节串解读为打包的二进制数据,可以方便地调整字节序,大小和对齐方式以及进行格式化
struct.pack
(format, v1, v2, …)
返回一个 bytes 对象,其中包含根据格式字符串 format 打包的值 v1, v2, … 参数个数必须与格式字符串所要求的值完全匹配。
struct.pack_into
(format, buffer, offset, v1, v2, …)
根据格式字符串 format 打包 v1, v2, … 等值并将打包的字节串写入可写缓冲区 buffer 从 offset 开始的位置。 请注意 offset 是必需的参数。
struct.unpack
(format, buffer)
根据格式字符串 format 从缓冲区 buffer 解包(假定是由 pack(format, ...)
打包)。 结果为一个元组,即使其只包含一个条目。 缓冲区的字节大小必须匹配格式所要求的大小,至少为calcsize()
显示的格式所要求的大小。
struct.unpack_from
(format, /, buffer, offset=0)
对 buffer 从位置 offset 开始根据格式字符串 format 进行解包。 结果为一个元组,即使其中只包含一个条目。 缓冲区的字节大小从位置 offset 开始必须至少为 calcsize()
显示的格式所要求的大小。
struct.iter_unpack
(format, buffer)
根据格式字符串 format 以迭代方式从缓冲区 buffer 解包。 此函数返回一个迭代器,它将从缓冲区读取相同大小的块直至其内容全部耗尽。 缓冲区的字节大小必须整数倍于格式所要求的大小,如 calcsize()
所示。
每次迭代将产生一个如格式字符串所指定的元组。
struct.calcsize(format)
,计算最终大小
字节顺序,大小和对齐方式
字符 | 字节顺序 | 大小 | 对齐方式 |
---|---|---|---|
@ |
按原字节 | 按原字节 | 按原字节 |
= |
按原字节 | 标准 | 无 |
< |
小端 | 标准 | 无 |
> |
大端 | 标准 | 无 |
! |
网络(=大端) | 标准 | 无 |
请注意 '@'
和 '='
之间的区别:两个都使用本机字节顺序,但后者的大小和对齐方式是标准化的
格式字符
格式字符具有以下含义;C 和 Python 值之间的按其指定类型的转换应当是相当明显的。 ‘标准大小’列是指当使用标准大小时以字节表示的已打包值大小;也就是当格式字符串以 '<'
, '>'
, '!'
或 '='
之一开头的情况。 当使用本机大小时,已打包值的大小取决于具体的平台。
格式 | C 类型 | Python 类型 | 标准大小 |
---|---|---|---|
x |
填充字节 | 无 | |
c |
char | 长度为 1 的字节串 | 1 |
b |
signed char | 整数 | 1 |
B |
unsigned char | 整数 | 1 |
? |
_Bool | bool | 1 |
h |
short | 整数 | 2 |
H |
unsigned short | 整数 | 2 |
i |
int | 整数 | 4 |
I |
unsigned int | 整数 | 4 |
l |
long | 整数 | 4 |
L |
unsigned long | 整数 | 4 |
q |
long long | 整数 | 8 |
Q |
unsigned long long | 整数 | 8 |
n |
ssize_t |
整数 | |
N |
size_t |
整数 | |
e |
(6) | float | 2 |
f |
float | float | 4 |
d |
double | float | 8 |
s |
char[] | 字节串 | |
p |
char[] | 字节串 | |
P |
void* | 整数 |
例子
1 | import struct |
binascii
二进制和 ASCII 码互转
hex
binascii.b2a_hex(data[, sep[, bytes_per_sep=1]])
binascii.hexlify(data[, sep[, bytes_per_sep=1]])
返回二进制数据 data 的十六进制表示形式。 data 的每个字节都被转换为相应的2位十六进制表示形式。因此返回的字节对象的长度是 data 的两倍。
使用bytes.hex()方法也可以方便地实现相似的功能(但仅返回文本字符串)。
如果指定了 sep,它必须为单字符 str 或 bytes 对象。 它将被插入每个 bytes_per_sep 输入字节之后。 分隔符位置默认从输出的右端开始计数,如果你希望从左端开始计数,请提供一个负的 bytes_per_sep 值。
1 | b'H\x8d\x85\xf0\xf7\xff\xff\xba\x00\x02') hexlify( |
binascii.a2b_hex(hexstr)
binascii.unhexlify(hexstr)
与上面相反
返回由十六进制字符串 hexstr 表示的二进制数据。此函数功能与 b2a_hex()
相反。 hexstr 必须包含偶数个十六进制数字(可以是大写或小写),否则会引发 Error 异常。
使用bytes.fromhex()
类方法也实现相似的功能(仅接受文本字符串参数,不限制其中的空白字符)。
base64
binascii.a2b_base64(string)
将 base64 数据块转换成二进制并以二进制数据形式返回。一次可以传递多行数据。
binascii.b2a_base64(data, *, newline=True)
将二进制数据转换为一行用 base64 编码的ASCII字符串。返回值是转换后的行数据,如果 newline 为true,则返回值包括换行符。该函数的输出符合:rfc:3548。
requests
requests是基于python的一个HTTP库,封装了许多针对HTTP协议的操作,可以方便的进行网页操作
requests支持的方法
方法 | 描述 |
---|---|
delete(url, args) | 发送 DELETE 请求到指定 url |
get(url, params, args) | 发送 GET 请求到指定 url |
head(url, args) | 发送 HEAD 请求到指定 url |
patch(url, data, args) | 发送 PATCH 请求到指定 url |
post(url, data, json, args) | 发送 POST 请求到指定 url |
put(url, data, args) | 发送 PUT 请求到指定 url |
request(method, url, args) | 向指定的 url 发送指定的请求方法 |
设置请求头headers
1 | headers = { |
设置data
1 | data = { |
设置查询参数
1 | params = { |
get()和post()等请求方法
1 | response = requests.post(url, headers=headers, params=params, data=data) |
返回值具有以下属性
1 | status_code#返回状态码 |
string
string提供不少方便的字符集分类
1 | whitespace -- a string containing all ASCII whitespace |
以及字符串模板
1 | from string import Template |
还有一些用的不多的方法
hashlib
在proof of work
或者一些其他场景中会出现
主要的功能是计算sha256以及md5
1 | md5_hash = hashlib.md5(data.encode()).hexdigest() |
random
用于快速生成随机数,常用几个方法
1 | random.randint(x,y) |
re
python的正则表达式方法包
re.search(pattern, string, flags=0)
在字符串中搜索匹配指定的正则表达式模式,返回一个匹配对象,如果找到则返回第一个匹配项,否则返回 None
。
1 | import re |
re.match(pattern, string, flags=0)
尝试从字符串的起始位置匹配正则表达式模式,如果成功匹配则返回一个匹配对象,否则返回 None
1 | import re |
re.findall(pattern, string, flags=0)
在字符串中查找所有匹配指定的正则表达式模式的子串,并以列表形式返回。
1 | import re |
re.sub(pattern, repl, string, count=0, flags=0)
使用指定的替换字符串(repl
)替换字符串中所有匹配指定的正则表达式模式的子串,并返回替换后的字符串。
1 | import re |
re.split(pattern, string, maxsplit=0, flags=0)
根据指定的正则表达式模式对字符串进行拆分,并返回拆分后的子串列表。
1 | import re |
re.compile(pattern, flags=0)
将正则表达式模式编译成一个可重复使用的正则表达式对象,可以提高匹配效率。
1 | import re |
re.finditer(pattern, string, flags=0)
在字符串中查找所有匹配指定的正则表达式模式的子串,并返回一个迭代器,每个元素是一个匹配对象。
1 | import re |
re.fullmatch(pattern, string, flags=0)
尝试完全匹配字符串与正则表达式模式,如果匹配成功则返回一个匹配对象,否则返回 None
。
1 | import re |
buildin
方法
dir()
函数返回对象的所有属性和方法的列表。
vars()
函数用于返回对象的 __dict__
属性,如果存在的话,否则会引发 TypeError
。
属性
__dict__
__dict__
它是一个字典,包含了类的命名空间中的所有属性和方法。
当你访问一个类的 __dict__
属性时,你会得到一个字典,其中包含了该类定义的所有属性和方法的名称及其对应的值。这包括类变量、实例变量、类方法、静态方法、实例方法等。
__doc__
__doc__
是一个特殊的属性,用于存储文档字符串(docstring)。文档字符串是对 Python 对象(如模块、类、函数或方法)的描述性文本,通常用于说明对象的作用、用法、参数、返回值等信息。
当你定义一个类、函数或方法时,可以在其顶部编写一个文档字符串,用 '''
或 """
包围起来,来描述该对象
base64
可以进行base64,base32,base16(hex),a85等多种编码解码
以base64为例
编码(将二进制数据转换为 Base64 字符串):
使用
base64.b64encode(data)
方法可以将二进制数据编码为 Base64 字符串。其中data
是要编码的二进制数据。1
2
3
4import base64
data = b'Hello, World!'
encoded_data = base64.b64encode(data)解码(将 Base64 字符串转换为二进制数据):
使用
base64.b64decode(encoded_data)
方法可以将 Base64 字符串解码为二进制数据。其中encoded_data
是要解码的 Base64 字符串。1
2
3
4import base64
encoded_data = b'SGVsbG8sIFdvcmxkIQ=='
decoded_data = base64.b64decode(encoded_data)解码后的二进制数据会以字节串的形式返回。