Browse Source

Add support for encrypted installers

Implements: issue #31
coverity_scan
Daniel Scharrer 8 years ago
parent
commit
baa8c1207e
  1. 1
      CHANGELOG
  2. 2
      README.md
  3. 6
      doc/innoextract.1
  4. 27
      src/cli/extract.cpp

1
CHANGELOG

@ -2,6 +2,7 @@
innoextract 1.7 (TDB)
- Added (preliminary) support for Inno Setup 5.6.0 installers
- Added support for new GOG installers with GOG Galaxy file parts
- Added support for encrypted installers with the --password and --password-file options
- Added a --show-password option to print password check information
- Added a --check-password option to abort if the provided password does not match the stored checksum
- Fixed building in paths that contain regex expressions

2
README.md

@ -100,8 +100,6 @@ Documentation is also available as a man page:
* Names for data slice/disk files in multi-file installers must follow the standard naming scheme.
* Encrypted installers are not supported.
A perhaps more complete, but Windows-only, tool to extract Inno Setup files is [innounp](http://innounp.sourceforge.net/).
Extracting Windows installer executables created by programs other than Inno Setup is out of the scope of this project. Some of these can be unpacked by the following programs:

6
doc/innoextract.1

@ -204,7 +204,7 @@ Specifies the password to decrypt encrypted files. The password is assumed to be
Use the \fB\-\-password-file\fP option to load the password from a file or standard input instead. This option cannot be combined with \fB\-\-password-file\fP.
Use the \fB\-\-check\-password\fP option to abort processing entirely if the password is incorrect.
If this password does not match the checksum stored in the installer, encrypted files will be skipped but unencrypted files will still be extracted. Use the \fB\-\-check\-password\fP option to abort processing entirely if the password is incorrect.
.TP
\fB\-\-password-file\fP \fIFILE\fP
Load a password form the specified file. Only the first line excluding the terminating carriage return and/or line break is used as the password. The password is assumed to be encoded as UTF-8 and converted the internal according used in the installer as needed.
@ -213,7 +213,7 @@ If the special file name "\fB-\fP" is used, the password will be read from stand
Use the \fB\-\-password\fP option to specify the password on the command\-line instead. This option cannot be combined with \fB\-\-password\fP.
Use the \fB\-\-check\-password\fP option to abort processing entirely if the password is incorrect.
If this password does not match the checksum stored in the installer, encrypted files will be skipped but unencrypted files will still be extracted. Use the \fB\-\-check\-password\fP option to abort processing entirely if the password is incorrect.
.TP
\fB\-p\fP, \fB\-\-progress\fP[=\fIENABLE\fP]
By default \fBinnoextract\fP will try to detect if the terminal supports shell escape codes and enable or disable progress bar output accordingly. Pass \fB1\fP or \fBtrue\fP to \fB\-\-progress\fP to force progress bar output. Pass \fB0\fP or \fBfalse\fP to never show a progress bar.
@ -290,8 +290,6 @@ Included scripts and checks are not executed.
The mapping from Inno Setup constants like the application directory to subdirectories is hard-coded.
Names for data slice/disk files in multi-file installers must follow the standard naming scheme.
Encrypted installers are not supported.
.SH SEE ALSO
\fBcabextract\fP(1), \fBunar\fP(1), \fBunrar\fP(1), \fBunshield\fP(1), \fBtzset\fP(3)
.SH BUGS

27
src/cli/extract.cpp

@ -881,8 +881,12 @@ void process_file(const fs::path & file, const extract_options & o) {
bool multiple_sections = print_file_info(o, info);
if(!o.password.empty()) {
std::string password;
std::string password;
if(o.password.empty()) {
if(!o.quiet && (o.list || o.test || o.extract) && (info.header.options & setup::header::EncryptionUsed)) {
log_warning << "Setup contains encrypted files, use the --password option to extract them";
}
} else {
util::from_utf8(o.password, password, info.version.codepage());
if(info.header.options & setup::header::Password) {
crypto::hasher checksum(info.header.password.type);
@ -894,8 +898,15 @@ void process_file(const fs::path & file, const extract_options & o) {
} else {
log_error << "Incorrect password provided";
}
password.clear();
}
}
#if !INNOEXTRACT_HAVE_ARC4
if((o.extract || o.test) && (info.header.options & setup::header::EncryptionUsed)) {
log_warning << "ARC4 decryption not supported in this build, skipping compressed chunks";
}
password.clear();
#endif
}
if(!o.list && !o.test && !o.extract) {
@ -1015,8 +1026,8 @@ void process_file(const fs::path & file, const extract_options & o) {
<< ']');
stream::chunk_reader::pointer chunk_source;
if((o.extract || o.test) && chunk.first.encryption == stream::Plaintext) {
chunk_source = stream::chunk_reader::get(*slice_reader, chunk.first, std::string());
if((o.extract || o.test) && (chunk.first.encryption == stream::Plaintext || !password.empty())) {
chunk_source = stream::chunk_reader::get(*slice_reader, chunk.first, password);
}
boost::uint64_t offset = 0;
@ -1058,7 +1069,11 @@ void process_file(const fs::path & file, const extract_options & o) {
named = true;
}
if(chunk.first.encryption != stream::Plaintext) {
std::cout << '"' << color::dim_yellow << output.first->path() << color::reset << '"';
if(password.empty()) {
std::cout << '"' << color::dim_yellow << output.first->path() << color::reset << '"';
} else {
std::cout << '"' << color::yellow << output.first->path() << color::reset << '"';
}
} else {
std::cout << '"' << color::white << output.first->path() << color::reset << '"';
}
@ -1069,7 +1084,7 @@ void process_file(const fs::path & file, const extract_options & o) {
if(!o.quiet) {
print_size_info(file, size);
}
if(chunk.first.encryption != stream::Plaintext) {
if(chunk.first.encryption != stream::Plaintext && password.empty()) {
std::cout << " - encrypted";
}
std::cout << '\n';

Loading…
Cancel
Save