├── README.md
├── Gatekeerper
├── Info.plist
├── configuration.h
├── utils.h
├── functions_clone.h
├── trustedbsd_hooks.h
├── logging.h
├── utils.c
├── Gatekeerper.c
├── kernel_symbols.h
├── functions_clone.c
├── cloned_functions.s
├── trustedbsd_hooks.c
└── kernel_symbols.c
└── Gatekeerper.xcodeproj
└── project.pbxproj
/README.md:
--------------------------------------------------------------------------------
1 | Gatekeerper
2 |
3 | A kernel extension to mitigate Gatekeeper bypasses
4 |
5 | Doesn't let linked (frameworks, libraries, bundles) unsigned code run if main binary is signed
6 |
7 | Untested with latest Gatekeeper bypass by Patrick Wardle (https://www.virusbtn.com/pdf/conference_slides/2015/Wardle-VB2015.pdf).
8 |
9 | I'm too lazy to create a PoC of that bypass. So I'm just guessing it will work but I'm pretty confident anyway :-)
10 |
11 | Copyright (c) fG!, 2015. All rights reserved.
12 |
13 | reverser@put.as - https://reverse.put.as
14 |
15 |
--------------------------------------------------------------------------------
/Gatekeerper/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | KEXT
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | NSHumanReadableCopyright
24 | Copyright © 2015 Put.as. All rights reserved.
25 | OSBundleLibraries
26 |
27 | com.apple.kpi.mach
28 | 10.0.0
29 | com.apple.kpi.libkern
30 | 10.0.0
31 | com.apple.kpi.bsd
32 | 10.0.0
33 | com.apple.kpi.dsep
34 | 10.0.0
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/Gatekeerper/configuration.h:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * ('-. .-') _ ('-. .-. .-') ('-. ('-. _ .-') _ (`-. ('-. _ .-')
4 | * ( OO ).-.( OO) ) _( OO) \ ( OO ) _( OO) _( OO)( \( -O ) ( (OO ) _( OO)( \( -O )
5 | * ,----. / . --. // '._(,------.,--. ,--. (,------.(,------.,------. _.` \(,------.,------.
6 | * ' .-./-') | \-. \ |'--...__)| .---'| .' / | .---' | .---'| /`. '(__...--'' | .---'| /`. '
7 | * | |_( O- ).-'-' | |'--. .--'| | | /, | | | | | / | | | / | | | | | / | |
8 | * | | .--, \ \| |_.' | | | (| '--. | ' _)(| '--. (| '--. | |_.' | | |_.' |(| '--. | |_.' |
9 | * (| | '. (_/ | .-. | | | | .--' | . \ | .--' | .--' | . '.' | .___.' | .--' | . '.'
10 | * | '--' | | | | | | | | `---.| |\ \ | `---. | `---.| |\ \ | | | `---.| |\ \
11 | * `------' `--' `--' `--' `------'`--' '--' `------' `------'`--' '--' `--' `------'`--' '--'
12 | *
13 | * Gatekeerper
14 | * A kernel extension to mitigate Gatekeeper bypasses
15 | * Doesn't let linked (frameworks, libraries, bundles) unsigned code run if main binary is signed
16 | *
17 | * Untested with latest Gatekeeper bypass, too lazy to create a PoC of that
18 | * So I'm just guessing it will work, I'm pretty confident anyway :P
19 | *
20 | * Not guaranteed to be secure code! It might even destroy your computer but that is your problem!
21 | *
22 | * Created by reverser on 01/10/15.
23 | * Copyright (c) fG!, 2015. All rights reserved.
24 | * reverser@put.as - https://reverse.put.as
25 | *
26 | * config.h
27 | *
28 | * Redistribution and use in source and binary forms, with or without
29 | * modification, are permitted provided that the following conditions
30 | * are met:
31 | * 1. Redistributions of source code must retain the above copyright
32 | * notice, this list of conditions and the following disclaimer.
33 | * 2. Redistributions in binary form must reproduce the above copyright
34 | * notice, this list of conditions and the following disclaimer in the
35 | * documentation and/or other materials provided with the distribution.
36 | * 3. The name of the author may not be used to endorse or promote products
37 | * derived from this software without specific prior written permission.
38 | *
39 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
40 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
41 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
42 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
43 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
45 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
46 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
47 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
48 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
49 | *
50 | */
51 |
52 | #ifndef gatekeerper_config_h
53 | #define gatekeerper_config_h
54 |
55 | #endif
56 |
--------------------------------------------------------------------------------
/Gatekeerper/utils.h:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * ('-. .-') _ ('-. .-. .-') ('-. ('-. _ .-') _ (`-. ('-. _ .-')
4 | * ( OO ).-.( OO) ) _( OO) \ ( OO ) _( OO) _( OO)( \( -O ) ( (OO ) _( OO)( \( -O )
5 | * ,----. / . --. // '._(,------.,--. ,--. (,------.(,------.,------. _.` \(,------.,------.
6 | * ' .-./-') | \-. \ |'--...__)| .---'| .' / | .---' | .---'| /`. '(__...--'' | .---'| /`. '
7 | * | |_( O- ).-'-' | |'--. .--'| | | /, | | | | | / | | | / | | | | | / | |
8 | * | | .--, \ \| |_.' | | | (| '--. | ' _)(| '--. (| '--. | |_.' | | |_.' |(| '--. | |_.' |
9 | * (| | '. (_/ | .-. | | | | .--' | . \ | .--' | .--' | . '.' | .___.' | .--' | . '.'
10 | * | '--' | | | | | | | | `---.| |\ \ | `---. | `---.| |\ \ | | | `---.| |\ \
11 | * `------' `--' `--' `--' `------'`--' '--' `------' `------'`--' '--' `--' `------'`--' '--'
12 | *
13 | * Gatekeerper
14 | * A kernel extension to mitigate Gatekeeper bypasses
15 | * Doesn't let linked (frameworks, libraries, bundles) unsigned code run if main binary is signed
16 | *
17 | * Untested with latest Gatekeeper bypass, too lazy to create a PoC of that
18 | * So I'm just guessing it will work, I'm pretty confident anyway :P
19 | *
20 | * Not guaranteed to be secure code! It might even destroy your computer but that is your problem!
21 | *
22 | * Created by reverser on 09/11/15.
23 | * Copyright (c) fG!, 2015. All rights reserved.
24 | * reverser@put.as - https://reverse.put.as
25 | *
26 | * utils.h
27 | *
28 | * Misc auxiliary kernel functions
29 | *
30 | * Redistribution and use in source and binary forms, with or without
31 | * modification, are permitted provided that the following conditions
32 | * are met:
33 | * 1. Redistributions of source code must retain the above copyright
34 | * notice, this list of conditions and the following disclaimer.
35 | * 2. Redistributions in binary form must reproduce the above copyright
36 | * notice, this list of conditions and the following disclaimer in the
37 | * documentation and/or other materials provided with the distribution.
38 | * 3. The name of the author may not be used to endorse or promote products
39 | * derived from this software without specific prior written permission.
40 | *
41 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
42 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
43 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
44 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
45 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
47 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
48 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
49 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
50 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51 | *
52 | */
53 |
54 | #ifndef gatekeerper_utils_h
55 | #define gatekeerper_utils_h
56 |
57 | #include
58 |
59 | uint8_t disable_wp(void);
60 | uint8_t enable_wp(void);
61 |
62 | #define enable_interrupts() __asm__ volatile("sti");
63 | #define disable_interrupts() __asm__ volatile("cli");
64 |
65 | #endif
66 |
--------------------------------------------------------------------------------
/Gatekeerper/functions_clone.h:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * ('-. .-') _ ('-. .-. .-') ('-. ('-. _ .-') _ (`-. ('-. _ .-')
4 | * ( OO ).-.( OO) ) _( OO) \ ( OO ) _( OO) _( OO)( \( -O ) ( (OO ) _( OO)( \( -O )
5 | * ,----. / . --. // '._(,------.,--. ,--. (,------.(,------.,------. _.` \(,------.,------.
6 | * ' .-./-') | \-. \ |'--...__)| .---'| .' / | .---' | .---'| /`. '(__...--'' | .---'| /`. '
7 | * | |_( O- ).-'-' | |'--. .--'| | | /, | | | | | / | | | / | | | | | / | |
8 | * | | .--, \ \| |_.' | | | (| '--. | ' _)(| '--. (| '--. | |_.' | | |_.' |(| '--. | |_.' |
9 | * (| | '. (_/ | .-. | | | | .--' | . \ | .--' | .--' | . '.' | .___.' | .--' | . '.'
10 | * | '--' | | | | | | | | `---.| |\ \ | `---. | `---.| |\ \ | | | `---.| |\ \
11 | * `------' `--' `--' `--' `------'`--' '--' `------' `------'`--' '--' `--' `------'`--' '--'
12 | *
13 | * Gatekeerper
14 | * A kernel extension to mitigate Gatekeeper bypasses
15 | * Doesn't let linked (frameworks, libraries, bundles) unsigned code run if main binary is signed
16 | *
17 | * Untested with latest Gatekeeper bypass, too lazy to create a PoC of that
18 | * So I'm just guessing it will work, I'm pretty confident anyway :P
19 | *
20 | * Not guaranteed to be secure code! It might even destroy your computer but that is your problem!
21 | *
22 | * Created by reverser on 01/10/15.
23 | * Copyright (c) fG!, 2015. All rights reserved.
24 | * reverser@put.as - https://reverse.put.as
25 | *
26 | * functions_clone.h
27 | *
28 | * Functions to clone and fix kernel functions
29 | * XXX: TODO!
30 | *
31 | * Redistribution and use in source and binary forms, with or without
32 | * modification, are permitted provided that the following conditions
33 | * are met:
34 | * 1. Redistributions of source code must retain the above copyright
35 | * notice, this list of conditions and the following disclaimer.
36 | * 2. Redistributions in binary form must reproduce the above copyright
37 | * notice, this list of conditions and the following disclaimer in the
38 | * documentation and/or other materials provided with the distribution.
39 | * 3. The name of the author may not be used to endorse or promote products
40 | * derived from this software without specific prior written permission.
41 | *
42 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
43 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
44 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
45 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
46 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
47 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
48 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
49 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
50 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
51 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52 | *
53 | */
54 |
55 | #ifndef gatekeerper_functions_clone_h
56 | #define gatekeerper_functions_clone_h
57 |
58 | #include
59 |
60 | kern_return_t clone_csfg_get_platform_binary(void);
61 | kern_return_t clone_csproc_get_teamid(void);
62 |
63 | #endif /* gatekeerper_functions_clone_h */
64 |
--------------------------------------------------------------------------------
/Gatekeerper/trustedbsd_hooks.h:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * ('-. .-') _ ('-. .-. .-') ('-. ('-. _ .-') _ (`-. ('-. _ .-')
4 | * ( OO ).-.( OO) ) _( OO) \ ( OO ) _( OO) _( OO)( \( -O ) ( (OO ) _( OO)( \( -O )
5 | * ,----. / . --. // '._(,------.,--. ,--. (,------.(,------.,------. _.` \(,------.,------.
6 | * ' .-./-') | \-. \ |'--...__)| .---'| .' / | .---' | .---'| /`. '(__...--'' | .---'| /`. '
7 | * | |_( O- ).-'-' | |'--. .--'| | | /, | | | | | / | | | / | | | | | / | |
8 | * | | .--, \ \| |_.' | | | (| '--. | ' _)(| '--. (| '--. | |_.' | | |_.' |(| '--. | |_.' |
9 | * (| | '. (_/ | .-. | | | | .--' | . \ | .--' | .--' | . '.' | .___.' | .--' | . '.'
10 | * | '--' | | | | | | | | `---.| |\ \ | `---. | `---.| |\ \ | | | `---.| |\ \
11 | * `------' `--' `--' `--' `------'`--' '--' `------' `------'`--' '--' `--' `------'`--' '--'
12 | *
13 | * Gatekeerper
14 | * A kernel extension to mitigate Gatekeeper bypasses
15 | * Doesn't let linked (frameworks, libraries, bundles) unsigned code run if main binary is signed
16 | *
17 | * Untested with latest Gatekeeper bypass, too lazy to create a PoC of that
18 | * So I'm just guessing it will work, I'm pretty confident anyway :P
19 | *
20 | * Not guaranteed to be secure code! It might even destroy your computer but that is your problem!
21 | *
22 | * Created by reverser on 01/10/15.
23 | * Copyright (c) fG!, 2015. All rights reserved.
24 | * reverser@put.as - https://reverse.put.as
25 | *
26 | * trustedbsd_hooks.h
27 | *
28 | * Functions to replace AMFI hooks and control unsigned code
29 | * Where all the magic happens!
30 | *
31 | * Redistribution and use in source and binary forms, with or without
32 | * modification, are permitted provided that the following conditions
33 | * are met:
34 | * 1. Redistributions of source code must retain the above copyright
35 | * notice, this list of conditions and the following disclaimer.
36 | * 2. Redistributions in binary form must reproduce the above copyright
37 | * notice, this list of conditions and the following disclaimer in the
38 | * documentation and/or other materials provided with the distribution.
39 | * 3. The name of the author may not be used to endorse or promote products
40 | * derived from this software without specific prior written permission.
41 | *
42 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
43 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
44 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
45 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
46 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
47 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
48 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
49 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
50 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
51 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52 | *
53 | */
54 |
55 | #ifndef gatekeerper_trustedbsd_hooks_h
56 | #define gatekeerper_trustedbsd_hooks_h
57 |
58 | #include
59 |
60 | kern_return_t start_trustedbsd_hooks(void *d);
61 | kern_return_t stop_trustedbsd_hooks(void);
62 |
63 | #endif /* gatekeerper_trustedbsd_hooks_h */
64 |
--------------------------------------------------------------------------------
/Gatekeerper/logging.h:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * ('-. .-') _ ('-. .-. .-') ('-. ('-. _ .-') _ (`-. ('-. _ .-')
4 | * ( OO ).-.( OO) ) _( OO) \ ( OO ) _( OO) _( OO)( \( -O ) ( (OO ) _( OO)( \( -O )
5 | * ,----. / . --. // '._(,------.,--. ,--. (,------.(,------.,------. _.` \(,------.,------.
6 | * ' .-./-') | \-. \ |'--...__)| .---'| .' / | .---' | .---'| /`. '(__...--'' | .---'| /`. '
7 | * | |_( O- ).-'-' | |'--. .--'| | | /, | | | | | / | | | / | | | | | / | |
8 | * | | .--, \ \| |_.' | | | (| '--. | ' _)(| '--. (| '--. | |_.' | | |_.' |(| '--. | |_.' |
9 | * (| | '. (_/ | .-. | | | | .--' | . \ | .--' | .--' | . '.' | .___.' | .--' | . '.'
10 | * | '--' | | | | | | | | `---.| |\ \ | `---. | `---.| |\ \ | | | `---.| |\ \
11 | * `------' `--' `--' `--' `------'`--' '--' `------' `------'`--' '--' `--' `------'`--' '--'
12 | *
13 | * Gatekeerper
14 | * A kernel extension to mitigate Gatekeeper bypasses
15 | * Doesn't let linked (frameworks, libraries, bundles) unsigned code run if main binary is signed
16 | *
17 | * Untested with latest Gatekeeper bypass, too lazy to create a PoC of that
18 | * So I'm just guessing it will work, I'm pretty confident anyway :P
19 | *
20 | * Not guaranteed to be secure code! It might even destroy your computer but that is your problem!
21 | *
22 | * Created by reverser on 01/10/15.
23 | * Copyright (c) fG!, 2015. All rights reserved.
24 | * reverser@put.as - https://reverse.put.as
25 | *
26 | * logging.h
27 | *
28 | * Redistribution and use in source and binary forms, with or without
29 | * modification, are permitted provided that the following conditions
30 | * are met:
31 | * 1. Redistributions of source code must retain the above copyright
32 | * notice, this list of conditions and the following disclaimer.
33 | * 2. Redistributions in binary form must reproduce the above copyright
34 | * notice, this list of conditions and the following disclaimer in the
35 | * documentation and/or other materials provided with the distribution.
36 | * 3. The name of the author may not be used to endorse or promote products
37 | * derived from this software without specific prior written permission.
38 | *
39 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
40 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
41 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
42 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
43 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
45 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
46 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
47 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
48 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
49 | *
50 | */
51 |
52 | #ifndef gatekeerper_logging_h
53 | #define gatekeerper_logging_h
54 |
55 | #include
56 |
57 | #if DEBUG == NO
58 |
59 | #define DEBUG_MSG(fmt, ...) do {} while (0)
60 | #define ERROR_MSG(fmt, ...) printf("[ERROR] " fmt "\n", ## __VA_ARGS__)
61 |
62 | #else /* DEBUG == YES */
63 |
64 | #define DEBUG_MSG(fmt, ...) printf("[DEBUG] " fmt "\n", ## __VA_ARGS__)
65 | #define ERROR_MSG(fmt, ...) printf("[ERROR] " fmt " (%s, %d)\n", ## __VA_ARGS__, __func__, __LINE__)
66 |
67 | #endif /* DEBUG */
68 |
69 | /* kernel symbols */
70 | #define SOLVE_KERNEL_SYMBOL(string, pointer) if (solve_kernel_symbol((string), (void**)&(pointer))) { ERROR_MSG("Can't solve kernel symbol %s", (string)); return KERN_FAILURE;}
71 | #define SOLVE_KERNEL_VARIABLE(string, output) if (solve_kernel_variable((string), &(output))) { ERROR_MSG("Can't solve kernel variable %s", (string)); return KERN_FAILURE;}
72 |
73 | #endif
74 |
--------------------------------------------------------------------------------
/Gatekeerper/utils.c:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * ('-. .-') _ ('-. .-. .-') ('-. ('-. _ .-') _ (`-. ('-. _ .-')
4 | * ( OO ).-.( OO) ) _( OO) \ ( OO ) _( OO) _( OO)( \( -O ) ( (OO ) _( OO)( \( -O )
5 | * ,----. / . --. // '._(,------.,--. ,--. (,------.(,------.,------. _.` \(,------.,------.
6 | * ' .-./-') | \-. \ |'--...__)| .---'| .' / | .---' | .---'| /`. '(__...--'' | .---'| /`. '
7 | * | |_( O- ).-'-' | |'--. .--'| | | /, | | | | | / | | | / | | | | | / | |
8 | * | | .--, \ \| |_.' | | | (| '--. | ' _)(| '--. (| '--. | |_.' | | |_.' |(| '--. | |_.' |
9 | * (| | '. (_/ | .-. | | | | .--' | . \ | .--' | .--' | . '.' | .___.' | .--' | . '.'
10 | * | '--' | | | | | | | | `---.| |\ \ | `---. | `---.| |\ \ | | | `---.| |\ \
11 | * `------' `--' `--' `--' `------'`--' '--' `------' `------'`--' '--' `--' `------'`--' '--'
12 | *
13 | * Gatekeerper
14 | * A kernel extension to mitigate Gatekeeper bypasses
15 | * Doesn't let linked (frameworks, libraries, bundles) unsigned code run if main binary is signed
16 | *
17 | * Untested with latest Gatekeeper bypass, too lazy to create a PoC of that
18 | * So I'm just guessing it will work, I'm pretty confident anyway :P
19 | *
20 | * Not guaranteed to be secure code! It might even destroy your computer but that is your problem!
21 | *
22 | * Created by reverser on 09/11/15.
23 | * Copyright (c) fG!, 2015. All rights reserved.
24 | * reverser@put.as - https://reverse.put.as
25 | *
26 | * utils.c
27 | *
28 | * Misc auxiliary kernel functions
29 | *
30 | * Redistribution and use in source and binary forms, with or without
31 | * modification, are permitted provided that the following conditions
32 | * are met:
33 | * 1. Redistributions of source code must retain the above copyright
34 | * notice, this list of conditions and the following disclaimer.
35 | * 2. Redistributions in binary form must reproduce the above copyright
36 | * notice, this list of conditions and the following disclaimer in the
37 | * documentation and/or other materials provided with the distribution.
38 | * 3. The name of the author may not be used to endorse or promote products
39 | * derived from this software without specific prior written permission.
40 | *
41 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
42 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
43 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
44 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
45 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
47 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
48 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
49 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
50 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51 | *
52 | */
53 |
54 | #include "utils.h"
55 |
56 | #include "logging.h"
57 | #include "configuration.h"
58 | #include
59 |
60 | /*
61 | * disable the Write Protection bit in CR0 register so we can modify kernel code
62 | */
63 | uint8_t
64 | disable_wp(void)
65 | {
66 | uintptr_t cr0;
67 | // retrieve current value
68 | cr0 = get_cr0();
69 | // remove the WP bit
70 | cr0 = cr0 & ~CR0_WP;
71 | // and write it back
72 | set_cr0(cr0);
73 | // verify if we were successful
74 | if ((get_cr0() & CR0_WP) == 0) return 0;
75 | else return 1;
76 | }
77 |
78 | /*
79 | * enable the Write Protection bit in CR0 register
80 | */
81 | uint8_t
82 | enable_wp(void)
83 | {
84 | uintptr_t cr0;
85 | // retrieve current value
86 | cr0 = get_cr0();
87 | // add the WP bit
88 | cr0 = cr0 | CR0_WP;
89 | // and write it back
90 | set_cr0(cr0);
91 | // verify if we were successful
92 | if ((get_cr0() & CR0_WP) != 0) return 0;
93 | else return 1;
94 | }
95 |
--------------------------------------------------------------------------------
/Gatekeerper/Gatekeerper.c:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * ('-. .-') _ ('-. .-. .-') ('-. ('-. _ .-') _ (`-. ('-. _ .-')
4 | * ( OO ).-.( OO) ) _( OO) \ ( OO ) _( OO) _( OO)( \( -O ) ( (OO ) _( OO)( \( -O )
5 | * ,----. / . --. // '._(,------.,--. ,--. (,------.(,------.,------. _.` \(,------.,------.
6 | * ' .-./-') | \-. \ |'--...__)| .---'| .' / | .---' | .---'| /`. '(__...--'' | .---'| /`. '
7 | * | |_( O- ).-'-' | |'--. .--'| | | /, | | | | | / | | | / | | | | | / | |
8 | * | | .--, \ \| |_.' | | | (| '--. | ' _)(| '--. (| '--. | |_.' | | |_.' |(| '--. | |_.' |
9 | * (| | '. (_/ | .-. | | | | .--' | . \ | .--' | .--' | . '.' | .___.' | .--' | . '.'
10 | * | '--' | | | | | | | | `---.| |\ \ | `---. | `---.| |\ \ | | | `---.| |\ \
11 | * `------' `--' `--' `--' `------'`--' '--' `------' `------'`--' '--' `--' `------'`--' '--'
12 | *
13 | * Gatekeerper
14 | * A kernel extension to mitigate Gatekeeper bypasses
15 | * Doesn't let linked (frameworks, libraries, bundles) unsigned code run if main binary is signed
16 | *
17 | * Untested with latest Gatekeeper bypass, too lazy to create a PoC of that
18 | * So I'm just guessing it will work, I'm pretty confident anyway :P
19 | *
20 | * Not guaranteed to be secure code! It might even destroy your computer but that is your problem!
21 | *
22 | * TESTED ONLY WITH YOSEMITE 10.10.5 - EVERYTHING ELSE = KERNEL PANIC!
23 | *
24 | * Created by reverser on 01/10/15.
25 | * Copyright (c) fG!, 2015. All rights reserved.
26 | * reverser@put.as - https://reverse.put.as
27 | *
28 | * Gatekeerper.c
29 | *
30 | * Redistribution and use in source and binary forms, with or without
31 | * modification, are permitted provided that the following conditions
32 | * are met:
33 | * 1. Redistributions of source code must retain the above copyright
34 | * notice, this list of conditions and the following disclaimer.
35 | * 2. Redistributions in binary form must reproduce the above copyright
36 | * notice, this list of conditions and the following disclaimer in the
37 | * documentation and/or other materials provided with the distribution.
38 | * 3. The name of the author may not be used to endorse or promote products
39 | * derived from this software without specific prior written permission.
40 | *
41 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
42 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
43 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
44 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
45 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
47 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
48 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
49 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
50 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51 | *
52 | */
53 |
54 | #include
55 | #include "logging.h"
56 | #include "configuration.h"
57 | #include "kernel_symbols.h"
58 | #include "trustedbsd_hooks.h"
59 | #include
60 |
61 | /* global variables */
62 | /* structure to hold kernel headers info we use to solve symbols */
63 | struct kernel_info g_kinfo;
64 |
65 | extern const int version_major;
66 | extern const int version_minor;
67 | extern const int version_revision;
68 |
69 | kern_return_t Gatekeerper_start(kmod_info_t * ki, void *d);
70 | kern_return_t Gatekeerper_stop(kmod_info_t *ki, void *d);
71 |
72 | kern_return_t Gatekeerper_start(kmod_info_t * ki, void *d)
73 | {
74 | /* TESTED ONLY WITH YOSEMITE 10.10.5 - EVERYTHING ELSE = KERNEL PANIC! */
75 | if (version_major != 14 && version_minor != 5 && version_revision != 0)
76 | {
77 | ERROR_MSG("This kext only supports Yosemite 10.10.5.");
78 | return KERN_NOT_SUPPORTED;
79 | }
80 |
81 | /* initialize structure with kernel information to solve symbols */
82 | if (init_kernel_info() != KERN_SUCCESS)
83 | {
84 | /* in case of failure buffers are freed inside */
85 | ERROR_MSG("Failed to init kernel info structure!");
86 | return KERN_FAILURE;
87 | }
88 |
89 | /* solve kernel symbols we need */
90 | SOLVE_KERNEL_SYMBOL("_csfg_get_path", _csfg_get_path)
91 | SOLVE_KERNEL_SYMBOL("_csfg_get_teamid", _csfg_get_teamid)
92 | SOLVE_KERNEL_SYMBOL("_csfg_get_platform_binary", _csfg_get_platform_binary)
93 | SOLVE_KERNEL_SYMBOL("_csproc_get_teamid", _csproc_get_teamid)
94 | SOLVE_KERNEL_SYMBOL("_ubc_cs_blob_get", _ubc_cs_blob_get)
95 |
96 | start_trustedbsd_hooks(d);
97 |
98 | return KERN_SUCCESS;
99 | }
100 |
101 | kern_return_t Gatekeerper_stop(kmod_info_t *ki, void *d)
102 | {
103 | stop_trustedbsd_hooks();
104 | return KERN_SUCCESS;
105 | }
106 |
--------------------------------------------------------------------------------
/Gatekeerper/kernel_symbols.h:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * ('-. .-') _ ('-. .-. .-') ('-. ('-. _ .-') _ (`-. ('-. _ .-')
4 | * ( OO ).-.( OO) ) _( OO) \ ( OO ) _( OO) _( OO)( \( -O ) ( (OO ) _( OO)( \( -O )
5 | * ,----. / . --. // '._(,------.,--. ,--. (,------.(,------.,------. _.` \(,------.,------.
6 | * ' .-./-') | \-. \ |'--...__)| .---'| .' / | .---' | .---'| /`. '(__...--'' | .---'| /`. '
7 | * | |_( O- ).-'-' | |'--. .--'| | | /, | | | | | / | | | / | | | | | / | |
8 | * | | .--, \ \| |_.' | | | (| '--. | ' _)(| '--. (| '--. | |_.' | | |_.' |(| '--. | |_.' |
9 | * (| | '. (_/ | .-. | | | | .--' | . \ | .--' | .--' | . '.' | .___.' | .--' | . '.'
10 | * | '--' | | | | | | | | `---.| |\ \ | `---. | `---.| |\ \ | | | `---.| |\ \
11 | * `------' `--' `--' `--' `------'`--' '--' `------' `------'`--' '--' `--' `------'`--' '--'
12 | *
13 | * Gatekeerper
14 | * A kernel extension to mitigate Gatekeeper bypasses
15 | * Doesn't let linked (frameworks, libraries, bundles) unsigned code run if main binary is signed
16 | *
17 | * Untested with latest Gatekeeper bypass, too lazy to create a PoC of that
18 | * So I'm just guessing it will work, I'm pretty confident anyway :P
19 | *
20 | * Not guaranteed to be secure code! It might even destroy your computer but that is your problem!
21 | *
22 | * Created by reverser on 01/10/15.
23 | * Copyright (c) fG!, 2015. All rights reserved.
24 | * reverser@put.as - https://reverse.put.as
25 | *
26 | * kernel_symbols.h
27 | *
28 | * Functions to solve kernel symbols
29 | *
30 | * Redistribution and use in source and binary forms, with or without
31 | * modification, are permitted provided that the following conditions
32 | * are met:
33 | * 1. Redistributions of source code must retain the above copyright
34 | * notice, this list of conditions and the following disclaimer.
35 | * 2. Redistributions in binary form must reproduce the above copyright
36 | * notice, this list of conditions and the following disclaimer in the
37 | * documentation and/or other materials provided with the distribution.
38 | * 3. The name of the author may not be used to endorse or promote products
39 | * derived from this software without specific prior written permission.
40 | *
41 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
42 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
43 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
44 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
45 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
47 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
48 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
49 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
50 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51 | *
52 | */
53 |
54 | #ifndef gatekeerper_kernel_symbols_h
55 | #define gatekeerper_kernel_symbols_h
56 |
57 | #include
58 | #include
59 | #include
60 | #include
61 |
62 | struct fileglob;
63 | struct cs_blob;
64 |
65 | /* exported data structures */
66 | struct kernel_info
67 | {
68 | mach_vm_address_t memory_text_addr; // the address of __TEXT segment in kernel memory
69 | mach_vm_address_t disk_text_addr; // the same address at /mach_kernel in filesystem
70 | mach_vm_address_t kaslr_slide; // the kernel aslr slide, computed as the difference between above's addresses
71 | mach_vm_address_t disk_DATA_addr; /* the address of __DATA segment in mach-o header */
72 | void *linkedit_buf; // pointer to __LINKEDIT buffer containing symbols to solve
73 | uint64_t linkedit_fileoff; // __LINKEDIT file offset so we can read
74 | // WARNING: does not contain the fat offset value in case it's a FAT kernel
75 | uint64_t linkedit_size;
76 | uint32_t symboltable_fileoff; // file offset to symbol table - used to position inside the __LINKEDIT buffer
77 | uint32_t symboltable_nr_symbols;
78 | uint32_t stringtable_fileoff; // file offset to string table
79 | uint32_t stringtable_size;
80 | // other info from the header we might need
81 | uint64_t text_size; // size of __text section to disassemble
82 | uint64_t DATA_size; /* the VM size of __DATA segment */
83 | };
84 |
85 | /* exported functions */
86 | kern_return_t init_kernel_info(void);
87 | kern_return_t cleanup_kernel_info(void);
88 | kern_return_t solve_kernel_symbol(char *symbol_to_solve, void **symbol_ptr);
89 | kern_return_t solve_kernel_variable(char *symbol_to_solve, mach_vm_address_t *output);
90 |
91 | /* kernel symbols we will manually solve */
92 | extern int (*_csfg_get_path)(struct fileglob *fg, char *path, int *len);
93 | extern const char * (*_csfg_get_teamid)(struct fileglob *fg);
94 | extern int (*_csfg_get_platform_binary)(struct fileglob *fg);
95 | extern struct cs_blob * (*_csproc_get_blob)(struct proc *p);
96 | extern const char * (*_csproc_get_teamid)(struct proc *p);
97 | extern struct cs_blob * (*_ubc_cs_blob_get)(struct vnode *vp, cpu_type_t cputype, off_t offset);
98 |
99 | #endif
100 |
--------------------------------------------------------------------------------
/Gatekeerper/functions_clone.c:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * ('-. .-') _ ('-. .-. .-') ('-. ('-. _ .-') _ (`-. ('-. _ .-')
4 | * ( OO ).-.( OO) ) _( OO) \ ( OO ) _( OO) _( OO)( \( -O ) ( (OO ) _( OO)( \( -O )
5 | * ,----. / . --. // '._(,------.,--. ,--. (,------.(,------.,------. _.` \(,------.,------.
6 | * ' .-./-') | \-. \ |'--...__)| .---'| .' / | .---' | .---'| /`. '(__...--'' | .---'| /`. '
7 | * | |_( O- ).-'-' | |'--. .--'| | | /, | | | | | / | | | / | | | | | / | |
8 | * | | .--, \ \| |_.' | | | (| '--. | ' _)(| '--. (| '--. | |_.' | | |_.' |(| '--. | |_.' |
9 | * (| | '. (_/ | .-. | | | | .--' | . \ | .--' | .--' | . '.' | .___.' | .--' | . '.'
10 | * | '--' | | | | | | | | `---.| |\ \ | `---. | `---.| |\ \ | | | `---.| |\ \
11 | * `------' `--' `--' `--' `------'`--' '--' `------' `------'`--' '--' `--' `------'`--' '--'
12 | *
13 | * Gatekeerper
14 | * A kernel extension to mitigate Gatekeeper bypasses
15 | * Doesn't let linked (frameworks, libraries, bundles) unsigned code run if main binary is signed
16 | *
17 | * Untested with latest Gatekeeper bypass, too lazy to create a PoC of that
18 | * So I'm just guessing it will work, I'm pretty confident anyway :P
19 | *
20 | * Not guaranteed to be secure code! It might even destroy your computer but that is your problem!
21 | *
22 | * Created by reverser on 01/10/15.
23 | * Copyright (c) fG!, 2015. All rights reserved.
24 | * reverser@put.as - https://reverse.put.as
25 | *
26 | * functions_clone.c
27 | *
28 | * Functions to clone and fix kernel functions
29 | *
30 | * Redistribution and use in source and binary forms, with or without
31 | * modification, are permitted provided that the following conditions
32 | * are met:
33 | * 1. Redistributions of source code must retain the above copyright
34 | * notice, this list of conditions and the following disclaimer.
35 | * 2. Redistributions in binary form must reproduce the above copyright
36 | * notice, this list of conditions and the following disclaimer in the
37 | * documentation and/or other materials provided with the distribution.
38 | * 3. The name of the author may not be used to endorse or promote products
39 | * derived from this software without specific prior written permission.
40 | *
41 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
42 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
43 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
44 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
45 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
47 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
48 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
49 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
50 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51 | *
52 | */
53 |
54 | #include "functions_clone.h"
55 |
56 | #include
57 | #include
58 | #include
59 | #include
60 | #include
61 | #include
62 | #include
63 |
64 | #include "logging.h"
65 | #include "configuration.h"
66 | #include "kernel_symbols.h"
67 | #include "utils.h"
68 |
69 | /* the island space */
70 | extern char cloned_csfg_get_platform_binary[], cloned_csproc_get_teamid[], jump_island1[], jump_island2[], jump_island3[];
71 |
72 | /*
73 | * clone csfg_get_platform_binary, fix relocations, and patch it the way we need
74 | *
75 | * HARDCODED OFFSETS - Only valid for latest Yosemite 10.10.5
76 | *
77 | * This can be obviously improved using a disassembler but this is just a PoC
78 | * and things are stable enough to be ok this way
79 | *
80 | */
81 | kern_return_t
82 | clone_csfg_get_platform_binary(void)
83 | {
84 | DEBUG_MSG("Address of cloned_space is %p", (void*)cloned_csfg_get_platform_binary);
85 | DEBUG_MSG("Address of csfg_get_platform_binary is %p", (void*)_csfg_get_platform_binary);
86 | DEBUG_MSG("Jump island 1 address %p", (void*)jump_island1);
87 | DEBUG_MSG("Jump island 2 address %p", (void*)jump_island2);
88 |
89 | void *_lck_mtx_lock = NULL;
90 | void *_lck_mtx_unlock = NULL;
91 | SOLVE_KERNEL_SYMBOL("_lck_mtx_lock", _lck_mtx_lock)
92 | SOLVE_KERNEL_SYMBOL("_lck_mtx_unlock", _lck_mtx_unlock)
93 |
94 | DEBUG_MSG("Locks %p and %p", _lck_mtx_lock, _lck_mtx_unlock);
95 |
96 | /* copy the function we want to clone into our cloned space */
97 | /* we need to disable kernel write protection to modify kext code - easier than calling mach_vm_protect */
98 | disable_interrupts();
99 | disable_wp();
100 | memcpy(cloned_csfg_get_platform_binary, (void*)_csfg_get_platform_binary, 100); // XXX: hardcoded size
101 |
102 | /* update first island - lck_mtx_lock */
103 | *(uint64_t*)(jump_island1 + 2) = (uint64_t)_lck_mtx_lock;
104 | /* update second island - lck_mtx_unlock */
105 | *(uint64_t*)(jump_island2 + 2) = (uint64_t)_lck_mtx_unlock;
106 |
107 | /* update calls to the islands in cloned function */
108 | *(int32_t*)(cloned_csfg_get_platform_binary + 0x1F) = (int32_t)(jump_island1 - (cloned_csfg_get_platform_binary + 0x1E + 5));
109 | *(int32_t*)(cloned_csfg_get_platform_binary + 0x48) = (int32_t)((jump_island2) - (cloned_csfg_get_platform_binary + 0x47 + 5));
110 |
111 | /* the original function returns csb_platform_binary
112 | * we patch it to return if uip->cs_blobs is NULL or not
113 | * meaning that it's code signed or not
114 | */
115 | *(int16_t*)(cloned_csfg_get_platform_binary + 0x41) = 0xC3FF; // inc ebx
116 | *(int8_t*)(cloned_csfg_get_platform_binary + 0x43) = 0x90; // ebx is then moved to eax and default is NULL
117 |
118 | /* and we are ready to continue */
119 | enable_wp();
120 | enable_interrupts();
121 | return KERN_SUCCESS;
122 | }
123 |
124 | /*
125 | * clone csproc_get_teamid, fix relocations, and patch it the way we need
126 | *
127 | * HARDCODED OFFSETS - Only valid for latest Yosemite 10.10.5
128 | *
129 | * This can be obviously improved using a disassembler but this is just a PoC
130 | * and things are stable enough to be ok this way
131 | *
132 | */
133 | kern_return_t
134 | clone_csproc_get_teamid(void)
135 | {
136 | DEBUG_MSG("Address of cloned_space is %p", (void*)cloned_csproc_get_teamid);
137 | DEBUG_MSG("Address of csproc_get_teamid is %p", (void*)_csproc_get_teamid);
138 | DEBUG_MSG("Jump island 3 address %p", (void*)jump_island3);
139 |
140 | /* copy the function we want to clone into our cloned space */
141 | /* we need to disable kernel write protection to modify kext code - easier than calling mach_vm_protect */
142 | disable_interrupts();
143 | disable_wp();
144 |
145 | /* clone _csproc_get_teamid and fix it with our patch */
146 | memcpy(cloned_csproc_get_teamid, (void*)_csproc_get_teamid, 100); // XXX: hardcoded size
147 |
148 | /* update _csproc_get_teamid island */
149 | *(uint64_t*)(jump_island3 + 2) = (uint64_t)_ubc_cs_blob_get;
150 | /* update calls to the islands in cloned function */
151 | *(int32_t*)(cloned_csproc_get_teamid + 0x29) = (int32_t)(jump_island3 - (cloned_csproc_get_teamid + 0x28 + 5));
152 |
153 | /* the original function returns a pointer
154 | * we modify it to return an int
155 | * 0 there's no code signing blob in current_proc() aka main binary not signed
156 | * 1 main binary is signed
157 | */
158 | *(uint32_t*)(cloned_csproc_get_teamid + 0x37) = 0x9090C0FF; // inc eax
159 |
160 | /* and we are ready to continue */
161 | enable_wp();
162 | enable_interrupts();
163 | return KERN_SUCCESS;
164 | }
165 |
--------------------------------------------------------------------------------
/Gatekeerper/cloned_functions.s:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * ('-. .-') _ ('-. .-. .-') ('-. ('-. _ .-') _ (`-. ('-. _ .-')
4 | * ( OO ).-.( OO) ) _( OO) \ ( OO ) _( OO) _( OO)( \( -O ) ( (OO ) _( OO)( \( -O )
5 | * ,----. / . --. // '._(,------.,--. ,--. (,------.(,------.,------. _.` \(,------.,------.
6 | * ' .-./-') | \-. \ |'--...__)| .---'| .' / | .---' | .---'| /`. '(__...--'' | .---'| /`. '
7 | * | |_( O- ).-'-' | |'--. .--'| | | /, | | | | | / | | | / | | | | | / | |
8 | * | | .--, \ \| |_.' | | | (| '--. | ' _)(| '--. (| '--. | |_.' | | |_.' |(| '--. | |_.' |
9 | * (| | '. (_/ | .-. | | | | .--' | . \ | .--' | .--' | . '.' | .___.' | .--' | . '.'
10 | * | '--' | | | | | | | | `---.| |\ \ | `---. | `---.| |\ \ | | | `---.| |\ \
11 | * `------' `--' `--' `--' `------'`--' '--' `------' `------'`--' '--' `--' `------'`--' '--'
12 | *
13 | * Gatekeerper
14 | * A kernel extension to mitigate Gatekeeper bypasses
15 | * Doesn't let linked (frameworks, libraries, bundles) unsigned code run if main binary is signed
16 | *
17 | * Untested with latest Gatekeeper bypass, too lazy to create a PoC of that
18 | * So I'm just guessing it will work, I'm pretty confident anyway :P
19 | *
20 | * Not guaranteed to be secure code! It might even destroy your computer but that is your problem!
21 | *
22 | * Created by reverser on 01/10/15.
23 | * Copyright (c) fG!, 2015. All rights reserved.
24 | * reverser@put.as - https://reverse.put.as
25 | *
26 | * cloned_functions.s
27 | *
28 | * Some lazy NOP space that can be used to copy cloned functions into
29 | * and jump islands for easily fixing the relocations
30 | * Easier and faster to do it this way than allocating memory, making it executable, and so on...
31 | *
32 | * Redistribution and use in source and binary forms, with or without
33 | * modification, are permitted provided that the following conditions
34 | * are met:
35 | * 1. Redistributions of source code must retain the above copyright
36 | * notice, this list of conditions and the following disclaimer.
37 | * 2. Redistributions in binary form must reproduce the above copyright
38 | * notice, this list of conditions and the following disclaimer in the
39 | * documentation and/or other materials provided with the distribution.
40 | * 3. The name of the author may not be used to endorse or promote products
41 | * derived from this software without specific prior written permission.
42 | *
43 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
44 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
45 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
46 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
47 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
48 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
49 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
50 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
51 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
52 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53 | *
54 | */
55 |
56 | .globl _cloned_csfg_get_platform_binary, _cloned_csproc_get_teamid, _jump_island1, _jump_island2, _jump_island3
57 |
58 | /* 1024 bytes space */
59 | /* 64 bytes each line */
60 | _cloned_csfg_get_platform_binary:
61 | .quad 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090
62 | .quad 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090
63 | .quad 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090
64 | .quad 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090
65 | .quad 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090
66 | .quad 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090
67 | .quad 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090
68 | .quad 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090
69 | .quad 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090
70 | .quad 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090
71 | .quad 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090
72 | .quad 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090
73 | .quad 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090
74 | .quad 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090
75 | .quad 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090
76 | .quad 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090
77 | /* unreachable */
78 | int3
79 |
80 | _cloned_csproc_get_teamid:
81 | .quad 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090
82 | .quad 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090
83 | .quad 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090
84 | .quad 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090
85 | .quad 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090
86 | .quad 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090
87 | .quad 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090
88 | .quad 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090
89 | .quad 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090
90 | .quad 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090
91 | .quad 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090
92 | .quad 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090
93 | .quad 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090
94 | .quad 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090
95 | .quad 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090
96 | .quad 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090, 0x9090909090909090
97 | /* unreachable */
98 | int3
99 |
100 | _jump_island1:
101 | movabsq $0, %rax
102 | jmp *%rax
103 | /* unreachable */
104 | int3
105 |
106 | _jump_island2:
107 | movabsq $0, %rax
108 | jmp *%rax
109 | /* unreachable */
110 | int3
111 |
112 | _jump_island3:
113 | movabsq $0, %rax
114 | jmp *%rax
115 | /* unreachable */
116 | int3
117 |
--------------------------------------------------------------------------------
/Gatekeerper/trustedbsd_hooks.c:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * ('-. .-') _ ('-. .-. .-') ('-. ('-. _ .-') _ (`-. ('-. _ .-')
4 | * ( OO ).-.( OO) ) _( OO) \ ( OO ) _( OO) _( OO)( \( -O ) ( (OO ) _( OO)( \( -O )
5 | * ,----. / . --. // '._(,------.,--. ,--. (,------.(,------.,------. _.` \(,------.,------.
6 | * ' .-./-') | \-. \ |'--...__)| .---'| .' / | .---' | .---'| /`. '(__...--'' | .---'| /`. '
7 | * | |_( O- ).-'-' | |'--. .--'| | | /, | | | | | / | | | / | | | | | / | |
8 | * | | .--, \ \| |_.' | | | (| '--. | ' _)(| '--. (| '--. | |_.' | | |_.' |(| '--. | |_.' |
9 | * (| | '. (_/ | .-. | | | | .--' | . \ | .--' | .--' | . '.' | .___.' | .--' | . '.'
10 | * | '--' | | | | | | | | `---.| |\ \ | `---. | `---.| |\ \ | | | `---.| |\ \
11 | * `------' `--' `--' `--' `------'`--' '--' `------' `------'`--' '--' `--' `------'`--' '--'
12 | *
13 | * Gatekeerper
14 | * A kernel extension to mitigate Gatekeeper bypasses
15 | * Doesn't let linked (frameworks, libraries, bundles) unsigned code run if main binary is signed
16 | *
17 | * Untested with latest Gatekeeper bypass, too lazy to create a PoC of that
18 | * So I'm just guessing it will work, I'm pretty confident anyway :P
19 | *
20 | * Not guaranteed to be secure code! It might even destroy your computer but that is your problem!
21 | *
22 | * Created by reverser on 01/10/15.
23 | * Copyright (c) fG!, 2015. All rights reserved.
24 | * reverser@put.as - https://reverse.put.as
25 | *
26 | * trustedbsd_hooks.c
27 | *
28 | * Functions to replace AMFI hooks and control unsigned code
29 | * Where all the magic happens!
30 | *
31 | * Redistribution and use in source and binary forms, with or without
32 | * modification, are permitted provided that the following conditions
33 | * are met:
34 | * 1. Redistributions of source code must retain the above copyright
35 | * notice, this list of conditions and the following disclaimer.
36 | * 2. Redistributions in binary form must reproduce the above copyright
37 | * notice, this list of conditions and the following disclaimer in the
38 | * documentation and/or other materials provided with the distribution.
39 | * 3. The name of the author may not be used to endorse or promote products
40 | * derived from this software without specific prior written permission.
41 | *
42 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
43 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
44 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
45 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
46 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
47 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
48 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
49 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
50 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
51 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52 | *
53 | */
54 |
55 | #include "trustedbsd_hooks.h"
56 |
57 | #include
58 | #include
59 | #include
60 | #include
61 | #include
62 | #include
63 | #include
64 | #define CONFIG_MACF 1
65 | #include
66 | #include
67 | #include
68 | #include
69 |
70 | #include "logging.h"
71 | #include "configuration.h"
72 | #include "kernel_symbols.h"
73 | #include "utils.h"
74 | #include "functions_clone.h"
75 |
76 | extern const int version_major;
77 | extern const int version_minor;
78 | extern char cloned_csfg_get_platform_binary[], cloned_csproc_get_teamid[];
79 |
80 | static void *original_amfi_hook = NULL;
81 | static int amfi_driver_position = -1;
82 |
83 | /* structures and definitions */
84 |
85 | /* NOTE: these structures are internal to TrustedBSD and not exposed in public includes */
86 | /* they are stable since the initial implementation but we still have some risk in defining them here */
87 | struct mac_policy_list_element {
88 | struct mac_policy_conf *mpc;
89 | };
90 |
91 | struct mac_policy_list {
92 | u_int numloaded;
93 | u_int max;
94 | u_int maxindex;
95 | u_int staticmax;
96 | u_int chunks;
97 | u_int freehint;
98 | struct mac_policy_list_element *entries;
99 | };
100 |
101 | typedef struct mac_policy_list mac_policy_list_t;
102 |
103 | mach_vm_address_t g_mac_policy_list; /* address of mac_policy_list kernel variable */
104 |
105 | /* the hook definition changed between Yosemite and El Capitan */
106 | typedef int mpo_file_check_mmap_14_t(
107 | kauth_cred_t cred,
108 | struct fileglob *fg,
109 | struct label *label,
110 | int prot,
111 | int flags,
112 | int *maxprot
113 | );
114 |
115 | mpo_file_check_mmap_14_t gatekeerper_hook_file_check_mmap_14;
116 |
117 | /* these are our modified prototypes for our modified cloned functions */
118 | typedef int csfg_get_platform_binary_t(struct fileglob *fg);
119 | typedef int csproc_get_teamid_t(struct proc *p);
120 |
121 | #pragma mark -
122 | #pragma mark Start and stop functions
123 |
124 | /*
125 | * replace Yosemite AMFI check_file_mmap hook with our own to control the mmap hook
126 | *
127 | */
128 | kern_return_t
129 | start_trustedbsd_hooks(void *d)
130 | {
131 | /* only support for Yosemite at the moment! */
132 | if (version_major != 14)
133 | {
134 | ERROR_MSG("Unsupported OS X version!");
135 | return KERN_FAILURE;
136 | }
137 |
138 | /* find where AMFI hooks are */
139 | /* Only relevant for Yosemite, El Capitan, and maybe higher */
140 | if (version_major == 14) // Yosemite
141 | {
142 | DEBUG_MSG("Replacing AMFI hook...");
143 |
144 | /* clone the functions we need inside our modified hook */
145 | if (clone_csfg_get_platform_binary() != KERN_SUCCESS)
146 | {
147 | ERROR_MSG("Can't clone csfg_get_platform_binary.");
148 | return KERN_FAILURE;
149 | }
150 | if (clone_csproc_get_teamid() != KERN_SUCCESS)
151 | {
152 | ERROR_MSG("Can't clone csproc_get_teamid.");
153 | return KERN_FAILURE;
154 | }
155 |
156 | /* we have the cloned functions ready
157 | * so next step is to exchange the AMFI hook with our version
158 | * that will use our cloned functions
159 | * and then return to the original AMFI hook
160 | */
161 |
162 | /* retrieve location of TrustedBSD base structure */
163 | SOLVE_KERNEL_VARIABLE("_mac_policy_list", g_mac_policy_list)
164 | /* find where AMFI is loaded */
165 | struct mac_policy_list policy_list = *(struct mac_policy_list*)g_mac_policy_list;
166 | for (int i = 0; i < policy_list.numloaded; i++)
167 | {
168 | struct mac_policy_conf *mpc = policy_list.entries[i].mpc;
169 | if (mpc != NULL)
170 | {
171 | if (strcmp(mpc->mpc_name, "AMFI") == 0)
172 | {
173 | DEBUG_MSG("Found AMFI driver %d.", i);
174 | amfi_driver_position = i;
175 | break;
176 | }
177 | }
178 | }
179 | /* if we don't know where AMFI is we can't do anything */
180 | if (amfi_driver_position == -1)
181 | {
182 | ERROR_MSG("No idea where AMFI position is. Can't proceed!");
183 | return KERN_FAILURE;
184 | }
185 |
186 | /* exchange hook inside AMFI driver */
187 | /* hook prototype changed between Yosemite and El Capitan */
188 | DEBUG_MSG("Ready to exchange AMFI hooks...");
189 | disable_interrupts();
190 | struct mac_policy_conf *temp = policy_list.entries[amfi_driver_position].mpc;
191 | struct mac_policy_ops *ops = temp->mpc_ops;
192 | switch (version_major) {
193 | case 14:
194 | {
195 | original_amfi_hook = (void*)ops->mpo_file_check_mmap;
196 | ops->mpo_file_check_mmap = (void*)gatekeerper_hook_file_check_mmap_14;
197 | break;
198 | }
199 | default:
200 | {
201 | ERROR_MSG("Unsupported OS X version.");
202 | enable_interrupts();
203 | return KERN_FAILURE;
204 | }
205 | }
206 | enable_interrupts();
207 | DEBUG_MSG("Replaced AMFI hook, Gatekeerper is now active.");
208 | return KERN_SUCCESS;
209 | }
210 |
211 | return KERN_FAILURE;
212 | }
213 |
214 | /* restore original AMFI hook */
215 | kern_return_t
216 | stop_trustedbsd_hooks(void)
217 | {
218 | if (version_major >= 14 && amfi_driver_position != -1)
219 | {
220 | disable_interrupts();
221 | struct mac_policy_list policy_list = *(struct mac_policy_list*)g_mac_policy_list;
222 | struct mac_policy_conf *temp = policy_list.entries[amfi_driver_position].mpc;
223 | struct mac_policy_ops *ops = temp->mpc_ops;
224 | switch (version_major) {
225 | case 14:
226 | {
227 | ops->mpo_file_check_mmap = (void*)original_amfi_hook;
228 | break;
229 | }
230 | default:
231 | {
232 | ERROR_MSG("Unsupported OS X version.");
233 | enable_interrupts();
234 | return KERN_FAILURE;
235 | }
236 | }
237 | enable_interrupts();
238 | DEBUG_MSG("AMFI original hook restored.");
239 | }
240 | return KERN_SUCCESS;
241 | }
242 |
243 | #pragma mark -
244 | #pragma mark The Hooks
245 |
246 | /* Our Yosemite AMFI hook*/
247 | int
248 | gatekeerper_hook_file_check_mmap_14(
249 | kauth_cred_t cred,
250 | struct fileglob *fg,
251 | struct label *label,
252 | int prot,
253 | int flags,
254 | int *maxprot
255 | )
256 | {
257 | char binary_path[MAXPATHLEN] = {0};
258 | int pathbuff_len = sizeof(binary_path);
259 |
260 | int result = 0;
261 |
262 | /* try to get some info about what is being mmap'ed */
263 | result = _csfg_get_path(fg, binary_path, &pathbuff_len);
264 | /* we only want to mess around with executable stuff */
265 | if (result == 0 && (prot & 0x4))
266 | {
267 | /* the platform binary field is not good enough for our purpose
268 | * so we need to use our cloned and patched functions
269 | * to understand if the mmap'ed binary is code signed
270 | * and if the main proc is also code signed
271 | *
272 | * not pretty but there's no full support in XNU to gather useful info from
273 | * code signing
274 | * It has improved in El Capitan but far from useful to external devs and hackers ;-)
275 | */
276 |
277 | /* first, get the status of the main proc */
278 | proc_t p = current_proc();
279 | if (p == (struct proc *)0)
280 | {
281 | ERROR_MSG("Can't retrieve current proc.");
282 | /* XXX: deny access */
283 | return 1;
284 | }
285 |
286 | /* verify is main process is signed or not
287 | * this could also be used to deny running any unsigned process
288 | */
289 | int is_main_signed = ((csproc_get_teamid_t*)(void*)(cloned_csproc_get_teamid))(p);
290 | /* just some debug code, can be removed */
291 | if (is_main_signed == 0)
292 | {
293 | DEBUG_MSG("current_proc is not signed");
294 | }
295 |
296 | /* verify if the binary code trying to be mapped is signed or not
297 | * we don't let unsigned code run if the main binary is signed
298 | */
299 | int is_mapped_signed = ((csfg_get_platform_binary_t*)cloned_csfg_get_platform_binary)(fg);
300 | if (is_mapped_signed == 0 && is_main_signed == 1)
301 | {
302 | ERROR_MSG("mmap'ed executable %s is not code signed for a signed main proc", binary_path);
303 | /* XXX: this will make the process crash because it can't load the linked external code */
304 | /* shouldn't we just kill it? we have current_proc() anyway */
305 | return 1;
306 | }
307 | }
308 | /* we can't get info about what is being mapped
309 | * what is the decision here? deny access?
310 | * for now just log the error and pass control to original AMFI hook
311 | */
312 | else if (result != 0)
313 | {
314 | ERROR_MSG("Failed to get path: %d", result);
315 | }
316 |
317 | /* pass control back to AMFI */
318 | return ((mpo_file_check_mmap_14_t*)original_amfi_hook)(cred, fg, label, prot, flags, maxprot);
319 | }
320 |
--------------------------------------------------------------------------------
/Gatekeerper.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 7B94C3F11BBDB0550084BCCE /* Gatekeerper.c in Sources */ = {isa = PBXBuildFile; fileRef = 7B94C3F01BBDB0550084BCCE /* Gatekeerper.c */; };
11 | 7B94C4271BBDB0A90084BCCE /* configuration.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B94C41D1BBDB0A90084BCCE /* configuration.h */; };
12 | 7B94C42B1BBDB0A90084BCCE /* kernel_symbols.c in Sources */ = {isa = PBXBuildFile; fileRef = 7B94C4211BBDB0A90084BCCE /* kernel_symbols.c */; };
13 | 7B94C42C1BBDB0A90084BCCE /* kernel_symbols.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B94C4221BBDB0A90084BCCE /* kernel_symbols.h */; };
14 | 7B94C42D1BBDB0A90084BCCE /* logging.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B94C4231BBDB0A90084BCCE /* logging.h */; };
15 | 7B94C42F1BBDB0A90084BCCE /* trustedbsd_hooks.c in Sources */ = {isa = PBXBuildFile; fileRef = 7B94C4251BBDB0A90084BCCE /* trustedbsd_hooks.c */; };
16 | 7B94C4301BBDB0A90084BCCE /* trustedbsd_hooks.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B94C4261BBDB0A90084BCCE /* trustedbsd_hooks.h */; };
17 | 7BAEA31D1BF0BB050002C5AC /* utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BAEA31B1BF0BB050002C5AC /* utils.c */; };
18 | 7BAEA31E1BF0BB050002C5AC /* utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BAEA31C1BF0BB050002C5AC /* utils.h */; };
19 | 7BF2AE151BC24FA400FD6D8B /* functions_clone.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BF2AE131BC24FA400FD6D8B /* functions_clone.c */; };
20 | 7BF2AE161BC24FA500FD6D8B /* functions_clone.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BF2AE141BC24FA400FD6D8B /* functions_clone.h */; };
21 | 7BF2AE181BC252DF00FD6D8B /* cloned_functions.s in Sources */ = {isa = PBXBuildFile; fileRef = 7BF2AE171BC252DF00FD6D8B /* cloned_functions.s */; };
22 | /* End PBXBuildFile section */
23 |
24 | /* Begin PBXFileReference section */
25 | 7B94C3ED1BBDB0550084BCCE /* Gatekeerper.kext */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Gatekeerper.kext; sourceTree = BUILT_PRODUCTS_DIR; };
26 | 7B94C3F01BBDB0550084BCCE /* Gatekeerper.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = Gatekeerper.c; sourceTree = ""; };
27 | 7B94C3F21BBDB0550084BCCE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
28 | 7B94C41D1BBDB0A90084BCCE /* configuration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = configuration.h; sourceTree = ""; };
29 | 7B94C4211BBDB0A90084BCCE /* kernel_symbols.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kernel_symbols.c; sourceTree = ""; };
30 | 7B94C4221BBDB0A90084BCCE /* kernel_symbols.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kernel_symbols.h; sourceTree = ""; };
31 | 7B94C4231BBDB0A90084BCCE /* logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = logging.h; sourceTree = ""; };
32 | 7B94C4251BBDB0A90084BCCE /* trustedbsd_hooks.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = trustedbsd_hooks.c; sourceTree = ""; };
33 | 7B94C4261BBDB0A90084BCCE /* trustedbsd_hooks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = trustedbsd_hooks.h; sourceTree = ""; };
34 | 7BAEA31B1BF0BB050002C5AC /* utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = utils.c; sourceTree = ""; };
35 | 7BAEA31C1BF0BB050002C5AC /* utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utils.h; sourceTree = ""; };
36 | 7BF2AE131BC24FA400FD6D8B /* functions_clone.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = functions_clone.c; sourceTree = ""; };
37 | 7BF2AE141BC24FA400FD6D8B /* functions_clone.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = functions_clone.h; sourceTree = ""; };
38 | 7BF2AE171BC252DF00FD6D8B /* cloned_functions.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = cloned_functions.s; sourceTree = ""; };
39 | /* End PBXFileReference section */
40 |
41 | /* Begin PBXFrameworksBuildPhase section */
42 | 7B94C3E91BBDB0550084BCCE /* Frameworks */ = {
43 | isa = PBXFrameworksBuildPhase;
44 | buildActionMask = 2147483647;
45 | files = (
46 | );
47 | runOnlyForDeploymentPostprocessing = 0;
48 | };
49 | /* End PBXFrameworksBuildPhase section */
50 |
51 | /* Begin PBXGroup section */
52 | 7B94C3E31BBDB0550084BCCE = {
53 | isa = PBXGroup;
54 | children = (
55 | 7B94C3EF1BBDB0550084BCCE /* Gatekeerper */,
56 | 7B94C3EE1BBDB0550084BCCE /* Products */,
57 | );
58 | sourceTree = "";
59 | };
60 | 7B94C3EE1BBDB0550084BCCE /* Products */ = {
61 | isa = PBXGroup;
62 | children = (
63 | 7B94C3ED1BBDB0550084BCCE /* Gatekeerper.kext */,
64 | );
65 | name = Products;
66 | sourceTree = "";
67 | };
68 | 7B94C3EF1BBDB0550084BCCE /* Gatekeerper */ = {
69 | isa = PBXGroup;
70 | children = (
71 | 7B94C3F01BBDB0550084BCCE /* Gatekeerper.c */,
72 | 7B94C41D1BBDB0A90084BCCE /* configuration.h */,
73 | 7B94C4231BBDB0A90084BCCE /* logging.h */,
74 | 7B94C4211BBDB0A90084BCCE /* kernel_symbols.c */,
75 | 7B94C4221BBDB0A90084BCCE /* kernel_symbols.h */,
76 | 7B94C4251BBDB0A90084BCCE /* trustedbsd_hooks.c */,
77 | 7B94C4261BBDB0A90084BCCE /* trustedbsd_hooks.h */,
78 | 7BF2AE131BC24FA400FD6D8B /* functions_clone.c */,
79 | 7BF2AE141BC24FA400FD6D8B /* functions_clone.h */,
80 | 7BAEA31B1BF0BB050002C5AC /* utils.c */,
81 | 7BAEA31C1BF0BB050002C5AC /* utils.h */,
82 | 7BF2AE171BC252DF00FD6D8B /* cloned_functions.s */,
83 | 7B94C3F21BBDB0550084BCCE /* Info.plist */,
84 | );
85 | path = Gatekeerper;
86 | sourceTree = "";
87 | };
88 | /* End PBXGroup section */
89 |
90 | /* Begin PBXHeadersBuildPhase section */
91 | 7B94C3EA1BBDB0550084BCCE /* Headers */ = {
92 | isa = PBXHeadersBuildPhase;
93 | buildActionMask = 2147483647;
94 | files = (
95 | 7BAEA31E1BF0BB050002C5AC /* utils.h in Headers */,
96 | 7B94C42D1BBDB0A90084BCCE /* logging.h in Headers */,
97 | 7BF2AE161BC24FA500FD6D8B /* functions_clone.h in Headers */,
98 | 7B94C42C1BBDB0A90084BCCE /* kernel_symbols.h in Headers */,
99 | 7B94C4271BBDB0A90084BCCE /* configuration.h in Headers */,
100 | 7B94C4301BBDB0A90084BCCE /* trustedbsd_hooks.h in Headers */,
101 | );
102 | runOnlyForDeploymentPostprocessing = 0;
103 | };
104 | /* End PBXHeadersBuildPhase section */
105 |
106 | /* Begin PBXNativeTarget section */
107 | 7B94C3EC1BBDB0550084BCCE /* Gatekeerper */ = {
108 | isa = PBXNativeTarget;
109 | buildConfigurationList = 7B94C3F51BBDB0550084BCCE /* Build configuration list for PBXNativeTarget "Gatekeerper" */;
110 | buildPhases = (
111 | 7B94C3E81BBDB0550084BCCE /* Sources */,
112 | 7B94C3E91BBDB0550084BCCE /* Frameworks */,
113 | 7B94C3EA1BBDB0550084BCCE /* Headers */,
114 | 7B94C3EB1BBDB0550084BCCE /* Resources */,
115 | );
116 | buildRules = (
117 | );
118 | dependencies = (
119 | );
120 | name = Gatekeerper;
121 | productName = Gatekeerper;
122 | productReference = 7B94C3ED1BBDB0550084BCCE /* Gatekeerper.kext */;
123 | productType = "com.apple.product-type.kernel-extension";
124 | };
125 | /* End PBXNativeTarget section */
126 |
127 | /* Begin PBXProject section */
128 | 7B94C3E41BBDB0550084BCCE /* Project object */ = {
129 | isa = PBXProject;
130 | attributes = {
131 | LastUpgradeCheck = 0700;
132 | ORGANIZATIONNAME = Put.as;
133 | TargetAttributes = {
134 | 7B94C3EC1BBDB0550084BCCE = {
135 | CreatedOnToolsVersion = 7.0.1;
136 | };
137 | };
138 | };
139 | buildConfigurationList = 7B94C3E71BBDB0550084BCCE /* Build configuration list for PBXProject "Gatekeerper" */;
140 | compatibilityVersion = "Xcode 3.2";
141 | developmentRegion = English;
142 | hasScannedForEncodings = 0;
143 | knownRegions = (
144 | en,
145 | );
146 | mainGroup = 7B94C3E31BBDB0550084BCCE;
147 | productRefGroup = 7B94C3EE1BBDB0550084BCCE /* Products */;
148 | projectDirPath = "";
149 | projectRoot = "";
150 | targets = (
151 | 7B94C3EC1BBDB0550084BCCE /* Gatekeerper */,
152 | );
153 | };
154 | /* End PBXProject section */
155 |
156 | /* Begin PBXResourcesBuildPhase section */
157 | 7B94C3EB1BBDB0550084BCCE /* Resources */ = {
158 | isa = PBXResourcesBuildPhase;
159 | buildActionMask = 2147483647;
160 | files = (
161 | );
162 | runOnlyForDeploymentPostprocessing = 0;
163 | };
164 | /* End PBXResourcesBuildPhase section */
165 |
166 | /* Begin PBXSourcesBuildPhase section */
167 | 7B94C3E81BBDB0550084BCCE /* Sources */ = {
168 | isa = PBXSourcesBuildPhase;
169 | buildActionMask = 2147483647;
170 | files = (
171 | 7B94C42F1BBDB0A90084BCCE /* trustedbsd_hooks.c in Sources */,
172 | 7B94C42B1BBDB0A90084BCCE /* kernel_symbols.c in Sources */,
173 | 7BF2AE181BC252DF00FD6D8B /* cloned_functions.s in Sources */,
174 | 7BAEA31D1BF0BB050002C5AC /* utils.c in Sources */,
175 | 7B94C3F11BBDB0550084BCCE /* Gatekeerper.c in Sources */,
176 | 7BF2AE151BC24FA400FD6D8B /* functions_clone.c in Sources */,
177 | );
178 | runOnlyForDeploymentPostprocessing = 0;
179 | };
180 | /* End PBXSourcesBuildPhase section */
181 |
182 | /* Begin XCBuildConfiguration section */
183 | 7B94C3F31BBDB0550084BCCE /* Debug */ = {
184 | isa = XCBuildConfiguration;
185 | buildSettings = {
186 | ALWAYS_SEARCH_USER_PATHS = NO;
187 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
188 | CLANG_CXX_LIBRARY = "libc++";
189 | CLANG_ENABLE_MODULES = YES;
190 | CLANG_ENABLE_OBJC_ARC = YES;
191 | CLANG_WARN_BOOL_CONVERSION = YES;
192 | CLANG_WARN_CONSTANT_CONVERSION = YES;
193 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
194 | CLANG_WARN_EMPTY_BODY = YES;
195 | CLANG_WARN_ENUM_CONVERSION = YES;
196 | CLANG_WARN_INT_CONVERSION = YES;
197 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
198 | CLANG_WARN_UNREACHABLE_CODE = YES;
199 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
200 | COPY_PHASE_STRIP = NO;
201 | DEBUG_INFORMATION_FORMAT = dwarf;
202 | ENABLE_STRICT_OBJC_MSGSEND = YES;
203 | ENABLE_TESTABILITY = YES;
204 | GCC_C_LANGUAGE_STANDARD = gnu99;
205 | GCC_DYNAMIC_NO_PIC = NO;
206 | GCC_NO_COMMON_BLOCKS = YES;
207 | GCC_OPTIMIZATION_LEVEL = 0;
208 | GCC_PREPROCESSOR_DEFINITIONS = (
209 | "DEBUG=1",
210 | "$(inherited)",
211 | );
212 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
213 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
214 | GCC_WARN_UNDECLARED_SELECTOR = YES;
215 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
216 | GCC_WARN_UNUSED_FUNCTION = YES;
217 | GCC_WARN_UNUSED_VARIABLE = YES;
218 | MACOSX_DEPLOYMENT_TARGET = 10.10;
219 | MTL_ENABLE_DEBUG_INFO = YES;
220 | ONLY_ACTIVE_ARCH = YES;
221 | SDKROOT = macosx;
222 | };
223 | name = Debug;
224 | };
225 | 7B94C3F41BBDB0550084BCCE /* Release */ = {
226 | isa = XCBuildConfiguration;
227 | buildSettings = {
228 | ALWAYS_SEARCH_USER_PATHS = NO;
229 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
230 | CLANG_CXX_LIBRARY = "libc++";
231 | CLANG_ENABLE_MODULES = YES;
232 | CLANG_ENABLE_OBJC_ARC = YES;
233 | CLANG_WARN_BOOL_CONVERSION = YES;
234 | CLANG_WARN_CONSTANT_CONVERSION = YES;
235 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
236 | CLANG_WARN_EMPTY_BODY = YES;
237 | CLANG_WARN_ENUM_CONVERSION = YES;
238 | CLANG_WARN_INT_CONVERSION = YES;
239 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
240 | CLANG_WARN_UNREACHABLE_CODE = YES;
241 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
242 | COPY_PHASE_STRIP = NO;
243 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
244 | ENABLE_NS_ASSERTIONS = NO;
245 | ENABLE_STRICT_OBJC_MSGSEND = YES;
246 | GCC_C_LANGUAGE_STANDARD = gnu99;
247 | GCC_NO_COMMON_BLOCKS = YES;
248 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
249 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
250 | GCC_WARN_UNDECLARED_SELECTOR = YES;
251 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
252 | GCC_WARN_UNUSED_FUNCTION = YES;
253 | GCC_WARN_UNUSED_VARIABLE = YES;
254 | MACOSX_DEPLOYMENT_TARGET = 10.10;
255 | MTL_ENABLE_DEBUG_INFO = NO;
256 | SDKROOT = macosx;
257 | };
258 | name = Release;
259 | };
260 | 7B94C3F61BBDB0550084BCCE /* Debug */ = {
261 | isa = XCBuildConfiguration;
262 | buildSettings = {
263 | CODE_SIGN_IDENTITY = "Mac Developer";
264 | INFOPLIST_FILE = Gatekeerper/Info.plist;
265 | MODULE_NAME = com.put.as.Gatekeerper;
266 | MODULE_START = Gatekeerper_start;
267 | MODULE_STOP = Gatekeerper_stop;
268 | MODULE_VERSION = 1.0.0d1;
269 | PRODUCT_BUNDLE_IDENTIFIER = com.put.as.Gatekeerper;
270 | PRODUCT_NAME = "$(TARGET_NAME)";
271 | WRAPPER_EXTENSION = kext;
272 | };
273 | name = Debug;
274 | };
275 | 7B94C3F71BBDB0550084BCCE /* Release */ = {
276 | isa = XCBuildConfiguration;
277 | buildSettings = {
278 | CODE_SIGN_IDENTITY = "Mac Developer";
279 | INFOPLIST_FILE = Gatekeerper/Info.plist;
280 | MODULE_NAME = com.put.as.Gatekeerper;
281 | MODULE_START = Gatekeerper_start;
282 | MODULE_STOP = Gatekeerper_stop;
283 | MODULE_VERSION = 1.0.0d1;
284 | PRODUCT_BUNDLE_IDENTIFIER = com.put.as.Gatekeerper;
285 | PRODUCT_NAME = "$(TARGET_NAME)";
286 | WRAPPER_EXTENSION = kext;
287 | };
288 | name = Release;
289 | };
290 | /* End XCBuildConfiguration section */
291 |
292 | /* Begin XCConfigurationList section */
293 | 7B94C3E71BBDB0550084BCCE /* Build configuration list for PBXProject "Gatekeerper" */ = {
294 | isa = XCConfigurationList;
295 | buildConfigurations = (
296 | 7B94C3F31BBDB0550084BCCE /* Debug */,
297 | 7B94C3F41BBDB0550084BCCE /* Release */,
298 | );
299 | defaultConfigurationIsVisible = 0;
300 | defaultConfigurationName = Release;
301 | };
302 | 7B94C3F51BBDB0550084BCCE /* Build configuration list for PBXNativeTarget "Gatekeerper" */ = {
303 | isa = XCConfigurationList;
304 | buildConfigurations = (
305 | 7B94C3F61BBDB0550084BCCE /* Debug */,
306 | 7B94C3F71BBDB0550084BCCE /* Release */,
307 | );
308 | defaultConfigurationIsVisible = 0;
309 | defaultConfigurationName = Release;
310 | };
311 | /* End XCConfigurationList section */
312 | };
313 | rootObject = 7B94C3E41BBDB0550084BCCE /* Project object */;
314 | }
315 |
--------------------------------------------------------------------------------
/Gatekeerper/kernel_symbols.c:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * ('-. .-') _ ('-. .-. .-') ('-. ('-. _ .-') _ (`-. ('-. _ .-')
4 | * ( OO ).-.( OO) ) _( OO) \ ( OO ) _( OO) _( OO)( \( -O ) ( (OO ) _( OO)( \( -O )
5 | * ,----. / . --. // '._(,------.,--. ,--. (,------.(,------.,------. _.` \(,------.,------.
6 | * ' .-./-') | \-. \ |'--...__)| .---'| .' / | .---' | .---'| /`. '(__...--'' | .---'| /`. '
7 | * | |_( O- ).-'-' | |'--. .--'| | | /, | | | | | / | | | / | | | | | / | |
8 | * | | .--, \ \| |_.' | | | (| '--. | ' _)(| '--. (| '--. | |_.' | | |_.' |(| '--. | |_.' |
9 | * (| | '. (_/ | .-. | | | | .--' | . \ | .--' | .--' | . '.' | .___.' | .--' | . '.'
10 | * | '--' | | | | | | | | `---.| |\ \ | `---. | `---.| |\ \ | | | `---.| |\ \
11 | * `------' `--' `--' `--' `------'`--' '--' `------' `------'`--' '--' `--' `------'`--' '--'
12 | *
13 | * Gatekeerper
14 | * A kernel extension to mitigate Gatekeeper bypasses
15 | * Doesn't let linked (frameworks, libraries, bundles) unsigned code run if main binary is signed
16 | *
17 | * Untested with latest Gatekeeper bypass, too lazy to create a PoC of that
18 | * So I'm just guessing it will work, I'm pretty confident anyway :P
19 | *
20 | * Not guaranteed to be secure code! It might even destroy your computer but that is your problem!
21 | *
22 | * Created by reverser on 01/10/15.
23 | * Copyright (c) fG!, 2015. All rights reserved.
24 | * reverser@put.as - https://reverse.put.as
25 | *
26 | * kernel_symbols.c
27 | *
28 | * Functions to solve kernel symbols
29 | *
30 | * Redistribution and use in source and binary forms, with or without
31 | * modification, are permitted provided that the following conditions
32 | * are met:
33 | * 1. Redistributions of source code must retain the above copyright
34 | * notice, this list of conditions and the following disclaimer.
35 | * 2. Redistributions in binary form must reproduce the above copyright
36 | * notice, this list of conditions and the following disclaimer in the
37 | * documentation and/or other materials provided with the distribution.
38 | * 3. The name of the author may not be used to endorse or promote products
39 | * derived from this software without specific prior written permission.
40 | *
41 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
42 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
43 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
44 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
45 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
47 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
48 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
49 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
50 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51 | *
52 | */
53 |
54 | #include "kernel_symbols.h"
55 |
56 | #include
57 | #include
58 | #include
59 | #include
60 | #include
61 | #include
62 | #include
63 | #include
64 | #include
65 |
66 | #include "logging.h"
67 |
68 | /* location of kernel in filesystem */
69 | #define MACH_KERNEL "/System/Library/Kernels/kernel"
70 |
71 | /* structures and definitions */
72 | /* 16 bytes IDT descriptor, used for 32 and 64 bits kernels (64 bit capable cpus!) */
73 | struct descriptor_idt
74 | {
75 | uint16_t offset_low;
76 | uint16_t seg_selector;
77 | uint8_t reserved;
78 | uint8_t flag;
79 | uint16_t offset_middle;
80 | uint32_t offset_high;
81 | uint32_t reserved2;
82 | };
83 |
84 | /* global variables */
85 | /* kernel symbols to be manually solved */
86 | int (*_csfg_get_path)(struct fileglob *fg, char *path, int *len);
87 | const char * (*_csfg_get_teamid)(struct fileglob *fg);
88 | int (*_csfg_get_platform_binary)(struct fileglob *fg);
89 | struct cs_blob * (*_csproc_get_blob)(struct proc *p);
90 | const char * (*_csproc_get_teamid)(struct proc *p);
91 | struct cs_blob * (*_ubc_cs_blob_get)(struct vnode *vp, cpu_type_t cputype, off_t offset);
92 |
93 | /* external global variables */
94 | extern struct kernel_info g_kinfo;
95 |
96 | /* local functions */
97 | static kern_return_t get_kernel_mach_header(void *buffer, vnode_t kernel_vnode);
98 | static kern_return_t process_kernel_mach_header(void *kernel_header, struct kernel_info *kinfo);
99 | static kern_return_t get_kernel_linkedit(vnode_t kernel_vnode, struct kernel_info *kinfo);
100 | static mach_vm_address_t calculate_int80address(const mach_vm_address_t idt_address);
101 | static kern_return_t get_running_text_address(struct kernel_info *kinfo);
102 | static mach_vm_address_t find_kernel_base(const mach_vm_address_t int80_address);
103 | static void get_addr_idt (mach_vm_address_t* idt);
104 |
105 | # pragma mark Exported functions
106 |
107 | /*
108 | * entrypoint function to read necessary information from running kernel and kernel at disk
109 | * such as kaslr slide, linkedit location
110 | * the reads from disk are implemented using the available KPI VFS functions
111 | */
112 | kern_return_t
113 | init_kernel_info(void)
114 | {
115 | struct kernel_info *kinfo = &g_kinfo;
116 | /* lookup vnode for /mach_kernel - remember to free reference count if successful */
117 | vnode_t kernel_vnode = NULLVP;
118 | /*
119 | * if we want to put the driver booting very early we need to create our own context
120 | * instead of passing NULL as usual
121 | * the reference count increases so we must release it later
122 | * the vfs_context_create() call is valid because it's made in a process context
123 | */
124 | vfs_context_t myvfs_context = vfs_context_create(NULL);
125 | if (myvfs_context == NULL)
126 | {
127 | ERROR_MSG("Failed to create context.");
128 | return KERN_FAILURE;
129 | }
130 | /* try to locate the kernel in one of the two valid locations */
131 | kern_return_t kr = 0;
132 | kr = vnode_lookup(MACH_KERNEL, 0, &kernel_vnode, myvfs_context);
133 | if (kr != KERN_SUCCESS)
134 | {
135 | ERROR_MSG("Kernel vnode lookup failed!");
136 | vfs_context_rele(myvfs_context);
137 | return KERN_FAILURE;
138 | }
139 |
140 | /* from this point failure is handled by goto failure; */
141 |
142 | /*
143 | * the first thing we do is to read 4k of the kernel header so we can extract
144 | * a bunch of information and __LINKEDIT location
145 | */
146 | void *kernel_header = _MALLOC(PAGE_SIZE_64, M_TEMP, M_WAITOK | M_ZERO);
147 | if (kernel_header == NULL)
148 | {
149 | ERROR_MSG("Can't allocate memory for initial kernel mach-o header.");
150 | goto failure;
151 | }
152 |
153 | if (get_kernel_mach_header(kernel_header, kernel_vnode) != KERN_SUCCESS)
154 | {
155 | ERROR_MSG("Failed to get initial kernel mach-o header!");
156 | goto failure;
157 | }
158 | if (process_kernel_mach_header(kernel_header, kinfo) != KERN_SUCCESS)
159 | {
160 | ERROR_MSG("Failed to process kernel mach-o header!");
161 | goto failure;
162 | }
163 |
164 | /* compute kaslr slide - difference between __TEXT in memory and disk*/
165 | if (get_running_text_address(kinfo) != KERN_SUCCESS)
166 | {
167 | ERROR_MSG("Can't find kernel's running text address!");
168 | goto failure;
169 | }
170 | kinfo->kaslr_slide = kinfo->memory_text_addr - kinfo->disk_text_addr;
171 | if (kinfo->kaslr_slide > kinfo->memory_text_addr)
172 | {
173 | ERROR_MSG("overflow?");
174 | goto failure;
175 | }
176 |
177 | DEBUG_MSG("Kernel ASLR slide: 0x%llx", kinfo->kaslr_slide);
178 | /*
179 | * we know the location of linkedit and offsets into symbols and their strings
180 | * now we need to read linkedit into a buffer so we can process it later
181 | * __LINKEDIT total size is around 1MB
182 | * we should free this buffer later when we don't need anymore to solve symbols
183 | */
184 | kinfo->linkedit_buf = _MALLOC(kinfo->linkedit_size, M_TEMP, M_WAITOK | M_ZERO);
185 | if (kinfo->linkedit_buf == NULL)
186 | {
187 | ERROR_MSG("Could not allocate enough memory for __LINKEDIT segment");
188 | goto failure;
189 | }
190 | if (get_kernel_linkedit(kernel_vnode, kinfo) != KERN_SUCCESS)
191 | {
192 | ERROR_MSG("Failed to get kernel linkedit info!");
193 | goto failure;
194 | }
195 |
196 | success:
197 | /* kinfo->linkedit_buf should be freed by the caller */
198 | _FREE(kernel_header, M_TEMP);
199 | /*
200 | * drop the iocount due to vnode_lookup()
201 | * we must do this else machine will block on shutdown/reboot
202 | */
203 | vnode_put(kernel_vnode);
204 | vfs_context_rele(myvfs_context);
205 | return KERN_SUCCESS;
206 |
207 | failure:
208 | if (kinfo->linkedit_buf)
209 | {
210 | _FREE(kinfo->linkedit_buf, M_TEMP);
211 | }
212 | if (kernel_header)
213 | {
214 | _FREE(kernel_header, M_TEMP);
215 | }
216 | vnode_put(kernel_vnode);
217 | vfs_context_rele(myvfs_context);
218 | return KERN_FAILURE;
219 | }
220 |
221 | /*
222 | * cleanup the kernel info buffer to avoid memory leak.
223 | * there's nothing else to cleanup here, for now
224 | */
225 | kern_return_t
226 | cleanup_kernel_info(void)
227 | {
228 | DEBUG_MSG("Cleaning up kernel info...");
229 | if (g_kinfo.linkedit_buf)
230 | {
231 | _FREE(g_kinfo.linkedit_buf, M_TEMP);
232 | }
233 | DEBUG_MSG("All done cleaning up kernel info.");
234 | return KERN_SUCCESS;
235 | }
236 |
237 | /*
238 | * function to solve a kernel symbol, 64 bits kernels support ONLY!
239 | */
240 | kern_return_t
241 | solve_kernel_symbol(char *symbol_to_solve, void **symbol_ptr)
242 | {
243 | if (symbol_to_solve == NULL || symbol_ptr == NULL)
244 | {
245 | ERROR_MSG("Bad parameters!");
246 | return KERN_FAILURE;
247 | }
248 |
249 | struct kernel_info *kinfo = &g_kinfo;
250 | struct nlist_64 *nlist = NULL;
251 |
252 | if (kinfo == NULL || kinfo->linkedit_buf == NULL)
253 | {
254 | ERROR_MSG("g_kernel_info is null or no kernel __LINKEDIT buffer available!");
255 | return KERN_FAILURE;
256 | }
257 | // symbols and strings offsets into LINKEDIT
258 | // we just read the __LINKEDIT but fileoff values are relative to the full /mach_kernel
259 | // subtract the base of LINKEDIT to fix the value into our buffer
260 | mach_vm_address_t symbol_off = kinfo->symboltable_fileoff - kinfo->linkedit_fileoff;
261 | mach_vm_address_t string_off = kinfo->stringtable_fileoff - kinfo->linkedit_fileoff;
262 | if (symbol_off > kinfo->symboltable_fileoff || string_off > kinfo->stringtable_fileoff)
263 | {
264 | ERROR_MSG("overflow?");
265 | return KERN_FAILURE;
266 |
267 | }
268 | // search for the symbol and get its location if found
269 | for (uint32_t i = 0; i < kinfo->symboltable_nr_symbols; i++)
270 | {
271 | // get the pointer to the symbol entry and extract its symbol string
272 | nlist = (struct nlist_64*)((char*)kinfo->linkedit_buf + symbol_off + i * sizeof(struct nlist_64));
273 | char *symbol_string = ((char*)kinfo->linkedit_buf + string_off + nlist->n_un.n_strx);
274 | // find if symbol matches
275 | if (strncmp(symbol_to_solve, symbol_string, strlen(symbol_to_solve)) == 0)
276 | {
277 | /* the symbols values are without kernel ASLR so we need to add it */
278 | mach_vm_address_t solved_addr = nlist->n_value + kinfo->kaslr_slide;
279 | /* verify if symbol is in the kernel __text section */
280 | mach_vm_address_t floor = kinfo->memory_text_addr;
281 | mach_vm_address_t cap = kinfo->memory_text_addr + kinfo->text_size;
282 | if (solved_addr < floor || solved_addr > cap)
283 | {
284 | ERROR_MSG("Solved symbol address doesn't belong to running __text section. Something is wrong!");
285 | return KERN_FAILURE;
286 | }
287 | *symbol_ptr = (void*)solved_addr;
288 | return KERN_SUCCESS;
289 | }
290 | }
291 | /* failure */
292 | ERROR_MSG("Failed to solve symbol %s", symbol_to_solve);
293 | return KERN_FAILURE;
294 | }
295 |
296 | /*
297 | * function to solve a kernel variable symbol, 64 bits kernels support ONLY!
298 | */
299 | kern_return_t
300 | solve_kernel_variable(char *symbol_to_solve, mach_vm_address_t *output)
301 | {
302 | if (symbol_to_solve == NULL || output == NULL)
303 | {
304 | ERROR_MSG("Bad parameters!");
305 | return KERN_FAILURE;
306 | }
307 |
308 | struct kernel_info *kinfo = &g_kinfo;
309 | struct nlist_64 *nlist = NULL;
310 |
311 | if (kinfo == NULL || kinfo->linkedit_buf == NULL)
312 | {
313 | ERROR_MSG("g_kernel_info is null or no kernel __LINKEDIT buffer available!");
314 | return KERN_FAILURE;
315 | }
316 | /* symbols and strings offsets into LINKEDIT
317 | * we just read the __LINKEDIT but fileoff values are relative to the full /mach_kernel
318 | * subtract the base of LINKEDIT to fix the value into our buffer
319 | */
320 | mach_vm_address_t symbol_off = kinfo->symboltable_fileoff - kinfo->linkedit_fileoff;
321 | mach_vm_address_t string_off = kinfo->stringtable_fileoff - kinfo->linkedit_fileoff;
322 | if (symbol_off > kinfo->symboltable_fileoff || string_off > kinfo->stringtable_fileoff)
323 | {
324 | ERROR_MSG("overflow?");
325 | return KERN_FAILURE;
326 |
327 | }
328 | /* search for the symbol and get its location if found */
329 | for (uint32_t i = 0; i < kinfo->symboltable_nr_symbols; i++)
330 | {
331 | /* get the pointer to the symbol entry and extract its symbol string */
332 | nlist = (struct nlist_64*)((char*)kinfo->linkedit_buf + symbol_off + i * sizeof(struct nlist_64));
333 | char *symbol_string = ((char*)kinfo->linkedit_buf + string_off + nlist->n_un.n_strx);
334 | /* find if symbol matches */
335 | if (strncmp(symbol_to_solve, symbol_string, strlen(symbol_to_solve)) == 0)
336 | {
337 | /* the symbols values are without kernel ASLR so we need to add it */
338 | mach_vm_address_t solved_addr = nlist->n_value + kinfo->kaslr_slide;
339 | /* verify if symbol is in the kernel __DATA segment */
340 | /* we are less precise than in solve_kernel_symbol() */
341 | mach_vm_address_t floor = kinfo->disk_DATA_addr + kinfo->kaslr_slide;
342 | mach_vm_address_t cap = floor + kinfo->DATA_size;
343 | if (solved_addr < floor || solved_addr > cap)
344 | {
345 | ERROR_MSG("Solved symbol address doesn't belong to running __DATA segment. Something is wrong!");
346 | return KERN_FAILURE;
347 | }
348 | *output = solved_addr;
349 | return KERN_SUCCESS;
350 | }
351 | }
352 | /* failure */
353 | ERROR_MSG("Failed to solve variable symbol %s", symbol_to_solve);
354 | return KERN_FAILURE;
355 | }
356 |
357 | #pragma mark Internal helper functions
358 |
359 | /*
360 | * retrieve the first page of kernel binary at disk into a buffer
361 | * version that uses KPI VFS functions and a ripped uio_createwithbuffer() from XNU
362 | * if it's a FAT kernel we locate the 64 bits kernel offset and reread to the same buffer
363 | * so the buffer always end with a 64 bits kernel or error
364 | */
365 | static kern_return_t
366 | get_kernel_mach_header(void *buffer, vnode_t kernel_vnode)
367 | {
368 | if (buffer == NULL || kernel_vnode == NULL)
369 | {
370 | ERROR_MSG("Bad parameters!");
371 | return KERN_FAILURE;
372 | }
373 |
374 | int error = 0;
375 |
376 | uio_t uio = NULL;
377 | uio = uio_create(1, 0, UIO_SYSSPACE, UIO_READ);
378 | if (uio == NULL)
379 | {
380 | ERROR_MSG("uio_create returned null!");
381 | return KERN_FAILURE;
382 | }
383 | // imitate the kernel and read a single page from the header
384 | if ( (error = uio_addiov(uio, CAST_USER_ADDR_T(buffer), PAGE_SIZE_64)) )
385 | {
386 | ERROR_MSG("uio_addiov returned error %d!", error);
387 | return KERN_FAILURE;
388 | }
389 | /* create a context - OS X 10.10 finally removed the "feature" to pass NULL */
390 | vfs_context_t context = vfs_context_create(NULL);
391 | if (context == NULL)
392 | {
393 | ERROR_MSG("Can't create context.");
394 | return KERN_FAILURE;
395 | }
396 | // read kernel vnode into the buffer
397 | if ( (error = VNOP_READ(kernel_vnode, uio, 0, context)) )
398 | {
399 | ERROR_MSG("VNOP_READ failed %d!", error);
400 | vfs_context_rele(context);
401 | return KERN_FAILURE;
402 | }
403 | else if (uio_resid(uio))
404 | {
405 | ERROR_MSG("uio_resid!");
406 | vfs_context_rele(context);
407 | return KERN_FAILURE;
408 | }
409 |
410 | vfs_context_rele(context);
411 | return KERN_SUCCESS;
412 | }
413 |
414 | /*
415 | * retrieve the whole linkedit segment into target buffer from kernel binary at disk
416 | * we keep this buffer until we don't need to solve symbols anymore
417 | */
418 | static kern_return_t
419 | get_kernel_linkedit(vnode_t kernel_vnode, struct kernel_info *kinfo)
420 | {
421 | if (kernel_vnode == NULL || kinfo == NULL)
422 | {
423 | ERROR_MSG("Bad parameters!");
424 | return KERN_FAILURE;
425 | }
426 |
427 | int error = 0;
428 | uio_t uio = NULL;
429 | uio = uio_create(1, kinfo->linkedit_fileoff, UIO_SYSSPACE, UIO_READ);
430 | if (uio == NULL)
431 | {
432 | ERROR_MSG("uio_create returned null!");
433 | return KERN_FAILURE;
434 | }
435 | if ( (error = uio_addiov(uio, CAST_USER_ADDR_T(kinfo->linkedit_buf), kinfo->linkedit_size)) )
436 | {
437 | ERROR_MSG("uio_addiov returned error %d!", error);
438 | return KERN_FAILURE;
439 | }
440 | /* create a context - OS X 10.10 finally removed the "feature" to pass NULL */
441 | vfs_context_t context = vfs_context_create(NULL);
442 | if (context == NULL)
443 | {
444 | ERROR_MSG("Can't create context.");
445 | return KERN_FAILURE;
446 | }
447 | if ( (error = VNOP_READ(kernel_vnode, uio, 0, context)) )
448 | {
449 | ERROR_MSG("VNOP_READ failed %d!", error);
450 | vfs_context_rele(context);
451 | return KERN_FAILURE;
452 | }
453 | else if (uio_resid(uio))
454 | {
455 | ERROR_MSG("uio_resid!");
456 | vfs_context_rele(context);
457 | return KERN_FAILURE;
458 | }
459 | vfs_context_rele(context);
460 | return KERN_SUCCESS;
461 | }
462 |
463 | /*
464 | * retrieve necessary mach-o header information from the kernel buffer
465 | * stored at our kernel_info structure
466 | * NOTE: we only process 64 bits kernels
467 | */
468 | static kern_return_t
469 | process_kernel_mach_header(void *kernel_header, struct kernel_info *kinfo)
470 | {
471 | if (kernel_header == NULL || kinfo == NULL)
472 | {
473 | ERROR_MSG("Bad parameters!");
474 | return KERN_FAILURE;
475 | }
476 |
477 | struct mach_header_64 *mh = (struct mach_header_64*)kernel_header;
478 | if (mh->magic != MH_MAGIC_64)
479 | {
480 | ERROR_MSG("Kernel is not 64bits!");
481 | return KERN_FAILURE;
482 | }
483 | if (mh->ncmds == 0 || mh->sizeofcmds == 0)
484 | {
485 | ERROR_MSG("Invalid kernel file");
486 | return KERN_FAILURE;
487 | }
488 |
489 | struct load_command *load_cmd = NULL;
490 | /* point to the first load command */
491 | char *load_cmd_addr = (char*)kernel_header + sizeof(struct mach_header_64);
492 | /* iterate over all load cmds and retrieve required info to solve symbols */
493 | /* __LINKEDIT location and symbol/string table location */
494 | for (uint32_t i = 0; i < mh->ncmds; i++)
495 | {
496 | load_cmd = (struct load_command*)load_cmd_addr;
497 | if (load_cmd->cmd == LC_SEGMENT_64)
498 | {
499 | struct segment_command_64 *seg_cmd = (struct segment_command_64*)load_cmd;
500 | /* use this one to retrieve the original vm address of __TEXT so we can compute kernel aslr slide */
501 | if (strncmp(seg_cmd->segname, "__TEXT", sizeof(seg_cmd->segname)) == 0)
502 | {
503 | kinfo->disk_text_addr = seg_cmd->vmaddr;
504 | kinfo->text_size = seg_cmd->vmsize;
505 | }
506 | else if (strncmp(seg_cmd->segname, "__DATA", sizeof(seg_cmd->segname)) == 0)
507 | {
508 | kinfo->disk_DATA_addr = seg_cmd->vmaddr;
509 | kinfo->DATA_size = seg_cmd->vmsize;
510 | }
511 | else if (strncmp(seg_cmd->segname, "__LINKEDIT", sizeof(seg_cmd->segname)) == 0)
512 | {
513 | kinfo->linkedit_fileoff = seg_cmd->fileoff;
514 | kinfo->linkedit_size = seg_cmd->filesize;
515 | }
516 | }
517 | /* table information available at LC_SYMTAB command */
518 | else if (load_cmd->cmd == LC_SYMTAB)
519 | {
520 | struct symtab_command *symtab_cmd = (struct symtab_command*)load_cmd;
521 | kinfo->symboltable_fileoff = symtab_cmd->symoff;
522 | kinfo->symboltable_nr_symbols = symtab_cmd->nsyms;
523 | kinfo->stringtable_fileoff = symtab_cmd->stroff;
524 | kinfo->stringtable_size = symtab_cmd->strsize;
525 | }
526 | load_cmd_addr += load_cmd->cmdsize;
527 | }
528 | return KERN_SUCCESS;
529 | }
530 |
531 | /*
532 | * retrieve the __TEXT address of current loaded kernel so we can compute the KASLR slide
533 | * also the size of __text
534 | * NOTE: only processing 64 bits kernels!
535 | */
536 | static kern_return_t
537 | get_running_text_address(struct kernel_info *kinfo)
538 | {
539 | if (kinfo == NULL)
540 | {
541 | ERROR_MSG("Bad parameters!");
542 | return KERN_FAILURE;
543 | }
544 |
545 | /* retrieves the address of the IDT */
546 | mach_vm_address_t idt_address = 0;
547 | get_addr_idt(&idt_address);
548 | /* calculate the address of the int80 handler */
549 | mach_vm_address_t int80_address = calculate_int80address(idt_address);
550 | /* search backwards for the kernel base address (mach-o header) */
551 | mach_vm_address_t kernel_base = find_kernel_base(int80_address);
552 | if (kernel_base != 0)
553 | {
554 | /* get the vm address of __TEXT segment */
555 | struct mach_header_64 *mh = (struct mach_header_64*)kernel_base;
556 | struct load_command *load_cmd = NULL;
557 | char *load_cmd_addr = (char*)kernel_base + sizeof(struct mach_header_64);
558 | for (uint32_t i = 0; i < mh->ncmds; i++)
559 | {
560 | load_cmd = (struct load_command*)load_cmd_addr;
561 | if (load_cmd->cmd == LC_SEGMENT_64)
562 | {
563 | struct segment_command_64 *seg_cmd = (struct segment_command_64*)load_cmd;
564 | if (strncmp(seg_cmd->segname, "__TEXT", sizeof(seg_cmd->segname)) == 0)
565 | {
566 | kinfo->memory_text_addr = seg_cmd->vmaddr;
567 | return KERN_SUCCESS;
568 | }
569 | }
570 | load_cmd_addr += load_cmd->cmdsize;
571 | }
572 | }
573 | return KERN_FAILURE;
574 | }
575 |
576 | /* calculate the address of the kernel int80 handler using the IDT array */
577 | static mach_vm_address_t
578 | calculate_int80address(const mach_vm_address_t idt_address)
579 | {
580 | if (idt_address == 0)
581 | {
582 | ERROR_MSG("Bogus idt address paramenter!");
583 | return 0;
584 | }
585 | /* find the address of interrupt 0x80 - EXCEP64_SPC_USR(0x80,hi64_unix_scall) @ osfmk/i386/idt64.s */
586 | struct descriptor_idt *int80_descriptor = NULL;
587 | mach_vm_address_t int80_address = 0;
588 | // we need to compute the address, it's not direct
589 | // extract the stub address
590 | // retrieve the descriptor for interrupt 0x80
591 | // the IDT is an array of descriptors
592 | int80_descriptor = (struct descriptor_idt*)(idt_address + sizeof(struct descriptor_idt)*0x80);
593 | uint64_t high = (unsigned long)int80_descriptor->offset_high << 32;
594 | uint32_t middle = (unsigned int)int80_descriptor->offset_middle << 16;
595 | int80_address = (mach_vm_address_t)(high + middle + int80_descriptor->offset_low);
596 | return int80_address;
597 | }
598 |
599 | /*
600 | * find the kernel base address (mach-o header)
601 | * by searching backwards using the int80 handler as starting point
602 | */
603 | static mach_vm_address_t
604 | find_kernel_base(const mach_vm_address_t int80_address)
605 | {
606 | if (int80_address == 0)
607 | {
608 | ERROR_MSG("Bogus int80 address!");
609 | return 0;
610 | }
611 | mach_vm_address_t temp_address = int80_address;
612 | struct segment_command_64 *segment_command = NULL;
613 | struct mach_header_64 *mh = NULL;
614 | while (temp_address > 0)
615 | {
616 | mh = (struct mach_header_64*)temp_address;
617 | if (mh->magic == MH_MAGIC_64 && mh->filetype == MH_EXECUTE && mh->ncmds > 0 && mh->sizeofcmds > 0)
618 | {
619 | /* make sure it's the header and not some reference to the MAGIC number */
620 | segment_command = (struct segment_command_64*)(temp_address + sizeof(struct mach_header_64));
621 | if (strncmp(segment_command->segname, "__TEXT", sizeof(segment_command->segname)) == 0)
622 | {
623 | return temp_address;
624 | }
625 | }
626 | /* check for int overflow */
627 | if (temp_address - 1 > temp_address)
628 | {
629 | break;
630 | }
631 | temp_address--;
632 | }
633 | return 0;
634 | }
635 |
636 | /* retrieve the address of the IDT */
637 | static void
638 | get_addr_idt(mach_vm_address_t *idt)
639 | {
640 | if (idt == NULL)
641 | {
642 | ERROR_MSG("Bad parameters!");
643 | return;
644 | }
645 |
646 | uint8_t idtr[10] = {0};
647 | __asm__ volatile ("sidt %0": "=m" (idtr));
648 | *idt = *(mach_vm_address_t *)(idtr+2);
649 | }
650 |
--------------------------------------------------------------------------------