pwntools
pwntools copied to clipboard
Add kCTF pow.py
This adds a very thin wrapper around Google's kCTF pow.py (https://github.com/google/kctf/blob/v1/docker-images/challenge/pow.py)
This is a draft and a request for comments. It should not be merged just yet.
Demo:
[/pwd/pwntools]% python3 pwnlib/data/kctf/pow.py ask
Usage:
Solve pow: {} solve $challenge
Check pow: {} ask $difficulty
$difficulty examples (for 1.6GHz CPU) in fast mode:
1337: 1 sec
31337: 30 secs
313373: 5 mins
[/pwd/pwntools]% python3 pwnlib/data/kctf/pow.py ask 1337
[WARNING] kctf-pow using random.randrange() which is not cryptographically secure
== proof-of-work: enabled ==
please solve a pow first
You can run the solver with:
python3 <(curl -sSL https://goo.gle/kctf-pow) solve s.AAU5.AACHSYfS7R9fjck4/AaU+qCG
===================
Solution? ^CTraceback (most recent call last):
File "/pwd/pwntools/pwnlib/data/kctf/pow.py", line 202, in <module>
main()
File "/pwd/pwntools/pwnlib/data/kctf/pow.py", line 169, in main
line = f.readline().decode("utf-8")
KeyboardInterrupt
[/pwd/pwntools]% python3
Python 3.9.2 (default, Feb 28 2021, 17:03:44)
[GCC 10.2.1 20210110] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pwn
>>> pwn.kctf_pow_<tab><tab>
pwn.kctf_pow_solve( pwn.kctf_pow_verify(
>>> pwn.kctf_pow_solve("s.AAU5.AACHSYfS7R9fjck4/AaU+qCG")
[NOTICE] kctf-pow running 10x slower, gotta go fast? pip3 install gmpy2
's.AAAHmgGmZgtfk2AfN0JgnyLN5gcXdNtgt6eUSL89gadobDu0gHhJTDtS8jUJ2VGNJ/yqSB1Iu09qwX62VHe1Q1LXdUadsWekt9zj2tpG4FGoMUPsRMtQzVNTfTKglWY5D+d0ts5fhBccRu3kbljpn0pmVezFEWvdLeyZ2tRUAs7V1I260gRewCMl4Wt1zQU2ZGNZ1khpni60SU09lEARUl8h'
>>> pwn.kctf_pow_verify("s.AAU5.AACHSYfS7R9fjck4/AaU+qCG", _)
True
TODO:
- [x] Get
pow.pyworking under Python2 or give up trying
Questions:
- Where should this live? Should we create a new module, say
pwnlib.pow? - Is it appropriate to be vendoring Google's
pow.py? It is Apache 2.0 and I've adhered to the requirement of "You must cause any modified files to carry prominent notices stating that You changed the files"- If it's not appropriate to be vendoring
pow.py, please reject this PR. I can't find a PyPi package containingpow.pyand don't want to make one. - If it's appropriate to be vendoring
pow.pywhere should it go? I'm assumingdatais a bad place for it. Should alibrariesorlibdirectory be created and referenced inLICENSE-pwntools.txtas being a place in which third-party code lives? - If it's appropriate to be vendoring
pow.pyshould some effort be made to hide it from consumers ofpwn? The following behavior seems a bit unwanted to me.
- If it's not appropriate to be vendoring
% python3
Python 3.9.2 (default, Feb 28 2021, 17:03:44)
[GCC 10.2.1 20210110] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pwn
>>> pwn.data.<tab><tab>
pwn.data.absolute_import pwn.data.kctf pwn.data.path
pwn.data.elf pwn.data.os
>>> pwn.data.kctf.pow.<tab><tab>
pwn.data.kctf.pow.CHALSIZE pwn.data.kctf.pow.gmpy_sloth_square(
pwn.data.kctf.pow.GMP_NOTICE_ISSUED pwn.data.kctf.pow.hashlib
pwn.data.kctf.pow.HAVE_GMP pwn.data.kctf.pow.main(
pwn.data.kctf.pow.MODULUS pwn.data.kctf.pow.os
pwn.data.kctf.pow.SOLVER_URL pwn.data.kctf.pow.python_sloth_root(
pwn.data.kctf.pow.VERSION pwn.data.kctf.pow.python_sloth_square(
pwn.data.kctf.pow.base64 pwn.data.kctf.pow.random
pwn.data.kctf.pow.can_bypass( pwn.data.kctf.pow.sloth_root(
pwn.data.kctf.pow.decode_challenge( pwn.data.kctf.pow.sloth_square(
pwn.data.kctf.pow.decode_number( pwn.data.kctf.pow.socket
pwn.data.kctf.pow.encode_challenge( pwn.data.kctf.pow.solve_challenge(
pwn.data.kctf.pow.encode_number( pwn.data.kctf.pow.sys
pwn.data.kctf.pow.get_challenge( pwn.data.kctf.pow.usage(
pwn.data.kctf.pow.gmpy_sloth_root( pwn.data.kctf.pow.verify_challenge(
Is kctf pow on pypi? Maybe it would be better to include it from there, or to make them submit it to pypi... otherwise looks fine
Is kctf pow on pypi?
I couldn't find any implementations on there, granted I didn't look too hard. I've also come to learn that the canonical pow.py is not Python 2 compatible, and so even if someone did put it on PyPi it probably wouldn't work for us.
It's still TODO for me to make the vendored kctf/pow.py Python 2 compatible.
I think pwntools should consider dropping Python 2 compatibility one day soon, but that's another matter... I see it was most recently discussed on #1741.
- What do you think of the use of
datafor holdingkctf/pow.pyas a library? Isdataan ok place for it? (constantsseemed like an even worse place) - Do you think
miscis an OK place for this, or should we create apowmodule to also hold things like #1318 (if it gets reopened one day)
Edited to add: Just for absolute clarity, #1318's pow.py is different to kctf/pow.py. It's why I prefixed the new functions with kctf_
Added wrapper around challenge generator
% python3
Python 3.9.2 (default, Feb 28 2021, 17:03:44)
[GCC 10.2.1 20210110] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pwn
>>> pwn.kctf_pow_<tab><tab>
pwn.kctf_pow_generate_challenge( pwn.kctf_pow_verify(
pwn.kctf_pow_solve(
>>> pwn.kctf_pow_ ^C
KeyboardInterrupt
>>> challenge = pwn.kctf_pow_generate_challenge(1337)
[WARNING] kctf-pow using random.randrange() which is not cryptographically secure
>>> challenge
's.AAU5.AACvAidE/gWv1+w9iNc0dqv2'
>>> pwn.kctf_pow_verify(challenge, pwn.kctf_pow_solve(challenge))
[NOTICE] kctf-pow running 10x slower, gotta go fast? pip3 install gmpy2
True
Used the following to connect to a host which was running the canonical pow.py under Python 3. This was done to stress test the changes made to pow.py to ensure the changes don't break compatibility.
import pwn
import six
import sys
while True:
with pwn.remote(sys.argv[1], sys.argv[2]) as t:
t.recvuntil(b"python3 <(curl -sSL https://goo.gle/kctf-pow) solve ")
challenge = six.ensure_str(t.recvline())
solution = pwn.kctf_pow_solve(challenge)
t.sendlineafter(six.ensure_binary("Solution? "), solution)
assert t.recvall() == six.ensure_binary("Correct\n")
Ran this stress test from a host running Python 2, a host running Python 3, and a host running Python 3 with gmpy2 installed.
Ready for review. I'm happy to squash the commits if that's preferred.
Is there anything I can do to get this across the line? In the meantime can this please be given the label hacktoberfest-accepted
I've realised that a new module requires changes to docs/ but I'm not sure how to do that. If someone can let me know what that change should look like I'm happy to make it.
@justinsteven sorry for the long silence! Are you willing to keep working on this? I could have used this a few times and was always annoyed this isn't merged yet.
I think having a pwnlib.pow module where other pow "providers" could live as well in the future would be great and having a tube.solve_pow("kctf") function to handle the pow for you. Stripping the implementation and keeping a notice at the top, that this is derived from kctf's pow.py + license should be fine for the kctf class.
@peace-maker I don't have time to work on this at the moment I'm afraid, please feel free to take over if you'd like :)