MacOS hook
背景
最近被Python libclang一个pthread.h文件打开被关闭的问题困扰,所以简单研究了下MacOS的hook。
使用工具是frida-trace。
要求:
(1)hook open/close,并打印出调用栈。
(2)hook的是Python进程。
操作
1、下载frida-trace。用的brew install frida-tools。
2、启动Python进程,需要注意的是MacOS不允许hook系统目录下的进程。所以这里我使用的是brew安装的python,例如这里我用的是前些日子刚发布的python3.11。
运行示例:python3.11 build.py
3、编写js脚本
语法请参考 JavaScript API
支持open、close的trace.js。
需要注意的是backtrace需要使用默认的,如果使用FUZZY,不准确。
var path;
var array;
Interceptor.attach(Module.getExportByName(null, "open"), {
onEnter(args) {
path = args[0].readUtf8String();
//if (path == "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/pthread.h") {
array = Thread.backtrace(this.context);
onLeave(retvalue) {
fd = retvalue.toInt32();
if (fd > 0) {
console.log("");
console.log(`"valid ${fd} ${path}"`);
array.forEach(element => {
const symbol = DebugSymbol.fromAddress(element);
console.log(`"${symbol}"`);
} else {
console.log("");
console.log(`"invalid ${path}"`);
array.forEach(element => {
const symbol = DebugSymbol.fromAddress(element);
console.log(`"${symbol}"`);
Interceptor.attach(Module.getExportByName(null, "close"), {
onEnter(args) {
fd = args[0].toInt32();
array = Thread.backtrace(this.context);
console.log("");
console.log(`"close ${fd} ${path}"`);
array.forEach(element => {
const symbol = DebugSymbol.fromAddress(element);
console.log(`"${symbol}"`);
4、监听目标进程
ps aux | grep Python查找目标进程pid,例如进程id是1818。
frida-trace -p 1818 -S ./trace.js
5、示例输出
先聚焦到pthread.h
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/pthread.h
"0x10bd3e87b libclang.dylib!llvm::sys::fs::openFile(llvm::Twine const&, int&, llvm::sys::fs::CreationDisposition, llvm::sys::fs::FileAccess, llvm::sys::fs::OpenFlags, unsigned int)"
"0x10bd3cbfe libclang.dylib!llvm::sys::fs::openFileForRead(llvm::Twine const&, int&, llvm::sys::fs::OpenFlags, llvm::SmallVectorImpl<char>*)"
"0x10bd3e92b libclang.dylib!llvm::sys::fs::openNativeFileForRead(llvm::Twine const&, llvm::sys::fs::OpenFlags, llvm::SmallVectorImpl<char>*)"
"0x10bd0ef62 libclang.dylib!(anonymous namespace)::RealFileSystem::openFileForRead(llvm::Twine const&)"
"0x109c6f9fb libclang.dylib!clang::FileSystemStatCache::get(llvm::StringRef, llvm::vfs::Status&, bool, std::__1::unique_ptr<llvm::vfs::File, std::__1::default_delete<llvm::vfs::File> >*, clang::FileSystemStatCache*, llvm::vfs::FileSystem&)"
"0x109c6c0fb libclang.dylib!clang::FileManager::getStatValue(llvm::StringRef, llvm::vfs::Status&, bool, std::__1::unique_ptr<llvm::vfs::File, std::__1::default_delete<llvm::vfs::File> >*)"
"0x109c6c4d9 libclang.dylib!clang::FileManager::getFileRef(llvm::StringRef, bool, bool)"
"0x109fa7e10 libclang.dylib!clang::HeaderSearch::getFileAndSuggestModule(llvm::StringRef, clang::SourceLocation, clang::DirectoryEntry const*, bool, clang::Module*, clang::ModuleMap::KnownHeader*)"
"0x109fa866e libclang.dylib!clang::DirectoryLookup::LookupFile(llvm::StringRef&, clang::HeaderSearch&, clang::SourceLocation, llvm::SmallVectorImpl<char>*, llvm::SmallVectorImpl<char>*, clang::Module*, clang::ModuleMap::KnownHeader*, bool&, bool&, bool&, llvm::SmallVectorImpl<char>&) const"
"0x109faa13d libclang.dylib!clang::HeaderSearch::LookupFile(llvm::StringRef, clang::SourceLocation, bool, clang::detail::SearchDirIteratorImpl<true>, clang::detail::SearchDirIteratorImpl<true>*, llvm::ArrayRef<std::__1::pair<clang::FileEntry const*, clang::DirectoryEntry const*> >, llvm::SmallVectorImpl<char>*, llvm::SmallVectorImpl<char>*, clang::Module*, clang::ModuleMap::KnownHeader*, bool*, bool*, bool, bool)"
"0x109fede4f libclang.dylib!clang::Preprocessor::LookupFile(clang::SourceLocation, llvm::StringRef, bool, clang::detail::SearchDirIteratorImpl<true>, clang::FileEntry const*, clang::detail::SearchDirIteratorImpl<true>*, llvm::SmallVectorImpl<char>*, llvm::SmallVectorImpl<char>*, clang::ModuleMap::KnownHeader*, bool*, bool*, bool)"
"0x10a00d3f3 libclang.dylib!EvaluateHasIncludeCommon(clang::Token&, clang::IdentifierInfo*, clang::Preprocessor&, clang::detail::SearchDirIteratorImpl<true>, clang::FileEntry const*)"
"0x10a00a1f5 libclang.dylib!clang::Preprocessor::ExpandBuiltinMacro(clang::Token&)"
"0x10a0089c6 libclang.dylib!clang::Preprocessor::HandleMacroExpandedIdentifier(clang::Token&, clang::MacroDefinition const&)"
"0x10a026a85 libclang.dylib!clang::Preprocessor::HandleIdentifier(clang::Token&)"
"0x109fc3e94 libclang.dylib!clang::Lexer::LexTokenInternal(clang::Token&, bool)"
跟这个调用栈一样的还有RTK_device_methods.h(不过找不到这个文件):
ExpandBuiltinMacro的场景
"0x1160e687b libclang.dylib!llvm::sys::fs::openFile(llvm::Twine const&, int&, llvm::sys::fs::CreationDisposition, llvm::sys::fs::FileAccess, llvm::sys::fs::OpenFlags, unsigned int)"
"0x1160e4bfe libclang.dylib!llvm::sys::fs::openFileForRead(llvm::Twine const&, int&, llvm::sys::fs::OpenFlags, llvm::SmallVectorImpl<char>*)"
"0x1160e692b libclang.dylib!llvm::sys::fs::openNativeFileForRead(llvm::Twine const&, llvm::sys::fs::OpenFlags, llvm::SmallVectorImpl<char>*)"
"0x1160b6f62 libclang.dylib!(anonymous namespace)::RealFileSystem::openFileForRead(llvm::Twine const&)"
"0x1140179fb libclang.dylib!clang::FileSystemStatCache::get(llvm::StringRef, llvm::vfs::Status&, bool, std::__1::unique_ptr<llvm::vfs::File, std::__1::default_delete<llvm::vfs::File> >*, clang::FileSystemStatCache*, llvm::vfs::FileSystem&)"
"0x1140140fb libclang.dylib!clang::FileManager::getStatValue(llvm::StringRef, llvm::vfs::Status&, bool, std::__1::unique_ptr<llvm::vfs::File, std::__1::default_delete<llvm::vfs::File> >*)"
"0x1140144d9 libclang.dylib!clang::FileManager::getFileRef(llvm::StringRef, bool, bool)"
"0x11434fe10 libclang.dylib!clang::HeaderSearch::getFileAndSuggestModule(llvm::StringRef, clang::SourceLocation, clang::DirectoryEntry const*, bool, clang::Module*, clang::ModuleMap::KnownHeader*)"
"0x11435066e libclang.dylib!clang::DirectoryLookup::LookupFile(llvm::StringRef&, clang::HeaderSearch&, clang::SourceLocation, llvm::SmallVectorImpl<char>*, llvm::SmallVectorImpl<char>*, clang::Module*, clang::ModuleMap::KnownHeader*, bool&, bool&, bool&, llvm::SmallVectorImpl<char>&) const"
"0x11435213d libclang.dylib!clang::HeaderSearch::LookupFile(llvm::StringRef, clang::SourceLocation, bool, clang::detail::SearchDirIteratorImpl<true>, clang::detail::SearchDirIteratorImpl<true>*, llvm::ArrayRef<std::__1::pair<clang::FileEntry const*, clang::DirectoryEntry const*> >, llvm::SmallVectorImpl<char>*, llvm::SmallVectorImpl<char>*, clang::Module*, clang::ModuleMap::KnownHeader*, bool*, bool*, bool, bool)"
"0x114395e4f libclang.dylib!clang::Preprocessor::LookupFile(clang::SourceLocation, llvm::StringRef, bool, clang::detail::SearchDirIteratorImpl<true>, clang::FileEntry const*, clang::detail::SearchDirIteratorImpl<true>*, llvm::SmallVectorImpl<char>*, llvm::SmallVectorImpl<char>*, clang::ModuleMap::KnownHeader*, bool*, bool*, bool)"
"0x1143b53f3 libclang.dylib!EvaluateHasIncludeCommon(clang::Token&, clang::IdentifierInfo*, clang::Preprocessor&, clang::detail::SearchDirIteratorImpl<true>, clang::FileEntry const*)"
"0x1143b21f5 libclang.dylib!clang::Preprocessor::ExpandBuiltinMacro(clang::Token&)"
"0x1143b09c6 libclang.dylib!clang::Preprocessor::HandleMacroExpandedIdentifier(clang::Token&, clang::MacroDefinition const&)"
"0x1143cea85 libclang.dylib!clang::Preprocessor::HandleIdentifier(clang::Token&)"
"0x11436be94 libclang.dylib!clang::Lexer::LexTokenInternal(clang::Token&, bool)"
不泄漏的场景
open
"valid 207 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/14.0.0/include/stdint.h"
"0x1160e687b libclang.dylib!llvm::sys::fs::openFile(llvm::Twine const&, int&, llvm::sys::fs::CreationDisposition, llvm::sys::fs::FileAccess, llvm::sys::fs::OpenFlags, unsigned int)"
"0x1160e4bfe libclang.dylib!llvm::sys::fs::openFileForRead(llvm::Twine const&, int&, llvm::sys::fs::OpenFlags, llvm::SmallVectorImpl<char>*)"
"0x1160e692b libclang.dylib!llvm::sys::fs::openNativeFileForRead(llvm::Twine const&, llvm::sys::fs::OpenFlags, llvm::SmallVectorImpl<char>*)"
"0x1160b6f62 libclang.dylib!(anonymous namespace)::RealFileSystem::openFileForRead(llvm::Twine const&)"
"0x1140179fb libclang.dylib!clang::FileSystemStatCache::get(llvm::StringRef, llvm::vfs::Status&, bool, std::__1::unique_ptr<llvm::vfs::File, std::__1::default_delete<llvm::vfs::File> >*, clang::FileSystemStatCache*, llvm::vfs::FileSystem&)"
"0x1140140fb libclang.dylib!clang::FileManager::getStatValue(llvm::StringRef, llvm::vfs::Status&, bool, std::__1::unique_ptr<llvm::vfs::File, std::__1::default_delete<llvm::vfs::File> >*)"
"0x1140144d9 libclang.dylib!clang::FileManager::getFileRef(llvm::StringRef, bool, bool)"
"0x11434fe10 libclang.dylib!clang::HeaderSearch::getFileAndSuggestModule(llvm::StringRef, clang::SourceLocation, clang::DirectoryEntry const*, bool, clang::Module*, clang::ModuleMap::KnownHeader*)"
"0x11435066e libclang.dylib!clang::DirectoryLookup::LookupFile(llvm::StringRef&, clang::HeaderSearch&, clang::SourceLocation, llvm::SmallVectorImpl<char>*, llvm::SmallVectorImpl<char>*, clang::Module*, clang::ModuleMap::KnownHeader*, bool&, bool&, bool&, llvm::SmallVectorImpl<char>&) const"
"0x11435213d libclang.dylib!clang::HeaderSearch::LookupFile(llvm::StringRef, clang::SourceLocation, bool, clang::detail::SearchDirIteratorImpl<true>, clang::detail::SearchDirIteratorImpl<true>*, llvm::ArrayRef<std::__1::pair<clang::FileEntry const*, clang::DirectoryEntry const*> >, llvm::SmallVectorImpl<char>*, llvm::SmallVectorImpl<char>*, clang::Module*, clang::ModuleMap::KnownHeader*, bool*, bool*, bool, bool)"
"0x114395e4f libclang.dylib!clang::Preprocessor::LookupFile(clang::SourceLocation, llvm::StringRef, bool, clang::detail::SearchDirIteratorImpl<true>, clang::FileEntry const*, clang::detail::SearchDirIteratorImpl<true>*, llvm::SmallVectorImpl<char>*, llvm::SmallVectorImpl<char>*, clang::ModuleMap::KnownHeader*, bool*, bool*, bool)"
"0x11439e41f libclang.dylib!clang::Preprocessor::LookupHeaderIncludeOrImport(clang::detail::SearchDirIteratorImpl<true>*, llvm::StringRef&, clang::SourceLocation, clang::CharSourceRange, clang::Token const&, bool&, bool, bool&, clang::detail::SearchDirIteratorImpl<true>, clang::FileEntry const*, llvm::StringRef&, llvm::SmallVectorImpl<char>&, llvm::SmallVectorImpl<char>&, clang::ModuleMap::KnownHeader&, bool)"
"0x11439cdb9 libclang.dylib!clang::Preprocessor::HandleHeaderIncludeOrImport(clang::SourceLocation, clang::Token&, clang::Token&, clang::SourceLocation, clang::detail::SearchDirIteratorImpl<true>, clang::FileEntry const*)"
"0x114396f14 libclang.dylib!clang::Preprocessor::HandleIncludeDirective(clang::SourceLocation, clang::Token&, clang::detail::SearchDirIteratorImpl<true>, clang::FileEntry const*)"
"0x114397a15 libclang.dylib!clang::Preprocessor::HandleDirective(clang::Token&)"
"0x11436bdeb libclang.dylib!clang::Lexer::LexTokenInternal(clang::Token&, bool)"
close
"close 207 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/14.0.0/include/stdint.h"
"0x1160e82bc libclang.dylib!llvm::sys::Process::SafelyCloseFileDescriptor(int)"
"0x1160b815c libclang.dylib!(anonymous namespace)::RealFile::~RealFile()"
"0x114015d00 libclang.dylib!clang::FileManager::getBufferForFile(clang::FileEntry const*, bool, bool)"
"0x114032cd6 libclang.dylib!clang::SrcMgr::ContentCache::getBufferOrNone(clang::DiagnosticsEngine&, clang::FileManager&, clang::SourceLocation) const"
"0x1143a9438 libclang.dylib!clang::Preprocessor::EnterSourceFile(clang::FileID, clang::detail::SearchDirIteratorImpl<true>, clang::SourceLocation, bool)"
"0x11439e101 libclang.dylib!clang::Preprocessor::HandleHeaderIncludeOrImport(clang::SourceLocation, clang::Token&, clang::Token&, clang::SourceLocation, clang::detail::SearchDirIteratorImpl<true>, clang::FileEntry const*)"
"0x114396f14 libclang.dylib!clang::Preprocessor::HandleIncludeDirective(clang::SourceLocation, clang::Token&, clang::detail::SearchDirIteratorImpl<true>, clang::FileEntry const*)"
"0x114397a15 libclang.dylib!clang::Preprocessor::HandleDirective(clang::Token&)"
"0x11436bdeb libclang.dylib!clang::Lexer::LexTokenInternal(clang::Token&, bool)"
"0x1143cf0e9 libclang.dylib!clang::Preprocessor::Lex(clang::Token&)"