├── LICENSE ├── README.md ├── ghidra_plugin_ioncube_decrypt.py └── string_decoder.c /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, ☃ Stephen Shkardoon ☃ 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ioncube-string-decoder 2 | ====================== 3 | 4 | Hacky script(s) for decoding strings stored in the ioncube loader 5 | 6 | No idea if this works for other versions. Feel free to send a PR with the encryption_data for other versions if it doesn't. 7 | -------------------------------------------------------------------------------- /ghidra_plugin_ioncube_decrypt.py: -------------------------------------------------------------------------------- 1 | # Decrypts "encrypted" strings from ioncube's loaders 2 | #@author ss23 3 | #@category _NEW_ 4 | #@keybinding 5 | #@menupath 6 | #@toolbar 7 | 8 | encryption_key = [0x25,0x68,0xd3,0xc2,0x28,0xf2,0x59,0x2e,0x94,0xee,0xf2,0x91,0xac,0x13,0x96,0x95] 9 | 10 | def attemptDecrypt(addr): 11 | tmplength = getByte(addr) 12 | if tmplength < 0: 13 | length = tmplength + 256 14 | else: 15 | length = tmplength 16 | #print length 17 | content = getBytes(addr.next(), length) 18 | 19 | # Convert negatives into positives 20 | # TODO: Surely there's an API call for this 21 | new_content = [] 22 | for i in range(0, length): 23 | # jython why 24 | if content[i] < 0: 25 | new_content.append(content[i] + 256) 26 | else: 27 | new_content.append(content[i]) 28 | 29 | decrypted_string = "" 30 | 31 | # Decrypt the content 32 | for i in range(0, length): 33 | decrypted_string += chr(new_content[i] ^ encryption_key[(length + i) % len(encryption_key)]) 34 | 35 | return decrypted_string 36 | 37 | funcs = getGlobalFunctions("ioncube_decrypt") 38 | if len(funcs) < 1: 39 | print "Could not identify ioncube_decrypt function" 40 | exit() 41 | elif len(funcs) > 1: 42 | print "Too many ioncube_decrypt functions identified" 43 | exit() 44 | 45 | 46 | refs = getReferencesTo(funcs[0].getEntryPoint()) 47 | for ref in refs: 48 | addr = ref.getFromAddress() 49 | # instruction before should be the "push encrypted_string" we want 50 | instr = getInstructionBefore(addr) 51 | if (type(instr) == type(None)): 52 | continue 53 | possible_data_addr = instr.getOpObjects(0)[0] 54 | 55 | # Java! 56 | addr_factory = getAddressFactory() 57 | # Get the assumed-length 58 | possible_data_addr_str = possible_data_addr.toString() 59 | possible_data_addr = addr_factory.getAddress(possible_data_addr_str) 60 | 61 | decrypted_string = attemptDecrypt(possible_data_addr) 62 | 63 | # TODO: Figure out how to set repeatable comments on a symbol / address 64 | # TODO: Do not duplicate comments 65 | setPreComment(possible_data_addr, "decrypted: " + decrypted_string) 66 | 67 | #print possible_data_addr 68 | 69 | print "Completed" 70 | 71 | -------------------------------------------------------------------------------- /string_decoder.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char * argv[]) { 4 | /* Extracted from 5.6 ioncube loader */ 5 | char encryption_data[] = { 6 | 0x25, 7 | 0x68, 8 | 0xd3, 9 | 0xc2, 10 | 0x28, 11 | 0xf2, 12 | 0x59, 13 | 0x2e, 14 | 0x94, 15 | 0xee, 16 | 0xf2, 17 | 0x91, 18 | 0xac, 19 | 0x13, 20 | 0x96, 21 | 0x95 22 | }; 23 | 24 | /* Replace with your dataz. Remember not to include the 0x00 at the end */ 25 | char encrypted_string[] = { 26 | 0x9b, 27 | 0x36, 28 | 0x40, 29 | 0xd7, 30 | 0x9b, 31 | 0x90, 32 | 0xf4, 33 | 0x8c, 34 | 0x56, 35 | 0xe0, 36 | 0xf0, 37 | 0x4b, 38 | 0x1c, 39 | 0xf3, 40 | 0x8a, 41 | 0x49, 42 | 0x9c, 43 | 0x3d, 44 | 0x42, 45 | 0xf1, 46 | 0x9c, 47 | 0xf2 48 | }; 49 | 50 | int size = sizeof(encrypted_string); 51 | for (int i = 0; i < size; i++) { 52 | encrypted_string[i] = encrypted_string[i] ^ encryption_data[(size + i - 1) % sizeof(encryption_data)]; 53 | } 54 | 55 | printf("%s\r\n", encrypted_string); 56 | } 57 | --------------------------------------------------------------------------------