Esempio n. 1
0
// callback for tracing invalid memory access (READ or WRITE)
static bool hook_mem_invalid(uc_engine *uc, uc_mem_type type,
        uint64_t addr, int size, int64_t value, void *user_data)
{
    uint32_t testval;
    switch(type) {
        default:
            printf("not ok %d - memory invalid type: %d at 0x%" PRIx64 "\n", log_num++, type, addr);
            return false;
        case UC_MEM_WRITE_UNMAPPED:
            printf("# write to invalid memory at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", addr, size, value);

            if (uc_mem_read(uc, addr, &testval, sizeof(testval)) != UC_ERR_OK) {
                printf("ok %d - uc_mem_read fail for address: 0x%" PRIx64 "\n", log_num++, addr);
            } else {
                printf("not ok %d - uc_mem_read success after unmap at test %d\n", log_num++, test_num - 1);
            }

            if (uc_mem_map(uc, addr & ~0xfffL, 0x1000, UC_PROT_READ | UC_PROT_WRITE) != UC_ERR_OK) {
                printf("not ok %d - uc_mem_map fail during hook_mem_invalid callback, addr: 0x%" PRIx64 "\n", log_num++, addr);
            } else {
                printf("ok %d - uc_mem_map success\n", log_num++);
            }
            return true;
    }
}
Esempio n. 2
0
/**
 * A basic test showing mapping of memory, and reading/writing it
 */
static void test_basic(void **state)
{
    uc_engine *uc = *state;
    const uint64_t mem_start = 0x1000;
    const uint64_t mem_len   = 0x1000;
    const uint64_t test_addr = mem_start + 0x100;

    /* Map a region */
    uc_assert_success(uc_mem_map(uc, mem_start, mem_len, UC_PROT_NONE));

    /* Write some data to it */
    uc_assert_success(uc_mem_write(uc, test_addr, "test", 4));

    uint8_t buf[4];
    memset(buf, 0xCC, sizeof(buf));

    /* Read it back */
    uc_assert_success(uc_mem_read(uc, test_addr, buf, sizeof(buf)));

    /* And make sure it matches what we expect */
    assert_memory_equal(buf, "test", 4);

    /* Unmap the region */
    //uc_assert_success(uc_mem_unmap(uc, mem_start, mem_len));
}
Esempio n. 3
0
void perform_read_step(uc_engine *uc){
    char buff[4096*4];
    uint64_t addr = get_addr();
    uint64_t len = get_len()%(4096*4);
    printf("read(uc,0x%"PRIx64",0x%"PRIx64"); //%d\n", addr, len, step);
    uc_mem_read(uc, addr, buff, len);
}
Esempio n. 4
0
// callback for tracing instruction
static void hook_code(uc_engine *uc, uint64_t addr, uint32_t size, void *user_data)
{
    uint8_t opcode;
    uint32_t testval;
    if (uc_mem_read(uc, addr, &opcode, 1) != UC_ERR_OK) {
        printf("not ok %d - uc_mem_read fail during hook_code callback, addr: 0x%" PRIx64 "\n", log_num++, addr);
    }
    printf("ok %d - uc_mem_read for opcode at address 0x%" PRIx64 "\n", log_num++, addr);
    switch (opcode) {
        case 0x90:  //nop
            printf("# Handling NOP\n");
            if (uc_mem_read(uc, 0x200000 + test_num * 0x100000, &testval, sizeof(testval)) != UC_ERR_OK) {
                printf("not ok %d - uc_mem_read fail for address: 0x%x\n", log_num++, 0x200000 + test_num * 0x100000);
            } else {
                printf("ok %d - good uc_mem_read for address: 0x%x\n", log_num++, 0x200000 + test_num * 0x100000);
                printf("# uc_mem_read for test %d\n", test_num);

                if (testval == tests[test_num]) {
                    printf("ok %d - passed test %d\n", log_num++, test_num);
                } else {
                    printf("not ok %d - failed test %d\n", log_num++, test_num);
                    printf("# Expected: 0x%x\n",tests[test_num]);
                    printf("# Received: 0x%x\n", testval);
                }
            }
            if (uc_mem_unmap(uc, 0x200000 + test_num * 0x100000, 0x1000) != UC_ERR_OK) {
                printf("not ok %d - uc_mem_unmap fail during hook_code callback, addr: 0x%x\n", log_num++, 0x200000 + test_num * 0x100000);
            } else {
                printf("ok %d - uc_mem_unmap success\n", log_num++);
            }
            test_num++;
            break;
        case 0xf4:  //hlt
            printf("# Handling HLT\n");
            if (uc_emu_stop(uc) != UC_ERR_OK) {
                printf("not ok %d - uc_emu_stop fail during hook_code callback, addr: 0x%" PRIx64 "\n", log_num++, addr);
                _exit(-1);
            } else {
                printf("ok %d - hlt encountered, uc_emu_stop called\n", log_num++);
            }
            break;
        default:  //all others
            printf("# Handling OTHER\n");
            break;
    }
}
Esempio n. 5
0
static void test_x86_16(void)
{
    uc_engine *uc;
    uc_err err;
    uint8_t tmp;

    int32_t eax = 7;
    int32_t ebx = 5;
    int32_t esi = 6;

    printf("Emulate x86 16-bit code\n");

    // Initialize emulator in X86-16bit mode
    err = uc_open(UC_ARCH_X86, UC_MODE_16, &uc);
    if (err) {
        printf("Failed on uc_open() with error returned: %u\n", err);
        return;
    }

    // map 8KB memory for this emulation
    uc_mem_map(uc, 0, 8 * 1024, UC_PROT_ALL);

    // write machine code to be emulated to memory
    if (uc_mem_write(uc, 0, X86_CODE16, sizeof(X86_CODE16) - 1)) {
        printf("Failed to write emulation code to memory, quit!\n");
        return;
    }

    // initialize machine registers
    uc_reg_write(uc, UC_X86_REG_EAX, &eax);
    uc_reg_write(uc, UC_X86_REG_EBX, &ebx);
    uc_reg_write(uc, UC_X86_REG_ESI, &esi);

    // emulate machine code in infinite time (last param = 0), or when
    // finishing all the code.
    err = uc_emu_start(uc, 0, sizeof(X86_CODE16) - 1, 0, 0);
    if (err) {
        printf("Failed on uc_emu_start() with error returned %u: %s\n",
                err, uc_strerror(err));
    }

    // now print out some registers
    printf(">>> Emulation done. Below is the CPU context\n");

    // read from memory
    if (!uc_mem_read(uc, 11, &tmp, 1))
        printf(">>> Read 1 bytes from [0x%x] = 0x%x\n", 11, tmp);
    else
        printf(">>> Failed to read 1 bytes from [0x%x]\n", 11);

    uc_close(uc);
}
Esempio n. 6
0
// Create a backup copy of the indicated MemoryRegion.
// Generally used in prepartion for splitting a MemoryRegion.
static uint8_t *copy_region(struct uc_struct *uc, MemoryRegion *mr)
{
    uint8_t *block = (uint8_t *)malloc(int128_get64(mr->size));
    if (block != NULL) {
        uc_err err = uc_mem_read(uc, mr->addr, block, int128_get64(mr->size));
        if (err != UC_ERR_OK) {
            free(block);
            block = NULL;
        }
    }

    return block;
}
Esempio n. 7
0
static void test_bad_read(void **state)
{
    uc_engine *uc = *state;

    uint8_t readbuf[0x10];
    memset(readbuf, 0xCC, sizeof(readbuf));

    uint8_t checkbuf[0x10];
    memset(checkbuf, 0xCC, sizeof(checkbuf));

    /* Reads to unmapped addresses should fail */
    /* TODO: Which error? */
    uc_assert_fail(uc_mem_read(uc, 0x1000, readbuf, sizeof(readbuf)));

    /* And our buffer should be unchanged */
    assert_memory_equal(readbuf, checkbuf, sizeof(checkbuf));
}
Esempio n. 8
0
static void dump_stack_mem(uc_engine *uc)
{
    uint8_t tmp[256];
    uint32_t size;

    size = sizeof(X86_CODE32_ALPHA_MIXED);
    if (size > 255) size = 255;
    if (!uc_mem_read(uc, PHY_STACK_REGION, tmp, size)) 
    {
        uint32_t i;

        printf("Stack region dump");
        for (i=0; i<size; i++) {
            if ((i % 16) == 0) printf("\n%x: ", PHY_STACK_REGION+i);
            printf("%x ", tmp[i]);
        }
        printf("\n");
    }
}
Esempio n. 9
0
static void test_x86_16(void **state)
{
    uc_engine *uc;
    uc_err err;
    uint8_t tmp;

    static const uint64_t address = 0;
    static const uint8_t code[] = {
        0x00, 0x00,         // add   byte ptr [bx + si], al
    };

    int32_t eax = 7;
    int32_t ebx = 5;
    int32_t esi = 6;

    // Initialize emulator in X86-16bit mode
    err = uc_open(UC_ARCH_X86, UC_MODE_16, &uc);
    uc_assert_success(err);

    // map 8KB memory for this emulation
    err = uc_mem_map(uc, address, 8 * 1024, UC_PROT_ALL);
    uc_assert_success(err);

    // write machine code to be emulated to memory
    err = uc_mem_write(uc, address, code, sizeof(code));
    uc_assert_success(err);

    // initialize machine registers
    uc_assert_success(uc_reg_write(uc, UC_X86_REG_EAX, &eax));
    uc_assert_success(uc_reg_write(uc, UC_X86_REG_EBX, &ebx));
    uc_assert_success(uc_reg_write(uc, UC_X86_REG_ESI, &esi));

    // emulate machine code in infinite time (last param = 0), or when
    // finishing all the code.
    err = uc_emu_start(uc, address, address+sizeof(code), 0, 0);
    uc_assert_success(err);

    // read from memory
    uc_assert_success(uc_mem_read(uc, 11, &tmp, 1));
    assert_int_equal(7, tmp);

    uc_assert_success(uc_close(uc));
}
Esempio n. 10
0
/**
 * Verify that we can read/write across memory map region boundaries
 */
static void test_rw_across_boundaries(void **state)
{
    uc_engine *uc = *state;

    /* Map in two adjacent regions */
    uc_assert_success(uc_mem_map(uc, 0,      0x1000, 0));   /* 0x0000 - 0x1000 */
    uc_assert_success(uc_mem_map(uc, 0x1000, 0x1000, 0));   /* 0x1000 - 0x2000 */

    const uint64_t addr = 0x1000 - 2;                       /* 2 bytes before end of block */

    /* Write some data across the boundary */
    uc_assert_success(uc_mem_write(uc, addr, "test", 4));

    uint8_t buf[4];
    memset(buf, 0xCC, sizeof(buf));

    /* Read the data across the boundary */
    uc_assert_success(uc_mem_read(uc, addr, buf, sizeof(buf)));

    assert_memory_equal(buf, "test", 4);
}
Esempio n. 11
0
// callback for tracing instructions, detect HLT and terminate emulation
static void hook_code(uc_engine *uc, uint64_t addr, uint32_t size, void *user_data)
{
    uint8_t opcode;
    unsigned char buf[256];

    insts_executed++;

    if (uc_mem_read(uc, addr, buf, size) != UC_ERR_OK) {
        printf("not ok - uc_mem_read fail during hook_code callback, addr: 0x%" PRIx64 "\n", addr);
        if (uc_emu_stop(uc) != UC_ERR_OK) {
            printf("not ok - uc_emu_stop fail during hook_code callback, addr: 0x%" PRIx64 "\n", addr);
            _exit(-1);
        }
    }

    opcode = buf[0];
    switch (opcode) {
        case 0x41:  // inc ecx
            if (uc_mem_protect(uc, 0x101000, 0x1000, UC_PROT_READ) != UC_ERR_OK) {
                printf("not ok - uc_mem_protect fail during hook_code callback, addr: 0x%" PRIx64 "\n", addr);
                _exit(-1);
            }
            break;
        case 0x42:  // inc edx
            if (uc_mem_unmap(uc, 0x101000, 0x1000) != UC_ERR_OK) {
                printf("not ok - uc_mem_unmap fail during hook_code callback, addr: 0x%" PRIx64 "\n", addr);
                _exit(-1);
            }
            break;
        case 0xf4:  // hlt
            if (uc_emu_stop(uc) != UC_ERR_OK) {
                printf("not ok - uc_emu_stop fail during hook_code callback, addr: 0x%" PRIx64 "\n", addr);
                _exit(-1);
            }
            break;
        default:  // all others
            break;
    }
}
Esempio n. 12
0
// callback for tracing instruction
static void hook_code(uc_engine *uc, uint64_t addr, uint32_t size, void *user_data)
{
    uint8_t opcode;

    if (uc_mem_read(uc, addr, &opcode, 1) != UC_ERR_OK) {
        printf("not ok %d - uc_mem_read fail during hook_code callback, addr: 0x%" PRIx64 "\n", log_num++, addr);
    }

    //   printf("ok %d - uc_mem_read for opcode at address 0x%" PRIx64 "\n", log_num++, addr);
    switch (opcode) {
        case 0xf4:  //hlt
            printf("# Handling HLT\n");
            if (uc_emu_stop(uc) != UC_ERR_OK) {
                printf("not ok %d - uc_emu_stop fail during hook_code callback, addr: 0x%" PRIx64 "\n", log_num++, addr);
                _exit(-1);
            } else {
                printf("ok %d - hlt encountered, uc_emu_stop called\n", log_num++);
            }
            break;
        default:  //all others
            //         printf("# Handling OTHER\n");
            break;
    }
}
Esempio n. 13
0
static void hook_code32(uc_engine *uc, 
                        uint64_t address, 
                        uint32_t size, 
                        void *user_data)
{
    //uint8_t opcode[256];
    uint8_t tmp[16];
    uint32_t tmp4[1];
    uint32_t ecx;

    printf("\nhook_code32: Address: %"PRIx64", Opcode Size: %d\n", address, size);
    print_registers(uc);
    size = MIN(sizeof(tmp), size);
    if (!uc_mem_read(uc, address, tmp, size)) 
    {
        uint32_t i;

        printf("Opcode: ");
        for (i=0; i<size; i++) {
            printf("%x ", tmp[i]);
        }
        printf("\n");
    }
    dump_stack_mem(uc);


    if (address == 0x60000025)
    {
        //  double-check that opcode is
        //      IMUL aex,[eax+0x41],0x10
        if ((tmp[0] != 0x6b) ||
            (tmp[1] != 0x41) ||
            (tmp[2] != 0x41) ||
            (tmp[3] != 0x10))
        {
            printf("FAILED set-up of opcode\n");
            exit(-1);
        }
        printf("IMUL eax,[ecx+0x41],0x10\n");

        //  double-check that memory operand points to 0x6000003a
        uc_reg_read(uc, UC_X86_REG_ECX, &ecx);
        if (ecx != 0x5ffffff9)
        {
            printf("FAILED EAX register not having 0x5ffffff9\n");
            exit(-1);
        }
        printf("ECX = %8.8x\n", ecx);

        printf("%8.8x + 0x41 = %8.8x\n", 0x5ffffff9, 0x5ffffff9 + 0x41);

        //  double-check that memory location 0x60000039
        //  contains 0x5151494a
        if (!uc_mem_read(uc, 0x6000003a, tmp4, 4)) 
        {
            if (tmp4[0] != 0x5151494a)
            {
                printf("FAILED set-up\n");
                exit(-1);
            }
            printf("Proved that 0x6000003a contains the proper 0x5151494a\n");
        }
    //    dump_stack_mem(uc);
    }

    // Stop after 'imul eax,[ecx+0x41],0x10
    if (address == 0x60000029)
    {
        uint32_t eax;
        // IMUL eax,mem,Ib
        // mem = [ecx+0x41]
        // ecx = 0x5ffffff9
        // [6000003A] = 0x5151494a
        // Stop after 'imul eax,[ecx+0x41],0x10
        // This step basically shifts left 8-bit...elaborately.
        // multiplying 0x5151494a x 0x10 = 0x151494a0
        uc_reg_read(uc, UC_X86_REG_EAX, &eax);
        if (eax != 0x151494a0)
        {
            fail_msg("FAIL: TB did not flush; eax is not the expected 0x151494a0\n");
            print_registers(uc);
            //dump_stack_mem(uc);
            exit(-1);
        }
        printf("PASS\n");
    }
    print_registers(uc);
    // dump_stack_mem(uc);
      
    return;
}
Esempio n. 14
0
int main(int argc, char **argv, char **envp)
{
    uc_engine *uc;
    uc_hook trace1;
    uc_err err;
    uint8_t bytes[8];
    uint32_t esp;
    int map_stack = 0;

    if (argc == 2 && strcmp(argv[1], "--map-stack") == 0) {
        map_stack = 1;
    }

    printf("Memory mapping test\n");

    // Initialize emulator in X86-32bit mode
    err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc);
    if (err) {
        printf("Failed on uc_open() with error returned: %u\n", err);
        return 1;
    }

    uc_mem_map(uc, 0x100000, 0x1000, UC_PROT_ALL);
    uc_mem_map(uc, 0x200000, 0x2000, UC_PROT_ALL);
    uc_mem_map(uc, 0x300000, 0x3000, UC_PROT_ALL);
    uc_mem_map(uc, 0x400000, 0x4000, UC_PROT_READ);

    if (map_stack) {
        printf("Pre-mapping stack\n");
        uc_mem_map(uc, STACK, STACK_SIZE, UC_PROT_READ | UC_PROT_WRITE);
    } else {
        printf("Mapping stack on first invalid memory access\n");
    }

    esp = STACK + STACK_SIZE;

    uc_reg_write(uc, UC_X86_REG_ESP, &esp); 

    // write machine code to be emulated to memory
    if (uc_mem_write(uc, 0x400000, PROGRAM, sizeof(PROGRAM))) {
        printf("Failed to write emulation code to memory, quit!\n");
        return 2;
    } else {
        printf("Allowed to write to read only memory via uc_mem_write\n");
    }

    //uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 0x400000, 0x400fff);

    // intercept invalid memory events
    uc_hook_add(uc, &trace1, UC_HOOK_MEM_WRITE_UNMAPPED | UC_HOOK_MEM_WRITE_PROT, hook_mem_invalid, NULL, 1, 0);

    // emulate machine code in infinite time
    printf("BEGIN execution - 1\n");
    err = uc_emu_start(uc, 0x400000, 0x400000 + sizeof(PROGRAM), 0, 10);
    if (err) {
        printf("Expected failue on uc_emu_start() with error returned %u: %s\n",
                err, uc_strerror(err));
    } else {
        printf("UNEXPECTED uc_emu_start returned UC_ERR_OK\n");
    }
    printf("END execution - 1\n");

    // emulate machine code in infinite time
    printf("BEGIN execution - 2\n");
    //update eax to point to aligned memory (same as add eax,7 above)
    uint32_t eax = 0x40002C;
    uc_reg_write(uc, UC_X86_REG_EAX, &eax); 
    //resume execution at the mov dword [eax], 0x87654321
    //to test an aligned write as well
    err = uc_emu_start(uc, 0x400015, 0x400000 + sizeof(PROGRAM), 0, 2);
    if (err) {
        printf("Expected failure on uc_emu_start() with error returned %u: %s\n",
                err, uc_strerror(err));
    } else {
        printf("UNEXPECTED uc_emu_start returned UC_ERR_OK\n");
    }
    printf("END execution - 2\n");

    printf("Verifying content at 0x400025 is unchanged\n");
    if (!uc_mem_read(uc, 0x400025, bytes, 4)) {
        printf(">>> Read 4 bytes from [0x%x] = 0x%x\n", (uint32_t)0x400025, *(uint32_t*) bytes);
        if (0x41414141 != *(uint32_t*) bytes) {
            printf("ERROR content in read only memory changed\n");
        } else {
            printf("SUCCESS content in read only memory unchanged\n");
        }
    } else {
        printf(">>> Failed to read 4 bytes from [0x%x]\n", (uint32_t)(esp - 4));
        return 4;
    }

    printf("Verifying content at 0x40002C is unchanged\n");
    if (!uc_mem_read(uc, 0x40002C, bytes, 4)) {
        printf(">>> Read 4 bytes from [0x%x] = 0x%x\n", (uint32_t)0x40002C, *(uint32_t*) bytes);
        if (0x42424242 != *(uint32_t*) bytes) {
            printf("ERROR content in read only memory changed\n");
        } else {
            printf("SUCCESS content in read only memory unchanged\n");
        }
    } else {
        printf(">>> Failed to read 4 bytes from [0x%x]\n", (uint32_t)(esp - 4));
        return 4;
    }

    printf("Verifying content at bottom of stack is readable and correct\n");
    if (!uc_mem_read(uc, esp - 4, bytes, 4)) {
        printf(">>> Read 4 bytes from [0x%x] = 0x%x\n", (uint32_t)(esp - 4), *(uint32_t*) bytes);
    } else {
        printf(">>> Failed to read 4 bytes from [0x%x]\n", (uint32_t)(esp - 4));
        return 4;
    }

    uc_close(uc);

    return 0;
}
Esempio n. 15
0
static void test_i386_map_ptr(void)
{
    uc_engine *uc;
    uc_err err;
    uint32_t tmp;
    uc_hook trace1, trace2;
    void *mem;

    int r_ecx = 0x1234;     // ECX register
    int r_edx = 0x7890;     // EDX register

    printf("===================================\n");
    printf("Emulate i386 code - use uc_mem_map_ptr()\n");

    // Initialize emulator in X86-32bit mode
    err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc);
    if (err) {
        printf("Failed on uc_open() with error returned: %u\n", err);
        return;
    }

    // malloc 2MB memory for this emulation
    mem = calloc(1, 2 * 1024 * 1024);
    if (mem == NULL) {
        printf("Failed to malloc()\n");
        return;
    }

    uc_mem_map_ptr(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL, mem);

    // write machine code to be emulated to memory
    if (!memcpy(mem, X86_CODE32, sizeof(X86_CODE32) - 1)) {
        printf("Failed to write emulation code to memory, quit!\n");
        return;
    }

    // initialize machine registers
    uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx);
    uc_reg_write(uc, UC_X86_REG_EDX, &r_edx);

    // tracing all basic blocks with customized callback
    uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, 1, 0);

    // tracing all instruction by having @begin > @end
    uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0);

    // emulate machine code in infinite time
    err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32) - 1, 0, 0);
    if (err) {
        printf("Failed on uc_emu_start() with error returned %u: %s\n",
                err, uc_strerror(err));
    }

    // now print out some registers
    printf(">>> Emulation done. Below is the CPU context\n");

    uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx);
    uc_reg_read(uc, UC_X86_REG_EDX, &r_edx);
    printf(">>> ECX = 0x%x\n", r_ecx);
    printf(">>> EDX = 0x%x\n", r_edx);

    // read from memory
    if (!uc_mem_read(uc, ADDRESS, &tmp, sizeof(tmp)))
        printf(">>> Read 4 bytes from [0x%x] = 0x%x\n", ADDRESS, tmp);
    else
        printf(">>> Failed to read 4 bytes from [0x%x]\n", ADDRESS);

    uc_close(uc);
}
Esempio n. 16
0
int main(int argc, char **argv, char **envp)
{
    uc_engine *uc;
    uc_hook trace1, trace2;
    uc_err err;
    uint32_t addr, testval;
    int32_t buf1[1024], buf2[1024], readbuf[1024];
    int i;

    //don't really care about quality of randomness
    srand(time(NULL));
    for (i = 0; i < 1024; i++) {
        buf1[i] = rand();
        buf2[i] = rand();
    }

    printf("# Memory unmapping test\n");

    // Initialize emulator in X86-32bit mode
    err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc);
    if (err) {
        printf("not ok %d - Failed on uc_open() with error returned: %u\n", log_num++, err);
        return 1;
    } else {
        printf("ok %d - uc_open() success\n", log_num++);
    }

    uc_mem_map(uc, CODE_SECTION, CODE_SIZE, UC_PROT_READ | UC_PROT_EXEC);
    uc_mem_map(uc, 0x200000, 0x1000, UC_PROT_READ | UC_PROT_WRITE);
    uc_mem_map(uc, 0x300000, 0x1000, UC_PROT_READ | UC_PROT_WRITE);
    uc_mem_map(uc, 0x3ff000, 0x3000, UC_PROT_READ | UC_PROT_WRITE);

    // fill in sections that shouldn't get touched
    if (uc_mem_write(uc, 0x3ff000, buf1, sizeof(buf1))) {
        printf("not ok %d - Failed to write random buffer 1 to memory, quit!\n", log_num++);
        return 2;
    } else {
        printf("ok %d - Random buffer 1 written to memory\n", log_num++);
    }

    if (uc_mem_write(uc, 0x401000, buf2, sizeof(buf1))) {
        printf("not ok %d - Failed to write random buffer 2 to memory, quit!\n", log_num++);
        return 3;
    } else {
        printf("ok %d - Random buffer 2 written to memory\n", log_num++);
    }

    // write machine code to be emulated to memory
    if (uc_mem_write(uc, CODE_SECTION, PROGRAM, sizeof(PROGRAM))) {
        printf("not ok %d - Failed to write emulation code to memory, quit!\n", log_num++);
        return 4;
    } else {
        printf("ok %d - Program written to memory\n", log_num++);
    }

    if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK) {
        printf("not ok %d - Failed to install UC_HOOK_CODE ucr\n", log_num++);
        return 5;
    } else {
        printf("ok %d - UC_HOOK_CODE installed\n", log_num++);
    }

    // intercept memory write events
    if (uc_hook_add(uc, &trace1, UC_HOOK_MEM_WRITE, hook_mem_write, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK) {
        printf("not ok %d - Failed to install UC_HOOK_MEM_WRITE ucr\n", log_num++);
        return 6;
    } else {
        printf("ok %d - UC_HOOK_MEM_WRITE installed\n", log_num++);
    }

    // intercept invalid memory events
    if (uc_hook_add(uc, &trace1, UC_HOOK_MEM_WRITE_UNMAPPED, hook_mem_invalid, NULL) != UC_ERR_OK) {
        printf("not ok %d - Failed to install memory invalid handler\n", log_num++);
        return 7;
    } else {
        printf("ok %d - memory invalid handler installed\n", log_num++);
    }

    // emulate machine code until told to stop by hook_code
    printf("# BEGIN execution\n");
    err = uc_emu_start(uc, CODE_SECTION, CODE_SECTION + CODE_SIZE, 0, 0);
    if (err != UC_ERR_OK) {
        printf("not ok %d - Failure on uc_emu_start() with error %u:%s\n", log_num++, err, uc_strerror(err));
        return 8;
    } else {
        printf("ok %d - uc_emu_start complete\n", log_num++);
    }
    printf("# END execution\n");

    //read from the remapped memory
    testval = 0x42424242;
    for (addr = 0x200000; addr <= 0x400000; addr += 0x100000) {
        uint32_t val;
        if (uc_mem_read(uc, addr, &val, sizeof(val)) != UC_ERR_OK) {
            printf("not ok %d - Failed uc_mem_read for address 0x%x\n", log_num++, addr);
        } else {
            printf("ok %d - Good uc_mem_read from 0x%x\n", log_num++, addr);
        }
        if (val != testval) {
            printf("not ok %d - Read 0x%x, expected 0x%x\n", log_num++, val, testval);
        } else {
            printf("ok %d - Correct value retrieved\n", log_num++);
        }
        testval += 0x02020202;
    }

    //make sure that random blocks didn't get nuked
    // fill in sections that shouldn't get touched
    if (uc_mem_read(uc, 0x3ff000, readbuf, sizeof(readbuf))) {
        printf("not ok %d - Failed to read random buffer 1 from memory\n", log_num++);
    } else {
        printf("ok %d - Random buffer 1 read from memory\n", log_num++);
        if (memcmp(buf1, readbuf, 4096)) {
            printf("not ok %d - Random buffer 1 contents are incorrect\n", log_num++);
        } else {
            printf("ok %d - Random buffer 1 contents are correct\n", log_num++);
        }
    }

    if (uc_mem_read(uc, 0x401000, readbuf, sizeof(readbuf))) {
        printf("not ok %d - Failed to read random buffer 2 from memory\n", log_num++);
    } else {
        printf("ok %d - Random buffer 2 read from memory\n", log_num++);
        if (memcmp(buf2, readbuf, 4096)) {
            printf("not ok %d - Random buffer 2 contents are incorrect\n", log_num++);
        } else {
            printf("ok %d - Random buffer 2 contents are correct\n", log_num++);
        }
    }

    if (uc_close(uc) == UC_ERR_OK) {
        printf("ok %d - uc_close complete\n", log_num++);
    } else {
        printf("not ok %d - uc_close complete\n", log_num++);
    }

    return 0;
}
Esempio n. 17
0
// emulate code that write invalid memory
static void test_i386_invalid_mem_write(void)
{
    uc_engine *uc;
    uc_err err;
    uc_hook trace1, trace2, trace3;
    uint32_t tmp;

    int r_ecx = 0x1234;     // ECX register
    int r_edx = 0x7890;     // EDX register

    printf("===================================\n");
    printf("Emulate i386 code that write to invalid memory\n");

    // Initialize emulator in X86-32bit mode
    err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc);
    if (err) {
        printf("Failed on uc_open() with error returned: %u\n", err);
        return;
    }

    // map 2MB memory for this emulation
    uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);

    // write machine code to be emulated to memory
    if (uc_mem_write(uc, ADDRESS, X86_CODE32_MEM_WRITE, sizeof(X86_CODE32_MEM_WRITE) - 1)) {
        printf("Failed to write emulation code to memory, quit!\n");
        return;
    }

    // initialize machine registers
    uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx);
    uc_reg_write(uc, UC_X86_REG_EDX, &r_edx);

    // tracing all basic blocks with customized callback
    uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, 1, 0);

    // tracing all instruction by having @begin > @end
    uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0);

    // intercept invalid memory events
    uc_hook_add(uc, &trace3, UC_HOOK_MEM_READ_UNMAPPED | UC_HOOK_MEM_WRITE_UNMAPPED, hook_mem_invalid, NULL, 1, 0);

    // emulate machine code in infinite time
    err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_MEM_WRITE) - 1, 0, 0);
    if (err) {
        printf("Failed on uc_emu_start() with error returned %u: %s\n",
                err, uc_strerror(err));
    }

    // now print out some registers
    printf(">>> Emulation done. Below is the CPU context\n");

    uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx);
    uc_reg_read(uc, UC_X86_REG_EDX, &r_edx);
    printf(">>> ECX = 0x%x\n", r_ecx);
    printf(">>> EDX = 0x%x\n", r_edx);

    // read from memory
    if (!uc_mem_read(uc, 0xaaaaaaaa, &tmp, sizeof(tmp)))
        printf(">>> Read 4 bytes from [0x%x] = 0x%x\n", 0xaaaaaaaa, tmp);
    else
        printf(">>> Failed to read 4 bytes from [0x%x]\n", 0xaaaaaaaa);

    if (!uc_mem_read(uc, 0xffffffaa, &tmp, sizeof(tmp)))
        printf(">>> Read 4 bytes from [0x%x] = 0x%x\n", 0xffffffaa, tmp);
    else
        printf(">>> Failed to read 4 bytes from [0x%x]\n", 0xffffffaa);

    uc_close(uc);
}
Esempio n. 18
0
int main(int argc, char **argv, char **envp)
{
    uc_engine *uc;
    uc_hook trace1, trace2;
    uc_err err;
    uint32_t esp, eip;
    int32_t buf1[1024], buf2[1024], readbuf[1024];
    int i;

    //don't really care about quality of randomness
    srand(time(NULL));
    for (i = 0; i < 1024; i++) {
        buf1[i] = rand();
        buf2[i] = rand();
    }

    printf("# Memory protect test\n");

    // Initialize emulator in X86-32bit mode
    err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc);
    if (err) {
        printf("not ok %d - Failed on uc_open() with error returned: %u\n", log_num++, err);
        return 1;
    } else {
        printf("ok %d - uc_open() success\n", log_num++);
    }

    uc_mem_map(uc, 0x100000, 0x1000, UC_PROT_READ | UC_PROT_EXEC);
    uc_mem_map(uc, 0x1ff000, 0x2000, UC_PROT_READ | UC_PROT_WRITE);
    uc_mem_map(uc, 0x300000, 0x2000, UC_PROT_READ);
    uc_mem_map(uc, 0xf00000, 0x1000, UC_PROT_READ | UC_PROT_WRITE);

    esp = 0xf00000 + 0x1000;

    // Setup stack pointer
    if (uc_reg_write(uc, UC_X86_REG_ESP, &esp)) {
        printf("not ok %d - Failed to set esp. quit!\n", log_num++);
        return 2;
    } else {
        printf("ok %d - ESP set\n", log_num++);
    }

    // fill in sections that shouldn't get touched
    if (uc_mem_write(uc, 0x1ff000, buf1, sizeof(buf1))) {
        printf("not ok %d - Failed to write random buffer 1 to memory, quit!\n", log_num++);
        return 3;
    } else {
        printf("ok %d - Random buffer 1 written to memory\n", log_num++);
    }

    if (uc_mem_write(uc, 0x301000, buf2, sizeof(buf2))) {
        printf("not ok %d - Failed to write random buffer 2 to memory, quit!\n", log_num++);
        return 4;
    } else {
        printf("ok %d - Random buffer 2 written to memory\n", log_num++);
    }

    // write machine code to be emulated to memory
    if (uc_mem_write(uc, 0x100000, PROGRAM, sizeof(PROGRAM))) {
        printf("not ok %d - Failed to write emulation code to memory, quit!\n", log_num++);
        return 5;
    } else {
        printf("ok %d - Program written to memory\n", log_num++);
    }

    if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) != UC_ERR_OK) {
        printf("not ok %d - Failed to install UC_HOOK_CODE ucr\n", log_num++);
        return 6;
    } else {
        printf("ok %d - UC_HOOK_CODE installed\n", log_num++);
    }

    // intercept memory write events
    if (uc_hook_add(uc, &trace1, UC_HOOK_MEM_WRITE, hook_mem_write, NULL, 1, 0) != UC_ERR_OK) {
        printf("not ok %d - Failed to install UC_HOOK_MEM_WRITE ucr\n", log_num++);
        return 7;
    } else {
        printf("ok %d - UC_HOOK_MEM_WRITE installed\n", log_num++);
    }

    // intercept invalid memory events
    if (uc_hook_add(uc, &trace1, UC_HOOK_MEM_WRITE_PROT | UC_HOOK_MEM_FETCH_PROT, hook_mem_invalid, NULL, 1, 0) != UC_ERR_OK) {
        printf("not ok %d - Failed to install memory invalid handler\n", log_num++);
        return 8;
    } else {
        printf("ok %d - memory invalid handler installed\n", log_num++);
    }

    // emulate machine code until told to stop by hook_code
    printf("# BEGIN execution\n");
    err = uc_emu_start(uc, 0x100000, 0x400000, 0, 0);
    if (err != UC_ERR_OK) {
        printf("not ok %d - Failure on uc_emu_start() with error %u:%s\n", log_num++, err, uc_strerror(err));
        return 9;
    } else {
        printf("ok %d - uc_emu_start complete\n", log_num++);
    }
    printf("# END execution\n");

    // get ending EIP
    if (uc_reg_read(uc, UC_X86_REG_EIP, &eip)) {
        printf("not ok %d - Failed to read eip.\n", log_num++);
    } else {
        printf("ok %d - Ending EIP 0x%x\n", log_num++, eip);
    }

    //make sure that random blocks didn't get nuked
    // fill in sections that shouldn't get touched
    if (uc_mem_read(uc, 0x1ff000, readbuf, sizeof(readbuf))) {
        printf("not ok %d - Failed to read random buffer 1 from memory\n", log_num++);
    } else {
        printf("ok %d - Random buffer 1 read from memory\n", log_num++);
        if (memcmp(buf1, readbuf, 4096)) {
            printf("not ok %d - Random buffer 1 contents are incorrect\n", log_num++);
        } else {
            printf("ok %d - Random buffer 1 contents are correct\n", log_num++);
        }
    }

    if (uc_mem_read(uc, 0x301000, readbuf, sizeof(readbuf))) {
        printf("not ok %d - Failed to read random buffer 2 from memory\n", log_num++);
    } else {
        printf("ok %d - Random buffer 2 read from memory\n", log_num++);
        if (memcmp(buf2, readbuf, 4096)) {
            printf("not ok %d - Random buffer 2 contents are incorrect\n", log_num++);
        } else {
            printf("ok %d - Random buffer 2 contents are correct\n", log_num++);
        }
    }

    if (uc_close(uc) == UC_ERR_OK) {
        printf("ok %d - uc_close complete\n", log_num++);
    } else {
        printf("not ok %d - uc_close complete\n", log_num++);
    }

    return 0;
}
Esempio n. 19
0
static void test_basic_blocks(void **state)
{
    uc_engine *uc = *state;
    uc_hook trace1;

#define BASEADDR    0x1000000

    uint64_t address = BASEADDR;
    const uint8_t code[] = {
        0x33, 0xC0,     // xor  eax, eax
        0x90,           // nop
        0x90,           // nop
        0xEB, 0x00,     // jmp  $+2
        0x90,           // nop
        0x90,           // nop
        0x90,           // nop
    };

    static const struct bb blocks[] = {
        {BASEADDR,      6},
        {BASEADDR+ 6,   3},
    };

    struct bbtest bbtest = {
        .blocks = blocks,
        .blocknum = 0,
    };


#undef BASEADDR

    // map 2MB memory for this emulation
    OK(uc_mem_map(uc, address, 2 * 1024 * 1024, UC_PROT_ALL));

    // write machine code to be emulated to memory
    OK(uc_mem_write(uc, address, code, sizeof(code)));

    // trace all basic blocks
    OK(uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, test_basic_blocks_hook, &bbtest, 1, 0));

    OK(uc_emu_start(uc, address, address+sizeof(code), 0, 0));
}

/******************************************************************************/

// callback for tracing basic blocks
static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
{
    //printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size);
}

// callback for tracing instruction
static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
{
    //int eflags;
    //printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size);

    //uc_reg_read(uc, UC_X86_REG_EFLAGS, &eflags);
    //printf(">>> --- EFLAGS is 0x%x\n", eflags);

    // Uncomment below code to stop the emulation using uc_emu_stop()
    // if (address == 0x1000009)
    //    uc_emu_stop(uc);
}

static void test_i386(void **state)
{
    uc_engine *uc;
    uc_err err;
    uint32_t tmp;
    uc_hook trace1, trace2;

    const uint8_t code[] = "\x41\x4a"; // INC ecx; DEC edx
    const uint64_t address = 0x1000000;

    int r_ecx = 0x1234;     // ECX register
    int r_edx = 0x7890;     // EDX register

    // Initialize emulator in X86-32bit mode
    err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc);
    uc_assert_success(err);

    // map 2MB memory for this emulation
    err = uc_mem_map(uc, address, 2 * 1024 * 1024, UC_PROT_ALL);
    uc_assert_success(err);

    // write machine code to be emulated to memory
    err = uc_mem_write(uc, address, code, sizeof(code)-1);
    uc_assert_success(err);

    // initialize machine registers
    err = uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx);
    uc_assert_success(err);
    err = uc_reg_write(uc, UC_X86_REG_EDX, &r_edx);
    uc_assert_success(err);

    // tracing all basic blocks with customized callback
    err = uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, 1, 0);
    uc_assert_success(err);

    // tracing all instruction by having @begin > @end
    err = uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0);
    uc_assert_success(err);

    // emulate machine code in infinite time
    err = uc_emu_start(uc, address, address+sizeof(code)-1, 0, 0);
    uc_assert_success(err);

    // now print out some registers
    //printf(">>> Emulation done. Below is the CPU context\n");

    uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx);
    uc_reg_read(uc, UC_X86_REG_EDX, &r_edx);

    assert_int_equal(r_ecx, 0x1235);
    assert_int_equal(r_edx, 0x788F);

    // read from memory
    err = uc_mem_read(uc, address, (uint8_t *)&tmp, 4);
    uc_assert_success(err);
    //printf(">>> Read 4 bytes from [0x%"PRIX64"] = 0x%x\n", address, tmp);

    uc_close(uc);
}
Esempio n. 20
0
static void test_i386(void)
{
    uc_engine *uc;
    uc_err err;
    uint32_t tmp;
    uc_hook trace1, trace2;

    int r_ecx = 0x1234;     // ECX register
    int r_edx = 0x7890;     // EDX register
    // XMM0 and XMM1 registers, low qword then high qword
    uint64_t r_xmm0[2] = {0x08090a0b0c0d0e0f, 0x0001020304050607};
    uint64_t r_xmm1[2] = {0x8090a0b0c0d0e0f0, 0x0010203040506070};

    printf("Emulate i386 code\n");

    // Initialize emulator in X86-32bit mode
    err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc);
    if (err) {
        printf("Failed on uc_open() with error returned: %u\n", err);
        return;
    }

    // map 2MB memory for this emulation
    uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);

    // write machine code to be emulated to memory
    if (uc_mem_write(uc, ADDRESS, X86_CODE32, sizeof(X86_CODE32) - 1)) {
        printf("Failed to write emulation code to memory, quit!\n");
        return;
    }

    // initialize machine registers
    uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx);
    uc_reg_write(uc, UC_X86_REG_EDX, &r_edx);
    uc_reg_write(uc, UC_X86_REG_XMM0, &r_xmm0);
    uc_reg_write(uc, UC_X86_REG_XMM1, &r_xmm1);

    // tracing all basic blocks with customized callback
    uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, 1, 0);

    // tracing all instruction by having @begin > @end
    uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0);

    // emulate machine code in infinite time
    err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32) - 1, 0, 0);
    if (err) {
        printf("Failed on uc_emu_start() with error returned %u: %s\n",
                err, uc_strerror(err));
    }

    // now print out some registers
    printf(">>> Emulation done. Below is the CPU context\n");

    uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx);
    uc_reg_read(uc, UC_X86_REG_EDX, &r_edx);
    uc_reg_read(uc, UC_X86_REG_XMM0, &r_xmm0);
    printf(">>> ECX = 0x%x\n", r_ecx);
    printf(">>> EDX = 0x%x\n", r_edx);
    printf(">>> XMM0 = 0x%.16"PRIx64"%.16"PRIx64"\n", r_xmm0[1], r_xmm0[0]);

    // read from memory
    if (!uc_mem_read(uc, ADDRESS, &tmp, sizeof(tmp)))
        printf(">>> Read 4 bytes from [0x%x] = 0x%x\n", ADDRESS, tmp);
    else
        printf(">>> Failed to read 4 bytes from [0x%x]\n", ADDRESS);

    uc_close(uc);
}
Esempio n. 21
0
void mem_read(uc_engine* uc, uint64_t addr, uint64_t len){
  uint8_t* buff = alloca(len);
  uc_mem_read(uc, addr, buff, len);
}