Encryption/Decryption

You are viewing a static copy of the old 2DBoy forum, which closed in 2010. It is preserved here for historical interest, but it is not possible to reply to topics. For more recent discussion about World of Goo, visit our new forum.
Encryption/DecryptionScaevolus10/27/2008 - 21:26

World of Goo uses AES in CBC mode with a 192 bit key, 0D0607070C01080506090904060D030F03060E010E02070B, to encrypt files ending in .bin, along with some other files, such as user profiles. This was discovered by a user on another forum I read, who goes by the name "gibbed".

Here is a simple Python program that will encrypt and decrypt files, and strip or add padding as appropriate. It uses a heuristic to detect whether a file is encrypted, so it might attempt to decrypt non-encrypted files with characters outside of the normal ASCII range, causing an error.

<br />#!/usr/bin/env python<br />import sys <br />from Crypto.Cipher import AES # http://www.dlitz.net/software/pycrypto/<br /><br />key = "\x0D\x06\x07\x07\x0C\x01\x08\x05\x06\x09\x09\x04\x06\x0D\x03\x0F"\<br />      "\x03\x06\x0E\x01\x0E\x02\x07\x0B"<br />aes = AES.new(key, AES.MODE_CBC)<br /><br />if len(sys.argv) > 1:<br />    text = open(sys.argv[1]).read()<br />else:<br />    text = sys.stdin.read()<br /><br />if not all(ord(c) < 128 for c in text[:100]): #check for encryption<br />    plain = aes.decrypt(text)<br />    plain = plain[:plain.rfind('\xfd\xfd\xfd\xfd')]<br />    sys.stdout.write(plain)<br />else:<br />    text += "\xfd"*4 + "\x00"*(16-(len(text)+4)%16)<br />    sys.stdout.write(aes.encrypt(text))<br />

Here is a plaintext dump of all such encrypted files: http://cyanyde.com/~scaevolus/WorldOfGoo/ (if an admin feels that hosting this infringes on your copyright, please tell me and I will remove it)

Re: Encryption/Decryptionltworek10/27/2008 - 22:36

Wow a mods forum, this is awesome thanks guys.

Anyway, heres a link to the gui app i wrote, only does one file at a time.

http://www.mediafire.com/?12yfwxqjdh1

Here's another python script written by SoulTaker

#!/usr/bin/env python                                                                                                                            <br /><br /># Uses the Python Cryptography Toolkit<br /># for Windows dummies: http://www.voidspace.org.uk/python/modules.shtml#pycrypto<br /><br />from Crypto.Cipher import AES<br />import sys                  <br />import os                    <br /><br /># AES encryption key used (192 bits)<br />key = "\x0D\x06\x07\x07\x0C\x01\x08\x05\x06\x09\x09\x04\x06\x0D\x03\x0F\x03\x06\x0E\x01\x0E\x02\x07\x0B"<br /><br />def decrypt(input):<br />    aes = AES.new(key, AES.MODE_CBC)<br />    output = aes.decrypt(input)    <br />    eof = output.find("\xfd")      <br />    if eof >= 0: output = output[:eof]<br />    return output                    <br /><br />def encrypt(input):<br />    input += "\xfd\xfd"<br />    padding = (16 - len(input)%16)%16<br />    input += padding*"\0"            <br />    aes = AES.new(key, AES.MODE_CBC) <br />    return aes.encrypt(input)        <br /><br />if len(sys.argv) <> 2 or sys.argv[1] not in ('-e','-d'):<br />    print 'Usage: goocrypt -d  (decrypt files)'<br />    print '      goocrypt -e  (encrypt files)'<br />    sys.exit(1)<br />if sys.argv[1] == '-d': what, ext_in, ext_out = 'decrypting', '.bin', '.txt'<br />if sys.argv[1] == '-e': what, ext_in, ext_out = 'encrypting', '.txt', '.bin'<br /><br />found = 0<br />for dirname in [ 'properties', 'res' ]:<br />    for (path, dirs, files) in os.walk(dirname):<br />        for name in files:<br />            if name.endswith(ext_in):<br />                found += 1<br />                path_in  = os.path.join(path, name)<br />                path_out = os.path.join(path, name[:-len(ext_in)]) + ext_out<br />                input = file(path_in, "rb").read()<br />                print "%s %s\n => %s"% (what, path_in, path_out)<br />                if what == 'decrypting': output = decrypt(input)<br />                if what == 'encrypting': output = encrypt(input)<br />                file(path_out, "wb").write(output)<br /><br />if not found:<br />    print 'No files found! (Did you run from the World Of Goo directory?)'<br />else:<br />    print found, 'files processed'

And then a third sent to me via pm by zark92

from __future__ import with_statement<br />import sys<br />from Crypto.Cipher import AES<br />import optparse <br /><br />def make_aes_cipher():<br />    """Returns a new cipher object initialized with the correct key<br />      that can be used to encrypt/decrypt files."""<br />    # AES 192 bits keys used to encrypt/decrypt data<br />    key = '0D0607070C01080506090904060D030F03060E010E02070B'<br /><br />    def key_as_binary( key ):<br />        """Converts the specified hexadecimal string into a byte string."""<br />        assert len(key) % 2 == 0<br />        binary_key = []<br />        for index in xrange(0,len(key),2):<br />            binary_key.append( chr(int(key[index:index+2],16)) )<br />        return ''.join( binary_key )<br />    <br />    binary_key = key_as_binary( key )<br />    cipher = AES.new(binary_key, AES.MODE_CBC)<br />    return cipher<br /><br />def encrypt_file( input_path, output_path ):<br />    """Encrypt XML file input_path into .bin file output_path using AES algorithm."""<br />    cipher = make_aes_cipher()<br />    with file( input_path, 'rb' ) as f:<br />        xml_data = f.read()<br />        # adds filler so that input data length is a multiple of 16<br />        filler = '\xfd\xfd\xfd\xfd' + '\0' * 12<br />        filler_size = 16 - len(xml_data) % 16<br />        xml_data += filler[0:filler_size]<br />        # encrypt the data<br />        encrypted_data = cipher.encrypt( xml_data )<br />        with file( output_path, 'wb' ) as fout:<br />            fout.write( encrypted_data )<br />            print 'Encrypted "%s" into "%s"' % (input_path, output_path)<br />    return True<br /><br />def decrypt_file( input_path, output_path ):<br />    """Decrypt a .bin file input_path into .xml file output_path using AES algorithm."""<br />    cipher = make_aes_cipher()<br />    with file( input_path, 'rb' ) as f:<br />        crypted_data = f.read()<br />        xml_data = cipher.decrypt( crypted_data )<br />        with file( output_path, 'wb' ) as fout:<br />            # clean-up the data. Usually has '\xfd\xfd\xfd\xfd\0' at the<br />            # end, but this may be truncated to first '\xfd' if<br />            # size is nearly a multiple of 16, though there will<br />            # always be at least one '\xfd'.<br />            zero_index = xml_data.find( '\0' )<br />            if zero_index != -1:<br />                xml_data = xml_data[:zero_index]<br />            fd_index = xml_data.find( '\xfd' )<br />            if fd_index != -1:<br />                xml_data = xml_data[:fd_index]<br />            fout.write( xml_data )<br />            print 'Decrypted "%s" into "%s"' % (input_path, output_path)<br />    return True<br /><br />def main():<br />    parser = optparse.OptionParser( """<br />1. %prog --decrypt encrypted-path decrypted-path<br />2. %prog --encrypt decrypted-path encrypted-path<br /><br />Usage 1 will decrypt the file specified by 'encrypted-path' into the<br />file 'decrypted-path' (the file is overwriten if it exist').<br /><br />Usage 2 will encrypt the file specified by 'decrypted-path' into the<br />file 'encrypted-path' (the file is overwriten if it exist').<br /><br />Typically, encrypted-path file should have an extension .bin, and<br />decrypted-path file should have an extension .xml.<br />""" )<br />    parser.add_option( '-d', '--decrypt', dest='decrypt', action="store_true", default = False,<br />                      help = 'Decrypt the input path into the output path' )<br />    parser.add_option( '-e', '--encrypt', dest='encrypt', action="store_true", default = False,<br />                      help = 'Encrypt the input path into the output path' )<br />    (options, args) = parser.parse_args()<br />    if len(args) != 2:<br />        parser.error( 'You must specify the input and ouput path' )<br />    if args[0] == args[1]:<br />        parser.error( 'Input path must be different from output path' )<br /><br />    if options.decrypt:<br />        return decrypt_file( args[0], args[1] )<br />    elif options.encrypt:<br />        return encrypt_file( args[0], args[1] )<br />    else:<br />        parser.error( 'You must specify either --decrypt or --encrypt' )<br /><br />if __name__ == '__main__':<br />    succeed = main()<br />    if not succeed:<br />        print 'Failed'<br />        sys.exit( 2 )<br />

You guys really all like python ehh? :)

Re: Encryption/DecryptionScaevolus10/27/2008 - 22:42

[quote author=ltworek link=topic=636.msg4527#msg4527 date=1225164986]
You guys really all like python ehh? :)

It's nice for rapid prototyping :)

I actually had this on October 15th, but didn't post it here because I wasn't sure of the reaction.

Re: Encryption/DecryptionMacatttack10/27/2008 - 23:21

It seems possible that a whole extra level could be added to the game, I'm not much of a programmer but I draw the same way and similarly to kyle in photoshop, so I'd be glad to do the mods artwork.  ;)

Re: Encryption/DecryptionMarius10/28/2008 - 03:49

Decripting and encrypting files and changing levels is possible. The main difficulty, at the moment, is getting to run the files without changing the pre-built levels. While this is not technically necessary, it would be a nice feature...

Scaevolus: We've had it since the beta ::)

Re: Encryption/DecryptionBoudin10/29/2008 - 19:11

Yet another tool to encrypt/decrypt I wrote in c++ with no depencies.
It's compiled for windows but it may be portable.
http://nioche1.free.fr/usr/AESTool.zip

This is a command line tool that just take the file name in parameters. If its extension is .bin it will decrypt the file in a file with same filename except .bin extension.
If it's another extension it will encrypt the file using the same filename plus .bin extension

If the output file already exists, it's erased with no asking so make backups before playing.

I've tested on few files and it seems to work but I there no warantee shiped with it.

A usefull tricks for moders/hackers under windows, you can easily add this tool in context menu for bin and xml file under explorer :

   - Open an explorer window
   - Click on Tools menu then Folder Options
   - Select FileTypes tab
   - In the list choose bin (if it doesn't appears, click on new, enter bin and Ok)
   - Click on Advanced button
   - Click on New button
   - In the action box, type what you want, for example Decrypt file
   - In the Application Used to Perform Action box select the AESTool.exe file you've download
   - That's it, now when you right click on a bin file you can decrypt the file and it will automaticly generate the xml under the same directory. You can also decrypt multiple files by selecting two or more.

You can do the same thing on XML files for easy encryption.

Edit 2008/10/30 :
I've updated the version, correcting a bug that was preventing from decrypt a file whose original size was a multiple of 16.
It add the possibility to force Decrypting/Encrypting using this command line :
Encrypt : AESTool -e input output
Decrypt : AESTool -d input output
It still can be used as the previous version, so the trick to add it in context menu still works.

I join src if someone want to try to compile under another os than windows (or to improve it)

31/10/08
I've corrected another little bug (encryption and decryption was going wrong with files that was 3 or less bytes under a 16 multiplier).
I've updated binary on the FTP and the source-code attached on the thred.


 


Last modified Fri, 10/31/2008 - 14:16 by Boudin
Attachment: AESTool_src.zip (25.8 KB, 308 downloads)
Re: Encryption/Decryptionzark9211/01/2008 - 05:31

I've polished up the tool I initially made. They are now available on sourceforge at:
http://sourceforge.net/projects/wogedit

Both as python source & windows executable.

Enjoy.

Re: Encryption/DecryptionNicosmos11/01/2008 - 06:00

Is it possible to encrypt and decrypt Goo files on Linux ?
I don't find PyCrypto binaries for Gnu/Linux.

Re: Encryption/DecryptionBoudin11/01/2008 - 06:25

You can try to compile my thing, there's no dependecies with windows librairies.
For that, unzip file into any directory and enter this :

gcc Rijndael.cpp main.cpp -o AESTool (I think, it's been a long time since I didn't build something under linux)

Re: Encryption/DecryptionSoultaker11/01/2008 - 09:04

[quote author=Nicosmos link=topic=636.msg4841#msg4841 date=1225537245]
Is it possible to encrypt and decrypt Goo files on Linux ?
I don't find PyCrypto binaries for Gnu/Linux.
Practically all distros have a package for it, but it might be called different. For example, it's python-crypto on Debian/Ubunty.

[quote author=Boudin link=topic=636.msg4848#msg4848 date=1225538717]
gcc Rijndael.cpp main.cpp -o AESTool
You should use g++ instead or gcc to ensure the linker is invoked correctly; otherwise, that line should work just fine. (You can add -O2 for a somewhat faster executable)

Re: Encryption/Decryptionzark9211/01/2008 - 11:29

[quote author=Nicosmos link=topic=636.msg4841#msg4841 date=1225537245]
Is it possible to encrypt and decrypt Goo files on Linux ?
I don't find PyCrypto binaries for Gnu/Linux.

It should be fairly to install from the source (I did it on Windows). Download the tarball (http://www.amk.ca/python/code/crypto.html) and run in the decompressed directory:
python setup.py install

It will compile the required module and install them in your python distribution automatically as long as you have a compiler available.

Re: Encryption/DecryptionNicosmos11/01/2008 - 12:36

I don't find the sources of your AESTools. Where are they ?
But I installed the python-crypto package and it works fine with Python scripts of this topic. ;D

Is it possible to decrypt the pers2.dat file ? I think yes because the Soultaker's site probably do it to import user data. I would like to merge two profile in one, selecting some scores (OCDs) from one (my demo profile) to insert them in the other. And I would like rename this profile too. :P

Re: Encryption/DecryptionBoudin11/01/2008 - 12:41

Sources are at the end of the post (attached file)

Re: Encryption/DecryptionDaid11/01/2008 - 16:58

I noticed that there are junk bytes behind each extracted file. Are those intended or is that a bug in the extractor?

Also, I changed my favorite map (Tumbler) to have a twice as large wheel, but the wheel was not stable. I'm guessing there are some problems with very large rotating things, but I could have made another error.

As for "extra" levels, I tried to get that working. But I got stuck on the button events. In the "islandX" en "MapWorldView" there are buttons that use event names. But I cannot find the event names anywhere else and I fear that they might be hardcoded. I did manage to add a 2nd button to an island.

Re: Encryption/DecryptionMarius11/01/2008 - 17:10

You managed to make a button on an island that actually boots a different level? That's pretty nice!

Re: Encryption/DecryptionSoultaker11/01/2008 - 17:27

Actually, adding new levels to existing islands is old news; I did that during the beta. ;) Adding a new "custom levels" island to the main menu is the tricky part, and that doesn't seem possible without modifying the executable. However, Ron more or less promised to add support for specifying levels on the command line in the future, so that should make custom level loading a whole lot easier.

[quote author=Daid link=topic=636.msg4895#msg4895 date=1225576714]In the "islandX" en "MapWorldView" there are buttons that use event names. But I cannot find the event names anywhere else and I fear that they might be hardcoded.
You're right, they are hardcoded. The only unused action I found was "island6" on the current version, but using that crashes the program, as the individual island levels that correspond to these actions are also hardcoded into an array with only five elements.

Quote:
I noticed that there are junk bytes behind each extracted file. Are those intended or is that a bug in the extractor?

Which extractor did you use? My tool explicitly removes those bytes from the end of the file. The problem is that the files must be padded to a 16-byte boundary before encryption, but no common padding method is used. In that sense, the extractor would be right to keep the junk, but I find it is better to strip them, otherwise the output may not be valid XML and more and more junk accumulates when you modify the file and re-encode it.

Re: Encryption/DecryptionDaid11/01/2008 - 17:48

[quote author=Soultaker link=topic=636.msg4902#msg4902 date=1225578469]
Actually, adding new levels to existing islands is old news; I did that during the beta. ;) Adding a new "custom levels" island to the main menu is the tricky part, and that doesn't seem possible without modifying the executable. However, Ron more or less promised to add support for specifying levels on the command line in the future, so that should make custom level loading a whole lot easier.

[quote author=Daid link=topic=636.msg4895#msg4895 date=1225576714]In the "islandX" en "MapWorldView" there are buttons that use event names. But I cannot find the event names anywhere else and I fear that they might be hardcoded.
You're right, they are hardcoded. The only unused action I found was "island6" on the current version, but using that crashes the program, as the individual island levels that correspond to these actions are also hardcoded into an array with only five elements.

Quote:
I noticed that there are junk bytes behind each extracted file. Are those intended or is that a bug in the extractor?

Which extractor did you use? My tool explicitly removes those bytes from the end of the file. The problem is that the files must be padded to a 16-byte boundary before encryption, but no common padding method is used. In that sense, the extractor would be right to keep the junk, but I find it is better to strip them, otherwise the output may not be valid XML and more and more junk accumulates when you modify the file and re-encode it.
I used the exe out of the topic here, not sure which. But the padding bytes make sense. Has any work started on a level editor? I wouldn't mind helping out.

Re: Encryption/DecryptionBoudin11/01/2008 - 20:39

If i've understood the bytes added, there's no padding if file size match exactly needed size for ecryption algortithm. If size doesn't match, there's one to 4 0xFD bytes added. If more bytes are needed, these are folowed by 1 to 11 0x00 bytes. My tool remove these to (or is supposed to since i may have missunderstood something and it is quick and dirty written).

I've begun to think about an editor but I'm trying to figure a way to add levels into the game without modify existing island but some things seems to be hardcoded (I managed to add a button on World of Goo main screen but I didn't found a way to link it to a new island, at least it is a godd exception generator :))

Re: Encryption/DecryptionPants11/01/2008 - 20:53

Anybody have some brilliant ideas for how to decrypt the mac versions? If that's solved, then we'll have a way of converting back and forth across platforms.

I bought WOG on steam before I even saw there was a Mac version coming out, so I bought a Mac copy too. :)

Re: Encryption/DecryptionSoultaker11/01/2008 - 21:21

[quote author=Daid link=topic=636.msg4903#msg4903 date=1225579706]
Has any work started on a level editor? I wouldn't mind helping out.
zark92 posted some info on a level editor he is working.

Re: Encryption/DecryptionMacatttack11/01/2008 - 23:00

[quote author=Soultaker link=topic=636.msg4917#msg4917 date=1225592467]
[quote author=Daid link=topic=636.msg4903#msg4903 date=1225579706]
Has any work started on a level editor? I wouldn't mind helping out.
zark92 posted some info on a level editor he is working.

Wow that's so cool!!! I can't wait to make my own levels.  :)

Re: Encryption/DecryptionBoudin11/02/2008 - 07:07

[quote author=Pants link=topic=636.msg4916#msg4916 date=1225590784]
Anybody have some brilliant ideas for how to decrypt the mac versions? If that's solved, then we'll have a way of converting back and forth across platforms.

I bought WOG on steam before I even saw there was a Mac version coming out, so I bought a Mac copy too. :)




I don't know if the encryption method (or key) changed bettween the window and macos versions. The quickest way to figure it out is to try existing tools on mac

Re: Encryption/DecryptionDaid11/02/2008 - 09:00

Great. Maybe we can make a mod installer that adds new levels to the last island before a custom island is supported? Because the last island is mostly empty, and with a good installer you should be able to get multiple level mods next to each other.

Re: Encryption/DecryptionSoultaker11/02/2008 - 09:11

[quote author=Boudin link=topic=636.msg4936#msg4936 date=1225627649]
I don't know if the encryption method (or key) changed bettween the window and macos versions. The quickest way to figure it out is to try existing tools on mac
For one thing, the file sizes aren't multiples of 16, so that suggests there have been more changes than just that.

A nice starting point would be to see if files with similar plaintext start with the same bytes. (For example, in the PC version, all Level.resrc.bin files start with the same data, because their plaintext begins with "<ResourceManifest> <Resources id=..." and no intialization vector is used to cover this up.

Re: Encryption/Decryptionzark9211/02/2008 - 11:20

[quote author=Soultaker link=topic=636.msg4902#msg4902 date=1225578469]
Actually, adding new levels to existing islands is old news; I did that during the beta. ;) Adding a new "custom levels" island to the main menu is the tricky part, and that doesn't seem possible without modifying the executable. However, Ron more or less promised to add support for specifying levels on the command line in the future, so that should make custom level loading a whole lot easier.

Would you mind providing the step to add a level to an existing island? I remember trying to do that and just ending up with a black screen when loading the island...

Re: Encryption/DecryptionSoultaker11/02/2008 - 12:18

Ok, a simply walkthrough. I assume you are able to decrypt and encrypt files; I use my tool to decrypt everything first and encrypt everything again in the end.

First, I'll copy an existing level to use for testing. For example, copy res/levels/GoingUp to res/levels/NewLevel. In res/levels/NewLevel/, rename the scene, level and resrc files from GoingUp to NewLevel; edit NewLevel.resrc and change the id from scene_GoingUp to scene_NewLevel.

In properties/text, add a level name and a level text, for example:
[pre]  <string id="LEVEL_NAME_NEWLEVEL" text="New Level Name"/>
  <string id="LEVEL_TEXT_NEWLEVEL" text="New Level Text"/>[/pre]
Now we're going to add our level to an island. Open res/levels/island5 and add:
[pre]  <level id="NewLevel" name="LEVEL_NAME_NEWLEVEL" text="LEVEL_TEXT_NEWLEVEL" />[/pre]
And add a button in res/levels/island5.scene (in or after the button group):
[pre]  <button id="lb_NewLevel" depth="8" x="50" y="900"
   up="IMAGE_SCENE_ISLAND5_LEVELMARKERA_UP"
   over="IMAGE_SCENE_ISLAND5_LEVELMARKERA_OVER"
   onclick="pl_NewLevel" onmouseenter="ss_NewLevel" onmouseexit="hs_NewLevel" />[/pre]
(The up, over, onmouseenter and onmousexit attributes are just to provide eyecandy; you can leave em out.)

Encrypt everything and presto! There is a new level button on the fifth island, right next to the final level. Click it to play our new level (which is still identical to Going Up, but you can edit it, of course). At least, that is what should happen if you did exactly what I described and I described it correctly. Let me know if this works for you.


Last modified Sun, 11/02/2008 - 12:22 by Soultaker
Re: Encryption/Decryptiondavidc11/03/2008 - 12:20

Did anyone else notice the 3 extraneous bytes at the start of the decrypted  text.xml.bin? They're 0xEF 0xBB 0xBF and don't seem to appear in any other decrypted files.

Any idea what they're for? Some kind of signature? Scaevolus's tool produces them too.

Re: Encryption/DecryptionSoultaker11/03/2008 - 12:42

[quote author=davidc link=topic=636.msg5034#msg5034 date=1225732816]
Did anyone else notice the 3 extraneous bytes at the start of the decrypted  text.xml.bin? They're 0xEF 0xBB 0xBF and don't seem to appear in any other decrypted files.
That would be an UTF-8 encoded byte order mark. It may be caused by text editors adding it, or by converting an encoded file from UCS-2 with BOM to UTF-8. At any rate, it's not necessary (UTF-8 has no byte ordering issues) but it causes no harm either.

Re: Encryption/Decryptiondavidc11/03/2008 - 14:16

Thanks, I'll just skip over the first 3 bytes if they match then.

Re: Encryption/Decryptionploppy11/05/2008 - 05:56

[quote author=Pants link=topic=636.msg4916#msg4916 date=1225590784]
Anybody have some brilliant ideas for how to decrypt the mac versions? If that's solved, then we'll have a way of converting back and forth across platforms.

I bought WOG on steam before I even saw there was a Mac version coming out, so I bought a Mac copy too. :)


In the Mac version, the obfuscation has changed from AES to a boring xor-based algorithm, and (I guess) as some sort of optimization the png images are stored as squares without the usual png headers.

Here is a Python program that will decrypt pers2.dat and files ending in .bin and repack images ending in .png.binltl into standard png. I'll leave it as an exercise to someone else to write a program to do the inverse.

#!/usr/bin/env python<br />import sys, zlib, struct<br /><br />if len(sys.argv) > 1:<br />  text = open(sys.argv[1]).read()<br />  if sys.argv[1][-4:] == ".bin" or sys.argv[1][-4:] == ".dat":<br />    size = len(text)<br />    a = (((size & 1) << 6) | ((size & 2) << 3) | (size & 4)) ^ 0xffffffab<br />    for c in text:<br />      sys.stdout.write(chr((a ^ ord(c)) & 0xff))<br />      a = ((a & ~0xff) | (a << 1 | (a & 0x80) >> 7) & 0xff) ^ ord(c)<br />  elif sys.argv[1][-11:] == ".png.binltl":<br />    # repack .png.binltl files into png<br />    width, height, size, fullsize = struct.unpack("<HHII", text[:12])<br />    data = zlib.decompress(text[12:12+size])<br />    side = 1<br />    while side < width or side < height:<br />      side *= 2<br />    assert fullsize == side * side * 4<br />    image = ""<br />    # images are stored as a square, so crop the image data<br />    for line in range(height):<br />      # 00 filter type byte for png<br />      image += "\x00" + data[line*side*4:(line*side + width)*4]<br />    # output png<br />    sys.stdout.write("\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")<br />    def chunk(type, data):<br />      check = type + data<br />      sys.stdout.write(struct.pack(">I", len(data)))<br />      sys.stdout.write(check)<br />      sys.stdout.write(struct.pack(">I", zlib.crc32(check) & 0xffffffff))<br />    chunk("IHDR", struct.pack(">II", width, height) + "\x08\x06\x00\x00\x00")<br />    chunk("IDAT", zlib.compress(image, 9))<br />    chunk("IEND", "")<br />  else:<br />    sys.stdout.write(text)<br />


Last modified Wed, 11/05/2008 - 07:10 by ploppy
Re: Encryption/DecryptionSoultaker11/07/2008 - 14:05

[quote author=ploppy link=topic=636.msg5170#msg5170 date=1225882594]
Here is a Python program that will decrypt pers2.dat and files ending in .bin and repack images ending in .png.binltl into standard png. I'll leave it as an exercise to someone else to write a program to do the inverse.
Great work! By the way, I noticed the XOR "encryption" only uses a single byte of state, so the algorithm can be somewhat simplified to:
    size = len(text)<br />    a = (((size & 1) << 6) | ((size & 2) << 3) | (size & 4)) ^ 0xab<br />    for c in text:<br />      sys.stdout.write(chr(a ^ ord(c)))<br />      a = ((a & 0x7f) << 1 | (a & 0x80) >> 7) ^ ord(c)<br />
I've used this to add Mac support to my profile page (pers2.dat files from the Mac can now be uploaded) and to provide Mac-compatible translation files.

Re: Encryption/DecryptionSoultaker11/10/2008 - 13:10

By the way, I created a quick tool to convert the Mac .png.binltl files to and from PNG; this will be useful to get custom fonts and images working on the Mac too. Credits go to ploppy for figuring out the file format!

A 32-bit Windows executable is here: convert-png-binltl-2008-11-10-win32.zip
C source code is attached too; you need libpng and zlib to compile.

Attachment: convert-png-binltl.c.txt (5.46 KB, 323 downloads)
Re: Encryption/Decryptiontridash11/12/2008 - 19:06

sorry, but could someone post a mac encryption program/script?

Re: Encryption/DecryptionSoultaker11/12/2008 - 20:00

Not entirely tested, but here is a Mac version of my program (Save to goocrypt-mac.py or something, and run from the World of Goo directory):

#!/usr/bin/env python<br /><br />import sys<br />import os<br /><br />def decrypt(input):<br />    output = ''<br />    size = len(input)<br />    a = (((size & 1) << 6) | ((size & 2) << 3) | (size & 4)) ^ 0xab<br />    for c in input:<br />      output += chr(a ^ ord(c))<br />      a = ((a & 0x7f) << 1 | (a & 0x80) >> 7) ^ ord(c)<br />    return output<br /><br />def encrypt(input):<br />    output = ''<br />    size = len(input)<br />    a = (((size & 1) << 6) | ((size & 2) << 3) | (size & 4)) ^ 0xab<br />    for c in input:<br />      output += chr(a ^ ord(c))<br />      a = ((a & 0x7f) << 1 | (a & 0x80) >> 7) ^ ord(output[-1])<br />    return output<br /><br />if len(sys.argv) <> 2 or sys.argv[1] not in ('-e','-d'):<br />    print 'Usage: goocrypt -d  (decrypt files)'<br />    print '      goocrypt -e  (encrypt files)'<br />    sys.exit(1)<br />if sys.argv[1] == '-d': what, ext_in, ext_out = 'decrypting', '.bin', '.txt'<br />if sys.argv[1] == '-e': what, ext_in, ext_out = 'encrypting', '.txt', '.bin'<br /><br />found = 0<br />for dirname in [ 'properties', 'res' ]: <br />    for (path, dirs, files) in os.walk(dirname):<br />        for name in files:<br />            if name.endswith(ext_in):<br />                found += 1<br />                path_in  = os.path.join(path, name)<br />                path_out = os.path.join(path, name[:-len(ext_in)]) + ext_out<br />                input = file(path_in, "rb").read()<br />                print "%s %s\n => %s"% (what, path_in, path_out)<br />                if what == 'decrypting': output = decrypt(input)<br />                if what == 'encrypting': output = encrypt(input)<br />                file(path_out, "wb").write(output)<br /><br />if not found:<br />    print 'No files found! (Did you run from the World Of Goo directory?)'<br />else:<br />    print found, 'files processed'<br />
Note that this will probably produce garbage with the PC version of the files.

Re: Encryption/Decryptionhakujin11/22/2008 - 12:11

[quote author=Scaevolus link=topic=636.msg4528#msg4528 date=1225165343]
[quote author=ltworek link=topic=636.msg4527#msg4527 date=1225164986]
You guys really all like python ehh? :)

It's nice for rapid prototyping :)

I actually had this on October 15th, but didn't post it here because I wasn't sure of the reaction.


With your tool, is it possible to make a windows save file work on Mac? I see a resulting .xml and wonder if one could rename that unencrypted dat and move it to the applicable mac save directory to resume where one left off.


Last modified Sat, 11/22/2008 - 12:15 by hakujin
Re: Encryption/Decryptionph.mongeau12/21/2008 - 12:31

I tried to run the two mac decrypter posted above and none of theme worked for me, the first one (decrypt only) outputed this :
"?PNG<br /><br />IHDR<br />]?IDATxڍӻ<br />?@??-,D??????`??P?."1????3?+㺎3?CH>?Nc?Xk?h?N??e??D??tC=?*hA? ??[?(`A0W???Ds???~}T?&Oגf?IEND?B`?"

And the other one said
"No files found! (Did you run from the World Of Goo directory?)"
Even if i was in the world of goo direcory.

Can someone help me to figure out what I'm doing wrong? ???

Re: Encryption/DecryptionSoultaker12/21/2008 - 12:54

The first one actually looks OK to me if you tried to decode an image (at least it looks like PNG headers; the data may still be garbage).

The second tool (my decryptor) looks for files named .bin in subdirectories of res/ and properties/ in the current directory, so if none are found, you probably are in the wrong directory (you should check whether e.g. a directory called "res" exists).

Note that my tool only decrypts files; to convert images to PNG and back (for example, if you want to edit them) I posted a different tool for that.

Re: Encryption/Decryptionph.mongeau12/21/2008 - 13:05

Quote:
The first one actually looks OK to me if you tried to decode an image (at least it looks like PNG headers; the data may still be garbage).


I tried to decode an image but it didn't create an png file, i just got the terminal output.

Quote:
The second tool (my decryptor) looks for files named .bin in subdirectories of res/ and properties/ in the current directory, so if none are found, you probably are in the wrong directory (you should check whether e.g. a directory called "res" exists).


There's a res and a properties in the directory from where I run the script, but it still doesn't work. Does it work with binltl files?

Re: Encryption/DecryptionSoultaker12/22/2008 - 06:54

Hmz, are there no .bin files at all in the Mac version? The decryption tool was intended to decode/encode level and resource scripts (.level.bin, .scene.bin, and so on); if you want to decode/encode images, there this tool instead.

Re: Encryption/Decryptionph.mongeau12/22/2008 - 10:58

Yes, what i wanted was a tool to decode pngs.
There's some .bin files on the mac to, i don't know why your tool didn't find theme ???
The tool to decode .png files could work, but it's for windows and i'm on a mac. I could maybe try running it with crossover but I don't have it with on this computer, I'll try next week, Thanks :)

Re: Encryption/DecryptionSoultaker12/22/2008 - 15:09

I also posted the source code for that tool; I understand compiling stuff on the Mac isn't too hard, but I don't know for sure as I don't have a Mac myself.

Another option is running the Windows executable using Wine, which should work on Mac OS to; just Google for Darwine and you should be able to find an installer.

Re: Encryption/Decryptionph.mongeau12/22/2008 - 15:33

Quote:
Another option is running the Windows executable using Wine


Yeah, that's what I meant when I said:

Quote:
I could maybe try running it with crossover

crossover is based on Darwine

Re: Encryption/DecryptionSoultaker12/22/2008 - 15:44

Ah, I didn't realize that. That'll probably work then.