compress the extracted information

This commit is contained in:
2023-07-10 14:14:03 +07:00
parent 2eede8f9b2
commit ed2f09348e
5 changed files with 220 additions and 94 deletions

View File

@ -1,7 +1,8 @@
package action
import (
"fmt"
// "fmt"
"sort"
// log "github.com/sirupsen/logrus"
. "ios-wrapper/internal/wrapper/ofile"
@ -11,25 +12,46 @@ import (
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
}
// 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() {
// symbols_storage := []*protomodel.MachoInfo_AllImportedSymbols{}
symbols_raw := mc.CollectBindSymbols()
sort.Slice(symbols_raw, func(i, j int) bool {
orderedByLibrary := symbols_raw[i].Dylib() < symbols_raw[j].Dylib()
if symbols_raw[i].Dylib() == symbols_raw[j].Dylib() {
orderedBySymbol := symbols_raw[i].Name() < symbols_raw[j].Name()
return orderedBySymbol
}
return orderedByLibrary
})
libs := []string{}
symbols := []string{}
tables := []*protomodel.MachoInfo_LibraryImportedSymbols{}
var current_table *protomodel.MachoInfo_LibraryImportedSymbols
current_lib := ""
current_symbol := ""
current_lib_idx := -1
current_symbol_idx := -1
// now we expect everything is sorted and easier to build strings tables
// this is not fully optimized, there can be repeated symbol name in different libraries
for _, symbol := range symbols_raw {
if symbol.Type() != "lazy" {
continue
}
dylib_hash := calculateHash(symbol.Dylib())
// dylib_hash := calculateHash(symbol.Dylib())
seg := mc.Segments()[symbol.Segment()]
var offset uint64
@ -42,22 +64,48 @@ func (action *saveImports) withMacho(mf *MachoFile) error {
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,
if current_lib != symbol.Dylib() {
current_lib_idx += len(current_lib) + 1
current_lib = symbol.Dylib()
libs = append(libs, symbol.Dylib())
tables = append(tables, &protomodel.MachoInfo_LibraryImportedSymbols{
LibIndex: uint32(current_lib_idx),
Nsymbols: 0,
Symbols: []*protomodel.MachoInfo_SymbolTable{},
})
current_table = tables[len(tables)-1]
}
if current_symbol != symbol.Name() {
current_symbol_idx += len(current_symbol) + 1
current_symbol = symbol.Name()
symbols = append(symbols, symbol.Name())
}
current_table.Nsymbols += 1
current_table.Symbols = append(current_table.Symbols, &protomodel.MachoInfo_SymbolTable{
SymbolIndex: uint32(current_symbol_idx),
SegmentIndex: symbol.Segment(),
Offset: uint32(offset),
})
// fmt.Printf("{\"%s\", \"%s\", 0x%x, 0x%x, 0x%x},\n",
// symbol.Name(), symbol.Dylib(), 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
mf.Info().Symbols = &protomodel.MachoInfo_AllImportedSymbols{
Libs: libs,
Symbols: symbols,
Tables: tables,
}
mf.Info().Main = mc.Main()
return nil
}

View File

@ -1,10 +1,11 @@
package wrapper
import (
"bufio"
"fmt"
"io/ioutil"
"os"
"strings"
// "strings"
"github.com/alecthomas/kong"
log "github.com/sirupsen/logrus"
@ -194,11 +195,11 @@ func displayBcell(bfile string) {
)
}
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)
}
// 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)
// }
}
}
@ -231,33 +232,73 @@ 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)")
log.Panic("Invalid Protobuf<BcellFile> bcell.dat")
}
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)
}
f, err := os.Create(header)
if err != nil {
log.Panic("Cannot open header file for writing")
}
defer f.Close()
w := bufio.NewWriter(f)
// fmt.Printf("[+] User Config: %+v\n", data.BcellConfig)
fmt.Fprintf(w, "#include<stdint.h>\n")
fmt.Fprintf(w, "namespace bshield_data{\n")
for arch, info := range data.MachoInfos {
fmt.Fprintf(w, "const char* arch = \"%s\";\n", arch)
fmt.Fprintf(w, "unsigned int pointer_size = %d;\n", info.PointerSize)
fmt.Fprintf(w, "uint64_t image_base = 0x%x;\n", info.ImageBase)
fmt.Fprintf(w, "uint64_t main = 0x%x;\n", info.Main)
fmt.Fprintf(w, "struct init_pointer {uint64_t offset; uint64_t value;};\n")
fmt.Fprintf(w, "int num_init_pointers = %d;\n", len(info.InitPointers))
fmt.Fprintf(w, "struct init_pointer init_pointers_offsets[] = {\n")
for _, init_ptr := range info.InitPointers {
fmt.Fprintf(w, " {0x%x, 0x%x},\n", init_ptr.Offset, init_ptr.Value)
}
fmt.Fprintf(w, "};\n")
fmt.Fprintf(w, "__attribute__((section(\"__DATA,.bshield_lib\")))\n")
fmt.Fprintf(w, "char libs[] =\n")
for _, lib := range info.Symbols.Libs {
fmt.Fprintf(w, " \"%s\\0\"\n", lib)
}
fmt.Fprintf(w, ";\n")
fmt.Fprintf(w, "__attribute__((section(\"__DATA,.bshield_sym\")))\n")
fmt.Fprintf(w, "char symbols[] =\n")
for _, symbol := range info.Symbols.Symbols {
fmt.Fprintf(w, " \"%s\\0\"\n", symbol)
}
fmt.Fprintf(w, ";\n")
fmt.Fprintf(w, "// very compact symbol table,\n")
fmt.Fprintf(w, "// [lib idx/*4 bytes*/, nsymbol/*4 byte*/]\n")
fmt.Fprintf(w, "// repeate nsymbol times [name offset/*3 bytes*/, segment idx/**/, offset /*4 btyes*/]\n")
fmt.Fprintf(w, "// name offset is 3 bytes because we don't think we should have a table size > 2^(3 * 8)\n")
fmt.Fprintf(w, "__attribute__((section(\"__DATA,.bshield_code\")))\n")
fmt.Fprintf(w, "uint32_t encoded_table[] = {\n")
n_instructions := 0
for i, table := range info.Symbols.Tables {
fmt.Fprintf(w, " // %s\n", info.Symbols.Libs[i])
fmt.Fprintf(w, " %d/*lib offset*/,\n", table.LibIndex)
fmt.Fprintf(w, " %d/*nsymbols*/,\n", table.Nsymbols)
n_instructions += 2
for _, symbol := range table.Symbols {
fmt.Fprintf(w, " %d, 0x%x,\n", (symbol.SymbolIndex<<8)|symbol.SegmentIndex, symbol.Offset)
n_instructions += 2
}
fmt.Fprintf(w, "\n")
}
fmt.Fprintf(w, "};\n")
fmt.Fprintf(w, "uint32_t n_instructions = %d;\n", n_instructions)
}
fmt.Fprintf(w, "}// namespace bshield_data\n")
w.Flush()
}