Skip to content

Commit 2dc7b37

Browse files
committed
Move kctf-pow wrappers into a dedicated pow module
1 parent c8739ad commit 2dc7b37

File tree

3 files changed

+75
-58
lines changed

3 files changed

+75
-58
lines changed

pwn/toplevel.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
from pwnlib.fmtstr import FmtStr, fmtstr_payload, fmtstr_split
3838
from pwnlib.log import getLogger
3939
from pwnlib.memleak import MemLeak, RelativeMemLeak
40+
from pwnlib.pow import *
4041
from pwnlib.regsort import *
4142
from pwnlib.replacements import *
4243
from pwnlib.rop import ROP

pwnlib/pow.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
"""
2+
CTF challenges are sometimes guarded by Proof of Work (PoW) challenges. These
3+
challenges require a connecting host to perform computational effort. Guarding
4+
a service with a Proof of Work challenge slows down the rate at which a user
5+
can connect to a service, reducing the effectiveness of brute-force techniques.
6+
7+
Different Proof of Work algorithms require the connecting host to perform
8+
different operations. The algorithms are not interoperable. You must choose the
9+
correct algorithm to satisfy the server's requirements. As a connecting user,
10+
you are normally told which Proof of Work algorithm is in use by the server.
11+
12+
Pwntools provides an implementation of Google's kCTF Proof of Work algorithm.
13+
"""
14+
15+
from pwnlib.data.kctf.pow import solve_challenge as _kctf_pow_solve_challenge, \
16+
verify_challenge as _kctf_pow_verify_challenge, get_challenge as _kctf_get_challenge
17+
18+
19+
def kctf_pow_solve(challenge):
20+
"""
21+
Solve a kCTF Proof of Work challenge
22+
23+
Arguments:
24+
`challenge` (str): The challenge to solve
25+
26+
Returns:
27+
A string representing an acceptable solution
28+
29+
>>> challenge = 's.AAAB.AAAvm89LbEt4meEnXGwbHp3z'
30+
>>> kctf_pow_solve(challenge)[:20] + '...'
31+
's.AAAo8s+2Q06cSBM4nf...'
32+
>>> hashes.sha256sumhex(six.ensure_binary(kctf_pow_solve(challenge)))
33+
'fd13e60761fb4119848f2d7704100f8737c0ed754ef90f573cff74faac8ca800'
34+
35+
>>> kctf_pow_verify(challenge, kctf_pow_solve(challenge))
36+
True
37+
"""
38+
return _kctf_pow_solve_challenge(challenge)
39+
40+
41+
def kctf_pow_verify(challenge, solution):
42+
"""
43+
Verify a kCFT Proof of Work solution
44+
45+
Arguments:
46+
`challenge` (str): The challenge that was solved
47+
`solution` (str): The solution to verify
48+
49+
Returns:
50+
True if the solution is acceptable, else False
51+
52+
>>> challenge1 = kctf_pow_generate_challenge(1)
53+
>>> challenge2 = kctf_pow_generate_challenge(1)
54+
>>> kctf_pow_verify(challenge1, kctf_pow_solve(challenge1))
55+
True
56+
57+
>>> kctf_pow_verify(challenge1, kctf_pow_solve(challenge2))
58+
False
59+
"""
60+
return _kctf_pow_verify_challenge(challenge, solution, False)
61+
62+
63+
def kctf_pow_generate_challenge(difficulty):
64+
"""
65+
Generate a kCTF Proof of Work challenge
66+
67+
Arguments:
68+
`difficulty` (int): The challenge difficulty. A difficulty of 31337 can be solved in ~30 seconds
69+
at 1.66GHz with gmpy2 installed
70+
71+
Returns:
72+
A string representing the challenge
73+
"""
74+
return _kctf_get_challenge(difficulty)

pwnlib/util/misc.py

Lines changed: 0 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,8 @@
1717
from pwnlib.context import context
1818
from pwnlib.log import getLogger
1919
from pwnlib.util import fiddling
20-
from pwnlib.util import hashes
2120
from pwnlib.util import lists
2221
from pwnlib.util import packing
23-
from pwnlib.data.kctf.pow import solve_challenge as _kctf_pow_solve_challenge, \
24-
verify_challenge as _kctf_pow_verify_challenge, get_challenge as _kctf_get_challenge
2522

2623
log = getLogger(__name__)
2724

@@ -137,61 +134,6 @@ def write(path, data = b'', create_dir = False, mode = 'w'):
137134
with open(path, mode) as f:
138135
f.write(data)
139136

140-
def kctf_pow_solve(challenge):
141-
"""
142-
Solve a kCTF Proof of Work challenge
143-
144-
Arguments:
145-
`challenge` (str): The challenge to solve
146-
147-
Returns:
148-
A string representing an acceptable solution
149-
150-
>>> challenge = 's.AAAB.AAAvm89LbEt4meEnXGwbHp3z'
151-
>>> kctf_pow_solve(challenge)[:20] + '...'
152-
's.AAAo8s+2Q06cSBM4nf...'
153-
>>> hashes.sha256sumhex(six.ensure_binary(kctf_pow_solve(challenge)))
154-
'fd13e60761fb4119848f2d7704100f8737c0ed754ef90f573cff74faac8ca800'
155-
156-
>>> kctf_pow_verify(challenge, kctf_pow_solve(challenge))
157-
True
158-
"""
159-
return _kctf_pow_solve_challenge(challenge)
160-
161-
def kctf_pow_verify(challenge, solution):
162-
"""
163-
Verify a kCFT Proof of Work solution
164-
165-
Arguments:
166-
`challenge` (str): The challenge that was solved
167-
`solution` (str): The solution to verify
168-
169-
Returns:
170-
True if the solution is acceptable, else False
171-
172-
>>> challenge1 = kctf_pow_generate_challenge(1)
173-
>>> challenge2 = kctf_pow_generate_challenge(1)
174-
>>> kctf_pow_verify(challenge1, kctf_pow_solve(challenge1))
175-
True
176-
177-
>>> kctf_pow_verify(challenge1, kctf_pow_solve(challenge2))
178-
False
179-
"""
180-
return _kctf_pow_verify_challenge(challenge, solution, False)
181-
182-
def kctf_pow_generate_challenge(difficulty):
183-
"""
184-
Generate a kCTF Proof of Work challenge
185-
186-
Arguments:
187-
`difficulty` (int): The challenge difficulty. A difficulty of 31337 can be solved in ~30 seconds
188-
at 1.66GHz with gmpy2 installed
189-
190-
Returns:
191-
A string representing the challenge
192-
"""
193-
return _kctf_get_challenge(difficulty)
194-
195137
def which(name, all = False, path=None):
196138
"""which(name, flags = os.X_OK, all = False) -> str or str set
197139

0 commit comments

Comments
 (0)