8

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オフセットです。現在のアドレス空間のアドレスが明らかになりますが、共有ライブラリのオフセットまたはアドレス空間の絶対アドレスに満足しています。さらに、ローカル ( ) シンボルがありますが、これはオフセット ( ) を使用して明らかにすることはできません。0x6cccddyld("NodeVolumeEject")dyld()t_ChildSetLabel0x9dbd7dyld()

この解決策をプログラムで実行できるようにしたいと思います (、、、またはその他の外部プログラムなしで) gobjdump。それを達成するための「簡単な」方法はありますか?上記のツールのソース コードには必要なコードが含まれていますが、もっと簡単なものはないのでしょうか。nmotool

ドメイン: このソリューションは、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 */
}

これは、_ChildSetLabelNodeVolumeEjectが同じ共有ライブラリにあれば十分です。したがって、ASLR はここでは問題になりません。

4

1 に答える 1

5

別の可能性 (私が最終的に使用したもの) は、Apple のプライベートCoreSymbolicationフレームワークです。

void *resolve_private(const char *symbol_owner, const char *symbol_to_resolve)
{
    task_t targetTask;
    int err = task_for_pid(mach_task_self(), getpid(), &targetTask);
    if (err) {
        fprintf(stderr, "couldn't get my Mach task\n");
        return NULL;
    }

    CSSymbolicatorRef targetSymbolicator;

    targetSymbolicator = CSSymbolicatorCreateWithTaskFlagsAndNotification(targetTask,
                                                                              kCSSymbolicatorTrackDyldActivity,
                                                                          ^(uint32_t     notification_type, CSNotificationData data) {
                                                                          });
    if(CSIsNull(targetSymbolicator)) {
        fprintf("CSSymbolicatorCreateWithTaskFlagsAndNotification failed\n");
        return NULL;
    }

    __block CSSymbolOwnerRef symbolOwner = kCSNull;
    CSSymbolicatorForeachSymbolOwnerWithNameAtTime(targetSymbolicator,
                                                   symbol_owner,
                                                   kCSNow,
                                                   ^(CSSymbolOwnerRef owner) {
                                                       symbolOwner = owner;
                                                   });
    if (CSIsNull(symbolOwner)) {
        CSRelease(targetSymbolicator);
        fprintf("CSSymbolicatorForeachSymbolOwnerWithNameAtTime failed\n");
        return NULL;
    }

    __block uintptr_t p = (uintptr_t)NULL;
    CSSymbolOwnerForeachSymbol(symbolOwner, ^(CSSymbolRef symbol) {
        const char *symbol_name = CSSymbolGetMangledName(symbol);
        if (0 == strcmp(symbol_name, symbol_to_resolve)) {
            p = CSSymbolGetRange(symbol).location;
        }
    });

    CSRelease(targetSymbolicator);
    if ((uintptr_t)NULL == p) {
        fprintf("symbol not found\n");
        return NULL;
    } else {
        return (void *)p;
    }
}
于 2014-02-18T13:22:41.173 に答える