Running cat command on a malformed file in OSX Maverick's Terminal.app results in crash. This post explains the crash analysis. Code execution was not achieved due to limited buffer.
While Fuzzing the Android's installd daemon, accidentally I did a cat on the fuzzer generated APK and OS X Mavericks's Terminal.app crashed. Shown below is the crash report.
So I thought to investigate further on this.
(lldb) register read
General Purpose Registers:
rax = 0x000000010c15b264
rbx = 0x0000000100457690
rcx = 0x0000000000000003
rdx = 0xfffffffffffa4d7c
rdi = 0x000000010c100020
rsi = 0x000000010c100018
rbp = 0x00007fff5fbfdc10
rsp = 0x00007fff5fbfdc10
r8 = 0x0000000000000000
r9 = 0x0000000000000009
r10 = 0x0000000101046880
r11 = 0x000000010c15b263
r12 = 0x0000000000000001
r13 = 0x0000000000000008
r14 = 0x0000000000000008
r15 = 0x000000000000000c
rip = 0x00007fff8bbced10 libsystem_platform.dylib`_platform_memmove $VARIANT$Unknown + 528
rflags = 0x0000000000010202
cs = 0x000000000000002b
fs = 0x0000000000000000
gs = 0x000000000c150000
* thread #1: tid = 0x4bd5, 0x00007fff8bbced10 libsystem_platform.dylib`_platform_memmove $VARIANT$Unknown + 528, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x10c0ffff8)
* frame #0: 0x00007fff8bbced10 libsystem_plaform.dylib`_platform_memmove$VARIANT$Unknown + 528
frame #1: 0x000000010002945d Terminal`___lldb_unnamed_function445$$Terminal + 96
frame #2: 0x00000001000293ca Terminal`___lldb_unnamed_function444$$Terminal + 632
frame #3: 0x000000010002876a Terminal`___lldb_unnamed_function438$$Terminal + 265
frame #4: 0x00000001000272dd Terminal`___lldb_unnamed_function433$$Terminal + 16104
frame #5: 0x0000000100023075 Terminal`___lldb_unnamed_function429$$Terminal + 114
frame #6: 0x0000000100022c5e Terminal`___lldb_unnamed_function426$$Terminal + 449
frame #7: 0x00007fff8e76075e Foundation`__NSThreadPerformPerform + 229
frame #8: 0x00007fff8982a5b1 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
frame #9: 0x00007fff8981bc62 CoreFoundation`__CFRunLoopDoSources0 + 242
frame #10: 0x00007fff8981b3ef CoreFoundation`__CFRunLoopRun + 831
frame #11: 0x00007fff8981ae75 CoreFoundation`CFRunLoopRunSpecific + 309
frame #12: 0x00007fff8bdf0a0d HIToolbox`RunCurrentEventLoopInMode + 226
frame #13: 0x00007fff8bdf07b7 HIToolbox`ReceiveNextEventCommon + 479
frame #14: 0x00007fff8bdf05bc HIToolbox`_BlockUntilNextEventMatchingListInModeWithFilter + 65
frame #15: 0x00007fff8cc4f24e AppKit`_DPSNextEvent + 1434
frame #16: 0x00007fff8cc4e89b AppKit`-[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 122
frame #17: 0x00007fff8cc4299c AppKit`-[NSApplication run] + 553
frame #18: 0x00007fff8cc2d783 AppKit`NSApplicationMain + 940
frame #19: 0x00007fff874fa5fd libdyld.dylib`start + 1
frame #20: 0x00007fff874fa5fd libdyld.dylib`start + 1
(lldb)
(lldb) di
libsystem_platform.dylib`_platform_memmove$VARIANT$Unknown:
0x7fff8bbceb00: push rbp
0x7fff8bbceb01: mov rbp, rsp
0x7fff8bbceb04: mov r11, rdi
0x7fff8bbceb07: sub r11, rsi
0x7fff8bbceb0a: mov rax, rdi
0x7fff8bbceb0d: cmp r11, rdx
0x7fff8bbceb10: jb 0x7fff8bbceb2d ; _platform_memmove$VARIANT$Unknown + 45
0x7fff8bbceb12: cmp rdx, 0x60
0x7fff8bbceb16: jbe 0x7fff8bbceb47 ; _platform_memmove$VARIANT$Unknown + 71
0x7fff8bbceb18: cmp rdx, 0x20000
0x7fff8bbceb1f: jb 0x7fff8bbcebe0 ; _platform_memmove$VARIANT$Unknown + 224
0x7fff8bbceb25: mov rcx, rdx
0x7fff8bbceb28: cld
0x7fff8bbceb29: rep
0x7fff8bbceb2a: movsb
0x7fff8bbceb2b: pop rbp
0x7fff8bbceb2c: ret
0x7fff8bbceb2d: cmp rsi, rdi
0x7fff8bbceb30: je 0x7fff8bbceb2b ; _platform_memmove$VARIANT$Unknown + 43
0x7fff8bbceb32: add rsi, rdx
0x7fff8bbceb35: add rdi, rdx
0x7fff8bbceb38: cmp rdx, 0x60
0x7fff8bbceb3c: jb 0x7fff8bbcec9e ; _platform_memmove$VARIANT$Unknown + 414
0x7fff8bbceb42: jmp 0x7fff8bbcecc0 ; _platform_memmove$VARIANT$Unknown + 448
0x7fff8bbceb47: cmp rdx, 0x10
0x7fff8bbceb4b: jbe 0x7fff8bbceb97 ; _platform_memmove$VARIANT$Unknown + 151
0x7fff8bbceb4d: movups xmm4, xmmword ptr [rsi + rdx - 0x10]
0x7fff8bbceb52: sub rdx, 0x20
0x7fff8bbceb56: jbe 0x7fff8bbceb85 ; _platform_memmove$VARIANT$Unknown + 133
0x7fff8bbceb58: vmovups ymm1, ymmword ptr [rsi]
0x7fff8bbceb5c: vmovups ymmword ptr [rdi], ymm1
0x7fff8bbceb60: add rsi, 0x20
0x7fff8bbceb64: add rdi, 0x20
0x7fff8bbceb68: sub rdx, 0x20
0x7fff8bbceb6c: jb 0x7fff8bbceb82 ; _platform_memmove$VARIANT$Unknown + 130
0x7fff8bbceb6e: vmovups ymm2, ymmword ptr [rsi]
0x7fff8bbceb72: vmovups ymmword ptr [rdi], ymm2
0x7fff8bbceb76: add rsi, 0x20
0x7fff8bbceb7a: add rdi, 0x20
0x7fff8bbceb7e: sub rdx, 0x20
0x7fff8bbceb82: vzeroupper
0x7fff8bbceb85: add rdx, 0x10
0x7fff8bbceb89: jle 0x7fff8bbceb91 ; _platform_memmove$VARIANT$Unknown + 145
0x7fff8bbceb8b: movups xmm3, xmmword ptr [rsi]
0x7fff8bbceb8e: movups xmmword ptr [rdi], xmm3
0x7fff8bbceb91: movups xmmword ptr [rdi + rdx], xmm4
0x7fff8bbceb95: pop rbp
0x7fff8bbceb96: ret
0x7fff8bbceb97: sub rdx, 0x8
0x7fff8bbceb9b: jb 0x7fff8bbcebad ; _platform_memmove$VARIANT$Unknown + 173
0x7fff8bbceb9d: mov rcx, qword ptr [rsi]
0x7fff8bbceba0: mov r8, qword ptr [rsi + rdx]
0x7fff8bbceba4: mov qword ptr [rdi], rcx
0x7fff8bbceba7: mov qword ptr [rdi + rdx], r8
0x7fff8bbcebab: pop rbp
0x7fff8bbcebac: ret
0x7fff8bbcebad: add rdx, 0x8
0x7fff8bbcebb1: je 0x7fff8bbcebd8 ; _platform_memmove$VARIANT$Unknown + 216
0x7fff8bbcebb3: xor r8, r8
0x7fff8bbcebb6: mov cl, byte ptr [rsi + r8]
0x7fff8bbcebba: mov byte ptr [rdi + r8], cl
0x7fff8bbcebbe: sub rdx, 0x1
0x7fff8bbcebc2: je 0x7fff8bbcebd8 ; _platform_memmove$VARIANT$Unknown + 216
0x7fff8bbcebc4: mov cl, byte ptr [rsi + r8 + 0x1]
0x7fff8bbcebc9: mov byte ptr [rdi + r8 + 0x1], cl
0x7fff8bbcebce: add r8, 0x2
0x7fff8bbcebd2: sub rdx, 0x1
0x7fff8bbcebd6: jne 0x7fff8bbcebb6 ; _platform_memmove$VARIANT$Unknown + 182
0x7fff8bbcebd8: pop rbp
0x7fff8bbcebd9: ret
0x7fff8bbcebda: nop word ptr [rax + rax]
0x7fff8bbcebe0: vmovups ymm0, ymmword ptr [rsi]
0x7fff8bbcebe4: add rdi, 0x20
0x7fff8bbcebe8: and rdi, -0x20
0x7fff8bbcebec: mov rcx, rdi
0x7fff8bbcebef: sub rcx, rax
0x7fff8bbcebf2: add rsi, rcx
0x7fff8bbcebf5: sub rdx, rcx
0x7fff8bbcebf8: vmovups ymm1, ymmword ptr [rsi]
0x7fff8bbcebfc: vmovups ymmword ptr [rax], ymm0
0x7fff8bbcec00: vmovups ymm2, ymmword ptr [rsi + 0x20]
0x7fff8bbcec05: add rsi, 0x40
0x7fff8bbcec09: sub rdx, 0x80
0x7fff8bbcec10: jbe 0x7fff8bbcec60 ; _platform_memmove$VARIANT$Unknown + 352
0x7fff8bbcec12: test rsi, 0x1f
0x7fff8bbcec19: je 0x7fff8bbcec40 ; _platform_memmove$VARIANT$Unknown + 320
0x7fff8bbcec1b: vmovaps ymmword ptr [rdi], ymm1
0x7fff8bbcec1f: vmovaps ymmword ptr [rdi + 0x20], ymm2
0x7fff8bbcec24: add rdi, 0x40
0x7fff8bbcec28: vmovups ymm1, ymmword ptr [rsi]
0x7fff8bbcec2c: vmovups ymm2, ymmword ptr [rsi + 0x20]
0x7fff8bbcec31: add rsi, 0x40
0x7fff8bbcec35: sub rdx, 0x40
0x7fff8bbcec39: ja 0x7fff8bbcec1b ; _platform_memmove$VARIANT$Unknown + 283
0x7fff8bbcec3b: jmp 0x7fff8bbcec60 ; _platform_memmove$VARIANT$Unknown + 352
0x7fff8bbcec3d: nop dword ptr [rax]
0x7fff8bbcec40: vmovaps ymmword ptr [rdi], ymm1
0x7fff8bbcec44: vmovaps ymmword ptr [rdi + 0x20], ymm2
0x7fff8bbcec49: add rdi, 0x40
0x7fff8bbcec4d: vmovaps ymm1, ymmword ptr [rsi]
0x7fff8bbcec51: vmovaps ymm2, ymmword ptr [rsi + 0x20]
0x7fff8bbcec56: add rsi, 0x40
0x7fff8bbcec5a: sub rdx, 0x40
0x7fff8bbcec5e: ja 0x7fff8bbcec40 ; _platform_memmove$VARIANT$Unknown + 320
0x7fff8bbcec60: vmovups ymm3, ymmword ptr [rsi + rdx]
0x7fff8bbcec65: vmovups ymm4, ymmword ptr [rsi + rdx + 0x20]
0x7fff8bbcec6b: vmovaps ymmword ptr [rdi], ymm1
0x7fff8bbcec6f: vmovaps ymmword ptr [rdi + 0x20], ymm2
0x7fff8bbcec74: vmovups ymmword ptr [rdi + rdx + 0x40], ymm3
0x7fff8bbcec7a: vmovups ymmword ptr [rdi + rdx + 0x60], ymm4
0x7fff8bbcec80: pop rbp
0x7fff8bbcec81: vzeroupper
0x7fff8bbcec84: ret
0x7fff8bbcec85: nop word ptr cs:[rax + rax]
0x7fff8bbcec90: sub rsi, 0x8
0x7fff8bbcec94: mov rcx, qword ptr [rsi]
0x7fff8bbcec97: sub rdi, 0x8
0x7fff8bbcec9b: mov qword ptr [rdi], rcx
0x7fff8bbcec9e: sub rdx, 0x8
0x7fff8bbceca2: jae 0x7fff8bbcec90 ; _platform_memmove$VARIANT$Unknown + 400
0x7fff8bbceca4: add rdx, 0x8
0x7fff8bbceca8: je 0x7fff8bbcecbc ; _platform_memmove$VARIANT$Unknown + 444
0x7fff8bbcecaa: sub rsi, 0x1
0x7fff8bbcecae: mov cl, byte ptr [rsi]
0x7fff8bbcecb0: sub rdi, 0x1
0x7fff8bbcecb4: mov byte ptr [rdi], cl
0x7fff8bbcecb6: sub rdx, 0x1
0x7fff8bbcecba: jne 0x7fff8bbcecaa ; _platform_memmove$VARIANT$Unknown + 426
0x7fff8bbcecbc: pop rbp
0x7fff8bbcecbd: ret
0x7fff8bbcecbe: nop
0x7fff8bbcecc0: vmovups ymm0, ymmword ptr [rsi - 0x20]
0x7fff8bbcecc5: mov r11, rdi
0x7fff8bbcecc8: sub rdi, 0x1
0x7fff8bbceccc: and rdi, -0x20
0x7fff8bbcecd0: mov rcx, r11
0x7fff8bbcecd3: sub rcx, rdi
0x7fff8bbcecd6: sub rsi, rcx
0x7fff8bbcecd9: sub rdx, rcx
0x7fff8bbcecdc: vmovups ymm1, ymmword ptr [rsi - 0x20]
0x7fff8bbcece1: vmovups ymmword ptr [r11 - 0x20], ymm0
0x7fff8bbcece7: vmovups ymm2, ymmword ptr [rsi - 0x40]
0x7fff8bbcecec: sub rsi, 0x40
0x7fff8bbcecf0: sub rdx, 0x80
0x7fff8bbcecf7: jbe 0x7fff8bbced62 ; _platform_memmove$VARIANT$Unknown + 610
0x7fff8bbcecf9: test rsi, 0x1f
0x7fff8bbced00: je 0x7fff8bbced40 ; _platform_memmove$VARIANT$Unknown + 576
0x7fff8bbced02: vmovaps ymmword ptr [rdi - 0x20], ymm1; memory write!!
0x7fff8bbced07: vmovaps ymmword ptr [rdi - 0x40], ymm2
0x7fff8bbced0c: sub rdi, 0x40
-> 0x7fff8bbced10: vmovups ymm1, ymmword ptr [rsi - 0x20]; underflow read
0x7fff8bbced15: vmovups ymm2, ymmword ptr [rsi - 0x40]
0x7fff8bbced1a: sub rsi, 0x40
0x7fff8bbced1e: sub rdx, 0x40
0x7fff8bbced22: ja 0x7fff8bbced02 ; _platform_memmove$VARIANT$Unknown + 514
0x7fff8bbced24: jmp 0x7fff8bbced62 ; _platform_memmove$VARIANT$Unknown + 610
0x7fff8bbced26: nop word ptr cs:[rax + rax]
0x7fff8bbced35: nop
0x7fff8bbced36: nop
0x7fff8bbced37: nop
0x7fff8bbced38: nop
0x7fff8bbced39: nop
0x7fff8bbced3a: nop
0x7fff8bbced3b: nop
0x7fff8bbced3c: nop
0x7fff8bbced3d: nop
0x7fff8bbced3e: nop
0x7fff8bbced3f: nop
0x7fff8bbced40: vmovaps ymmword ptr [rdi - 0x20], ymm1
0x7fff8bbced45: vmovaps ymmword ptr [rdi - 0x40], ymm2
0x7fff8bbced4a: sub rdi, 0x40
0x7fff8bbced4e: vmovaps ymm1, ymmword ptr [rsi - 0x20]
0x7fff8bbced53: vmovaps ymm2, ymmword ptr [rsi - 0x40]
0x7fff8bbced58: sub rsi, 0x40
0x7fff8bbced5c: sub rdx, 0x40
0x7fff8bbced60: ja 0x7fff8bbced40 ; _platform_memmove$VARIANT$Unknown + 576
0x7fff8bbced62: sub rsi, rdx
0x7fff8bbced65: vmovups ymm3, ymmword ptr [rsi - 0x20]
0x7fff8bbced6a: vmovups ymm4, ymmword ptr [rsi - 0x40]
0x7fff8bbced6f: vmovaps ymmword ptr [rdi - 0x20], ymm1
0x7fff8bbced74: vmovaps ymmword ptr [rdi - 0x40], ymm2
0x7fff8bbced79: vmovups ymmword ptr [rax + 0x20], ymm3
0x7fff8bbced7e: vmovups ymmword ptr [rax], ymm4
0x7fff8bbced82: pop rbp
0x7fff8bbced83: vzeroupper
0x7fff8bbced86: ret
(lldb)
This appears to be a possible out of bound read/write in memmove()
.As per the memmove source code available here: http://www.opensource.apple.com/source/ntp/ntp-13/ntp/libntp/memmove.c
memmove() takes three parameters the destination, source and size. Here I suspect that the crash happens during a backward copy from destination to source, resulting in an underflow read. In real world this is difficult to exploit due to limited buffer space.
Crash PoC : Download
To trigger the crash, Open your OS X Mavericks Terminal and do a cat on the PoC file.
cat terminal-poc
The issue was reported to Apple Product Security on 28th June 2015 and after so much follow up from both sides they finally concluded that they won't fix it as the crash is not reproducible on OS X Yosemite. I would like to thank my friend Dhanesh Kizhakkinan for helping me with the crash analysis.
Ajin Abraham is a Security Engineer with 10+ years of experience in Application Security, Research and Engineering. He is passionate about building and maintaining open source security tools and communities. Some of his contributions to Hacker's arsenal include Mobile Security Framework (MobSF), nodejsscan, OWASP Xenotix, etc. Areas of interest include runtime security instrumentation, offensive security, web and mobile application security, code and architectural reviews, cloud-native runtime security, security tool development, security automation, breaking and fixing security products, reverse engineering, and exploit development.