Skip to content

Commit b3f25a1

Browse files
committed
fix: bad output ipas (v2.1.0)
also: - changed some codesigning behavior to hopefully be better - added --zip option in case someone wants that - windows support should be fixed
1 parent d5f7bc1 commit b3f25a1

File tree

8 files changed

+59
-23
lines changed

8 files changed

+59
-23
lines changed

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ a cli tool to patch IPAs and their plugins, fixing problems with the share sheet
33

44
it uses [zxPluginsInject](https://github.com/asdfzxcvbn/zxPluginsInject) by default, which is a rewrite of choco's original patch.
55

6-
due to being written in go and having **native load command injection**, it's fully cross-compatible with macOS, linux, and iOS! (windows untested, but it should work)
6+
due to being written in go and having **native load command injection**, it's fully cross-compatible with macOS, linux, and iOS! (windows untested, but it should work correctly from v2.1.0)
77

88
you can find the latest binaries on the [release page](https://github.com/asdfzxcvbn/ipapatch/releases/latest).
99

@@ -12,10 +12,12 @@ you can find the latest binaries on the [release page](https://github.com/asdfzx
1212

1313
v2.0.0 has removed the dependency on `zip`! i figured it would be nice to just test whether or not this will REALLY noticably break things. for now, ipapatch is a fully portable, native binary!
1414

15+
v2.1.0 fixed an issue where the output ipa wasnt able to be extracted by some signing apps and other tools. you can also pass `--zip` to use the `zip` command, although this isn't really required anymore
16+
1517
# usage
1618
```bash
1719
$ ipapatch --help
18-
usage: ipapatch [-h/--help] --input <path> [--output <path] [--dylib <path>] [--inplace] [--noconfirm] [--plugins-only] [--version]
20+
usage: ipapatch [-h/--help] --input <path> [--output <path] [--dylib <path>] [--inplace] [--noconfirm] [--plugins-only] [--zip] [--version]
1921

2022
flags:
2123
--input path the path to the ipa file to patch
@@ -24,6 +26,7 @@ flags:
2426
--inplace takes priority over --output, use this to overwrite the input file
2527
--noconfirm skip interactive confirmation when not using --inplace, overwriting a file that already exists, etc
2628
--plugins-only only inject into plugin binaries (not the main executable)
29+
--zip use the zip cli tool to remove files (shouldnt be needed anymore)
2730

2831
info:
2932
-h, --help show usage and exit

cmd.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
"go.uber.org/zap/zapcore"
88
)
99

10-
const helpText = `usage: ipapatch [-h/--help] --input <path> [--output <path] [--dylib <path>] [--inplace] [--noconfirm] [--plugins-only] [--version]
10+
const helpText = `usage: ipapatch [-h/--help] --input <path> [--output <path] [--dylib <path>] [--inplace] [--noconfirm] [--plugins-only] [--no-zip] [--version]
1111
1212
flags:
1313
--input path the path to the ipa file to patch
@@ -16,6 +16,7 @@ flags:
1616
--inplace takes priority over --output, use this to overwrite the input file
1717
--noconfirm skip interactive confirmation when not using --inplace, overwriting a file that already exists, etc
1818
--plugins-only only inject into plugin binaries (not the main executable)
19+
--zip use the zip cli tool to remove files (shouldnt be needed anymore)
1920
2021
info:
2122
-h, --help show usage and exit
@@ -28,10 +29,11 @@ type Args struct {
2829
InPlace bool `arg:"--inplace"`
2930
NoConfirm bool `arg:"--noconfirm"`
3031
PluginsOnly bool `arg:"--plugins-only"`
32+
UseZip bool `arg:"--zip"`
3133
}
3234

3335
func (Args) Version() string {
34-
return "ipapatch v2.0.0"
36+
return "ipapatch v2.1.0"
3537
}
3638

3739
func AskInteractively(question string) bool {

go.mod

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ module github.com/asdfzxcvbn/ipapatch
33
go 1.24.3
44

55
require (
6-
github.com/STARRY-S/zip v0.2.1
7-
github.com/alexflint/go-arg v1.5.1
8-
github.com/blacktop/go-macho v1.1.245
6+
github.com/STARRY-S/zip v0.2.3
7+
github.com/alexflint/go-arg v1.6.0
8+
github.com/blacktop/go-macho v1.1.249
99
go.uber.org/zap v1.27.0
1010
howett.net/plist v1.0.1
1111
)

go.sum

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
github.com/STARRY-S/zip v0.2.1 h1:pWBd4tuSGm3wtpoqRZZ2EAwOmcHK6XFf7bU9qcJXyFg=
2-
github.com/STARRY-S/zip v0.2.1/go.mod h1:xNvshLODWtC4EJ702g7cTYn13G53o1+X9BWnPFpcWV4=
3-
github.com/alexflint/go-arg v1.5.1 h1:nBuWUCpuRy0snAG+uIJ6N0UvYxpxA0/ghA/AaHxlT8Y=
4-
github.com/alexflint/go-arg v1.5.1/go.mod h1:A7vTJzvjoaSTypg4biM5uYNTkJ27SkNTArtYXnlqVO8=
1+
github.com/STARRY-S/zip v0.2.3 h1:luE4dMvRPDOWQdeDdUxUoZkzUIpTccdKdhHHsQJ1fm4=
2+
github.com/STARRY-S/zip v0.2.3/go.mod h1:lqJ9JdeRipyOQJrYSOtpNAiaesFO6zVDsE8GIGFaoSk=
3+
github.com/alexflint/go-arg v1.6.0 h1:wPP9TwTPO54fUVQl4nZoxbFfKCcy5E6HBCumj1XVRSo=
4+
github.com/alexflint/go-arg v1.6.0/go.mod h1:A7vTJzvjoaSTypg4biM5uYNTkJ27SkNTArtYXnlqVO8=
55
github.com/alexflint/go-scalar v1.2.0 h1:WR7JPKkeNpnYIOfHRa7ivM21aWAdHD0gEWHCx+WQBRw=
66
github.com/alexflint/go-scalar v1.2.0/go.mod h1:LoFvNMqS1CPrMVltza4LvnGKhaSpc3oyLEBUZVhhS2o=
77
github.com/blacktop/go-dwarf v1.0.14 h1:OjmzfSgg/qAKckn2tWFebcgKgJ7HOqCj7bS+CiE1lrY=
88
github.com/blacktop/go-dwarf v1.0.14/go.mod h1:4W2FKgSFYcZLDwnR7k+apv5i3nrau4NGl9N6VQ9DSTo=
9-
github.com/blacktop/go-macho v1.1.245 h1:RxZc/yvau+W63/rK5Ag6zpYDHj241HEbToyb9Iw9blI=
10-
github.com/blacktop/go-macho v1.1.245/go.mod h1:qtWG1+TBJfq/8fs2Jg50v0P3LxzAZC1yLmT/rPXxuz8=
9+
github.com/blacktop/go-macho v1.1.249 h1:HJlYj9xsdbCHc6PYrrjLIdqhEtR3imrshzcC4p8OdSE=
10+
github.com/blacktop/go-macho v1.1.249/go.mod h1:qtWG1+TBJfq/8fs2Jg50v0P3LxzAZC1yLmT/rPXxuz8=
1111
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
1212
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
1313
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=

inject.go

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import (
1313
"github.com/blacktop/go-macho/types"
1414
)
1515

16+
var ErrNoCodeDirectories = errors.New("no code directories")
17+
1618
var dylibCmdSize = binary.Size(types.DylibCmd{})
1719

1820
func injectLC(fsPath, bundleID, lcName, tmpdir string) error {
@@ -102,15 +104,24 @@ func addDylibCommand(m *macho.File, name, bundleID string) error {
102104
Name: name,
103105
})
104106
if cs != nil {
105-
if bundleID == "" {
106-
bundleID = "fyi.zxcvbn.ipapatch.app" // shouldnt happen, but best to be safe
107+
if len(cs.CodeDirectories) == 0 {
108+
return ErrNoCodeDirectories
109+
}
110+
cd := cs.CodeDirectories[0]
111+
if cd.ID == "" {
112+
cd.ID = bundleID
113+
if bundleID == "" {
114+
cd.ID = "fyi.zxcvbn.ipapatch.app" // shouldnt happen, but best to be safe
115+
}
107116
}
108-
m.CodeSign(&codesign.Config{
109-
Flags: cstypes.ADHOC,
110-
ID: bundleID,
117+
118+
// https://github.com/blacktop/go-macho/blob/0247374e8fc354e575b62401a6ec2195d1fae49f/export.go#L265
119+
return m.CodeSign(&codesign.Config{
120+
Flags: cd.Header.Flags | cstypes.ADHOC,
121+
ID: cd.ID,
122+
TeamID: cd.TeamID,
111123
Entitlements: []byte(cs.Entitlements),
112124
EntitlementsDER: cs.EntitlementsDER,
113-
SpecialSlots: []cstypes.SpecialSlot{{Hash: cstypes.EmptySha256Slot}}, // i think this was needed, found it in an old project
114125
})
115126
}
116127
return nil

ipa.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"io"
77
"io/fs"
88
"os"
9+
"path"
910
"path/filepath"
1011
"strings"
1112

@@ -51,7 +52,7 @@ func injectAll(args Args, tmpdir string) (map[string]string, error) {
5152
return nil, err
5253
}
5354

54-
path := filepath.Join(filepath.Dir(p), pl.Executable)
55+
path := path.Join(path.Dir(p), pl.Executable)
5556
fsPath, err := extractToPath(z, tmpdir, path)
5657
if err != nil {
5758
return nil, fmt.Errorf("error extracting %s: %w", pl.Executable, err)

main.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"errors"
66
"fmt"
77
"os"
8+
"os/exec"
89

910
"github.com/alexflint/go-arg"
1011
"go.uber.org/zap/zapcore"
@@ -30,6 +31,11 @@ func main() {
3031
logger.Fatalf("%v (see --help for usage)", err)
3132
}
3233

34+
if args.UseZip {
35+
if _, err := exec.LookPath("zip"); err != nil {
36+
logger.Fatal("zip command not found in PATH, you need to install it or omit --zip (see help)")
37+
}
38+
}
3339
if args.InPlace {
3440
logger.Info("--inplace specified, will overwrite input")
3541
args.Output = args.Input

patch.go

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"io"
66
"os"
7+
"os/exec"
78
"path/filepath"
89
"strings"
910

@@ -34,9 +35,21 @@ func Patch(args Args) error {
3435
}
3536

3637
var appName string
37-
for _, val := range paths {
38-
appName = strings.Split(val, "/")[1] // yeah i couldnt figure out another way to do this lmao
39-
break
38+
if args.UseZip {
39+
zipArgs := make([]string, 0, len(paths)+2)
40+
zipArgs = append(zipArgs, "-d", args.Output)
41+
for _, val := range paths {
42+
zipArgs = append(zipArgs, val)
43+
}
44+
appName = strings.Split(zipArgs[2], "/")[1]
45+
if err = exec.Command("zip", zipArgs...).Run(); err != nil {
46+
return fmt.Errorf("error deleting from zipfile: %w", err)
47+
}
48+
} else {
49+
for _, val := range paths {
50+
appName = strings.Split(val, "/")[1] // yeah i couldnt figure out another way to do this lmao
51+
break
52+
}
4053
}
4154

4255
//

0 commit comments

Comments
 (0)