A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 169 lines 4.8 kB view raw
1/* zenutils - Utilities for working with creative firmwares. 2 * Copyright 2007 (c) Rasmus Ry <rasmus.ry{at}gmail.com> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 */ 18 19#include "updater.h" 20#include <file.h> 21#include <pe.h> 22#include <utils.h> 23 24 25const char* zen::find_firmware_key(const byte* buffer, size_t len) 26{ 27 char szkey1[] = "34d1"; 28 size_t cchkey1 = strlen(szkey1); 29 char szkey2[] = "TbnCboEbn"; 30 size_t cchkey2 = strlen(szkey2); 31 for (int i = 0; i < static_cast<int>(len); i++) 32 { 33 if (len >= cchkey1) 34 { 35 if (!strncmp((char*)&buffer[i], szkey1, cchkey1)) 36 { 37 return (const char*)&buffer[i]; 38 } 39 } 40 if (len >= cchkey2) 41 { 42 if (!strncmp((char*)&buffer[i], szkey2, cchkey2)) 43 { 44 return (const char*)&buffer[i]; 45 } 46 } 47 } 48 return ""; 49} 50 51dword zen::find_firmware_offset(byte* buffer, size_t len) 52{ 53 for (dword i = 0; i < static_cast<dword>(len); i += 4) 54 { 55 dword size = *(dword*)&buffer[i]; 56 if (size != 0 57 && buffer[i + 4] != 0 58 && buffer[i + 4 + 1] != 0 59 && buffer[i + 4 + 2] != 0 60 && buffer[i + 4 + 3] != 0) 61 { 62 return i; 63 } 64 if(i > 0xFF) /* Arbitrary guess */ 65 return 0; 66 } 67 return 0; 68} 69 70bool zen::find_firmware_archive(const std::string& filename, dword& va, dword& pa) 71{ 72 shared::pe_file pef; 73 if (!pef.read(filename)) 74 { 75 return false; 76 } 77 shared::section_info data_section; 78 if (!pef.find_section(".data", data_section)) 79 { 80 return false; 81 } 82 shared::bytes buffer; 83 if (!shared::read_file(filename, buffer, data_section.raw_address, 84 data_section.raw_size)) 85 { 86 return false; 87 } 88 dword offset = find_firmware_offset(&buffer[0], buffer.size()); 89 if (!offset) 90 { 91 return false; 92 } 93 va = data_section.virtual_address + offset; 94 pa = data_section.raw_address + offset; 95 96 return true; 97} 98 99 100bool zen::crypt_firmware(const char* key, byte* buffer, size_t len) 101{ 102#if 1 103 char key_cpy[255]; 104 unsigned int i; 105 unsigned int tmp = 0; 106 int key_length = strlen(key); 107 108 for(i=0; i < strlen(key); i++) 109 key_cpy[i] = key[i] - 1; 110 111 for(i=0; i < len; i++) 112 { 113 buffer[i] ^= key_cpy[tmp] | 0x80; 114 tmp = (tmp + 1) % key_length; 115 } 116 117 return true; 118#else 119 /* Determine if the key length is dword aligned. */ 120 int keylen = strlen(key); 121 int keylen_rem = keylen % sizeof(dword); 122 123 /* Determine how many times the key must be repeated to be dword aligned. */ 124 int keycycle = keylen_rem ? (sizeof(dword) / keylen_rem) : 1; 125 int keyscount = (keylen * keycycle) / sizeof(dword); 126 127 /* Allocate a buffer to hold the key as an array of dwords. */ 128 dword* keys = new dword[keyscount]; 129 130 /* Copy the key into the key array, whilst mutating it. */ 131 for (int i = 0; i < keyscount; i++) 132 { 133 dword val; 134 int keyoffset = (i * sizeof(dword)) % keylen; 135 if ((keyoffset+sizeof(dword)) < keylen) 136 { 137 val = *(dword*)&key[keyoffset]; 138 } 139 else 140 { 141 val = key[keyoffset] 142 | (key[(keyoffset + 1) % keylen] << 8) 143 | (key[(keyoffset + 2) % keylen] << 16) 144 | (key[(keyoffset + 3) % keylen] << 24); 145 } 146 keys[i] = (val - 0x01010101) | 0x80808080; 147 } 148 149 /* Determine the number of dwords in the buffer. */ 150 int len_div = len / sizeof(dword); 151 152 /* Decrypt all dwords of the buffer. */ 153 for (int i = 0; i < len_div; i++) 154 { 155 ((dword*)buffer)[i] ^= keys[i % keyscount]; 156 } 157 158 /* Determine the remaining number of bytes in the buffer. */ 159 int len_rem = len % sizeof(dword); 160 161 /* Decrypt the remaining number of bytes in the buffer. */ 162 for (int i = len_div * sizeof(dword); i < len; i++) 163 { 164 buffer[i] ^= ((key[i % keylen] - 0x01) | 0x80); 165 } 166 167 return true; 168#endif 169}