rework ios-wrapper cli parsing

This commit is contained in:
2023-06-15 10:41:18 +07:00
parent a257286d2e
commit e2c75bf718
12 changed files with 269 additions and 63 deletions

View File

@ -7,7 +7,7 @@ import (
type removeClassicSymbol struct{}
func (action *removeClassicSymbol) withMacho(mf *MachoFile) error {
mf.Context().RemoveClassicSymbol()
mf.Context().RemoveSymbolTable()
return nil
}

View File

@ -0,0 +1,21 @@
package action
import (
. "ios-wrapper/internal/wrapper/ofile"
)
type removeExports struct{}
func (action *removeExports) withMacho(mf *MachoFile) error {
mf.Context().RemoveExportTrie()
return nil
}
func (action *removeExports) withFat(ff *FatFile) error {
return defaultWithFat(action, ff)
}
func NewRemoveExportsAction() *removeExports {
return &removeExports{}
}

View File

@ -0,0 +1,71 @@
package action
import (
"fmt"
// log "github.com/sirupsen/logrus"
. "ios-wrapper/internal/wrapper/ofile"
"ios-wrapper/pkg/protomodel"
)
type saveImports struct{}
func (action *saveImports) withMacho(mf *MachoFile) error {
calculateHash := func(name string) uint32 {
var h uint32 = 0x811c9dc5
for _, s := range name {
h ^= uint32(s)
h *= 0x01000193
}
return h
}
mc := mf.Context()
symbols := []*protomodel.MachoInfo_BindSymbol{}
fmt.Println("struct imported_symbol {const char* name; const char* lib; uint32_t hash; int segment_i; uint64_t offset;};")
fmt.Println("const char* lib_to_resolve = \"main\";")
fmt.Println("struct imported_symbol imported_table[] = {")
for _, symbol := range mc.CollectBindSymbols() {
if symbol.Type() != "lazy" {
continue
}
dylib_hash := calculateHash(symbol.Dylib())
seg := mc.Segments()[symbol.Segment()]
var offset uint64
if symbol.Address() >= seg.Vmaddr() {
// this is virtual address
offset = symbol.Address() - seg.Vmaddr()
} else {
// this is file address
offset = symbol.Address() - seg.Fileoff()
}
fmt.Printf("{\"%s\", \"%s\", 0x%x, 0x%x, 0x%x},\n",
symbol.Name(), symbol.Dylib(), dylib_hash, symbol.Segment(), offset);
symbols = append(symbols,
&protomodel.MachoInfo_BindSymbol{
Name: symbol.Name(),
Libname: symbol.Dylib(),
Libhash: dylib_hash,
Segment: symbol.Segment(),
Offset: offset,
})
}
fmt.Println("};")
fmt.Printf("uint32_t nimports = %d;\n", len(symbols));
mf.Info().Symbols = symbols
return nil
}
func (action *saveImports) withFat(ff *FatFile) error {
return defaultWithFat(action, ff)
}
func NewSaveImportsAction() *saveImports {
return &saveImports{}
}

View File

@ -4,6 +4,7 @@ import (
"fmt"
"io/ioutil"
"os"
"strings"
"github.com/alecthomas/kong"
log "github.com/sirupsen/logrus"
@ -63,7 +64,11 @@ func Cli() {
arg := cli.Lipo.Join
fat.FatJoin(arg.Macho, arg.Out)
return
}
} else if command == "bcell2header" {
arg := cli.BcellToHeader
bcell2header(arg.Bcell, arg.Out)
return
}
var pc ProgramContext
var ofile OFile = nil
@ -73,7 +78,7 @@ func Cli() {
arg := cli.Wrap
ofile = NewOFile(arg.OFile)
pc.remove_codesign = true
pc.strip_init_pointers = true
pc.remove_inits = true
pc.dylib_to_add = []string{"@rpath/bcell.framework/bcell"}
pc.rpath_to_add = []string{"@executable_path/Frameworks"}
pc.outfile = arg.Out
@ -99,6 +104,29 @@ func Cli() {
ofile = NewOFile(arg.OFile)
pc.remove_imports = true
pc.outfile = arg.Out
pc.bcellfile = arg.Bcell
case "pepe":
arg := cli.Pepe
ofile = NewOFile(arg.OFile)
if arg.FullRemoval {
pc.remove_exports = true
pc.remove_symbol_table = true
pc.remove_imports = true
pc.remove_inits = true
pc.remove_codesign = true
pc.remove_others = true
}
pc.remove_imports = arg.RemoveBindSymbols
pc.remove_codesign = arg.RemoveCodeSign
pc.remove_inits = arg.RemoveInitFunctions
pc.remove_others = arg.RemoveOthers
pc.remove_exports = arg.RemoveExports
pc.remove_symbol_table = arg.RemoveSymbolTable
pc.dylib_to_add = arg.Dylibs
pc.rpath_to_add = arg.Rpath
pc.outfile = arg.Out
pc.bcellfile = arg.Bcell
default:
return
@ -165,6 +193,12 @@ func displayBcell(bfile string) {
init_ptr.Value,
)
}
fmt.Printf(" | Bind Symbols:\n")
for _, symbol := range info.Symbols {
lib := strings.Replace(symbol.Libname, "/System/Library/Frameworks/", "", 1)
fmt.Printf(" | %s offset=0x%x segmentID=0x%x\n", symbol.Name, symbol.Offset, symbol.Segment)
fmt.Printf(" | from=%s\n", lib)
}
}
}
@ -194,3 +228,36 @@ func resolveAddresses(dwarf string, load string, addresses []string) {
}
}
}
func bcell2header(bfile string, header string) {
raw_data, err := ioutil.ReadFile(bfile)
if err != nil {
log.Panic("Invalid Protobuf<BcellFile> bcell.dat (1)")
}
data := &protomodel.BcellFile{}
err = proto.Unmarshal(raw_data, data)
if err != nil {
log.Panic("Invalid Protobuf<BcellFile> bcell.dat (2)")
}
fmt.Printf("[+] User Config: %+v\n", data.BcellConfig)
for arch, info := range data.MachoInfos {
fmt.Printf("[+] Arch %s:\n", arch)
fmt.Printf(" | PointerSize : %+v\n", info.PointerSize)
fmt.Printf(" | Image Base : 0x%x\n", info.ImageBase)
fmt.Printf(" | Init Pointers:\n")
for _, init_ptr := range info.InitPointers {
fmt.Printf(
" | offset 0x%x => addr 0x%x\n",
init_ptr.Offset,
init_ptr.Value,
)
}
fmt.Printf(" | Bind Symbols:\n")
for _, symbol := range info.Symbols {
lib := strings.Replace(symbol.Libname, "/System/Library/Frameworks/", "", 1)
fmt.Printf(" | %s offset=0x%x segmentID=0x%x\n", symbol.Name, symbol.Offset, symbol.Segment)
fmt.Printf(" | from=%s\n", lib)
}
}
}

View File

@ -26,6 +26,7 @@ type RemoveCodesignArgument struct {
type RemoveImportsArgument struct {
Out string `short:"o" required name:"outfile" help:"Modified Mach-O/Fat binary output file" type:"path"`
Bcell string `short:"b" required help:"bcell.dat output file" type:"path"`
OFile string `arg help:"Path to Mach-O/Fat binary file" type:"existingfile"`
}
@ -55,7 +56,26 @@ type LipoArgument struct {
}
type PepeArgument struct {
Out string `short:"o" required name:"outfile" help:"Output file after transformation" type:"path"`
Bcell string `short:"b" required help:"bcell.dat output file" type:"path"`
OFile string `arg help:"Path to Mach-O/Fat binary file" type:"existingfile"`
Dylibs []string `short:"l" help:"Add more LC_DYLIB"`
Rpath []string `short:"r" help:"Add more LC_RPATH"`
RemoveCodeSign bool `default:"false" negatable:"" help:"Remove LC_CODE_SIGNATURE"`
RemoveExports bool `default:"false" negatable:"" help:"Clear the export table/trie"`
RemoveSymbolTable bool `default:"true" negatable:"" help:"Remove LC_SYMTAB and LC_DYSYMTAB"`
RemoveOthers bool `default:"false" negatable:"" help:"Remove LC_FUNCTION_STARTS, LC_DATA_IN_CODE, ..."`
RemoveID bool `default:"false" negatable:"" help:"(TODO) Remove LC_ID_DYLIB"`
RemoveInitFunctions bool `default:"false" name:"remove-inits" negatable:"" help:"Clear MOD_INIT_FUNC section"`
RemoveBindSymbols bool `default:"false" name:"remove-imports" negatable:"" help:"Remove all bind symbols information"`
RemoveObjCString bool `default:"false" negatable:"" help:"(TODO) Remove references, string litteral to Objctive-C strings"`
RebuildLinkEdit bool `default:"false" negatable:"" help:"(TODO) Rebuild the LINKEDIT section"`
FullRemoval bool `default:"false" help:"Apply every removal possible"`
}
type BcellToHeaderArgument struct {
Out string `short:"o" required name:"outfile" help:"Header file name to output to" type:"path"`
Bcell string `short:"b" required help:"Input bcell.dat file" type:"existingfile"`
}
type Argument struct {
@ -68,5 +88,14 @@ type Argument struct {
DisplayBcell DisplayBcellArgument `cmd name:"display-bcell" help:"Display Protobuf<BcellFile> content"`
Addr2Line Addr2LineArgument `cmd name:"addr2line" help:"Resolve crash address from DWARF file"`
Lipo LipoArgument `cmd help:"split Fat binary or join Mach-O binares"`
Pepe PepeArgument `cmd help:"split Fat binary or join Mach-O binares"`
Pepe PepeArgument `cmd help:"custom command"`
BcellToHeader BcellToHeaderArgument `cmd name:"bcell2header" help:"Build C header file from bcell file"`
AddSection struct {
Out string `short:"o" required name:"outfile" help:"Output file after transformation"`
Data string `arg help:"Input data file to fill in this section, or null if not provided" type:"existingfile"`
OFile string `arg help:"Path to Mach-O/Fat binary file" type:"existingfile"`
Segment string `required help:"Segment name"`
Section string `required help:"Section name"`
Size int `required help:"Size of segment/section"`
} `cmd:"" default:"false" help:"(TODO) Add a new segment with 1 section, segment starts at the end of last segment"`
}

View File

@ -38,9 +38,12 @@ func (uc *UserConfig) Protomodel() *protomodel.Config {
}
type ProgramContext struct {
strip_init_pointers bool
remove_inits bool
remove_codesign bool
remove_imports bool
remove_others bool
remove_exports bool
remove_symbol_table bool
dylib_to_add []string
rpath_to_add []string
@ -84,24 +87,27 @@ func (pc *ProgramContext) dispatchActions(ofile OFile) {
}
func (pc *ProgramContext) Process(ofile OFile) {
if pc.remove_imports {
pc.AddAction(NewRemoveImportsAction())
pc.AddAction(NewWriteFileAction(pc.outfile))
pc.dispatchActions(ofile)
return
}
if pc.remove_codesign {
pc.AddAction(NewRemoveCodeSignatureAction())
}
if pc.strip_init_pointers {
if pc.remove_inits {
pc.AddAction(NewSaveInitPointerAction())
pc.AddAction(NewRemoveInitPointerAction())
}
ExperimentalFeature("Remove Unnecessary Info", func() {
pc.AddAction(NewRemoveUnnecessaryInfoAction())
})
ExperimentalFeature("Remove Classic Symbol", func() {
if pc.remove_imports {
pc.AddAction(NewSaveImportsAction())
pc.AddAction(NewRemoveImportsAction())
}
if pc.remove_symbol_table {
pc.AddAction(NewRemoveClassicSymbolAction())
}
if pc.remove_exports {
pc.AddAction(NewRemoveExportsAction())
}
ExperimentalFeature("Remove Unnecessary Info", func() {
if pc.remove_others {
pc.AddAction(NewRemoveUnnecessaryInfoAction())
}
})
pc.AddAction(NewAddRpathAction(pc.rpath_to_add))
pc.AddAction(NewAddDylibAction(pc.dylib_to_add))