背景
在算法竞赛和CTF的Misc/Crypto类题中,我们有时时间仓促,无法花费时间于代码/公式/定理分析,或规律推断;或者时间非常充裕,有能力采取暴力枚举的方式解题。
工具mBruteforce
应运而生
简介
mBruteForce
pwnlib.util.iters.mbruteforce
(func, alphabet, length, method = 'upto', start = None, threads = None)[source]
与bruteforce()
具有相同功能,但却是多线程实现。
参数: | 属性 |
---|---|
alphabet | 字符集合 |
length | 字符串长度 |
method | 枚举方式 |
start (*func**,*) | 被枚举函数表达式 |
threads | 线程数 |
Example:
>>> mbruteforce(lambda x: x == 'hello', string.ascii_lowercase, length = 10)
'hello'
>>> mbruteforce(lambda x: x == 'hello', 'hlo', 5, 'downfrom') is None
True
>>> mbruteforce(lambda x: x == 'no', string.ascii_lowercase, length=2, method='fixed')
'no'
>>> mbruteforce(lambda x: x == '9999', string.digits, length=4, threads=1, start=(2, 2))
'9999'
运行参数
mbruteforce(func, alphabet, length, method='upto', start=None, threads=None)
func
在其返回1前枚举;alphabet
输入的字符集合,如string.ascii_letters
,string.hexdigits
;length
最大字符串长度;method
缺省 'upto',指定穷举的字符串长度从1增大到length;'fixed'
固定字符串长度;'downfrom'
递减;start=(N,i)
,将搜索空间分成N块从第i块开始穷举;缺省为(1,1)threads
线程数,缺省为CPU核心数;
使用方法
安装 PwnTools
$ apt-get update
$ apt-get install python3 python3-pip python3-dev git libssl-dev libffi-dev build-essential
$ python3 -m pip install --upgrade pip
$ python3 -m pip install --upgrade pwntools
调用
from pwn import pwnlib
from pwnlib.util.iters import mbruteforce
或
from pwn import *
注意事项
自行注意时间复杂度,无法爆破的就不要无谓尝试了。
示例
Simon Cipher 中已知密钥、密文针对原文爆破(解密算法不可用时)
# Author: sfc9982
# Contest: 春秋杯-Reverse
from pwn import *
from simon import SimonCipher
import binascii
enc = [
0x9D71B8C865FB877F,
0x9A9CB1DF658F9D39,
0x8F11F68E6542DAB4,
0x8C39FB9965486ACA,
0x63E7A479FFFFFFFF,
]
def simonbf():
key = 0x8040201008040201
for ans in enc:
iters.mbruteforce(
lambda x: SimonCipher(
key,
mode="ECB",
key_size=64,
block_size=32,
).encrypt(int(x, 16))
== ans,
string.hexdigits,
16,
"fixed",
)
# print(s)
if __name__ == "__main__":
simonbf()
SHA256
from pwn import *
from parse import *
from pwnlib.util.iters import bruteforce
import string
from hashlib import sha256
def brute_force(prefix,s):
return bruteforce(lambda x:sha256(x+prefix).hexdigest()==s,string.ascii_letters+string.digits,length=4,method='fixed')
r = remote("localhost",9982)
data = r.recvline()
prefix, s = parse("sha256(flag{}) == {}",data)
r.recvline()
r.sendline(brute_force(prefix,s))
使用迭代器
def f(x):
return sha1(prefix + x).digest()[-2:] == '\0\0'
sh = remote('localhost', 52511)
sh.recvuntil('starting with ')
prefix = sh.recvuntil('\n', drop=True)
print string.ascii_letters
s = util.iters.mbruteforce(f, string.ascii_letters + string.digits, 5, 'fixed')
test = prefix + s
sh.send(test)