altstoreio / AltStore

AltStore is an alternative app store for non-jailbroken iOS devices.
https://altstore.io
GNU Affero General Public License v3.0
11.34k stars 860 forks source link

Sideloading giving ldid error #1034

Open bensh opened 2 years ago

bensh commented 2 years ago

Recently updated AltServer, reinstalled AltStore and uninstalled/reinstalled the Mail plugin, but getting an ldid error when I use the sideload functionality.

AltServer: 1.5 (65) iPhone 7Plus - 14.4

/Users/rileytestut/iCloud Drive (Archive)/Documents/Developer/Projects/AltStore/Dependencies/AltSign/AltSign/ldid/../../Dependencies/ldid/ldid.cpp(1354): _assert(): end >= size - 0x10

Kairixir commented 4 months ago

I'm having the issue too. It happens while trying to sideload Spotube

AltServer: 1.7 iOS: 16.3.1 Spotube: v3.4.1

What might be the root of the issue?

wavecommander commented 3 months ago

Looking at the AltStore GitHub fork of ldid, the _assert() that is failing is here:

        if (symtab != NULL) {
            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;
            }
        }

This is the only instance of _assert(end >= size - 0x10) in that repo.

I have never looked at ldid so I don't know much about what is going on in the greater context, but it looks like the two _assert()s here exist to ensure that the symbol table (symtab) size fits within the size of the header and comes after the first 16 bits (0x10) of the header if the load command is recognized as a symbol table.

This makes sense as the Mach-O header format specifies the offset of the symbol table "String table" to be offset 16 bits from the start of the symbol table load command

So it would make sense that the apps in question (Spotube, Kodi, etc.) have an issue in their compilation where the relevant Mach-O header(s) doesn't obey this requirement.

Specifically, it looks like the symbol table is small enough to fit in the header size, but it is not offset correctly. But that is assuming that there are no other problems with the header(s) and symbol table where it would erroneously make it past the _assert(end <= size) and the previous if statements.

Again, I have no experience with ldid or macOS/iOS/Darwin binaries, but this is my cursory investigation as I would really like to be able to sideload Spotube with SideStore 😅

wavecommander commented 3 months ago

An update. I can confirm that the symbol table not being offset correctly is not the issue.

TLDR: I still think that this is an issue with the way these apps are being built and signed (or not signed) before attempting to sideload. I may be wrong, but I have some reasons to believe it. I think it would be best to track down the exact building/signing/distribution method that DolphiniOS uses to become a .ipa that can be sideloaded via AltStore/SideStore.

Analyzing the stable executable inside the official Spotube-iOS.ipa with MachOView shows that the symbol table "String Table Offset" is correctly offset 16 bits from the start of the load command and it is 4 bytes long: image

So there is another issue somewhere, either in the built Spotube-iOS.ipa (more likely), or in ldid (less likely).

Comparing Spotube to 2 sideloaded apps that I know work, DolphiniOS and iTorrent, I noticed that both of them are signed.

DolphiniOS uses a self made certificate authority "OatmealDome Software":

$ codesign -dv --verbose=4 DolphiniOS.app
Executable=./DolphiniOS.app/DolphiniOS
Identifier=me.oatmealdome.DolphiniOS-njb
Format=app bundle with Mach-O thin (arm64)
CodeDirectory v=20400 size=104726 flags=0x0(none) hashes=3262+7 location=embedded
VersionPlatform=2
VersionMin=786432
VersionSDK=983040
Hash type=sha256 size=32
CandidateCDHash sha256=e1acad35a66e8c5a6b7210a9e6e65d619b9512b2
CandidateCDHashFull sha256=e1acad35a66e8c5a6b7210a9e6e65d619b9512b28f55214ec2c4d2b30b2145f9
Hash choices=sha256
CMSDigest=e1acad35a66e8c5a6b7210a9e6e65d619b9512b28f55214ec2c4d2b30b2145f9
CMSDigestType=2
Executable Segment base=0
Executable Segment limit=8683520
Executable Segment flags=0x11
Page size=4096
CDHash=e1acad35a66e8c5a6b7210a9e6e65d619b9512b2
Signature size=1769
Authority=OatmealDome Software
Signed Time=Sep 11, 2022 at 5:43:41 PM
Info.plist entries=38
TeamIdentifier=not set
Sealed Resources version=2 rules=10 files=1877
Internal requirements count=1 size=108

and iTorrent uses an official Apple Developer certificate:

$ codesign -dv --verbose=4 iTorrent.app
Executable=./iTorrent.app/iTorrent
Identifier=ru.nonamedude.iTorrent
Format=app bundle with Mach-O universal (armv7 arm64)
CodeDirectory v=20400 size=55066 flags=0x0(none) hashes=1712+5 location=embedded
VersionPlatform=2
VersionMin=590592
VersionSDK=917504
Hash type=sha256 size=32
CandidateCDHash sha1=504550c07491f59c132159747d754e9c5d81a830
CandidateCDHashFull sha1=504550c07491f59c132159747d754e9c5d81a830
CandidateCDHash sha256=a1d4d14c9450dd377347e321f683372239b4ad43
CandidateCDHashFull sha256=a1d4d14c9450dd377347e321f683372239b4ad431d63329462e359b041b40bec
Hash choices=sha1,sha256
CMSDigest=307f2cab0dbebf6b47b08edc2579ddf05f089260e1b8c62a68096a8a0d17f4b2
CMSDigestType=2
Executable Segment base=0
Executable Segment limit=5193728
Executable Segment flags=0x11
Page size=4096
CDHash=a1d4d14c9450dd377347e321f683372239b4ad43
Signature size=4822
Authority=Apple Development: Daniil Vinogradov (Z7SC2JZ38Y)
Authority=Apple Worldwide Developer Relations Certification Authority
Authority=Apple Root CA
Signed Time=Sep 20, 2020 at 4:57:41 PM
Info.plist entries=42
TeamIdentifier=D5UQ7XT49T
Sealed Resources version=2 rules=10 files=184
Internal requirements count=1 size=192

Whereas Spotube is not signed in any way:

$ codesign -dv --verbose=4 stable.app
stable.app: code object is not signed at all

I attempted to replicate what was done to sign DolphiniOS with a self made authority cert, but I was unable to sideload it with AltStore/SideStore:

$ codesign -dv --verbose=4 ~/Downloads/Payload/my-stable.app
Executable=~/Downloads/Payload/my-stable.app/stable
Identifier=oss.krtirtho.spotube.stable
Format=app bundle with Mach-O thin (arm64)
CodeDirectory v=20400 size=1332 flags=0x0(none) hashes=35+3 location=embedded
VersionPlatform=2
VersionMin=917504
VersionSDK=1049088
Hash type=sha256 size=32
CandidateCDHash sha256=c45a29369bcf772a1bf6572b5daa0b1e225ecca0
CandidateCDHashFull sha256=c45a29369bcf772a1bf6572b5daa0b1e225ecca0523ddec85e3b62b8bcaecd86
Hash choices=sha256
CMSDigest=c45a29369bcf772a1bf6572b5daa0b1e225ecca0523ddec85e3b62b8bcaecd86
CMSDigestType=2
Executable Segment base=0
Executable Segment limit=49152
Executable Segment flags=0x1
Page size=4096
CDHash=c45a29369bcf772a1bf6572b5daa0b1e225ecca0
Signature size=1377
Authority=my-test-cert
Signed Time=Mar 14, 2024 at 2:49:53 PM
Info.plist entries=39
TeamIdentifier=not set
Sealed Resources version=2 rules=10 files=338
Internal requirements count=1 size=104

The output is much the same, but there is a key difference and I'm not sure how important it is or how to change it yet.

Both DolphiniOS and iTorrent have Executable Segment flags=0x11, my bundle only has Executable Segment flags=0x1.

This is extra interesting because in this issue https://github.com/SideStore/SideStore/issues/227, there is an issue with Kodi and its file type being recognized as MH_EXECUTE. Looking at Kodi with codesign reveals that, while the executable is signed, it has no information about an "Executable Segment":

$ codesign -dv --verbose=4 Kodi.app
Executable=./Kodi.app/Kodi
Identifier=Kodi
Format=app bundle with Mach-O thin (arm64)
CodeDirectory v=20400 size=684061 flags=0x0(none) hashes=21369+5 location=embedded
VersionPlatform=2
VersionMin=720896
VersionSDK=918528
Hash type=sha256 size=32
CandidateCDHash sha1=1458b772c1724a54fbc6801af05d587124296c2f
CandidateCDHashFull sha1=1458b772c1724a54fbc6801af05d587124296c2f
CandidateCDHash sha256=8e345fa8e9cdad05d27b3f293d438832c8fdcc45
CandidateCDHashFull sha256=8e345fa8e9cdad05d27b3f293d438832c8fdcc45f5003903a34f05feb040f519
Hash choices=sha1,sha256
CMSDigest=6321353749a14cb316a30e6503256bec577d8ea3eb72d7dd1b3aaed3d564f5b1
CMSDigestType=2
Page size=4096
CDHash=8e345fa8e9cdad05d27b3f293d438832c8fdcc45
Kodi.app: no signature
Info.plist=not bound
TeamIdentifier=not set
Sealed Resources=none
Internal requirements count=1 size=120

So again, I would like to find how DolphiniOS solves this when building and signing. If anyone else has any info to share before I try more to find it, please do.

arjpar commented 1 month ago

@wavecommander I would love to help out this issue too. Do you think its a product of spotube not being signed?