CVE-2021-36979 (published 2021-07-20T07:15Z)

Unicorn Engine 1.0.2 has an out-of-bounds write in tb_flush_armeb (called from cpu_arm_exec_armeb and tcg_cpu_exec_armeb).

Severity: MEDIUM
CVSS v2 base score: 4.3 (AV:N/AC:M/Au:N/C:N/I:N/A:P)
CVSS v3 base score: 5.5, MEDIUM (CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H)

Weakness information:
cwe_id: CWE-787
cwe_name: Out-of-bounds Write
description: The product writes data past the end, or before the beginning, of the intended buffer.
extended_description: 
            
            
             
			 
         
         

Fix information:
repo_url: https://github.com/unicorn-engine/unicorn
commit_details: repo_url: https://github.com/unicorn-engine/unicorn
author: lazymio
author_date: 2021-03-30 12:06:26+08:00
msg: Add arm ite blocks samples from #853 (#1381)
repository: repo_url: https://github.com/unicorn-engine/unicorn
repo_name: unicorn-engine/unicorn
description: Unicorn CPU emulator framework (ARM, AArch64, M68K, Mips, Sparc, PowerPC, RiscV, S390x, TriCore, X86)
repo_language: C
owner: unicorn-engine
file_changes: filename: sample_arm.c
change_type: ModificationType.MODIFY
diff: @@ -11,6 +11,8 @@
 #define ARM_CODE "\x37\x00\xa0\xe3\x03\x10\x42\xe0" // mov r0, #0x37; sub r1, r2, r3
 #define THUMB_CODE "\x83\xb0" // sub    sp, #0xc
 
+#define ARM_THUM_COND_CODE "\x9a\x42\x14\xbf\x68\x22\x4d\x22" // 'cmp r2, r3\nit ne\nmov r2, #0x68\nmov r2, #0x4d'
+
 // memory address where emulation starts
 #define ADDRESS 0x10000
 
@@ -130,6 +132,69 @@ static void test_thumb(void)
     uc_close(uc);
 }
 
+static void test_thumb_ite() {
+    uc_engine *uc;
+    uc_err err;
+
+    uint32_t sp = 0x1234;
+    uint32_t r2 = 0, r3 = 1;
+    uint32_t step_r2, step_r3;
+
+    int i, addr=ADDRESS;
+
+    printf("Emulate a THUMB ITE block as a whole or per instruction.\n");
+    err = uc_open(UC_ARCH_ARM, UC_MODE_THUMB, &uc);
+    if (err) {
+        printf("Failed on uc_open() with error returned: %u (%s)\n",
+                err, uc_strerror(err));
+        return;
+    }
+
+    uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
+
+    uc_mem_write(uc, ADDRESS, ARM_THUM_COND_CODE, sizeof(ARM_THUM_COND_CODE) - 1);
+
+    uc_reg_write(uc, UC_ARM_REG_SP, &sp);
+
+    uc_reg_write(uc, UC_ARM_REG_R2, &r2);
+    uc_reg_write(uc, UC_ARM_REG_R3, &r3);
+
+    // Run once.
+    printf("Running the entire binary.\n");
+    err = uc_emu_start(uc, ADDRESS | 1, ADDRESS + sizeof(ARM_THUM_COND_CODE) - 1, 0, 0);
+    if (err) {
+        printf("Failed on uc_emu_start() with error returned: %u\n", err);
+    }
+    uc_reg_read(uc, UC_ARM_REG_R2, &r2);
+    uc_reg_read(uc, UC_ARM_REG_R3, &r3);
+
+    printf(">>> R2: %d\n", r2);
+    printf(">>> R3: %d\n\n", r3);
+
+    // Step each instruction.
+    printf("Running the binary one instruction at a time.\n");
+    for (i = 0; i < sizeof(ARM_THUM_COND_CODE) / 2; i++) {
+        err = uc_emu_start(uc, addr | 1, ADDRESS + sizeof(ARM_THUM_COND_CODE) - 1, 0, 1);
+        if (err) {
+            printf("Failed on uc_emu_start() with error returned: %u\n", err);
+        }
+        uc_reg_read(uc, UC_ARM_REG_PC, &addr);
+    }
+
+    uc_reg_read(uc, UC_ARM_REG_R2, &step_r2);
+    uc_reg_read(uc, UC_ARM_REG_R3, &step_r3);
+
+    printf(">>> R2: %d\n", step_r2);
+    printf(">>> R3: %d\n\n", step_r3);
+
+    if (step_r2 != r2 || step_r3 != r3) {
+        printf("Failed with ARM ITE blocks stepping!\n");
+    }
+
+    uc_close(uc);
+}
+
+
 int main(int argc, char **argv, char **envp)
 {
     // dynamically load shared library
@@ -146,7 +211,8 @@ int main(int argc, char **argv, char **envp)
     test_arm();
     printf("==========================\n");
     test_thumb();
-
+    printf("==========================\n");
+    test_thumb_ite();
     // dynamically free shared library
 #ifdef DYNLOAD
     uc_dyn_free();

programming_language: C