Frida之API使用进阶

Frida之API使用进阶

首页角色扮演无情剑客更新时间:2024-04-22

在前面的文章中,对图中大部分的API进行了介绍,今天继续后面内容的介绍。

Kernel

顾名思义,与内核相关的,枚举内核加载的模块,或者操控内核内存部分。经过测试,在Android和Linux系统下,Kernel.available是false,相关的API都是不能够使用的。

Kernel.available: a boolean specifying whether the Kernel API is available. Do not invoke any other Kernel properties or methods unless this is the case. 如果不是可获取的,那么后面的所有属性和方法都不能使用。

Kernel.base: base address of the kernel, as a UInt64.

Kernel.pageSize: size of a kernel page in bytes, as a number.

Kernel.enumerateModules(): enumerates kernel modules loaded right now, returning an array of objects containing the following properties:

Kernel.enumerateRanges(protection|specifier): enumerate kernel memory ranges satisfying protection given as a string of the form: rwx, where rw- means “must be at least readable and writable”. Alternatively you may provide a specifier object with a protection key whose value is as aforementioned, and a coalesce key set to true if you’d like neighboring ranges with the same protection to be coalesced (the default is false; i.e. keeping the ranges separate). Returns an array of objects containing the following properties:

Kernel.enumerateModuleRanges(name, protection): just like Kernel.enumerateRanges, except it’s scoped to the specified module name – which may be null for the module of the kernel itself. Each range also has a name field containing a unique identifier as a string.

Kernel.alloc(size): allocate size bytes of kernel memory, rounded up to a multiple of the kernel’s page size. The returned value is a UInt64 specifying the base address of the allocation.

Kernel.protect(address, size, protection): update protection on a region of kernel memory, where protection is a string of the same format as Kernel.enumerateRanges().

For example:

Kernel.protect(UInt64('0x1234'), 4096, 'rw-');

Kernel.readByteArray(address, length): just like NativePointer#readByteArray, but reading from kernel memory.

Kernel.writeByteArray(address, bytes): just like NativePointer#writeByteArray, but writing to kernel memory.

Kernel.scan(address, size, pattern, callbacks): just like Memory.scan, but scanning kernel memory.

Kernel.scanSync(address, size, pattern): synchronous version of scan() that returns the matches in an array.

setTimeout(function (){ Java.perform(function (){ console.log(Kernel.available); console.log(Kernel.base); console.log(Kernel.pageSize); }); });

运行结果,在Android和Linux系统上运行结果相同:

CModule

简单理解就是在代码中插入C模块。

new CModule(source[, symbols]): compiles C source code string to machine code, straight to memory. Useful for implementing hot callbacks, e.g. for Interceptor and Stalker, but also useful when needing to start new threads in order to call functions in a tight loop, e.g. for fuzzing purposes. Global functions are automatically exported as NativePointer properties named exactly like in the C source code. This means you can pass them to Interceptor and Stalker, or call them using NativePointer. The optional second argument, symbols, is an object specifying additional symbol names and their NativePointer values, each of which will be plugged in at creation. This may for example be one or more memory blocks allocated using Memory.alloc(), and/or NativeCallback values for receiving callbacks from the C module.

To perform initialization and cleanup, you may define functions with the following names and signatures:

dispose(): eagerly unmaps the module from memory. Useful for short-lived modules when waiting for a future garbage collection isn’t desirable. 例子:

var source = [ '#include <stdio.h>', '', 'void hello(void) {', ' printf("Hello World from CModule\\n");', '}',].join('\n');var cm = new CModule(source);console.log(JSON.stringify(cm));var hello = new NativeFunction(cm.hello, 'void', []);hello();

运行

frida -p 0 --runtime=v8 -l example.js

结果如下所示:

DebugSymbol

调试符号相关内容。

DebugSymbol.fromAddress(address), DebugSymbol.fromName(name): look up debug information for address/name and return it as an object containing:

You may also call toString() on it, which is very useful when combined with Thread.backtrace():

DebugSymbol.getFunctionByName(name): resolves a function name and returns its address as a NativePointer. Returns the first if more than one function is found. Throws an exception if the name cannot be resolved.

DebugSymbol.findFunctionsNamed(name): resolves a function name and returns its addresses as an array of NativePointer objects.

DebugSymbol.findFunctionsMatching(glob): resolves function names matching glob and returns their addresses as an array of NativePointer objects.

DebugSymbol.load(path): loads debug symbols for a specific module.

例子:

Interceptor.attach(Module.getExportByName(null, 'read'), { onEnter: function (args) { console.log('read called from:\n' Thread.backtrace(this.context, Backtracer.ACCURATE) .map(DebugSymbol.fromAddress).join('\n') '\n'); }})

Interceptor在后面的文章中会介绍,根据英文翻译大致能推测出来它的功能类似拦截器。

运行 frida-U-l hello.js com.lingpao.lpcf622b–debug--runtime=v8 结果:

写在最后

Frida 基本API的使用到这里基本上差不多了。在接下来的文章中,会介绍一些高级的API及他们的使用。本篇文章涉及的API使用的不是很多,在解决一些疑难问题的时候,可能会用到。

公众号

更多内容,欢迎关注我的公众号:无情剑客。

查看全文
大家还看了
也许喜欢
更多游戏

Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved