def _CreateOutputDir(self): """Windows templates also include the nanny.""" build_helpers.MakeBuildDirectory(context=self.context) output_dir = build_helpers.BuildWithPyInstaller(context=self.context) # Get any dll's that pyinstaller forgot: for module in _EnumMissingModules(): logging.info("Copying additional dll %s.", module) shutil.copy(module, output_dir) self.BuildNanny(output_dir) # Generate a prod and a debug version of nanny executable. shutil.copy(os.path.join(output_dir, "GRRservice.exe"), os.path.join(output_dir, "dbg_GRRservice.exe")) with io.open(os.path.join(output_dir, "GRRservice.exe"), "rb+") as fd: build_helpers.SetPeSubsystem(fd, console=False) with io.open(os.path.join(output_dir, "dbg_GRRservice.exe"), "rb+") as fd: build_helpers.SetPeSubsystem(fd, console=True) # Generate a prod and a debug version of client executable. shutil.copy(os.path.join(output_dir, "grr-client.exe"), os.path.join(output_dir, "dbg_grr-client.exe")) with io.open(os.path.join(output_dir, "grr-client.exe"), "rb+") as fd: build_helpers.SetPeSubsystem(fd, console=False) with io.open(os.path.join(output_dir, "dbg_grr-client.exe"), "rb+") as fd: build_helpers.SetPeSubsystem(fd, console=True) self.CopyBundledFleetspeak(output_dir) return output_dir
def _MakeSelfExtractingZip(self, payload_data, output_path): """Repack the installer into the payload. Args: payload_data: data payload for zip file output_path: filename for the zip output Raises: RuntimeError: if the ClientBuilder.unzipsfx_stub doesn't require admin. Returns: output_path: filename string of zip output file """ context = self.context + ["Client Context"] src_zip = zipfile.ZipFile(io.BytesIO(payload_data), mode="r") zip_data = io.BytesIO() output_zip = zipfile.ZipFile(zip_data, mode="w", compression=zipfile.ZIP_DEFLATED) config_file_name = config.CONFIG.Get("ClientBuilder.config_filename", context=context) # Copy the rest of the files from the package to the new zip. for template_file in src_zip.namelist(): if template_file != config_file_name: # Avoid writing the config file twice if we're repacking a binary that # has already been run through deployment. We write it in the next step, # so no need to copy over from the original here. _CopyFileInZip(src_zip, template_file, output_zip) client_config_content = build_helpers.GetClientConfig(context) self._ValidateEndConfig(client_config_content) output_zip.writestr( config_file_name, client_config_content.encode("utf-8"), # pytype: disable=attribute-error compress_type=zipfile.ZIP_STORED) # The zip file comment is used by the self extractor to run the installation # script. Comment has to be `bytes` object because `zipfile` module is not # smart enough to properly handle `unicode` objects. output_zip.comment = b"$AUTORUN$>%s" % config.CONFIG.Get( "ClientBuilder.autorun_command_line", context=context).encode("utf-8") output_zip.close() utils.EnsureDirExists(os.path.dirname(output_path)) with io.open(output_path, "wb") as fd: # First write the installer stub stub_data = io.BytesIO() unzipsfx_stub = config.CONFIG.Get("ClientBuilder.unzipsfx_stub", context=context) stub_raw = io.open(unzipsfx_stub, "rb").read() # Check stub has been compiled with the requireAdministrator manifest. if b"level=\"requireAdministrator" not in stub_raw: raise RuntimeError( "Bad unzip binary in use. Not compiled with the" "requireAdministrator manifest option.") stub_data.write(stub_raw) # If in verbose mode, modify the unzip bins PE header to run in console # mode for easier debugging. build_helpers.SetPeSubsystem(stub_data, console=config.CONFIG.Get( "ClientBuilder.console", context=context)) # Now patch up the .rsrc section to contain the payload. end_of_file = zip_data.tell() + stub_data.tell() # This is the IMAGE_SECTION_HEADER.Name which is also the start of # IMAGE_SECTION_HEADER. offset_to_rsrc = stub_data.getvalue().find(b".rsrc") # IMAGE_SECTION_HEADER.PointerToRawData is a 32 bit int. stub_data.seek(offset_to_rsrc + 20) start_of_rsrc_section = struct.unpack("<I", stub_data.read(4))[0] # Adjust IMAGE_SECTION_HEADER.SizeOfRawData to span from the old start to # the end of file. stub_data.seek(offset_to_rsrc + 16) stub_data.write( struct.pack("<I", end_of_file - start_of_rsrc_section)) # Concatenate stub and zip file. out_data = io.BytesIO() out_data.write(stub_data.getvalue()) out_data.write(zip_data.getvalue()) # Then write the actual output file. fd.write(out_data.getvalue()) if self.signer: self.signer.SignFile(output_path) logging.info("Deployable binary generated at %s", output_path) return output_path