javacommons
@javacommons

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

unicorn engine でホストの c 関数で計算を行って エミュレーションのコードに値を返すサンプル

解決したいこと

以下のコードで、host_function が呼ばれない(ように見える)のを解決したい。
以下のコードは、ChatGPT に「unicorn engine でホストの c 関数で計算を行って エミュレーションのコードに値を返すサンプルを書いて」とお願いして書いてもらったコードです。

#include <unicorn/unicorn.h>
#include <iostream>

// ホストのC関数
int host_function(uc_engine* uc, void* user_data) {
    // Unicornエミュレーションコンテキストからデータを取得
    uint64_t arg1, arg2;
    uc_reg_read(uc, UC_X86_REG_RDI, &arg1);
    uc_reg_read(uc, UC_X86_REG_RSI, &arg2);

    // ホスト関数で計算
    uint64_t result = arg1 + arg2;
    std::cout << "arg1:" << arg1 << std::endl;
    std::cout << "arg2:" << arg2 << std::endl;
    std::cout << "result:" << result << std::endl;

    // 結果をUnicornエミュレーションコンテキストに書き込む
    uc_reg_write(uc, UC_X86_REG_RAX, &result);

    return 0;
}

int main() {
    // Unicornエミュレーションエンジンの初期化
    uc_engine* uc;
    uc_err err = uc_open(UC_ARCH_X86, UC_MODE_64, &uc);
    if (err != UC_ERR_OK) {
        printf("uc_open() failed with error: %s\n", uc_strerror(err));
        return -1;
    }

    // メモリを割り当ててエミュレーションコードをロード
    uint64_t code_address = 0x1000;
    uint8_t code[] = {
        0x48, 0xC7, 0xC6, 0x05, 0x00, 0x00, 0x00, // mov rsi, 5
        0x48, 0xC7, 0xC7, 0x03, 0x00, 0x00, 0x00, // mov rdi, 3
        0xE8, 0x00, 0x00, 0x00, 0x00,             // call host_function
        0xC3                                      // ret
    };

    uc_mem_map(uc, code_address, sizeof(code), UC_PROT_ALL);
    uc_mem_write(uc, code_address, code, sizeof(code));

    // ホスト関数をUnicornエミュレーションコンテキストに登録
    uc_hook hook;
    uc_hook_add(uc, &hook, UC_HOOK_INSN, (void*)host_function, NULL, code_address, code_address + sizeof(code));

    // エミュレーションを開始
    uc_reg_write(uc, UC_X86_REG_RSP, &code_address); // スタックの初期化
    uc_emu_start(uc, code_address, code_address + sizeof(code), 0, 0);

    // 結果を取得
    uint64_t result;
    uc_reg_read(uc, UC_X86_REG_RAX, &result);

    printf("Emulation result: %lu\n", result);

    // Unicornエミュレーションエンジンをクローズ
    uc_close(uc);

    return 0;
}

発生している問題・エラー

$ g++ host-calc.cpp -lunicorn -static
$ ./a.exe
Emulation result: 0
0

1Answer

こちらに issue として質問を投げてます:
https://github.com/unicorn-engine/unicorn/issues/1896

一応動くコードができてます。エラーを無視すれば・・・

#include <unicorn/unicorn.h>
#include <assert.h>
#include <stdio.h>
#include <iostream>

#define OK(x) {uc_err __err; if ((__err = x)) { fprintf(stderr, "%s", uc_strerror(__err)); assert(false); } }

int host_function(uc_engine* uc, void* user_data) {
    std::cout << "host_function(begin)" << std::endl;
    uint64_t arg1, arg2;
    uc_reg_read(uc, UC_X86_REG_RDI, &arg1);
    uc_reg_read(uc, UC_X86_REG_RSI, &arg2);
    uint64_t result = arg1 + arg2;
    std::cout << "arg1:" << arg1 << std::endl;
    std::cout << "arg2:" << arg2 << std::endl;
    std::cout << "result:" << result << std::endl;
    uc_reg_write(uc, UC_X86_REG_RAX, &result);
    std::cout << "host_function(end)" << std::endl;
    return 0;
}

int main() {
    uc_engine* uc;
    uc_err err = uc_open(UC_ARCH_X86, UC_MODE_64, &uc);
    if (err != UC_ERR_OK) {
        printf("uc_open() failed with error: %s\n", uc_strerror(err));
        return -1;
    }
    uint64_t code_address = 0x1000;
#if 0x0
// https://disasm.pro/
mov rsi, 50
mov rdi, 30
mov eax, 1
int 0x80 
mov rsi, 5
mov rdi, 3
mov eax, 1
int 0x80 
ret
#endif
    char code[] = "\x48\xC7\xC6\x32\x00\x00\x00\x48\xC7\xC7\x1E\x00\x00\x00\xB8\x01\x00\x00\x00\xCD\x80\x48\xC7\xC6\x05\x00\x00\x00\x48\xC7\xC7\x03\x00\x00\x00\xB8\x01\x00\x00\x00\xCD\x80\xC3";
    OK(uc_mem_map(uc, code_address, 0x1000/*sizeof(code)*/, UC_PROT_ALL));
    OK(uc_mem_write(uc, code_address, code, sizeof(code)));
    uc_hook hook;
    OK(uc_hook_add(uc, &hook, UC_HOOK_INTR,
                   (void*)host_function, NULL, code_address, code_address + sizeof(code)));
    OK(uc_reg_write(uc, UC_X86_REG_RSP, &code_address));
#ifdef DEBUG // abort on uc_emu_start()'s error
    OK(uc_emu_start(uc, code_address, code_address + sizeof(code), 0, 0));
#else // ignore uc_emu_start()'s error
    uc_emu_start(uc, code_address, code_address + sizeof(code), 0, 0);
#endif
    uint64_t result;
    OK(uc_reg_read(uc, UC_X86_REG_RAX, &result));
    printf("Emulation result: %lu\n", result);
    uc_close(uc);
    return 0;
}
0Like

Your answer might help someone💌