Skip to content

Commit

Permalink
Implement -w flag, fix misc bugs (ProcursusTeam#28)
Browse files Browse the repository at this point in the history
* Fix -U support for blank passwords

* Fix an alignment issue with LC_CODE_SIGNATURE

* Remov one particular _assert() that seems to be preventing legitimate cases

* Forward the user's choice of entitlements/requirements to nested bundles/stray binaries

Should resolve issue ProcursusTeam#24

ldid uses recursion in order to sign nested bundles, but it did not forward the user's choice of entitlements and requirements to said recursion, potentially resulting in improperly entitled binaries. This fixes that.

* Implement the -w flag: shallow sign

* Update manpage description for -w
  • Loading branch information
captinc authored Jan 13, 2023
1 parent 3d2bea0 commit ac9086a
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 35 deletions.
1 change: 1 addition & 0 deletions _ldid
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

_arguments \
'-S-[Add signature]:entitlements:_files' \
'-w[Shallow sign]' \
'-Q-[Embed requirements]:requirements:_files' \
'(-S)-r[Remove signature]' \
'(-r)-h[Print signature information]' \
Expand Down
13 changes: 13 additions & 0 deletions docs/ldid.1
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
.Op Fl q
.Op Fl r | Fl S Ns Ar file.xml | Fl s
.Op Fl u
.Op Fl w
.Op Fl arch Ar arch_type
.Ar
.Sh DESCRIPTION
Expand Down Expand Up @@ -142,6 +143,18 @@ This is a Procursus extension.
.It Fl u
If the binary was linked against UIKit, then print the UIKit version that the
Mach-O binary was linked against.
.It Fl w
Shallow sign. Only the main binary of the specified bundle will be signed, as
specified by
.Ar CFBundleIdentifier
in
.Ar Info.plist .
Any nested bundles and/or stray binaries will be completely
left alone and interpreted at face-value. Applicable only when the signing
target is a bundle directory, and not a specific Mach-O file.
.Fl w
can be used on any bundle, not just the root .app, including frameworks,
appexes, and more.
.El
.Sh EXAMPLES
To fakesign
Expand Down
83 changes: 48 additions & 35 deletions ldid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@
#define _packed \
__attribute__((packed))

bool flag_w(false);
bool flag_U(false);
std::string password;
std::vector<std::string> cleanup;
bool flag_H(false);
Expand Down Expand Up @@ -1479,11 +1481,12 @@ static void Allocate(const void *idata, size_t isize, std::streambuf &output, co
auto end(mach_header.Swap(symtab->stroff) + mach_header.Swap(symtab->strsize));
if (symtab->stroff != 0 || symtab->strsize != 0) {
_assert(end <= size);
_assert(end >= size - 0x10);
size = end;
}
}

size = (size + 15) & ~(15);

Baton baton;
size_t alloc(allocate(mach_header, baton, size));

Expand Down Expand Up @@ -1823,7 +1826,7 @@ class Stuff {
exit(1);
}

if (!PKCS12_verify_mac(value_, "", 0) && password.empty()) {
if (!flag_U) {
char passbuf[2048];
UI_UTIL_read_pw_string(passbuf, 2048, "Enter password: ", 0);
password = passbuf;
Expand Down Expand Up @@ -3061,23 +3064,25 @@ Bundle Sign(const std::string &root, Folder &parent, const std::string &key, Sta
Expression nested("^(Frameworks/[^/]*\\.framework|PlugIns/[^/]*\\.appex(()|/[^/]*.app))/(" + failure + ")Info\\.plist$");
std::map<std::string, Bundle> bundles;

folder.Find("", fun([&](const std::string &name) {
if (!nested(name))
return;
auto bundle(Split(name).dir);
if (mac) {
_assert(!bundle.empty());
bundle = Split(bundle.substr(0, bundle.size() - 1)).dir;
}
SubFolder subfolder(folder, bundle);

State remote;
bundles[nested[1]] = Sign(root + bundle, subfolder, key, remote, "", Starts(name, "PlugIns/") ? alter :
static_cast<const Functor<std::string (const std::string &, const std::string &)> &>(fun([&](const std::string &, const std::string &) -> std::string { return entitlements; }))
, merge, platform, progress);
local.Merge(bundle, remote);
}), fun([&](const std::string &name, const Functor<std::string ()> &read) {
}));
if (!flag_w) {
folder.Find("", fun([&](const std::string &name) {
if (!nested(name))
return;
auto bundle(Split(name).dir);
if (mac) {
_assert(!bundle.empty());
bundle = Split(bundle.substr(0, bundle.size() - 1)).dir;
}
SubFolder subfolder(folder, bundle);

State remote;
bundles[nested[1]] = Sign(root + bundle, subfolder, key, remote, requirements, Starts(name, "PlugIns/") ? alter :
static_cast<const Functor<std::string (const std::string &, const std::string &)> &>(fun([&](const std::string &, const std::string &) -> std::string { return entitlements; }))
, merge, platform, progress);
local.Merge(bundle, remote);
}), fun([&](const std::string &name, const Functor<std::string ()> &read) {
}));
}

std::set<std::string> excludes;

Expand Down Expand Up @@ -3117,21 +3122,23 @@ Bundle Sign(const std::string &root, Folder &parent, const std::string &key, Sta

auto size(most(data, &header.bytes, sizeof(header.bytes)));

if (name != "_WatchKitStub/WK" && size == sizeof(header.bytes))
switch (Swap(header.magic)) {
case FAT_MAGIC:
// Java class file format
if (Swap(header.count) >= 40)
break;
case FAT_CIGAM:
case MH_MAGIC: case MH_MAGIC_64:
case MH_CIGAM: case MH_CIGAM_64:
folder.Save(name, true, flag, fun([&](std::streambuf &save) {
Slots slots;
Sign(header.bytes, size, data, hash, save, identifier, "", false, "", key, slots, length, 0, platform, Progression(progress, root + name));
}));
return;
}
if (!flag_w) {
if (name != "_WatchKitStub/WK" && size == sizeof(header.bytes))
switch (Swap(header.magic)) {
case FAT_MAGIC:
// Java class file format
if (Swap(header.count) >= 40)
break;
case FAT_CIGAM:
case MH_MAGIC: case MH_MAGIC_64:
case MH_CIGAM: case MH_CIGAM_64:
folder.Save(name, true, flag, fun([&](std::streambuf &save) {
Slots slots;
Sign(header.bytes, size, data, hash, save, identifier, entitlements, merge, requirements, key, slots, length, 0, platform, Progression(progress, root + name));
}));
return;
}
}

folder.Save(name, false, flag, fun([&](std::streambuf &save) {
HashProxy proxy(hash, save);
Expand Down Expand Up @@ -3289,9 +3296,10 @@ static void usage(const char *argv0) {
fprintf(stderr, " host | kill | library-validation | restrict | runtime | linker-signed]] [-D] [-d]\n");
fprintf(stderr, " [-Enum:file] [-e] [-H[sha1 | sha256]] [-h] [-Iname]\n");
fprintf(stderr, " [-Kkey.p12 [-Upassword]] [-M] [-P[num]] [-Qrequirements.xml] [-q]\n");
fprintf(stderr, " [-r | -Sfile.xml | -s] [-u] [-arch arch_type] file ...\n");
fprintf(stderr, " [-r | -Sfile.xml | -s] [-w] [-u] [-arch arch_type] file ...\n");
fprintf(stderr, "Common Options:\n");
fprintf(stderr, " -S[file.xml] Pseudo-sign using the entitlements in file.xml\n");
fprintf(stderr, " -w Shallow sign\n");
fprintf(stderr, " -Kkey.p12 Sign using private key in key.p12\n");
fprintf(stderr, " -Upassword Use password to unlock key.p12\n");
fprintf(stderr, " -M Merge entitlements with any existing\n");
Expand Down Expand Up @@ -3541,11 +3549,16 @@ int main(int argc, char *argv[]) {
}
break;

case 'w':
flag_w = true;
break;

case 'M':
flag_M = true;
break;

case 'U':
flag_U = true;
password = argv[argi] + 2;
break;

Expand Down

0 comments on commit ac9086a

Please sign in to comment.