Projects STRLCPY BananaPhone Commits 316f0a9f
🤬
  • Add mode HalosGateBananaPhoneMode and function getSysIDFromNeighbor

  • Loading...
  • nodauf committed 2 years ago
    316f0a9f
    1 parent 1526021b
Revision indexing in progress... (symbol navigation in revisions will be accurate after indexed)
  • ■ ■ ■ ■ ■ ■
    pkg/BananaPhone/bananaphone.go
    skipped 19 lines
    20 20   DiskBananaPhoneMode
    21 21   //AutoBananaPhoneMode will resolve by first trying to resolve in-memory, and then falling back to loading from disk if in-memory fails (eg, if it's hooked and the sysid's have been moved).
    22 22   AutoBananaPhoneMode
     23 + //HalosGateBananaPhoneMode will resolve by first trying to resolve in-memory, and then falling back to deduce the syscall by searching a non-hooked function
     24 + HalosGateBananaPhoneMode
    23 25  )
    24 26   
    25 27  //BananaPhone will resolve SysID's used for syscalls while making minimal API calls. These ID's can be used for functions like NtAllocateVirtualMemory as defined in functions.go.
    26 28  type BananaPhone struct {
    27  - banana *pe.File
    28  - isAuto bool
    29  - memloc uintptr
     29 + banana *pe.File
     30 + isAuto bool
     31 + isHalosGate bool
     32 + memloc uintptr
    30 33  }
    31 34   
    32 35  //NewBananaPhone creates a new instance of a bananaphone with behaviour as defined by the input value. Use AutoBananaPhoneMode if you're not sure.
    skipped 2 lines
    35 38   - MemoryBananaPhoneMode
    36 39   - DiskBananaPhoneMode
    37 40   - AutoBananaPhoneMode
     41 + - HalosGate
    38 42  */
    39 43  func NewBananaPhone(t PhoneMode) (*BananaPhone, error) {
    40 44   return NewBananaPhoneNamed(t, "ntdll.dll", `C:\Windows\system32\ntdll.dll`)
    skipped 11 lines
    52 56   - MemoryBananaPhoneMode
    53 57   - DiskBananaPhoneMode
    54 58   - AutoBananaPhoneMode
     59 + - HalosGate
    55 60  */
    56 61  func NewBananaPhoneNamed(t PhoneMode, name, diskpath string) (*BananaPhone, error) {
    57 62   var p *pe.File
    58 63   var e error
    59 64   var bp = &BananaPhone{}
    60 65   switch t {
     66 + case HalosGateBananaPhoneMode:
     67 + fallthrough
    61 68   case AutoBananaPhoneMode:
    62 69   fallthrough
    63 70   case MemoryBananaPhoneMode:
    skipped 19 lines
    83 90   }
    84 91   bp.banana = p
    85 92   bp.isAuto = t == AutoBananaPhoneMode
     93 + bp.isHalosGate = t == HalosGateBananaPhoneMode
    86 94   return bp, e
    87 95  }
    88 96   
    skipped 39 lines
    128 136   return 0, e2
    129 137   }
    130 138   r, e = b.getSysID(funcname, 0, false)
     139 + } else if b.isHalosGate && errors.As(e, &err) {
     140 + r, e = b.getSysIDFromNeighbor(funcname, 0, false)
    131 141   }
    132 142   }
    133 143   return r, e
    skipped 34 lines
    168 178   buff := b[offset : offset+10]
    169 179   
    170 180   return sysIDFromRawBytes(buff)
     181 + }
     182 + }
     183 + return 0, errors.New("Could not find syscall ID")
     184 +}
     185 + 
     186 +//getSysIDFromNeighboor deduces the syscall ID based on the a neighbor's syscall that is not hooked
     187 +func (b BananaPhone) getSysIDFromNeighbor(funcname string, ord uint32, useOrd bool) (uint16, error) {
     188 + 
     189 + ex, e := b.banana.Exports()
     190 + if e != nil {
     191 + return 0, e
     192 + }
     193 + 
     194 + for _, exp := range ex {
     195 + if (useOrd && exp.Ordinal == ord) || // many bothans died for this feature (thanks awgh). Turns out that a value can be exported by ordinal, but not by name! man I love PE files. ha ha jk.
     196 + exp.Name == funcname {
     197 + offset := rvaToOffset(b.banana, exp.VirtualAddress)
     198 + bBytes, e := b.banana.Bytes()
     199 + if e != nil {
     200 + return 0, e
     201 + }
     202 + buff := bBytes[offset : offset+10]
     203 + 
     204 + sysId, e := sysIDFromRawBytes(buff)
     205 + var err MayBeHookedError
     206 + // Look for the syscall ID in the neighborhood
     207 + if errors.As(e, &err) {
     208 + start, size := GetNtdllStart()
     209 + distanceNeighbor := 0
     210 + // Search forward
     211 + for i := uintptr(offset); i < start+size; i += 1 {
     212 + if bBytes[i] == byte('\x0f') && bBytes[i+1] == byte('\x05') && bBytes[i+2] == byte('\xc3') {
     213 + distanceNeighbor++
     214 + // The sysid should be located 14 bytes after the syscall; ret instruction.
     215 + sysId, e := sysIDFromRawBytes(bBytes[i+14 : i+14+8])
     216 + if !errors.As(e, &err) {
     217 + return sysId - uint16(distanceNeighbor), e
     218 + }
     219 + }
     220 + }
     221 + // reset the value to 1. When we go forward we catch the current syscall; ret but not when we go backward, so distanceNeighboor = 0 for forward and distanceNeighboor = 1 for backward
     222 + distanceNeighbor = 1
     223 + // If nothing has been found forward, search backward
     224 + for i := uintptr(offset) - 1; i > 0; i -= 1 {
     225 + if bBytes[i] == byte('\x0f') && bBytes[i+1] == byte('\x05') && bBytes[i+2] == byte('\xc3') {
     226 + distanceNeighbor++
     227 + // The sysid should be located 14 bytes after the syscall; ret instruction.
     228 + sysId, e := sysIDFromRawBytes(bBytes[i+14 : i+14+8])
     229 + if !errors.As(e, &err) {
     230 + return sysId + uint16(distanceNeighbor) - 1, e
     231 + }
     232 + }
     233 + }
     234 + } else {
     235 + return sysId, e
     236 + }
    171 237   }
    172 238   }
    173 239   return 0, errors.New("Could not find syscall ID")
    skipped 18 lines
Please wait...
Page is in error, reload to recover