Last active
May 29, 2024 06:31
-
-
Save FrankSpierings/40d03161ad706d343d416b808c8ac5d3 to your computer and use it in GitHub Desktop.
Frida code to enumerate the Golang symbols
This file contains hidden or 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
const utils = { | |
colors: { | |
red: function(string) { | |
return '\x1b[31m' + string + '\x1b[0m'; | |
}, | |
green: function(string) { | |
return '\x1b[32m' + string + '\x1b[0m'; | |
}, | |
yellow: function(string) { | |
return '\x1b[33m' + string + '\x1b[0m'; | |
}, | |
blue: function(string) { | |
return '\x1b[34m' + string + '\x1b[0m'; | |
}, | |
cyan: function(string) { | |
return '\x1b[36m' + string + '\x1b[0m'; | |
}, | |
}, | |
ascii: function(address) { | |
var address = ptr(address); | |
var output = []; | |
for (var i=0; i<Process.pointerSize; i++) { | |
var b = address.shr(Process.pointerSize * i).and(0xff); | |
if ((b > 0x1f) && (b < 0x7f)) { | |
output.push(this.colors.green(String.fromCharCode(b))); | |
} else { | |
output.push(this.colors.red('.')) | |
} | |
} | |
return output.join(''); | |
}, | |
backtrace: function(context) { | |
return 'Backtrace:\n' + Thread.backtrace(context, Backtracer.FUZZY).map(DebugSymbol.fromAddress).join('\n') + '\n'; | |
}, | |
telescope: function(address) { | |
var items = this.addressResolve(address); | |
var results = []; | |
for (var i=0; i < items.length - 1; i++) { | |
var item = items[i]; | |
var range = Process.findRangeByAddress(item['address']); | |
if(range) { | |
if (range.protection.match(/^.w.$/)) { | |
results.push(this.colors.blue(item['address'])); | |
} | |
else if (range.protection.match(/^..x$/)) { | |
results.push(this.colors.red(item['address'])); | |
} | |
else if (range.protection.match(/^r..$/)) { | |
results.push(this.colors.yellow(item['address'])); | |
} | |
else { | |
results.push(this.colors.cyan(item['address'])); | |
} | |
} | |
} | |
var output = results.join(' -> '); | |
output += (" = " + items[items.length - 1]['address']); | |
output += (": " + this.ascii(items[items.length - 1]['address'])); | |
return output; | |
}, | |
addressResolve: function(address, stack) { | |
address = ptr(address); | |
if (!stack) { | |
stack = []; | |
} | |
if (stack.length > 10) { | |
return stack; | |
} | |
var record = { | |
address: address, | |
}; | |
try { | |
if (Process.pointerSize == 8) { | |
record['value'] = address.readU64(); | |
} else { | |
record['value'] = address.readU32(); | |
} | |
try { | |
record['string'] = address.readUtf8String(); | |
} catch (error) {} | |
} | |
catch (error) { | |
// console.warn('Address ' + address + ' is not a pointer'); | |
} | |
stack.push(record); | |
if (record['value']) { | |
stack = this.addressResolve(ptr(record['value']), stack); | |
} | |
return stack; | |
} | |
}; | |
const Golang = { | |
gopclntab: null, | |
symbolmap: null, | |
findGopclntab: function() { | |
if (this.gopclntab) { | |
return this.gopclntab; | |
} | |
const pattern = "FB FF FF FF 00 00"; | |
var mainmodule = Process.enumerateModules()[0]; | |
var ranges = Process.enumerateRangesSync('r--'); | |
for (var ri in ranges) { | |
var range = ranges[ri]; | |
if (range['base'] && range['size'] && | |
range['file'] && (range['file']['path'] == mainmodule['path'])) { | |
var matches = Memory.scanSync(range['base'], range['size'], pattern); | |
if (matches && matches.length > 0) { | |
// console.log(JSON.stringify(matches)); | |
for (var mi in matches) { | |
// Check if this is the table by comparing its first entry defined | |
// address with the defined offset + the found address. | |
var address = matches[mi]['address']; | |
// console.log(hexdump(address)); | |
var entry = address.add(8).add(Process.pointerSize).readPointer(); | |
var offset = address.add(8).add(Process.pointerSize * 2).readPointer(); | |
if (address.add(offset).readPointer().compare(entry) == 0) { | |
// console.log(address); | |
this.gopclntab = address; | |
return this.gopclntab; | |
} | |
}; | |
} | |
} | |
} | |
return null; | |
}, | |
enumerateSymbolsSync: function() { | |
if (this.symbolmap) { | |
return this.symbolmap; | |
} | |
var address = this.findGopclntab(); | |
var output = []; | |
if(address) { | |
// Read the header | |
var headerSize = 8; | |
var tableBase = address; | |
var recordSize = Process.pointerSize * 2; | |
var cursor = address.add(headerSize); | |
var tableEnd = address.add(cursor.readUInt() * recordSize); | |
cursor = cursor.add(Process.pointerSize); | |
// Enumerate the records | |
while ((cursor.compare(tableEnd) == -1)) { | |
var offset = cursor.add(Process.pointerSize).readPointer(); | |
var functionAddress = tableBase.add(offset).readPointer(); | |
var nameOffset = tableBase.add(offset).add(Process.pointerSize).readU32(); | |
var name = tableBase.add(nameOffset).readUtf8String(); | |
output.push({ | |
address: functionAddress, | |
name: name, | |
table: tableBase.add(offset), | |
tableBase: tableBase, | |
}) | |
cursor = cursor.add(recordSize); | |
} | |
} | |
this.symbolmap = output; | |
return this.symbolmap; | |
}, | |
findSymbolByName: function(name) { | |
var map = this.enumerateSymbolsSync(); | |
for (var index in map) { | |
if (map[index]['name'] === name) { | |
return map[index]['address']; | |
} | |
} | |
return null; | |
}, | |
findSymbolsByPattern: function(pattern) { | |
var map = this.enumerateSymbolsSync(); | |
var output = [] | |
for (var index in map) { | |
if (map[index]['name'].match(pattern)) { | |
output.push(map[index]); | |
} | |
} | |
return output; | |
}, | |
}; | |
function golanghooks() { | |
(function() { | |
var name = 'crypto/aes.NewCipher'; | |
var address = Golang.findSymbolByName(name); | |
if (address != null) { | |
console.log('[!] Hooking: ' + name + ' @ 0x' + address.toString(16)); | |
try { | |
Interceptor.attach(address, { | |
onEnter: function(args) { | |
}, | |
onLeave: function(result) { | |
console.log(name); | |
var rsp = this.context['rsp']; | |
var key = hexdump(rsp.add(Process.pointerSize * 1).readPointer(), {length:32}); | |
for (var i=0; i<4; i++) { | |
console.log('[' + i +'] ' + utils.telescope(rsp)); | |
rsp = rsp.add(Process.pointerSize); | |
} | |
console.log(utils.colors.red("Key:\n" + key)); | |
console.log(utils.colors.yellow(utils.backtrace(this.context))); | |
}, | |
}); | |
} | |
catch (error) { | |
console.error(error); | |
} | |
} | |
})(); | |
(function() { | |
var name = 'crypto/cipher.newCFB'; | |
var address = Golang.findSymbolByName(name); | |
if (address != null) { | |
console.log('[!] Hooking: ' + name + ' @ 0x' + address.toString(16)); | |
try { | |
Interceptor.attach(address, { | |
onEnter: function(args) { | |
}, | |
onLeave: function(result) { | |
console.log(name); | |
var rsp = this.context['rsp']; | |
var iv = hexdump(rsp.add(Process.pointerSize * 3).readPointer(), {length:16}); | |
for (var i=0; i<4; i++) { | |
console.log('[' + i +'] ' + utils.telescope(rsp)); | |
rsp = rsp.add(Process.pointerSize); | |
} | |
console.log(utils.colors.red("IV:\n" + iv)); | |
console.log(utils.colors.yellow(utils.backtrace(this.context))); | |
}, | |
}); | |
} | |
catch (error) { | |
console.error(error); | |
} | |
} | |
})(); | |
} | |
golanghooks(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment