Last active
December 29, 2022 19:03
-
-
Save NSEcho/5bd1d91c9509dc14bd7d662f910078e2 to your computer and use it in GitHub Desktop.
go runtime analysis
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let Pointer = Process.pointerSize; | |
let syms = Process.enumerateModules()[0].enumerateSymbols(); | |
let PCLNTAB = "runtime.pclntab" | |
let GOBUILDID = "go.buildid" | |
let GOROOTC = "runtime.defaultGOROOT.str" | |
let BUILDVERSIONC = "runtime.buildVersion.str" | |
let FIRSTMODULEDATAC = "runtime.firstmoduledata" | |
let GOSTRING = "go.string.*" | |
let TFLAGEXTRASTAR = 1 << 1 | |
class Sym { | |
constructor(name, sizeOfArgs, entry) { | |
this.name = name; | |
this.sizeOfArgs = sizeOfArgs; | |
this.entry = entry; | |
} | |
} | |
let kinds = { | |
0:"Invalid Kind", | |
1:"Bool", | |
2:"Int", | |
3:"Int8", | |
4:"Int16", | |
5:"Int32", | |
6:"Int64", | |
7:"Uint", | |
8:"Uint8", | |
9:"Uint16", | |
10:"Uint32", | |
11:"Uint64", | |
12:"Uintptr", | |
13:"Float32", | |
14:"Float64", | |
15:"Complex64", | |
16:"Complex128", | |
17:"Array", | |
18:"Chan", | |
19:"Func", | |
20:"Interface", | |
21:"Map", | |
22:"Pointer", | |
23:"Slice", | |
24:"String", | |
25:"Struct", | |
26:"UnsafePointer" | |
} | |
class Go { | |
constructor() { | |
this.available = false; | |
this.pcl = null; | |
this.goroot = ""; | |
this.buildVersion = ""; | |
this.firstModuledata = ""; | |
for (var i = 0; i < syms.length; i++) { | |
switch(syms[i].name) { | |
case GOBUILDID: | |
this.available = true; | |
break; | |
case GOROOTC: | |
this.goroot = Memory.readCString(ptr(syms[i].address)) | |
break; | |
case BUILDVERSIONC: | |
this.buildVersion = Memory.readCString(ptr(syms[i].address)); | |
break; | |
case FIRSTMODULEDATAC: | |
this.firstModuledata = syms[i].address; | |
} | |
} | |
this.available = (function() { | |
var av = false; | |
for (var i = 0; i < syms.length; i++) { | |
if (syms[i].name == GOBUILDID) { | |
av = true; | |
break; | |
} | |
} | |
return av; | |
})(); | |
if (this.available) { | |
this.symbols = [] | |
this.pcl = (function() { | |
var addr = null; | |
for (var i = 0; i < syms.length; i++) { | |
if (syms[i].name == PCLNTAB) { | |
addr = syms[i].address; | |
break; | |
} | |
} | |
return ptr(addr); | |
})(); | |
this.nfunc = Memory.readLong(this.pcl.add(Pointer)); | |
this.nfile = Memory.readLong(this.pcl.add(Pointer*2)); | |
this.textStart = Memory.readLong(this.pcl.add(Pointer * 3)); | |
this.cuOffset = Memory.readLong(this.pcl.add(Pointer*5)); | |
this.cutab = this.pcl.add(this.cuOffset); | |
this.funcnameOffset = Memory.readLong(this.pcl.add(Pointer * 4)); | |
this.filetabOffset = Memory.readLong(this.pcl.add(Pointer*6)); | |
this.pctabOffset = Memory.readLong(this.pcl.add(Pointer*7)); | |
this.pctab = this.pcl.add(this.pctabOffset); | |
this.pclnOffset = Memory.readLong(this.pcl.add(Pointer * 8)); | |
this.pcln = this.pcl.add(this.pclnOffset); | |
this.funcnametab = this.pcl.add(this.funcnameOffset); | |
this.fileTab = this.pcl.add(this.filetabOffset); | |
this.functab = this.pcl.add(this.pclnOffset); | |
} | |
}; | |
enumerateExports() { | |
if (!this.available) { | |
console.log("Binary is not built with go!"); | |
return; | |
} | |
if (this.symbols.length == 0) { | |
var p = this.functab; | |
for (var i = 0; i < this.nfunc; i++) { | |
var funcAddress = Memory.readInt(p) + this.textStart; | |
p = p.add(4); | |
var funcOffset = Memory.readInt(p); | |
p = p.add(4); | |
var nameOffset = Memory.readU32(this.functab.add(funcOffset + 4)); | |
var sizeOfArgs = Memory.readU32(this.functab.add(funcOffset + 8)); | |
if (sizeOfArgs == 2147483648) { | |
sizeOfArgs = 0; | |
} | |
var name = Memory.readUtf8String(this.funcnametab.add(nameOffset)); | |
var sym = new Sym(name, sizeOfArgs, "0x" + funcAddress.toString(16)); | |
this.symbols.push(sym); | |
} | |
} | |
return this.symbols; | |
}; | |
typeOfPtr() { | |
return "this method will return the type of pointer"; | |
}; | |
// returns symbols inside the filetab | |
readFileTabSymbols() { | |
var filetabStrings = [] | |
var finished = false; | |
var p = go.fileTab; | |
while (!finished) { | |
var bt = Memory.readU8(p); | |
var peekbt = Memory.readU8(p.add(1)); | |
if (bt == 0 && peekbt == 0) { | |
finished = true; | |
break; | |
} | |
var s = Memory.readUtf8String(p); | |
filetabStrings.push(s); | |
p = p.add(s.length+1); | |
} | |
return filetabStrings; | |
}; | |
// It disassembles function that ends only with the ret | |
disassembleFn(fnAddr) { | |
var addr = ptr(fnAddr); | |
var inst = Instruction.parse(addr); | |
console.log(addr, inst.toString()); | |
var next = inst.next; | |
while (next != null) { | |
inst = Instruction.parse(ptr(next)); | |
console.log(inst.address, inst.toString()); | |
if (inst.mnemonic == "ret") { | |
break; | |
} | |
next = inst.next; | |
}; | |
}; | |
getType(addr) { | |
var kind = Memory.readU8(ptr(addr).add(23)) // kind inside _type struct | |
switch (kinds[kind]) { | |
case "Struct": | |
case "Array": | |
var nm = Memory.readU32(ptr(addr).add(40)) // str inside _type struct | |
var tflag = Memory.readU8(ptr(addr).add(20)) // tflag inside _type struct | |
var types = Memory.readPointer(go.firstModuledata.add(168+8*16)) // types section holding _type structures | |
var off = 0; | |
var flagRes = tflag & TFLAGEXTRASTAR; | |
if (flagRes != 0) { | |
off = 2; | |
} | |
var typeName = Memory.readUtf8String(types.add(nm+off)); | |
var match = /[\u0000-\u0008,\u000A-\u001F,\u007F-\u00A0]+/.exec(typeName); // remove nonprintable chars | |
if (match != null) { | |
typeName = typeName.slice(0, match.index); | |
} | |
return kinds[kind] + " => " + typeName; | |
break; | |
default: | |
return kinds[kind] | |
} | |
}; | |
} | |
var go = new Go(); | |
global.go = go; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment