Exploitation
PYC Files
PYC files are Python bytecode files. They can be decompiled using uncompyle6, like so:
$ uncompyle6 ./PYTHON2.pyc
# uncompyle6 version 3.9.0
# Python bytecode version base 2.7 (62211)
# Decompiled from: Python 3.10.8 (main, Jan 11 2023, 17:52:38) [GCC 9.4.0]
# Embedded file name: NCL-2015-Python2.py
# Compiled at: 2015-11-12 17:43:01
import sys
def main():
if len(sys.argv) != 2:
print 'Invalid args'
return
password = sys.argv[1]
counter = 0
vals = list('tfzbwlyzljylawhzzdvyk')
if len(password) != len(vals):
print 'incorrect'
return
while counter < len(password):
x = ord(password[counter]) + 7
if x > ord('z'):
x -= 26
if chr(x) != vals[counter]:
print 'incorrect'
return
counter += 1
print 'correct'
if __name__ == '__main__':
main()
# okay decompiling ./PYTHON2.pyc
So for the above example, the password is mysupersecretpassword
. We get this by determining that the correct password has 21 characters, where each character is the result of adding 7 to the corresponding character in the string "tfzbwlyzljylawhzzdvyk", modulo 26. This can be achieved by applying a Caesar cipher with a shift of 7 on the string "tfzbwlyzljylawhzzdvyk".
Python
Another Python example:
import sys
def main():
if len(sys.argv) != 2:
print 'Invalid args'
return
password = sys.argv[1]
builder = 0
for c in password:
builder += ord(c)
builder = builder << 2
builder = ~builder
builder = builder ^ 12648430
builder = ~builder
if builder == 12645638 and ord(password[0]) == 78 and len(password) == 11:
print 'correct'
else:
print 'incorrect'
if __name__ == '__main__':
main()
The way this one was solved is:
- The password is 11 characters long.
- The first character is
N
, which is78
in ASCII. - The password is the result of applying the following operations to the sum of the ASCII values of the characters in the password:
- Bitwise left shift by 2.
- Bitwise NOT.
- Bitwise XOR with
12648430
. - Bitwise NOT.
- The result of the above operations is
12645638
.
So to solve it, we must perform the above operations in reverse order, and then convert the result to ASCII. This can be done in Python:
>>> builder = 12645638
>>> builder = ~builder
>>> builder = builder ^ 12648430
>>> builder = ~builder
>>> builder = builder >> 2
>>> builder
698
# We know the first character is N, so we can subtract 78 from the result
>>> builder = builder - 78
# We know the password is 11 characters long, so we can divide the result by 10
>>> builder = builder / 10
>>> builder
62
# We can now convert the result to ASCII
>>> chr(builder)
'>'
# That leaves us with the final password: 'N>>>>>>>>>>'
Binaries
The first step when reversing a binary is always to run strings
and skim the results for anything that looks interesting.