hu1y40's blog

hu1y40'blog
天堂的穹空遍布地狱之火的颜色,但也是天堂。
  1. 首页
  2. Python
  3. 正文

Python bitstring库使用

2023年10月7日 1798点热度 0人点赞 0条评论

位,字节,字

位、字节、字是计算机数据存储的基本单位,每一个位存储一个1位的二进制编码(即0或1),一个字节由八位组成。字是代表计算机处理指令或数据的二进制位数,32位系统1字=32位,64位系统1字=64位

bitstring 库

bitstring是一个python的库,可以使得对二进制数据的操作变得简单。

下载

https://bitstring.readthedocs.io/en/latest/

创建bitArray

a = bitArray('0xff91')
b = bitArray('0b110')

0x是十六进制前缀,0b是二进制前缀。文档中说其未成bytes会内部处理。若输入的不是字符串会创造输入整数位的空比特串。

使用内部转换

a.bin
'1111111100000001'
b.oct
'6'
b.int
-2
a.bytes
b'\xff\x01'

这些属性是在执行时开始计算,bin以及oct返回的是字符串。并且需要oct原比特串满足是3位的倍数。而hex需要是4位。bytes属性可以返回python3的bytes对象。

比特串填充

(b + [0]).hex
'c'
([0] + b).hex
'6'

零位[0]也可以写成BitArray([0]), BitArray([0]), BitArray('0b0'), BitArray(bin='0'),'0b0' 可以是1

修改比特串

bitArray可以将其视为位列表,使用索引可以对其进行切片,删除,插入。

删除

print(a[3:9])
0b111110
del a[-6:]
print(a)
0b1111111100

这里的del是删除列表中的a[-1]~a[-6]对象,解除了对原数据的引用。不过我想既然引用计数已经为0,数据占用的空间应该也被释放了。

切片

单个的元素会返回一个bool值

添加

a.prepend('0b01')
a.append('0o7')
a += '0x06'

查找

a = BitArray('0xa9f')
a.find('0x4f')
(3,)
a == '0b101, 0x4f, 0b1'
True

构造比特串

sequence_header() No. of bits Mnemonic
sequence_header_code 32 bslbf
horizontal_size_value 12 uimsbf
vertical_size_value 12 uimsbf
aspect_ratio_information 4 uimsbf
frame_rate_code 4 uimsbf
bit_rate_value 18 uimsbf
marker_bit 1 bslbf
vbv_buffer_size_value 10 uimsbf
constrained_parameters_flag 1 bslbf
load_intra_quantiser_matrix 1 uimsbf
if (load_intra_quantiser_matrix)
{ intra_quantiser_matrix[64] } 8*64 uimsbf
load_non_intra_quantiser_matrix 1 uimsbf
if (load_non_intra_quantiser_matrix)
{ non_intra_quantiser_matrix[64] } 8*64 uimsbf
next_start_code()

s = BitArray()
s.append('0x000001b3') # the sequence_header_code
s.append('uint:12=352') # 12 bit unsigned integer
s.append('uint:12=288')
...
# s = BitArray('0x000001b3, uint:12=352, uint:12=288')
'''
width, height = 352, 288
s = bitstring.pack('0x000001b3, 2*uint:12', width, height)
'''

其中pack函数可以用字典作为第二个参数

fmt = 'sequence_header_code,
uint:12=horizontal_size_value,
uint:12=vertical_size_value,
uint:4=aspect_ratio_information,
...
'
d = {'sequence_header_code': '0x000001b3',
'horizontal_size_value': 352,
'vertical_size_value': 288,
'aspect_ratio_information': 1,
...
}

s = bitstring.pack(fmt, **d)

pack 返回的是bit流

操作如下:

>>> s
BitStream('0x000001b31601201')
>>> s.pos
0
>>> s.read(24)
BitStream('0x000001')
>>> s.pos
24
>>> s.read('hex:8')
'b3'
>>> s.pos
32
>>> s.readlist('2*uint:12')
[352, 288]
>>> s.unpack('bytes:4, 2*uint:12, uint:4')
['\x00\x00\x01\xb3', 352, 288, 1]

bitStream的操作有类似游标的位移,unpack是从比特串开头开始。

创建

bitstrings库一共提供了四个类,Bits,BitArray,BitStream,ConstBitStream。

使用类的情况

  • 如果要改变比特串的内容,使用bitArray或者bitSteam
  • 如果要作为字典中的key使用,那么使用bits或者constBitSteam
  • 如果直接从文件中读取比特流,bitArray 或者bitSteam会将整个文件读入内存,而bits或者constBitStream不会。
  • 内存效率最高的类是bits。

从原始字节数据创建

a = BitArray(bytes=b'\x00\x01\x02\xff', length=28, offset=1)
b = BitArray(bytes=open("somefile", 'rb').read())

lenth的单位是bits,offset同理偏移量截断开头。

包装

创建bitStream对象可以用pack函数,

bitstring.pack(format, *values, **kwargs)

例如:

s = bitstring.pack('hex:32, uint:12, uint:12', '0x000001b3', 352, 288)
# 相当于
s = BitStream('0x0000001b3, uint:12=352, uint:12=288')

这个可以用函数实现更通用的创建

def foo(a, b, c, d):
return bitstring.pack('uint:8, 0b110, int:6, bin, bits', a, b, c, d)

s1 = foo(12, 5, '0b00000', '')
s2 = foo(101, 3, '0b11011', s1)

切片,索引,拼接。

切片

>>> a = BitArray('0b00011110')
>>> b = a[3:7]
>>> print(a, b)
0x1e 0xf

索引

单个位索引返回一个布尔值,len属性返比特串长度

拼接

  • append和prepend
  • join拼接比特串
  • del删除
  • insert在bitarray使用时需要指定pos,bitstream会在当前pos进行insert。
  • overwrite和insert大致相同,但是会覆盖。
使用函数 使用切片
s.insert(bs, pos) s[pos:pos] = bs
s.overwrite(bs, pos) s[pos:pos + bs.len] = bs
s.append(bs) s[s.len:s.len] = bs
s.prepend(bs) s[0:0] = bs`

分割

>>> a = BitArray('0x4700004711472222')
>>> for s in a.split('0x47', bytealigned=True):
... print(s.hex)

470000
4711
472222

spilit返回迭代器

>>> a = BitArray('0x47001243')
>>> for byte in a.cut(8):
... print(byte.hex)
47
00
12
43

cut可以分成相等的部分。

读取和解析

每一个比特流都有一个pos属性,长度范围为0到最后一位。

>>> s = ConstBitStream(filename='test/test.m1v')
>>> print(s.pos)
0
>>> start_code = s.read(32).hex
>>> width = s.read(12).uint
>>> height = s.read(12).uint
>>> print(start_code, width, height, s.pos)
000001b3 352 288 56
>>> s.pos += 37
>>> flags = s.read(2)
>>> constrained_parameters_flag = flags.read(1)
>>> load_intra_quantiser_matrix = flags.read(1)
>>> print(s.pos, flags.pos)
95 2

如果一次读取多个数据可以用readlist

a, b, c = s.readlist([32, 8, 24])

peek方法不会改变bitstream的pos属性。其使用和read类似。

查找等操作和字符串类似不在列举

官方文档

杂项

  1. bytealign()方法返回跳跃步数,使得pos成为8的倍数
  2. reverse将bitarray反转,可以指定范围
  3. tobytes会把bitarray转换为字节,如果不够8位在后面补0
  4. startswith / endswith判断比特串是否已某开头或结束

 

标签: MISC
最后更新:2023年10月7日

hu1y40

这个人很懒,什么都没留下

点赞

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复
文章目录
  • 位,字节,字
  • bitstring 库
  • 下载
  • 创建bitArray
  • 使用内部转换
  • 比特串填充
  • 修改比特串
    • 切片
    • 添加
    • 查找
  • 构造比特串
  • 创建
    • 使用类的情况
    • 从原始字节数据创建
  • 包装
    • 切片,索引,拼接。
      • 切片
      • 索引
      • 拼接
      • 分割
    • 读取和解析
    • 杂项

分类目录

  • 0day安全
  • Bypass
  • C++Prime
  • CTF
  • DoS
  • DoS
  • FUZZ
  • iot
  • JSONP
  • MISC
  • MISC
  • PHP伪协议
  • Python
  • REVERSE
  • sqli-labs
  • SQL注入
  • Trick
  • UAF
  • WEB
  • WEB
  • XXE
  • 书籍阅读
  • 二进制
  • 代码阅读
  • 信息搜集
  • 信息泄露
  • 加密与解密
  • 双重释放漏洞
  • 反序列化
  • 命令执行
  • 命令执行
  • 堆溢出
  • 密码学
  • 弱加密
  • 提权漏洞
  • 整数溢出
  • 文件上传
  • 未分类
  • 栈溢出
  • 格式化字符串漏洞
  • 模型
  • 汇编语言
  • 渗透测试
  • 漏洞分析
  • 漏洞利用
  • 漏洞战争
  • 漏洞挖掘
  • 病毒分析
  • 越界读取
  • 路径遍历
  • 逻辑漏洞
  • 配置不当
  • 钓鱼
  • 靶场
最新 热点 随机
最新 热点 随机
加密算法 2023年度总结 RTSPServer StackOverflow Vulnerability FUZZ 总览篇 MP4Box 无限循环漏洞 CVE-2023-40477 Winrar RCE漏洞分析
CVE-2018-17297 Hutool 路径遍历漏洞 0day安全 第1-9章总结 Git使用及ctf实战 DIR503A Remote Command Execute Fuzzing101 8 CVE-2019-13990 Quartz XXE漏洞

COPYRIGHT © 2023 hu1y40's blog. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

鄂ICP备2021009673号-1