mirror of
https://github.com/Karmaz95/Snake_Apple.git
synced 2026-04-09 14:42:03 +02:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d3b1e459ec | ||
|
|
d0d8b8a471 | ||
|
|
13c8587f28 | ||
|
|
ea0d485e57 | ||
|
|
acaa13158b | ||
|
|
464f5317ae | ||
|
|
73bf3b3aa0 | ||
|
|
ba7fdc92f2 | ||
|
|
c8425c8430 | ||
|
|
bf82224406 | ||
|
|
c5c1aeef65 | ||
|
|
6b614c778e | ||
|
|
c58ca4bed6 | ||
|
|
9f67cfcf99 |
14
.gitignore
vendored
14
.gitignore
vendored
@@ -1,2 +1,14 @@
|
||||
# Exclude .DS_Store files
|
||||
**/.DS_Store
|
||||
**/.vscode
|
||||
|
||||
# Exclude .vscode directory
|
||||
**/.vscode/
|
||||
|
||||
# Exclude __pycache__ directories
|
||||
__pycache__/
|
||||
|
||||
# Exclude pytest_cache directories
|
||||
.pytest_cache/
|
||||
|
||||
# Exclude changes_release.md
|
||||
changes_release.md
|
||||
@@ -1,3 +1,4 @@
|
||||
// clang -fobjc-arc -framework Foundation example.m -o arc_example
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface Person : NSObject
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
89
README.md
89
README.md
@@ -13,28 +13,29 @@ Each article directory contains three subdirectories:
|
||||
* ☑ [II. Code Signing](https://karol-mazurek95.medium.com/snake-apple-ii-code-signing-f0a9967b7f02?sk=v2%2Fbbc87007-89ca-4135-91d6-668b5d2fe9ae)
|
||||
* ☑ [III. Checksec](https://karol-mazurek95.medium.com/snake-apple-iii-checksec-ed64a4b766c1?sk=v2%2Fb4b8d637-e906-4b6b-8088-ca1f893cd787)
|
||||
* ☑ [IV. Dylibs](https://karol-mazurek.medium.com/snake-apple-iv-dylibs-2c955439b94e?sk=v2%2Fdef72b7a-121a-47a1-af89-7bf53aed1ea2)
|
||||
* ☐ [V. Dyld]()
|
||||
* ☑ [DYLD — Do You Like Death? (I)](https://karol-mazurek.medium.com/dyld-do-you-like-death-i-8199faad040e?sk=v2%2F359b081f-d944-409b-9e7c-95f7c171b969)
|
||||
* ☑ [DYLD — Do You Like Death? (II)](https://karol-mazurek.medium.com/dyld-do-you-like-death-ii-b74360b8af47?sk=v2%2Ff0cff71c-5345-4228-a639-653325fc979d)
|
||||
* ☑ [DYLD — Do You Like Death? (III)](https://karol-mazurek.medium.com/dyld-do-you-like-death-iii-af77701a3034?sk=v2%2F06c92503-2db9-40e2-b139-c9ae0a35e7b3)
|
||||
* ☑ [DYLD — Do You Like Death? (IV)](https://karol-mazurek.medium.com/dyld-do-you-like-death-iv-ede6b157752c?sk=v2%2F87ebe38d-004c-41a6-bc1f-43898494a512)
|
||||
* ☐ [DYLD — Do You Like Death? (V)]()
|
||||
* ☑ [V. Dyld](https://karol-mazurek.medium.com/snake-apple-v-dyld-8b36b674cc44?sk=v2%2F4acb16f8-fa88-41f0-8d7c-1362f4060010)
|
||||
* ☐ [VI. AMFI]()
|
||||
|
||||
## TOOLS
|
||||
[CrimsonUroboros](#crimsonuroboros) • [MachOFileFinder](#machofilefinder) • [TrustCacheParser](#trustcacheparser) • [SignatureReader](#signaturereader) • [extract_cms.sh](#extract_cmssh) • [ModifyMachOFlags](#modifymachoflags) • [LCFinder](#lcfinder)
|
||||
[CrimsonUroboros](#crimsonuroboros) • [MachOFileFinder](#machofilefinder) • [TrustCacheParser](#trustcacheparser) • [SignatureReader](#signaturereader) • [extract_cms.sh](#extract_cmssh) • [ModifyMachOFlags](#modifymachoflags) • [LCFinder](#lcfinder) • [MachODylibLoadCommandsFinder](#machodylibloadcommandsfinder)
|
||||
***
|
||||
|
||||
### [CrimsonUroboros](IV.%20Dylibs/python/CrimsonUroboros.py)
|
||||
### [CrimsonUroboros](tests/CrimsonUroboros.py)
|
||||

|
||||
Core program resulting from the Snake&Apple article series for binary analysis. You may find older versions of this script in each article directory in this repository.
|
||||
* Usage
|
||||
```console
|
||||
usage: CrimsonUroboros [-h] -p PATH [--file_type] [--header_flags] [--endian] [--header] [--load_commands] [--segments]
|
||||
[--sections] [--symbols] [--chained_fixups] [--exports_trie] [--uuid] [--main]
|
||||
[--encryption_info [(optional) save_path.bytes]] [--strings_section] [--all_strings]
|
||||
[--save_strings all_strings.txt] [--info] [--verify_signature] [--cd_info] [--cd_requirements]
|
||||
[--entitlements [human|xml|var]] [--extract_cms cms_signature.der]
|
||||
[--extract_certificates certificate_name] [--remove_sig unsigned_binary]
|
||||
[--sign_binary [adhoc|identity_number]] [--has_pie] [--has_arc] [--is_stripped] [--has_canary]
|
||||
[--has_nx_stack] [--has_nx_heap] [--has_xn] [--is_notarized] [--is_encrypted] [--has_restrict]
|
||||
[--is_hr] [--is_as] [--is_fort] [--has_rpath] [--checksec] [--dylibs] [--rpaths] [--rpaths_u]
|
||||
[--dylibs_paths] [--dylibs_paths_u] [--broken_relative_paths]
|
||||
[--dylibtree [cache_path,output_path,is_extracted]] [--dylib_id] [--reexport_paths] [--hijack_sec]
|
||||
[--dylib_hijacking [cache_path]] [--prepare_dylib [target_dylib_path]]
|
||||
usage: CrimsonUroboros [-h] -p PATH [--file_type] [--header_flags] [--endian] [--header] [--load_commands] [--segments] [--sections] [--symbols] [--imported_symbols] [--chained_fixups] [--exports_trie] [--uuid] [--main] [--encryption_info [(optional) save_path.bytes]] [--strings_section] [--all_strings]
|
||||
[--save_strings all_strings.txt] [--info] [--verify_signature] [--cd_info] [--cd_requirements] [--entitlements [human|xml|var]] [--extract_cms cms_signature.der] [--extract_certificates certificate_name] [--remove_sig unsigned_binary] [--sign_binary [adhoc|identity]] [--has_pie] [--has_arc]
|
||||
[--is_stripped] [--has_canary] [--has_nx_stack] [--has_nx_heap] [--has_xn] [--is_notarized] [--is_encrypted] [--is_restricted] [--is_hr] [--is_as] [--is_fort] [--has_rpath] [--has_lv] [--checksec] [--dylibs] [--rpaths] [--rpaths_u] [--dylibs_paths] [--dylibs_paths_u]
|
||||
[--broken_relative_paths] [--dylibtree [cache_path,output_path,is_extracted]] [--dylib_id] [--reexport_paths] [--hijack_sec] [--dylib_hijacking [(optional) cache_path]] [--dylib_hijacking_a [cache_path]] [--prepare_dylib [(optional) target_dylib_name]] [--is_built_for_sim] [--get_dyld_env]
|
||||
[--compiled_with_dyld_env] [--has_interposing] [--interposing_symbols]
|
||||
|
||||
Mach-O files parser for binary analysis
|
||||
|
||||
@@ -51,13 +52,13 @@ MACH-O ARGS:
|
||||
--segments Print binary segments in human-friendly form
|
||||
--sections Print binary sections in human-friendly form
|
||||
--symbols Print all binary symbols
|
||||
--imported_symbols Print symbols imported from external libraries
|
||||
--chained_fixups Print Chained Fixups information
|
||||
--exports_trie Print Export Trie information
|
||||
--uuid Print UUID
|
||||
--main Print entry point and stack size
|
||||
--encryption_info [(optional) save_path.bytes]
|
||||
Print encryption info if any. Optionally specify an output path to dump the encrypted data (if
|
||||
cryptid=0, data will be in plain text)
|
||||
Print encryption info if any. Optionally specify an output path to dump the encrypted data (if cryptid=0, data will be in plain text)
|
||||
--strings_section Print strings from __cstring section
|
||||
--all_strings Print strings from all sections
|
||||
--save_strings all_strings.txt
|
||||
@@ -73,13 +74,11 @@ CODE SIGNING ARGS:
|
||||
--extract_cms cms_signature.der
|
||||
Extract CMS Signature from the Code Signature and save it to a given file
|
||||
--extract_certificates certificate_name
|
||||
Extract Certificates and save them to a given file. To each filename will be added an index at
|
||||
the end: _0 for signing, _1 for intermediate, and _2 for root CA certificate
|
||||
Extract Certificates and save them to a given file. To each filename will be added an index at the end: _0 for signing, _1 for intermediate, and _2 for root CA certificate
|
||||
--remove_sig unsigned_binary
|
||||
Save the new file on a disk with removed signature
|
||||
--sign_binary [adhoc|identity_number]
|
||||
Sign binary using specified identity - use : 'security find-identity -v -p codesigning' to get
|
||||
the identity (default: adhoc)
|
||||
--sign_binary [adhoc|identity]
|
||||
Sign binary using specified identity - use : 'security find-identity -v -p codesigning' to get the identity (default: adhoc)
|
||||
|
||||
CHECKSEC ARGS:
|
||||
--has_pie Check if Position-Independent Executable (PIE) is set
|
||||
@@ -91,41 +90,43 @@ CHECKSEC ARGS:
|
||||
--has_xn Check if binary is protected by eXecute Never (XN) ARM protection
|
||||
--is_notarized Check if the application is notarized and can pass the Gatekeeper verification
|
||||
--is_encrypted Check if the application is encrypted (has LC_ENCRYPTION_INFO(_64) and cryptid set to 1)
|
||||
--has_restrict Check if binary has __RESTRICT segment
|
||||
--is_restricted Check if binary has __RESTRICT segment or CS_RESTRICT flag set
|
||||
--is_hr Check if the Hardened Runtime is in use
|
||||
--is_as Check if the App Sandbox is in use
|
||||
--is_fort Check if the binary is fortified
|
||||
--has_rpath Check if the binary utilise any @rpath variables
|
||||
--has_lv Check if the binary has Library Validation (protection against Dylib Hijacking)
|
||||
--checksec Run all checksec module options on the binary
|
||||
|
||||
DYLIBS ARGS:
|
||||
--dylibs Print shared libraries used by specified binary with compatibility and the current version
|
||||
(loading paths unresolved, like @rpath/example.dylib)
|
||||
--dylibs Print shared libraries used by specified binary with compatibility and the current version (loading paths unresolved, like @rpath/example.dylib)
|
||||
--rpaths Print all paths (resolved) that @rpath can be resolved to
|
||||
--rpaths_u Print all paths (unresolved) that @rpath can be resolved to
|
||||
--dylibs_paths Print absolute dylib loading paths (resolved @rpath|@executable_path|@loader_path) in order they
|
||||
are searched for
|
||||
--dylibs_paths Print absolute dylib loading paths (resolved @rpath|@executable_path|@loader_path) in order they are searched for
|
||||
--dylibs_paths_u Print unresolved dylib loading paths.
|
||||
--broken_relative_paths
|
||||
Print 'broken' relative paths from the binary (cases where the dylib source is specified for an
|
||||
executable directory without @executable_path)
|
||||
Print 'broken' relative paths from the binary (cases where the dylib source is specified for an executable directory without @executable_path)
|
||||
--dylibtree [cache_path,output_path,is_extracted]
|
||||
Print the dynamic dependencies of a Mach-O binary recursively. You can specify the Dyld Shared
|
||||
Cache path in the first argument, the output directory as the 2nd argument, and if you have
|
||||
already extracted DSC in the 3rd argument (0 or 1). The output_path will be used as a base for
|
||||
dylibtree. For example, to not extract DSC, use: --dylibs ",,1", or to extract from default to
|
||||
default use just --dylibs or --dylibs ",,0" which will extract DSC to extracted_dyld_share_cache/
|
||||
in the current directory
|
||||
Print the dynamic dependencies of a Mach-O binary recursively. You can specify the Dyld Shared Cache path in the first argument, the output directory as the 2nd argument, and if you have already extracted DSC in the 3rd argument (0 or 1). The output_path will be used as a base for
|
||||
dylibtree. For example, to not extract DSC, use: --dylibs ",,1", or to extract from default to default use just --dylibs or --dylibs ",,0" which will extract DSC to extracted_dyld_share_cache/ in the current directory
|
||||
--dylib_id Print path from LC_ID_DYLIB
|
||||
--reexport_paths Print paths from LC_REEXPORT_DLIB
|
||||
--hijack_sec Check if binary is protected against Dylib Hijacking
|
||||
--dylib_hijacking [cache_path]
|
||||
Check for possible Direct and Indirect Dylib Hijacking loading paths. (optional) Specify the path
|
||||
to the Dyld Shared Cache
|
||||
--prepare_dylib [target_dylib_path]
|
||||
Compile rogue dylib. (optional) Specify target_dylib_path, it will search for the imported
|
||||
symbols from it in the dylib specified in the --path argument and automatically add it to the
|
||||
source code of the rogue lib. Example: --path lib1.dylib --prepare_dylib /path/to/lib2.dylib
|
||||
--dylib_hijacking [(optional) cache_path]
|
||||
Check for possible Direct and Indirect Dylib Hijacking loading paths. The output is printed to console and saved in JSON format to /tmp/dylib_hijacking_log.json(append mode). Optionally, specify the path to the Dyld Shared Cache
|
||||
--dylib_hijacking_a [cache_path]
|
||||
Like --dylib_hijacking, but shows only possible vectors (without protected binaries)
|
||||
--prepare_dylib [(optional) target_dylib_name]
|
||||
Compile rogue dylib. Optionally, specify target_dylib_path, it will search for the imported symbols from it in the dylib specified in the --path argument and automatically add it to the source code of the rogue lib. Example: --path lib1.dylib --prepare_dylib /path/to/lib2.dylib
|
||||
|
||||
DYLD ARGS:
|
||||
--is_built_for_sim Check if binary is built for simulator platform.
|
||||
--get_dyld_env Extract Dyld environment variables from the loader binary.
|
||||
--compiled_with_dyld_env
|
||||
Check if binary was compiled with -dyld_env flag and print the environment variables and its values.
|
||||
--has_interposing Check if binary has interposing sections.
|
||||
--interposing_symbols
|
||||
Print interposing symbols if any.
|
||||
```
|
||||
* Example:
|
||||
```bash
|
||||
@@ -268,7 +269,7 @@ MachODylibLoadCommandsFinder 2>/dev/null
|
||||
|
||||
## INSTALL
|
||||
```
|
||||
pip -r requirements.txt
|
||||
pip3 install -r requirements.txt
|
||||
wget https://github.com/CRKatri/trustcache/releases/download/v2.0/trustcache_macos_arm64 -O /usr/local/bin/trustcache
|
||||
chmod +x /usr/local/bin/trustcache
|
||||
xattr -d com.apple.quarantine /usr/local/bin/trustcache
|
||||
@@ -297,5 +298,5 @@ I will write the code for each article as a class SnakeX, where X will be the ar
|
||||
* Every method in the Snake class that use Entitlements should parse first XML > DER (currently, only XML parser exists)
|
||||
* After making a SuperBlob parser and CodeDirectory blob parser, modify hasHardenedRuntime to check Runtime flag by using bitmask, instead of string.
|
||||
* Build Dyld Shared Cache parser and extractor to make SnakeIV independant of dyld-shared-cache-extractor.
|
||||
* Add check for `CS_RESTRICT` (`0x800`) in --`checksec` to `RESTRICTED`
|
||||
* Add check for `DYLIB HIJACKING` to --`checksec`
|
||||
* Make testing branch and implement tests, before pushing new updates.
|
||||
* Create `RottenApple.app` in another repository and use it for testing.
|
||||
22
V. Dyld/custom/arg_printer.c
Normal file
22
V. Dyld/custom/arg_printer.c
Normal file
@@ -0,0 +1,22 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char *argv[], char *envp[], char *apple[]) {
|
||||
printf("Argument count: %d\n", argc);
|
||||
|
||||
printf("Standard arguments:\n");
|
||||
for (int i = 0; i < argc; i++) {
|
||||
printf("Argument %d: %s\n", i, argv[i]);
|
||||
}
|
||||
|
||||
printf("Environment variables:\n");
|
||||
for (int i = 0; envp[i] != NULL; i++) {
|
||||
printf("Environment Variable %d: %s\n", i, envp[i]);
|
||||
}
|
||||
|
||||
printf("Apple-specific arguments:\n");
|
||||
for (int i = 0; apple[i] != NULL; i++) {
|
||||
printf("Apple Argument %d: %s\n", i, apple[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
15
V. Dyld/custom/con_des.c
Normal file
15
V. Dyld/custom/con_des.c
Normal file
@@ -0,0 +1,15 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <syslog.h>
|
||||
|
||||
// Constructor
|
||||
__attribute__((constructor)) void crimson_constructor() {
|
||||
syslog(LOG_ERR, "[+] crimson_constructor called\n");
|
||||
printf("[+] crimson_constructor called\n");
|
||||
}
|
||||
|
||||
// Destructor
|
||||
__attribute__((destructor)) void crimson_destructor() {
|
||||
syslog(LOG_ERR, "[+] crimson_destructor called\n");
|
||||
printf("[+] crimson_destructor called\n");
|
||||
}
|
||||
8
V. Dyld/custom/hello.c
Normal file
8
V. Dyld/custom/hello.c
Normal file
@@ -0,0 +1,8 @@
|
||||
// clang -o hello hello.c
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
printf("Hello!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
22
V. Dyld/custom/interpose.c
Normal file
22
V. Dyld/custom/interpose.c
Normal file
@@ -0,0 +1,22 @@
|
||||
// clang -dynamiclib -o libinterpose.dylib interpose.c
|
||||
#include <stdio.h>
|
||||
|
||||
// Define the interpose macro
|
||||
#define DYLD_INTERPOSE(_replacement,_replacee) \
|
||||
__attribute__((used)) static struct { \
|
||||
const void* replacement; \
|
||||
const void* replacee; \
|
||||
} \
|
||||
_interpose_##_replacee \
|
||||
__attribute__ ((section ("__DATA,__interpose,interposing"))) = { \
|
||||
(const void*)(unsigned long)&_replacement, \
|
||||
(const void*)(unsigned long)&_replacee };
|
||||
|
||||
// Define the replacement function
|
||||
int my_printf(const char *format, ...) {
|
||||
int ret = printf("Hello from my_printf!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Apply the interposing macro to replace printf with my_printf
|
||||
DYLD_INTERPOSE(my_printf, printf)
|
||||
63
V. Dyld/custom/lambda_capture_example.cpp
Normal file
63
V. Dyld/custom/lambda_capture_example.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
//g++ -std=c++11 lambda_capture_example.cpp -o lambda_capture_example
|
||||
|
||||
/*
|
||||
This example demonstrates how lambda capture by reference [&] allows the lambda function to access and modify variables from the outer scope directly.
|
||||
|
||||
1. We have a function withWritableMemory that simulates the process of making memory writable, executing some work, and then restoring memory protection.
|
||||
2. In the main function, we have variables x and y.
|
||||
3. We define a lambda function lambda capturing all variables by reference [&]().
|
||||
4. Inside the lambda, we modify the values of x and y.
|
||||
5. We call withWritableMemory and pass the lambda as an argument.
|
||||
6. The lambda is executed within the withWritableMemory function.
|
||||
7. After the lambda execution, we print the values of x and y to see the changes made inside the lambda.
|
||||
*/
|
||||
#include <iostream>
|
||||
|
||||
void withWritableMemory(std::function<void()> work) {
|
||||
std::cout << "Entering withWritableMemory function" << std::endl;
|
||||
// Simulating the setup before making memory writable
|
||||
std::cout << "Setting up memory..." << std::endl;
|
||||
|
||||
// Make memory writable
|
||||
|
||||
// Execute the provided work function
|
||||
work();
|
||||
|
||||
// Restore memory protection
|
||||
std::cout << "Restoring memory protection..." << std::endl;
|
||||
|
||||
std::cout << "Exiting withWritableMemory function" << std::endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
int x = 5;
|
||||
int y = 3;
|
||||
|
||||
// Lambda function capturing all variables by reference
|
||||
auto lambda = [&]() {
|
||||
// Access and modify variables from the outer scope
|
||||
x = x + 10;
|
||||
y = y * 2;
|
||||
|
||||
std::cout << "Inside lambda: x = " << x << ", y = " << y << std::endl;
|
||||
};
|
||||
|
||||
// Call the function with the lambda as an argument
|
||||
withWritableMemory(lambda);
|
||||
|
||||
// After the lambda is executed
|
||||
std::cout << "After lambda: x = " << x << ", y = " << y << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
./lambda_capture_example
|
||||
|
||||
Entering withWritableMemory function
|
||||
Setting up memory...
|
||||
Inside lambda: x = 15, y = 6
|
||||
Restoring memory protection...
|
||||
Exiting withWritableMemory function
|
||||
After lambda: x = 15, y = 6
|
||||
*/
|
||||
26
V. Dyld/custom/rosetta_dyld_is_translated_pointer_example.c
Normal file
26
V. Dyld/custom/rosetta_dyld_is_translated_pointer_example.c
Normal file
@@ -0,0 +1,26 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int rosetta_dyld_is_translated(bool *is_translated);
|
||||
|
||||
// Pseudo implementation of SyscallDelegate::isTranslated
|
||||
bool isTranslated() {
|
||||
bool is_translated = false;
|
||||
if (rosetta_dyld_is_translated(&is_translated) == 0) {
|
||||
return is_translated;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Mock implementation of rosetta_dyld_is_translated for demonstration purposes
|
||||
// This function always sets is_translated to true using pointer - for the sake of the example
|
||||
int rosetta_dyld_is_translated(bool *is_translated) {
|
||||
*is_translated = true; // Simulated behavior: always set is_translated to true
|
||||
return 0; // Return success
|
||||
}
|
||||
|
||||
int main() {
|
||||
bool translated = isTranslated();
|
||||
printf("Is translated: %s\n", translated ? "true" : "false");
|
||||
return 0;
|
||||
}
|
||||
1686
V. Dyld/python/CrimsonUroboros.py
Executable file
1686
V. Dyld/python/CrimsonUroboros.py
Executable file
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,7 @@
|
||||
lief
|
||||
uuid
|
||||
argparse
|
||||
subprocess
|
||||
os
|
||||
sys
|
||||
asn1crypto
|
||||
glob
|
||||
shutil
|
||||
pyimg4
|
||||
pyimg4
|
||||
treelib
|
||||
xattr
|
||||
1
tests/CrimsonUroboros.py
Symbolic link
1
tests/CrimsonUroboros.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../V. Dyld/python/CrimsonUroboros.py
|
||||
1439
tests/test_CrimsonUroboros.py
Normal file
1439
tests/test_CrimsonUroboros.py
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user