■ ■ ■ ■ ■ ■
pkg/BananaPhone/bananaphone.go
skipped 2 lines 3 3 import ( 4 4 "errors" 5 5 "fmt" 6 + "path/filepath" 7 + "strings" 6 8 7 9 "github.com/awgh/rawreader" 8 10 "github.com/binject/debug/pe" skipped 15 lines 24 26 type BananaPhone struct { 25 27 banana *pe.File 26 28 isAuto bool 29 + memloc uintptr 27 30 } 28 31 29 32 //NewBananaPhone creates a new instance of a bananaphone with behaviour as defined by the input value. Use AutoBananaPhoneMode if you're not sure. skipped 4 lines 34 37 - AutoBananaPhoneMode 35 38 */ 36 39 func NewBananaPhone(t PhoneMode) (*BananaPhone, error) { 40 + return NewBananaPhoneNamed(t, "ntdll.dll", `C:\Windows\system32\ntdll.dll`) 41 + } 42 + 43 + //NewSystemBananaPhoneNamed is literally just an un-error handled passthrough for NewBananaPhoneNamed to easily work with mkwinsyscall. The ptr might be nil, who knows! lol! yolo! 44 + func NewSystemBananaPhoneNamed(t PhoneMode, name, diskpath string) *BananaPhone { 45 + r, _ := NewBananaPhoneNamed(t, name, diskpath) 46 + return r 47 + } 48 + 49 + //NewBananaPhoneNamed creates a new instance of a bananaphone with behaviour as defined by the input value, specifying the module provided. Use AutoBananaPhoneMode if you're not sure which mode and specify the path. Path only used for disk/auto modes. 50 + /* 51 + Possible values: 52 + - MemoryBananaPhoneMode 53 + - DiskBananaPhoneMode 54 + - AutoBananaPhoneMode 55 + */ 56 + func NewBananaPhoneNamed(t PhoneMode, name, diskpath string) (*BananaPhone, error) { 37 57 var p *pe.File 38 58 var e error 39 - 59 + var bp = &BananaPhone{} 40 60 switch t { 41 61 case AutoBananaPhoneMode: 42 62 fallthrough 43 63 case MemoryBananaPhoneMode: 44 - start, size := GetNtdllStart() 45 - rr := rawreader.New(start, int(size)) 46 - p, e = pe.NewFileFromMemory(rr) 64 + loads, err := InMemLoads() 65 + if err != nil { 66 + return nil, err 67 + } 68 + found := false 69 + for k, load := range loads { //shout out to Frank Reynolds 70 + if strings.ToLower(k) == strings.ToLower(diskpath) || strings.ToLower(name) == strings.ToLower(filepath.Base(k)) { 71 + rr := rawreader.New(uintptr(load.BaseAddr), int(load.Size)) 72 + p, e = pe.NewFileFromMemory(rr) 73 + bp.memloc = uintptr(load.BaseAddr) 74 + found = true 75 + break 76 + } 77 + } 78 + if !found { 79 + return nil, fmt.Errorf("module not found, bad times (%s %s)", diskpath, filepath.Base(diskpath)) 80 + } 81 + case DiskBananaPhoneMode: 82 + p, e = pe.Open(diskpath) 83 + } 84 + bp.banana = p 85 + bp.isAuto = t == AutoBananaPhoneMode 86 + return bp, e 87 + } 47 88 48 - case DiskBananaPhoneMode: 49 - p, e = pe.Open(`C:\Windows\system32\ntdll.dll`) 89 + //GetFuncPtr returns a pointer to the function (Virtual Address) 90 + func (b *BananaPhone) GetFuncPtr(funcname string) (uint64, error) { 91 + exports, err := b.banana.Exports() 92 + if err != nil { 93 + return 0, err 94 + } 95 + for _, ex := range exports { 96 + if strings.ToLower(funcname) == strings.ToLower(ex.Name) { 97 + return uint64(b.memloc) + uint64(ex.VirtualAddress), nil 98 + } 50 99 } 100 + return 0, fmt.Errorf("could not find function: %s", funcname) 101 + } 51 102 52 - return &BananaPhone{ 53 - banana: p, 54 - isAuto: t == AutoBananaPhoneMode, 55 - }, e 103 + //BananaProc emulates the windows proc thing 104 + type BananaProcedure struct { 105 + address uintptr 106 + } 107 + 108 + //Addr returns the address of this procedure 109 + func (b BananaProcedure) Addr() uintptr { 110 + return b.address 111 + } 112 + 113 + //NewProc emulates the windows NewProc call :-) 114 + func (b *BananaPhone) NewProc(funcname string) BananaProcedure { 115 + addr, _ := b.GetFuncPtr(funcname) //yolo error handling 116 + return BananaProcedure{address: uintptr(addr)} 56 117 } 57 118 58 119 //GetSysID resolves the provided function name into a sysid. skipped 72 lines