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 is78in 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.