-
-
Save konwa/ea081af5c51508ce3baa64b717f9a684 to your computer and use it in GitHub Desktop.
参考了Wallbreaker,把全部父类的的field也打印了,可以直接在hook脚本接入,不需要额外代码
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
function log(msg) { | |
console.log(msg); | |
} | |
let handleCache = []; | |
function getRealClassName(object) { | |
const objClass = Java.use("java.lang.Object").getClass.apply(object); | |
return Java.use("java.lang.Class").getName.apply(objClass) | |
} | |
function getAllFields(cls) { | |
let fields = []; | |
let currentClass = cls; | |
while (currentClass != null) { | |
fields.push(...currentClass.getDeclaredFields()); | |
currentClass = currentClass.getSuperclass(); | |
} | |
return fields; | |
} | |
function getRealClassNameByHandle(handle) { | |
let obj = Java.use("java.lang.Object"); | |
let jObject = Java.cast(ptr(handle), obj); | |
return getRealClassName(jObject); | |
}; | |
function handledump(handle) { | |
Java.performNow(function () { | |
let origClassName = getRealClassNameByHandle(handle); | |
if (!origClassName) { | |
return | |
} | |
let obj = Java.cast(ptr(handle), Java.use(origClassName)); | |
objectdump(obj); | |
}) | |
} | |
function objectdump(obj) { | |
Java.performNow(function () { | |
function toHexString(payload) { | |
let HexDump = Java.use("com.android.internal.util.HexDump"); | |
return HexDump.toHexString(payload); | |
} | |
function toHexStringLen(payload, length) { | |
let HexDump = Java.use("com.android.internal.util.HexDump"); | |
return HexDump.toHexString(payload, 0, length); | |
} | |
function hasOwnProperty(obj, name) { | |
try { | |
return obj.hasOwnProperty(name) || name in obj; | |
} catch (e) { | |
return false; | |
} | |
} | |
function objectToStr(object) { | |
try { | |
return Java.use("java.lang.Object").toString.apply(object); | |
} catch (e) { | |
return "" + object; | |
} | |
} | |
function getHandle(object) { | |
try { | |
object = Java.retain(object); | |
if (hasOwnProperty(object, '$handle') && object.$handle != undefined) { | |
handleCache[object.$handle] = object; | |
return object.$handle; | |
} else if (hasOwnProperty(object, '$h') && object.$h != undefined) { | |
handleCache[object.$h] = object; | |
return object.$h; | |
} else { | |
const hashcode = Java.use("java.lang.Object").hashCode.apply(object); | |
handleCache[hashcode] = object; | |
return hashcode; | |
} | |
} catch (e) { | |
return null; | |
} | |
} | |
let realClassName = getRealClassName(obj); | |
obj = Java.cast(obj, Java.use(realClassName)); | |
let clazz = obj.class; | |
let clazzName = clazz.getSimpleName(); | |
let packageName = clazz.getPackage().getName(); | |
// let clazzFullName = clazz.getCanonicalName(); | |
// let fields = clazz.getDeclaredFields(); | |
let fields = getAllFields(clazz); | |
let objHandle = getHandle(obj); | |
let logs = [`[${objHandle}]:${objectToStr(obj)}`, `package ${packageName}`, `class ${clazzName} {`]; | |
let static_fields_logs = [" /* static fields */"]; | |
let instance_fields_logs = [" /* instance fields */"]; | |
let Modifier = Java.use("java.lang.reflect.Modifier"); | |
for (let index = 0; index < fields.length; index++) { | |
let field = fields[index]; | |
let isStatic = Modifier.isStatic(field.getModifiers()); | |
let fieldType = field.getType().getName(); | |
let fieldName = field.getName(); | |
let fieldValue = typeof obj[fieldName] == "function" ? obj["_" + fieldName] : obj[fieldName]; | |
let fieldObjStr = null; | |
if (fieldValue !== undefined) { | |
fieldValue = fieldValue.value; | |
if (fieldValue != null) { | |
if (fieldType == "[B") { | |
// 考虑到数组有时候太大... 根据情况修改脚本进行打印完整的数据吧 | |
if (fieldValue.length > 32) { | |
fieldObjStr = `len:${fieldValue.length} => ${toHexStringLen(fieldValue, 32)}...`; | |
} else { | |
fieldObjStr = `len:${fieldValue.length} => ${toHexString(fieldValue)}`; | |
} | |
// fieldObjStr = `${fieldValue}`; | |
} else { | |
fieldObjStr = objectToStr(fieldValue); | |
} | |
let fieldHandle = getHandle(fieldValue); | |
if (fieldHandle != null) { | |
fieldObjStr = `[${fieldHandle}]:${fieldObjStr}`; | |
} | |
} | |
} | |
if (isStatic) { | |
static_fields_logs.push(` static ${fieldType} ${fieldName}; => ${fieldObjStr}`); | |
} else { | |
instance_fields_logs.push(` ${fieldType} ${fieldName}; => ${fieldObjStr}`); | |
} | |
} | |
if (static_fields_logs.length > 1) { | |
Array.prototype.push.apply(logs, static_fields_logs); | |
logs.push(""); | |
} | |
if (instance_fields_logs.length > 1) { | |
Array.prototype.push.apply(logs, instance_fields_logs); | |
logs.push(""); | |
} | |
logs.push(`}`); | |
log(`\n[objectdump] => ${logs.join("\n")}`); | |
}) | |
} | |
rpc.exports = { | |
handledump:handledump | |
} | |
// 在 objectdump 输出内容后,可以交互式具体打印field的内容,例如`handledump(0x6ad6)` |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment