Search code examples
macosclangllvmdarwinmach

SIGKILL termination when trying to modify hex in mach object executable


I'm trying to learn more about how kernel's and executables work. To do this I'm starting with some basic experiments in regards to static and dynamic binaries compiled with aarch64 and x86_64 targets for macOS (Darwin), Linux, and Windows NT. All code and hex dumps for this issue can be found in this git repo. I have the following C program

#include <stdio.h>

int main() {
    printf("This is the message.");
    
    return 0;
}

I have compiled the code as is, renamed the output to b.out, then I changed the end of the printed string from a "." to a "!" just to use as a reference later. When I run a.out and b.out I get the expected output:

a.out

This is the message.

b.out

This is the message!

I then attempted to change the last character in the printed string to "!" in .a.out and saved the result as a binary to c.out. But when I run it I get the following output:

c.out

zsh: killed     ./c.out

Which appears to be a kernel kill rather than a zsh kill or anything programmed within the executable. When I look at the kernel logs I do see the following error:

-------------------------------------
Translated Report (Full Report Below)
-------------------------------------

Incident Identifier: 20C3E121-ED70-4F38-8795-D8CD6ED08F36
CrashReporter Key:   3BBE0F5E-25FE-9F02-ED42-03CD4C637157
Hardware Model:      Mac14,6
Process:             c.out [3352]
Path:                /Users/USER/Documents/*/c.out
Identifier:          c.out
Version:             ???
Code Type:           ARM-64 (Native)
Role:                Unspecified
Parent Process:      zsh [2823]
Coalition:           com.apple.Terminal [3459]
Responsible Process: Terminal [2821]

Date/Time:           2024-02-09 09:35:57.9854 -0500
Launch Time:         2024-02-09 09:35:57.9160 -0500
OS Version:          macOS 14.3.1 (23D60)
Release Type:        User
Report Version:      104

Exception Type:  EXC_BAD_ACCESS (SIGKILL (Code Signature Invalid))
Exception Subtype: UNKNOWN_0x32 at 0x0000000102d44000
Exception Codes: 0x0000000000000032, 0x0000000102d44000
VM Region Info: 0x102d44000 is in 0x102d44000-0x102d48000;  bytes after start: 0  bytes before end: 16383
      REGION TYPE                    START - END         [ VSIZE] PRT/MAX SHRMOD  REGION DETAIL
      UNUSED SPACE AT START
--->  __TEXT                      102d44000-102d48000    [   16K] r-x/r-x SM=COW  
      __DATA_CONST                102d48000-102d4c000    [   16K] rw-/rw- SM=COW  
Termination Reason: CODESIGNING 2 Invalid Page

Triggered by Thread:  0

Thread 0 Crashed:
0                                          0x102f0e204 dyld3::MachOFile::forEachLoadCommand(Diagnostics&, void (load_command const*, bool&) block_pointer) const + 52
1                                          0x102f102ac dyld3::MachOFile::forEachSupportedPlatform(void (dyld3::Platform, unsigned int, unsigned int) block_pointer) const + 160
2                                          0x102f662e4 dyld3::MachOFile::isBuiltForSimulator() const + 124
3                                          0x102f11b88 start + 992


Thread 0 crashed with ARM Thread State (64-bit):
    x0: 0x0000000102d44000   x1: 0x000000016d0bb4d8   x2: 0x000000016d0bb480   x3: 0x0000000102f0de44
    x4: 0x0000000000000070   x5: 0x0000000000000073   x6: 0x0000000000000000   x7: 0x0000000000000ca0
    x8: 0x000000016d0bb4b8   x9: 0x0000000102fa75f8  x10: 0x0000000102f8f000  x11: 0x0000000102f9c7af
   x12: 0x0000000000000065  x13: 0x0000000000000073  x14: 0x0000000000058a70  x15: 0x0000000000000000
   x16: 0x0000000102f1034c  x17: 0x6ae100016d0bb480  x18: 0x0000000000000000  x19: 0x000000016d0bb4d8
   x20: 0x0000000102d44000  x21: 0x000000016d0bb480  x22: 0x0000000102f0c000  x23: 0x000000016d0bb638
   x24: 0x000000016d0bb610  x25: 0x0000000000000000  x26: 0x0000000000000000  x27: 0x0000000000000000
   x28: 0x0000000000000000   fp: 0x000000016d0bb470   lr: 0x2056000102f102ac
    sp: 0x000000016d0bb3e0   pc: 0x0000000102f0e204 cpsr: 0x80001000
   far: 0x0000000102d44000  esr: 0x92000007 (Data Abort) byte read Translation fault

Binary Images:
       0x102f0c000 -        0x102fa3fff  (*) <50746901-db0e-39a0-b391-baaa6b82ad0f> ???
       0x102d44000 -        0x102d47fff  (*) <8a6e71e1-eed6-3905-9bb4-9258440c0fe2> ???
               0x0 - 0xffffffffffffffff ??? (*) <00000000-0000-0000-0000-000000000000> ???

Error Formulating Crash Report:
dyld_process_snapshot_get_shared_cache failed

EOF

-----------
Full Report
-----------

{"app_name":"c.out","timestamp":"2024-02-09 09:35:58.00 -0500","app_version":"","slice_uuid":"8a6e71e1-eed6-3905-9bb4-9258440c0fe2","build_version":"","platform":0,"share_with_app_devs":0,"is_first_party":1,"bug_type":"309","os_version":"macOS 14.3.1 (23D60)","roots_installed":0,"incident_id":"20C3E121-ED70-4F38-8795-D8CD6ED08F36","name":"c.out"}
{
  "uptime" : 4500,
  "procRole" : "Unspecified",
  "version" : 2,
  "userID" : 501,
  "deployVersion" : 210,
  "modelCode" : "Mac14,6",
  "coalitionID" : 3459,
  "osVersion" : {
    "train" : "macOS 14.3.1",
    "build" : "23D60",
    "releaseType" : "User"
  },
  "captureTime" : "2024-02-09 09:35:57.9854 -0500",
  "codeSigningMonitor" : 1,
  "incident" : "20C3E121-ED70-4F38-8795-D8CD6ED08F36",
  "pid" : 3352,
  "translated" : false,
  "cpuType" : "ARM-64",
  "roots_installed" : 0,
  "bug_type" : "309",
  "procLaunch" : "2024-02-09 09:35:57.9160 -0500",
  "procStartAbsTime" : 110142542836,
  "procExitAbsTime" : 110144134578,
  "procName" : "c.out",
  "procPath" : "\/Users\/USER\/Documents\/*\/c.out",
  "parentProc" : "zsh",
  "parentPid" : 2823,
  "coalitionName" : "com.apple.Terminal",
  "crashReporterKey" : "3BBE0F5E-25FE-9F02-ED42-03CD4C637157",
  "responsiblePid" : 2821,
  "responsibleProc" : "Terminal",
  "codeSigningID" : "a.out",
  "codeSigningTeamID" : "",
  "codeSigningFlags" : 587334144,
  "codeSigningValidationCategory" : 0,
  "codeSigningTrustLevel" : 4294967295,
  "instructionByteStream" : {"beforePC":"+mcFqfhfBqn2Vwep9E8Iqf17Can9QwKR9QMCqvMDAar0AwCq\/\/8AOQ==","atPC":"CABAuelZn1Kp3b9yHwEJa+AAAFTJWZ9Sqd2\/ch8BCWthAQBUiQOAUg=="},
  "wakeTime" : 4394,
  "sleepWakeUUID" : "6725BB24-D686-433E-A28E-9F055451A803",
  "sip" : "enabled",
  "vmRegionInfo" : "0x102d44000 is in 0x102d44000-0x102d48000;  bytes after start: 0  bytes before end: 16383\n      REGION TYPE                    START - END         [ VSIZE] PRT\/MAX SHRMOD  REGION DETAIL\n      UNUSED SPACE AT START\n--->  __TEXT                      102d44000-102d48000    [   16K] r-x\/r-x SM=COW  \n      __DATA_CONST                102d48000-102d4c000    [   16K] rw-\/rw- SM=COW  ",
  "exception" : {"codes":"0x0000000000000032, 0x0000000102d44000","rawCodes":[50,4342431744],"type":"EXC_BAD_ACCESS","signal":"SIGKILL (Code Signature Invalid)","subtype":"UNKNOWN_0x32 at 0x0000000102d44000"},
  "termination" : {"flags":0,"code":2,"namespace":"CODESIGNING","indicator":"Invalid Page"},
  "vmregioninfo" : "0x102d44000 is in 0x102d44000-0x102d48000;  bytes after start: 0  bytes before end: 16383\n      REGION TYPE                    START - END         [ VSIZE] PRT\/MAX SHRMOD  REGION DETAIL\n      UNUSED SPACE AT START\n--->  __TEXT                      102d44000-102d48000    [   16K] r-x\/r-x SM=COW  \n      __DATA_CONST                102d48000-102d4c000    [   16K] rw-\/rw- SM=COW  ",
  "extMods" : {"caller":{"thread_create":0,"thread_set_state":0,"task_for_pid":0},"system":{"thread_create":0,"thread_set_state":0,"task_for_pid":0},"targeted":{"thread_create":0,"thread_set_state":0,"task_for_pid":0},"warnings":0},
  "faultingThread" : 0,
  "threads" : [{"triggered":true,"id":77191,"threadState":{"x":[{"value":4342431744},{"value":6124451032},{"value":6124450944},{"value":4344307268},{"value":112},{"value":115},{"value":0},{"value":3232},{"value":6124451000},{"value":4344935928,"symbolLocation":0,"symbol":"__block_descriptor_tmp.61"},{"value":4344836096,"symbolLocation":20,"symbol":"objc_visitor::ProtocolList::getProtocolField(objc_visitor::Visitor const&, unsigned long long) const (.cold.2)"},{"value":4344891311},{"value":101},{"value":115},{"value":363120},{"value":0},{"value":4344316748,"symbolLocation":0,"symbol":"invocation function for block in dyld3::MachOFile::forEachSupportedPlatform(void (dyld3::Platform, unsigned int, unsigned int) block_pointer) const"},{"value":7701436843904709760},{"value":0},{"value":6124451032},{"value":4342431744},{"value":6124450944},{"value":4344299520},{"value":6124451384},{"value":6124451344},{"value":0},{"value":0},{"value":0},{"value":0}],"flavor":"ARM_THREAD_STATE64","lr":{"value":2330049861555126956},"cpsr":{"value":2147487744},"fp":{"value":6124450928},"sp":{"value":6124450784},"esr":{"value":2449473543,"description":"(Data Abort) byte read Translation fault"},"pc":{"value":4344308228,"matchesCrashFrame":1},"far":{"value":4342431744}},"frames":[{"imageOffset":8708,"symbol":"dyld3::MachOFile::forEachLoadCommand(Diagnostics&, void (load_command const*, bool&) block_pointer) const","symbolLocation":52,"imageIndex":0},{"imageOffset":17068,"symbol":"dyld3::MachOFile::forEachSupportedPlatform(void (dyld3::Platform, unsigned int, unsigned int) block_pointer) const","symbolLocation":160,"imageIndex":0},{"imageOffset":369380,"symbol":"dyld3::MachOFile::isBuiltForSimulator() const","symbolLocation":124,"imageIndex":0},{"imageOffset":23432,"symbol":"start","symbolLocation":992,"imageIndex":0}]}],
  "usedImages" : [
  {
    "source" : "P",
    "arch" : "arm64e",
    "base" : 4344299520,
    "size" : 622592,
    "uuid" : "50746901-db0e-39a0-b391-baaa6b82ad0f",
    "name" : ""
  },
  {
    "source" : "P",
    "arch" : "arm64",
    "base" : 4342431744,
    "size" : 16384,
    "uuid" : "8a6e71e1-eed6-3905-9bb4-9258440c0fe2",
    "name" : ""
  },
  {
    "size" : 0,
    "source" : "A",
    "base" : 0,
    "uuid" : "00000000-0000-0000-0000-000000000000"
  }
],
  "vmSummary" : "ReadOnly portion of Libraries: Total=1008K resident=0K(0%) swapped_out_or_unallocated=1008K(100%)\nWritable regions: Total=8176K written=0K(0%) resident=0K(0%) swapped_out=0K(0%) unallocated=8176K(100%)\n\n                                VIRTUAL   REGION \nREGION TYPE                        SIZE    COUNT (non-coalesced) \n===========                     =======  ======= \nSTACK GUARD                       56.0M        1 \nStack                             8176K        1 \n__DATA                              16K        1 \n__DATA_CONST                        48K        2 \n__DATA_DIRTY                        16K        1 \n__LINKEDIT                         384K        2 \n__TEXT                             624K        2 \n===========                     =======  ======= \nTOTAL                             65.1M       10 \n",
  "legacyInfo" : {
  "threadTriggered" : {

  }
},
  "logWritingSignature" : "f13fb427e44496b8a2cba53558762cf657744a7e",
  "trialInfo" : {
  "rollouts" : [
    {
      "rolloutId" : "64b21a7351cbb02ce3442e4e",
      "factorPackIds" : {
        "REMINDERS_GROCERY" : "65542c604a6560536bdb1d22"
      },
      "deploymentId" : 240000032
    },
    {
      "rolloutId" : "6425c75e4327780c10cc4252",
      "factorPackIds" : {
        "SIRI_HOME_AUTOMATION_INTENT_SELECTION_CACHE" : "642600a457e7664b1698eb32"
      },
      "deploymentId" : 240000004
    }
  ],
  "experiments" : [

  ]
},
  "reportNotes" : [
  "dyld_process_snapshot_get_shared_cache failed"
]
}


Which leads me to believe there is a crypto mechanism that is causing the kernel to have a problem with the executable. After some searching I found references to MACH-EXECUTE object files having a checksum, and when comparing found the following set of characters which based on the length I assume to be a MD5 hash:

00000378:  1b00 0000 1800 0000 8a6e 71e1 eed6 3905 9bb4 9258 440c 0fe2

So I start by trying to update that hash found in c.out with the contents of b.out's hash, so that the result looks like this:

00000378:  1b00 0000 1800 0000 e92b 09d1 5e12 30a5 b9f2 f0c1 8b21 a74d

I tried to execute the binary again and the same kernel error occurs. The only other difference which I've not been able to identify is found at the bottom of the hex dump which could be the problem, but I'm not sure what it is:

a.out

00008160:  0000 0034 0000 0000 0000 0001 612e 6f75 7400 a099 e717 e474
00008178:  e85d 7190 c6bb 2c0a 0f08 56e5 e1cc d752 c26c a377 9142 1c4b
00008190:  a6e2 ad7f acb2 586f c6e9 66c0 04d7 d1d1 6b02 4f58 05ff 7cb4
000081a8:  7c7a 85da bd8b 4889 2ca7 ad7f acb2 586f c6e9 66c0 04d7 d1d1
000081c0:  6b02 4f58 05ff 7cb4 7c7a 85da bd8b 4889 2ca7 b263 8efb 717d
000081d8:  ee06 21e4 651a ecb1 09bc 2aba 80db 7c57 5aca a99a a5ff 987e
000081f0:  a3b5 dfd5 eb86 f195 6603 a12c 0636 f463 1f66 f10d 0bb8 d4ee
00008208:  a3d2 5b82 e0e5 9202 b4ed ad7f acb2 586f c6e9 66c0 04d7 d1d1
00008220:  6b02 4f58 05ff 7cb4 7c7a 85da bd8b 4889 2ca7 ad7f acb2 586f
00008238:  c6e9 66c0 04d7 d1d1 6b02 4f58 05ff 7cb4 7c7a 85da bd8b 4889
00008250:  2ca7 ad7f acb2 586f c6e9 66c0 04d7 d1d1 6b02 4f58 05ff 7cb4
00008268:  7c7a 85da bd8b 4889 2ca7 521e 9e92 c0d7 f140 79c7 e903 71dc
00008280:  b96b ebb4 dca7 c209 1dba 1d71 6bf4 aea0 2586 0000 0000 0000

b.out

00008160:  0000 0034 0000 0000 0000 0001 612e 6f75 7400 fca1 75f4 4ef7
00008178:  c187 a241 56d2 9d13 7ba4 7060 3e95 4111 900e 2364 644a 5cc1
00008190:  a785 ad7f acb2 586f c6e9 66c0 04d7 d1d1 6b02 4f58 05ff 7cb4
000081a8:  7c7a 85da bd8b 4889 2ca7 ad7f acb2 586f c6e9 66c0 04d7 d1d1
000081c0:  6b02 4f58 05ff 7cb4 7c7a 85da bd8b 4889 2ca7 1a07 1b89 4002
000081d8:  ab65 ddc7 6901 1a11 cec2 5d81 b1ef f3eb 6a62 f1fb eeae eaa1
000081f0:  a9da dfd5 eb86 f195 6603 a12c 0636 f463 1f66 f10d 0bb8 d4ee
00008208:  a3d2 5b82 e0e5 9202 b4ed ad7f acb2 586f c6e9 66c0 04d7 d1d1
00008220:  6b02 4f58 05ff 7cb4 7c7a 85da bd8b 4889 2ca7 ad7f acb2 586f
00008238:  c6e9 66c0 04d7 d1d1 6b02 4f58 05ff 7cb4 7c7a 85da bd8b 4889
00008250:  2ca7 ad7f acb2 586f c6e9 66c0 04d7 d1d1 6b02 4f58 05ff 7cb4
00008268:  7c7a 85da bd8b 4889 2ca7 521e 9e92 c0d7 f140 79c7 e903 71dc
00008280:  b96b ebb4 dca7 c209 1dba 1d71 6bf4 aea0 2586 0000 0000 0000

assuming by the error I'm guessing that it's a encrypted digest of some sort? But what algorithm and am I even right? And when I update the last set of segments with the ending binary of b.out I still get the same SIGKIKLL?

The actual question: What am I doing wrong here if I want to be able to execute the updated binary?


Solution

  • You need to codesign c.out, since your crash report indicates an invalid code signature:

    Exception Type: EXC_BAD_ACCESS (SIGKILL (Code Signature Invalid))

    To codesign the binary ad-hoc first remove any extended attributes:

    $ xattr -c c.out
    

    Then codesign it:

    $ sudo codesign -f -s - c.out
    

    You'll need a legit certificate if you intend to run the modified binary on other machines.