OS X の共有ライブラリでローカル シンボルのオフセットを見つける必要があります。ローカル シンボルは、エクスポートされていないシンボルと同じです。したがってdyld("symbol_name")
、動作しません。
ただし、これらのオフセットを見つけるために使用できnm
ます。たとえば、
$ nm /System/Library/PrivateFrameworks/DesktopServicesPriv.framework/DesktopServicesPriv | grep -e ChildSetLabel -e NodeVolumeEject
000000000006cccd T _NodeVolumeEject
000000000009dbd7 t __ChildSetLabel
そこには、エクスポートされた ( T
) シンボルが表示されます。これは、を使用して簡単に表示できるNodeVolumeEject
オフセットです。現在のアドレス空間のアドレスが明らかになりますが、共有ライブラリのオフセットまたはアドレス空間の絶対アドレスに満足しています。さらに、ローカル ( ) シンボルがありますが、これはオフセット ( ) を使用して明らかにすることはできません。0x6cccd
dyld("NodeVolumeEject")
dyld()
t
_ChildSetLabel
0x9dbd7
dyld()
この解決策をプログラムで実行できるようにしたいと思います (、、、またはその他の外部プログラムなしで) gobjdump
。それを達成するための「簡単な」方法はありますか?上記のツールのソース コードには必要なコードが含まれていますが、もっと簡単なものはないのでしょうか。nm
otool
ドメイン: このソリューションは、x86_64 MachO バイナリの OS X 10.8 以降でのみ動作する必要があります。
明確化:現在のオフセット(ASLRによる)の絶対オフセットが明らかに静的ではないことを理解していただければ幸いです。しかし、(再コンパイルするまで) 静的なままである、そのライブラリの開始点に対するオフセットを把握することもできてうれしいです。「ライブラリ内のアドレス」から「アドレス空間内のアドレス」までの部分は非常に簡単です。
off_t sym_offset_child_set_label = ANSWER_TO_THIS_QUESTION("_ChildSetLabel");
Dl_info info;
void *abs_volume_eject = dlsym(RTLD_DEFAULT, "NodeVolumeEject");
void *abs_child_set_label = NULL;
if (dladdr(abs_volume_eject, &info)) {
abs_child_set_label = (void *)((char *)info.dli_fbase + sym_offset_child_set_label);
/* abs_child_set_label now points to the function in question */
}
これは、_ChildSetLabel
とNodeVolumeEject
が同じ共有ライブラリにあれば十分です。したがって、ASLR はここでは問題になりません。