diff options
Diffstat (limited to 'utils/zenutils/source/shared/updater.cpp')
-rwxr-xr-x | utils/zenutils/source/shared/updater.cpp | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/utils/zenutils/source/shared/updater.cpp b/utils/zenutils/source/shared/updater.cpp new file mode 100755 index 0000000000..77d3f2876c --- /dev/null +++ b/utils/zenutils/source/shared/updater.cpp | |||
@@ -0,0 +1,151 @@ | |||
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 | |||
25 | const 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 NULL; | ||
49 | } | ||
50 | |||
51 | dword zen::find_firmware_offset(byte* buffer, size_t len) | ||
52 | { | ||
53 | for (dword i = 0; i < static_cast<dword>(len); i += 0x10) | ||
54 | { | ||
55 | dword size = *(dword*)&buffer[i]; | ||
56 | if (size < (i + len) && size > (len >> 1)) | ||
57 | { | ||
58 | if (buffer[i + sizeof(dword)] != 0 | ||
59 | && buffer[i + sizeof(dword) + 1] != 0 | ||
60 | && buffer[i + sizeof(dword) + 2] != 0 | ||
61 | && buffer[i + sizeof(dword) + 3] != 0) | ||
62 | { | ||
63 | return i; | ||
64 | } | ||
65 | } | ||
66 | } | ||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | bool 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 | |||
100 | bool zen::crypt_firmware(const char* key, byte* buffer, size_t len) | ||
101 | { | ||
102 | // Determine if the key length is dword aligned. | ||
103 | int keylen = strlen(key); | ||
104 | int keylen_rem = keylen % sizeof(dword); | ||
105 | |||
106 | // Determine how many times the key must be repeated to be dword aligned. | ||
107 | int keycycle = keylen_rem ? (sizeof(dword) / keylen_rem) : 1; | ||
108 | int keyscount = (keylen * keycycle) / sizeof(dword); | ||
109 | |||
110 | // Allocate a buffer to hold the key as an array of dwords. | ||
111 | dword* keys = new dword[keyscount]; | ||
112 | |||
113 | // Copy the key into the key array, whilst mutating it. | ||
114 | for (int i = 0; i < keyscount; i++) | ||
115 | { | ||
116 | dword val; | ||
117 | int keyoffset = (i * sizeof(dword)) % keylen; | ||
118 | if ((keyoffset+sizeof(dword)) < keylen) | ||
119 | { | ||
120 | val = *(dword*)&key[keyoffset]; | ||
121 | } | ||
122 | else | ||
123 | { | ||
124 | val = key[keyoffset] | ||
125 | | (key[(keyoffset + 1) % keylen] << 8) | ||
126 | | (key[(keyoffset + 2) % keylen] << 16) | ||
127 | | (key[(keyoffset + 3) % keylen] << 24); | ||
128 | } | ||
129 | keys[i] = (val - 0x01010101) | 0x80808080; | ||
130 | } | ||
131 | |||
132 | // Determine the number of dwords in the buffer. | ||
133 | int len_div = len / sizeof(dword); | ||
134 | |||
135 | // Decrypt all dwords of the buffer. | ||
136 | for (int i = 0; i < len_div; i++) | ||
137 | { | ||
138 | ((dword*)buffer)[i] ^= keys[i % keyscount]; | ||
139 | } | ||
140 | |||
141 | // Determine the remaining number of bytes in the buffer. | ||
142 | int len_rem = len % sizeof(dword); | ||
143 | |||
144 | // Decrypt the remaining number of bytes in the buffer. | ||
145 | for (int i = len_div * sizeof(dword); i < len; i++) | ||
146 | { | ||
147 | buffer[i] ^= ((key[i % keylen] - 0x01) | 0x80); | ||
148 | } | ||
149 | |||
150 | return true; | ||
151 | } | ||