Skip to content

Instantly share code, notes, and snippets.

@jjrscott
Created May 3, 2019 14:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jjrscott/348b8765913d083c33d13964f24f4214 to your computer and use it in GitHub Desktop.
Save jjrscott/348b8765913d083c33d13964f24f4214 to your computer and use it in GitHub Desktop.
Script to resign an IPA file (packaged iOS application)
#!/usr/bin/perl
use strict;
use Data::Dumper;
use Getopt::Long;
use File::Temp 'tempdir';
use DirHandle;
use File::Slurp;
my $tempdir = tempdir(CLEANUP => 1);
print "chdir temporary directory\n";
print "^^^^^^^^^^^^^\n\n";
print "chdir $tempdir\n";
chdir $tempdir;
my $mobileprovision_path;
my $encode_mobileprovision;
my $ipa_path;
my $command_result = 0;
my $version_suffix = 'a';
my $append_mobileprovision_name = 1;
GetOptions
(
'version_suffix=s' => \$version_suffix,
'mobileprovision_path=s' => \$mobileprovision_path,
'encode_mobileprovision!' => \$encode_mobileprovision,
'append_mobileprovision_name!' => \$append_mobileprovision_name,
'ipa_path=s' => \$ipa_path,
);
if (!-e $mobileprovision_path)
{
die "Could not find the mobileprovision:\n $mobileprovision_path\n";
}
my ($codesign_allocate) = qx(xcrun -find codesign_allocate);
if ($?)
{
die "Could not xcrun or codesign_allocate\n";
}
chomp $codesign_allocate;
$ENV{'CODESIGN_ALLOCATE'} = $codesign_allocate;
my $mobileprovision_content = read_file($mobileprovision_path);
if ($encode_mobileprovision)
{
my $mobileprovision_content_hex = unpack "H*", $mobileprovision_content;
print join "\n", $mobileprovision_content_hex =~ /(.{0,64})/g;
exit 0;
}
if (!-e $ipa_path)
{
die "Could not find the IPA:\n $ipa_path\n";
}
print "unzip the IPA\n";
print "^^^^^^^^^^^^^\n\n";
$command_result = system 'unzip', '-qo', $ipa_path;
if ($command_result != 0)
{
die "Could not unzip the IPA file\n";
}
my $application_name;
my $payload_dir_handle = DirHandle->new('Payload');
foreach my $leaf ($payload_dir_handle->read)
{
if ($leaf !~ /^\.{1,2}$/)
{
$application_name = $leaf;
last;
}
}
print "extract entitlements\n";
print "^^^^^^^^^^^^^^^^^^^^\n\n";
# $command_result = system 'xcrun', 'codesign', '-d', '-vv', '--entitlements', ':entitlements.plist', 'Payload/'.$application_name;
#
# if ($command_result != 0)
# {
# die "Could not get the entitlements\n";
# }
my ($application_identifier) = $mobileprovision_content =~ m!<key>application-identifier</key>\s*<string>([^<]+)</string>!s;
my ($team_name) = $mobileprovision_content =~ m!<key>TeamName</key>
\s*<string>([^<]+)</string>!s;
my ($mobileprovision_name) = $mobileprovision_content =~ m!<key>Name</key>
\s*<string>([^<]+)</string>!s;
my $entitlements_content = read_file('Payload/'.$application_name.'/entitlements.plist');
$entitlements_content =~ s!(<key>application-identifier</key>\s*<string>)([^<]+)(</string>)!$1$application_identifier$3!s;
my $previous_application_identifier = quotemeta $2;
$entitlements_content =~ s!(<key>com.apple.developer.team-identifier</key>\s*<string>)([^<]+)(</string>)!!s;
$entitlements_content =~ s!(<key>com.apple.external-accessory.wireless-configuration</key>\s*<(true|false)/>)!!s;
$entitlements_content =~ s~$previous_application_identifier~$application_identifier~s;
write_file('Payload/'.$application_name.'/entitlements.plist', $entitlements_content);
print "\ninsert updated entitlements\n";
print "^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n";
$command_result = system 'cp', '-vf', $mobileprovision_path, 'Payload/'.$application_name.'/embedded.mobileprovision';
if ($command_result != 0)
{
die "Could not copy the mobileprovision\n";
}
print "\nupdate info plist\n";
print "^^^^^^^^^^^^^^^^^^^\n\n";
my $info_path = 'Payload/'.$application_name.'/Info.plist';
my $bundleShortVersion = plist($info_path, ":CFBundleShortVersionString");
plist($info_path, ":CFBundleShortVersionString", $bundleShortVersion.$version_suffix);
my $bundleVersion = plist($info_path, ":CFBundleVersion");
plist($info_path, ":CFBundleVersion", $bundleVersion.$version_suffix);
print "\nresign the app\n";
print "^^^^^^^^^^^^^^\n\n";
$command_result = system 'xcrun', 'codesign', '-f', '-s', 'iPhone Distribution: '.$team_name, '--entitlements=Payload/'.$application_name.'/entitlements.plist', '-vv', 'Payload/'.$application_name;
if ($command_result != 0)
{
die "Could not codesign the app\n";
}
print "\nverify the app\n";
print "^^^^^^^^^^^^^^\n\n";
$command_result = system 'xcrun', 'codesign', '-dvvv', 'Payload/'.$application_name;
if ($command_result != 0)
{
die "Could not verify the codesign\n";
}
my $resigned_ipa_path = $ipa_path;
$mobileprovision_name =~ s|[^a-zA-Z0-9]|_|g;
$mobileprovision_name =~ s|_+|_|g;
$mobileprovision_name = lc $mobileprovision_name;
if ($append_mobileprovision_name)
{
$resigned_ipa_path =~ s!\.ipa!.${mobileprovision_name}.ipa!;
}
print "\nzip the resigned IPA\n";
print "^^^^^^^^^^^^^^^^^^^^\n\n";
$command_result = system 'zip', '-qr', $resigned_ipa_path, 'Payload';
if ($command_result != 0)
{
die "Could not zip up the new IPA\n";
}
print "the new IPA is at $resigned_ipa_path\n\n";
chdir '/';
sub plist
{
my ($path, $key, $value) = @_;
if (defined $value)
{
return qx(/usr/libexec/PlistBuddy -c "Set $key $value" $path);
}
else
{
my $value = qx(/usr/libexec/PlistBuddy -c "Print $key" $path);
$value =~ s/[\n\l\r]//g;
return $value;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment