Dump decrypted mach-o apps

Posted: August 4th, 2016 | Author: | Filed under: code injection, DYLD_INSERT_LIBRARIES, MacOSX, OS X, Programming | Tags: , , , , , , , , | 2 Comments »

 
In a previous post “CryptedHelloWorld: App with encrypted mach-o sections”, I created a simple macOS app ‘CryptedHelloWorld’ with its (__TEXT, __text) section encrypted. The section is decrypted by a constructor function.

 
This post explains how to dump the decrypted app. A common way is to attach the app with a debugger (GDB, LLDB) and manually dump the decrypted memory to disk.

However I will use a different solution by using 2 techniques already presented in previous posts: a destructor function and code injection.

The targeted app is the precompiled CryptedHelloWorld command line tool that can be downloaded here.

This command line tool has its (__TEXT, __text) section encrypted. Once its main() function is called, we know that the section is decrypted. Thus we can create a destructor function – which is called just before the app is quit – to dump the decrypted memory to disk. This destructor function will be injected into the app using the DYLD_INSERT_LIBRARIES environment variable.

The destructor function needs to read the executable from disk, dump the decrypted (__TEXT, __text) section and replace the encrypted bytes by the decrypted bytes.

 
 
Code injection

I already described how to inject code using DYLD_INSERT_LIBRARIES in this post. We will use the exact same technique by building a dynamic library like this:

gcc -o DumpBinary.dylib -dynamiclib DumpBinary.c

and then run it using the DYLD_INSERT_LIBRARIES environment variable:

DYLD_INSERT_LIBRARIES=./DumpBinary.dylib ./CryptedHelloWorld

 
 
Destructor function

Creating a destructor function has been described in this post. Such a function will be called just before the app quits:

void __attribute__((destructor)) DumpBinaryDestructor()
{
     // Executed just before the app quits
}

 
 
Finding the targeted app mach-o header

The first problem to solve is to find the mach-o header of the targeted app. This is easily done using the dyld function _dyld_get_image_header and searching for the first image of type MH_EXECUTE:


//
// Find the main executable
//
const struct mach_header_64 *machHeader = NULL;

for(uint32_t imageIndex = 0 ; imageIndex < _dyld_image_count() ; imageIndex++)
{
	const struct mach_header_64 *mH = (const struct mach_header_64 *)_dyld_get_image_header(imageIndex);
	if (mH->filetype == MH_EXECUTE)
	{
		const char* imageName = _dyld_get_image_name(imageIndex);
		fprintf(stderr, "Found main executable '%s'\n", imageName);
		
		machHeader = mH;
		break;
	}
}

 
 
Finding the executable path on disk

The dynamic library will need to read the app binary from disk: it needs the executable path. This is done using the dyld function _NSGetExecutablePath which copies the path of the main executable into a buffer:


//
// Get the real executable path
//
char executablePath[PATH_MAX];

/*
_NSGetExecutablePath() copies the path of the main executable into the
 buffer buf.  The bufsize parameter should initially be the size of the
 buffer.  This function returns 0 if the path was successfully copied, and
 * bufsize is left unchanged.  It returns -1 if the buffer is not large
 enough, and * bufsize is set to the size required.  Note that
 _NSGetExecutablePath() will return "a path" to the executable not a "real
 path" to the executable.  That is, the path may be a symbolic link and
 not the real file. With deep directories the total bufsize needed could
 be more than MAXPATHLEN.
*/
uint32_t len = sizeof(executablePath);
if (_NSGetExecutablePath(executablePath, &len) != 0)
{
	fprintf(stderr, "Buffer is not large enough to copy the executable path\n");
	exit(1);
}

We then get the canonical path using realpath:



//
// Get the canonicalized absolute path
//
char *canonicalPath = realpath(executablePath, NULL);
if (canonicalPath != NULL)
{
	strlcpy(executablePath, canonicalPath, sizeof(executablePath));
	free(canonicalPath);
}

 
 
Reading from disk

Reading from disk is done using fopen/fread:


//
// Open the executable file for reading
//
FILE *sourceFile = fopen(executablePath, "r");
if (sourceFile == NULL)
{
	fprintf(stderr, "Error: Could not open executable path '%s'\n", executablePath);
	exit(1);
}

//
// Read the source file and store it into a buffer
//
fseek(sourceFile, 0, SEEK_END);
long fileLen = ftell(sourceFile);
fseek(sourceFile, 0, SEEK_SET);

uint8_t *fileBuffer = (uint8_t *)calloc(fileLen, 1);
if (fileBuffer == NULL)
{
	fprintf(stderr, "Error: Could not allocate buffer\n");
	exit(1);
}

if (fread(fileBuffer, 1, fileLen, sourceFile) != fileLen)
{
	fprintf(stderr, "Error: Could not read the file '%s'\n", executablePath);
	exit(1);
}

 
 
Finding the (__TEXT, __text) and (__DATA, __mod_init_func) sections

We already have the mach-o header. We need to loop through all segments and sections until we find the interesting sections:


//
// Loop through each section
//
size_t segmentOffset = sizeof(struct mach_header_64);

for (uint32_t i = 0; i < machHeader->ncmds; i++)
{
	struct load_command *loadCommand = (struct load_command *)((uint8_t *) machHeader + segmentOffset);
	
	if(loadCommand->cmd == LC_SEGMENT_64)
	{
		// Found a 64-bit segment
		struct segment_command_64 *segCommand = (struct segment_command_64 *) loadCommand;

		// For each section in the 64-bit segment
		void *sectionPtr = (void *)(segCommand + 1);
		for (uint32_t nsect = 0; nsect < segCommand->nsects; ++nsect)
		{
			struct section_64 *section = (struct section_64 *)sectionPtr;
			
			fprintf(stderr, "Found the section (%s, %s)\n", section->segname, section->sectname);
			
			if (strncmp(segCommand->segname, SEG_TEXT, 16) == 0)
			{
				if (strncmp(section->sectname, SECT_TEXT, 16) == 0)
				{
					// This is the (__TEXT, __text) section.

				}
			}
			else if (strncmp(segCommand->segname, SEG_DATA, 16) == 0)
			{
				if (strncmp(section->sectname, "__mod_init_func", 16) == 0)
				{
					// This is the (__DATA, __mod_init_func) section.

				}
			}
			
			sectionPtr += sizeof(struct section_64);
		}
	}
	
	segmentOffset += loadCommand->cmdsize;
}



 
 
Dumping the decrypted (__TEXT, __text) section

We just use a simple memcpy to replace in the buffer the encrypted bytes by the decrypted bytes:

fprintf(stderr, "\t Save the unencrypted (%s, %s) section to the buffer\n", section->segname, section->sectname);
memcpy(fileBuffer + section->offset, (uint8_t *) machHeader + section->offset, section->size);

 
 
Removing the constructor function

We now have a decrypted binary. However if we launch it, its constructor function will be called and corrupt the (__TEXT, __text) section. We need to prevent the constructor function to be executed. There are several solutions and I chose to zero out the (__DATA, __mod_init_func) section. I kept the segname and sectname info so that MachOView can nicely display it.


fprintf(stderr, "\t Zero out the (%s, %s) section\n", section->segname, section->sectname);

size_t sectionOffset = sectionPtr - (void *)machHeader;

// Size of char sectname[16] + char segname[16]
size_t namesSize = 2 * 16 * sizeof(char);

// Zero out the section_64 but keep the sectname and segname
bzero(fileBuffer + sectionOffset + namesSize, sizeof(struct section_64) - namesSize);

 
 
Writing the decrypted binary to disk

The last step consists of writing the decrypted app to disk. This is done with fwrite:


//
// Create the output file
//
char destinationPath[PATH_MAX];
strlcpy(destinationPath, executablePath, sizeof(destinationPath));
strlcat(destinationPath, "_Decrypted", sizeof(destinationPath));

FILE *destinationFile = fopen(destinationPath, "w");
if (destinationFile == NULL)
{
	fprintf(stderr, "Error: Could create the output file '%s'\n", destinationPath);
	exit(1);
}

//
// Save the data into the output file
//
if (fwrite(fileBuffer, 1, fileLen, destinationFile) != fileLen)
{
	fprintf(stderr, "Error: Could not write to the output file\n");
	exit(1);
}


 
 
Log output

To run the CryptedHelloWorld app and inject our code:

DYLD_INSERT_LIBRARIES=./DumpBinary.dylib ./CryptedHelloWorld

Here is the log output when running the CryptedHelloWorld:


*** Constructor called to decrypt sections
Found the section (__TEXT, __text)
Decrypting the (__TEXT, __text) section
Found the section (__TEXT, __stubs)
Found the section (__TEXT, __stub_helper)
Found the section (__TEXT, __timac)
Found the section (__TEXT, __cstring)
Found the section (__TEXT, __unwind_info)
Found the section (__DATA, __nl_symbol_ptr)
Found the section (__DATA, __got)
Found the section (__DATA, __la_symbol_ptr)
Found the section (__DATA, __mod_init_func)
Found the section (__DATA, __data)
Found the section (__DATA, __bss)
*** The sections should now be decrypted. main() will be called soon.


------------------
Hello, World!
------------------


*********************************
*** DumpBinaryDestructor CALLED
*********************************
Found main executable '/CryptedHelloWorld/DumpBinary/./CryptedHelloWorld'
Found absolute path: '/CryptedHelloWorld/DumpBinary/CryptedHelloWorld'
Found the section (__TEXT, __text)
	 Save the unencrypted (__TEXT, __text) section to the buffer
Found the section (__TEXT, __stubs)
Found the section (__TEXT, __stub_helper)
Found the section (__TEXT, __timac)
Found the section (__TEXT, __cstring)
Found the section (__TEXT, __unwind_info)
Found the section (__DATA, __nl_symbol_ptr)
Found the section (__DATA, __got)
Found the section (__DATA, __la_symbol_ptr)
Found the section (__DATA, __mod_init_func)
	 Zero out the (__DATA, __mod_init_func) section
Found the section (__DATA, __data)
Found the section (__DATA, __bss)
*********************************
*** Decryption completed
*********************************

 
 
Examining the decrypted app

Using MachOView, we see that the (__TEXT, __text) section is decrypted:


(__TEXT, __text)

 

We also see that the (__DATA, __mod_init_func) has been zeroed out:


(__DATA, __mod_init_func)

 
 
Limitations of the dynamic library

  • it only supports 64-bit intel Mach-O files. Adding 32-bit, ARM or fat Mach-O support is fairly simple and left to the reader.
  • it only dumps the (__TEXT, __text) section.
  • it zeroes out the (__DATA, __mod_init_func) section which would cause problems if there are multiple constructors.

 
 
Downloads

The dynamic library source code can be downloaded here.

The precompiled dynamic library can be downloaded here.


Mail.app plugin compatibility for macOS Sierra (10.12)

Posted: July 27th, 2016 | Author: | Filed under: MacOSX, Mail, OS X, Programming | Tags: , , , , , , , , , | No Comments »

 
Mail.app in macOS 10.11 and earlier used to check the plugins compatibility using the SupportedPluginCompatibilityUUIDs key in the plugin’s Info.plist. For example a Mail plugin would only be compatible with macOS 10.11.6 if its Info.plist contained the following:

<key>SupportedPluginCompatibilityUUIDs</key>
<array>
   <string>71562B89-0D90-4588-8E94-A75B701D6443</string>
</array>

  
Mail.app version 10.0 in macOS Sierra (10.12) now uses a different key to check the plugins compatibility. It now requires a key with the format Supported%ld.%ldPluginCompatibilityUUIDs where “%ld.%ld” is the operating system version like “10.12”.

If you want to make your Mail.app plugin compatible with macOS Sierra, you will need to add a key in your Info.plist like:

<key>Supported10.12PluginCompatibilityUUIDs</key>
<array>
    <string>36CCB8BB-2207-455E-89BC-B9D6E47ABB5B</string>
</array>

Note that the UUID “36CCB8BB-2207-455E-89BC-B9D6E47ABB5B” is for macOS Sierra 10.12 beta 3.

  
Also by default the Mail plugins support is disabled. In order to enable it you first need to run in the Terminal the following:

defaults write com.apple.mail EnableBundles -bool true

  
Related post: Disable swipe to delete in Mail.app on OS X 10.11


CryptedHelloWorld: App with encrypted mach-o sections

Posted: July 23rd, 2016 | Author: | Filed under: crypto, MacOSX, OS X, Programming | Tags: , , , , , , , | No Comments »

 
In a previous post ( constructor and destructor attributes ), I described the constructor attribute and mentioned software protection as a possible use case:

A constructor attribute could be used to implement a software protection. You could encrypt your executable with a custom encryption and use a constructor function to decrypt the binary just before it is loaded.

In this post I describe such a protection with an example.

 
 
Mach-O file format

Let’s start with a brief summary of the Mach-O file format. For more information you should definitively read the OS X ABI Mach-O File Format Reference.

A Mach-O file contains 3 regions:

  • header structure: describes the Mach-O file
  • load commands: describes the segments and their sections
  • actual segment data

 
Here is the figure from the OS X ABI Mach-O File Format Reference:


Mach-O file format basic structure

The goal is to encrypt the data of the __text section from the __TEXT segment. This is the section containing the code of the executable. The other sections and segments will be left untouched.

 
 
The target application: CryptedHelloWorld

The target application is called ‘CryptedHelloWorld’. Its (__TEXT, __text) section is encrypted, meaning that the main() function needs to be decrypted before running. When launched, a constructor function will decrypt the encrypted section and the decrypted main() will be called.

The application itself is a simple command line ‘Hello World’ written in C. Here is the source code of the main function:


int main(int argc, const char * argv[])
{
	printf("\n\n");
	printf("------------------\n");
	printf("Hello, World!\n");
	printf("------------------\n");
	printf("\n\n");
	
    return 0;
}

 
 
CryptoTool

When building the project with Xcode, the target dependency ‘CryptoTool’ is built. At the end of the compilation of the CryptedHelloWorld app, a Run Script phase is executed which runs ‘CryptoTool’ on the just compiled CryptedHelloWorld binary. ‘CryptoTool’:

  • reads the binary of the CryptedHelloWorld application from the disk
  • locates the (__TEXT, __text) section in the file
  • encrypts it using AES 128
  • replaces the bytes with the encrypted bytes in the binary on the disk.

 
The Run Script phase is straightforward:


Run Script phase

 
 
Location of the constructor function

When you launch the application, the constructor function will be triggered and will need to decrypt the (__TEXT, __text) section. Obviously this constructor function can’t be located in the (__TEXT, __text) section. I store it in a custom (__TEXT,__timac) section using the attribute __attribute__((section(“__TEXT,__timac”))):

void __attribute__((constructor)) __attribute__((section("__TEXT,__timac"))) decryptTextSection()

 
 
Self contained constructor function

We need to make sure that the constructor function doesn’t call any functions that are located in the (__TEXT, __text) section. To ensure that I made all the required functions inlined. For example:

static inline void __attribute__((always_inline)) EncryptDecryptMachoFile(struct mach_header_64 *machHeader, CCOperation operation)

The attribute __attribute__((always_inline)) ensures that the function is inlined even for debug builds when optimizations are turned off.

 
 
Locating the (__TEXT, __text) section

The constructor function uses the _dyld_get_image_header() dyld function to get the Mach-O header. It then loops though all the commands and all the sections of the LC_SEGMENT_64 segments to find the (__TEXT, __text) section:

static inline void __attribute__((always_inline)) EncryptDecryptMachoFile(struct mach_header_64 *machHeader, CCOperation operation)
{
	size_t segmentOffset = sizeof(struct mach_header_64);
	
	// For each load command of the mach-o file
	for (uint32_t i = 0; i < machHeader->ncmds; i++)
	{
		struct load_command *loadCommand = (struct load_command *)((uint8_t *) machHeader + segmentOffset);
		if(loadCommand->cmd == LC_SEGMENT_64)
		{
			// We found a 64-bit segment
			struct segment_command_64 *segCommand = (struct segment_command_64 *) loadCommand;
			
			// For each section in the 64-bit segment
			void *sectionPtr = (void *)(segCommand + 1);
			for (uint32_t nsect = 0; nsect < segCommand->nsects; ++nsect)
			{
				struct section_64 *section = (struct section_64 *)sectionPtr;
				fprintf(stderr, "Found the section (%s, %s)\n", section->segname, section->sectname);
				
				// Check if this is the __TEXT segment
				if (strncmp(segCommand->segname, SEG_TEXT, 16) == 0)
				{
					// Check if this is the __text section
					if (strncmp(section->sectname, SECT_TEXT, 16) == 0)
					{
						// This is the (__TEXT, __text) section.
						// We should encrypt/decrypt it in place.
						fprintf(stderr, "%s the (%s, %s) section\n", (operation == kCCEncrypt) ? "Encrypting" : "Decrypting", section->segname, section->sectname);
						EncryptDecryptBuffer((uint8_t *) machHeader + section->offset, (uint8_t *) machHeader + section->offset, section->size, operation);
						
					}
				}
				
				sectionPtr += sizeof(struct section_64);
			}
		}
		
		segmentOffset += loadCommand->cmdsize;
	}
}

 
 
Encryption

The section is encrypted using AES 128 by chunks of PAGE_SIZE bytes (4096 bytes). If there are less than PAGE_SIZE bytes to encrypt, chunks of 16 bytes are used. I use the CommonCrypto implementation of AES 128:

static inline void __attribute__((always_inline)) EncryptDecryptBytes(const void *srcBuffer, void *dstBuffer, uint64_t len, CCOperation operation)
{
	// Encrypt/decrypt the data from the source buffer using the AES key
	size_t outLength = 0;
	CCCryptorStatus result = CCCrypt(operation,
                   kCCAlgorithmAES128,
                   kCCOptionPKCS7Padding,
                   sAesKey,
                   kCCKeySizeAES128,
                   NULL,
                   srcBuffer,
                   len,
                   sEncryptionBuffer,
                   len + kCCBlockSizeAES128,
                   &outLength);
	
	if (result == kCCSuccess)
	{
		// Copy the encrypted/decrypted data into the destination buffer
		memcpy(dstBuffer, sEncryptionBuffer, len);
	}
	else
	{
		fprintf(stderr, "Error %d: Could not %s the data\n", result, (operation == kCCEncrypt) ? "encrypt" : "decrypt");
		exit(1);
	}
}

 
 
Virtual memory protections

The __TEXT segment is not writable by default. In order to decrypt the memory in place, the virtual memory protections need to be changed to allow writes. This is done using vm_protect:


static inline void __attribute__((always_inline)) ChangeVirtualMemoryProtections(vm_address_t addr, vm_size_t size)
{
	kern_return_t returnValue = vm_protect(mach_task_self(), addr, size, false, VM_PROT_ALL);
	if ( returnValue != KERN_SUCCESS )
	{
		fprintf(stderr, "Error %d: Fail to change virtual memory protections\n", returnValue);
		exit(1);
	}
}

 
 
Testing the compiled application

Here is the log output when launching the binary using the Terminal:

*** Constructor called to decrypt sections
Found the section (__TEXT, __text)
Decrypting the (__TEXT, __text) section
Found the section (__TEXT, __stubs)
Found the section (__TEXT, __stub_helper)
Found the section (__TEXT, __timac)
Found the section (__TEXT, __cstring)
Found the section (__TEXT, __unwind_info)
Found the section (__DATA, __nl_symbol_ptr)
Found the section (__DATA, __got)
Found the section (__DATA, __la_symbol_ptr)
Found the section (__DATA, __mod_init_func)
Found the section (__DATA, __data)
Found the section (__DATA, __bss)
*** The sections should now be decrypted. main() will be called soon.

——————
Hello, World!
——————

 
 
Examining the compiled application

 
Using MachOView, we see that the (__TEXT, __text) section is encrypted:


Section __text

 
This is confirmed with Hopper. The main() function doesn’t make any sense:


Hopper

 
Back to MachOView, we see that the (__TEXT, __timac) section contains unencrypted code:


Section __timac

 
 
Limitations of this proof of concept

As mentioned this example is a proof of concept and has several limitations:

  • it only supports 64-bit Mach-O files. Adding 32-bit and fat Mach-O support is fairly simple and left to the reader.
  • only the (__TEXT, __text) section is encrypted. It is possible to encrypt other sections or maybe even the whole __TEXT segment.
  • the target application is a really simple command line application written in C.
  • As mentioned earlier all the functions required in the constructor function have been made inlined. This makes it difficult to debug. If you want to debug this code I recommend to debug the CryptoTool app. It supports the parameters -decrypt and -encrypt. You should also remove the always_inline attribute otherwise breakpoints won’t fire as you would expect.

 
 
Should you use such code to protect your application?

I wouldn’t. Although this might prevent a user to look at the code, this won’t defeat an experienced attacker. Also note that this is a proof of concept.

 
 
Downloads

You can download the precompiled CryptedHelloWorld command line tool here.

The whole source code is available here.


constructor and destructor attributes

Posted: July 16th, 2016 | Author: | Filed under: code injection, Debugging, MacOSX, OS X, Programming | Tags: , , , , , , | 3 Comments »

GCC (and Clang) supports constructor and destructor attributes:

__attribute__((constructor))
__attribute__((destructor))

 
 
Description

A function marked with the __attribute__((constructor)) attribute will be called automatically before your main() function is called. Similarly a function marked with the __attribute__((destructor)) attribute will be called automatically after your main() function returns.

You can find the GCC documentation here:

constructor
destructor
The constructor attribute causes the function to be called automatically before execution enters main (). Similarly, the destructor attribute causes the function to be called automatically after main () has completed or exit () has been called. Functions with these attributes are useful for initializing data that will be used implicitly during the execution of the program.
These attributes are not currently implemented for Objective C.

Note: The GCC documentation tells that these attributes are not implemented for Objective-C. However this seems to work as expected with my tests using Clang ‘clang-703.0.31’ from Xcode 7.3.1.

 
 
Example

Here is an example of C code to demonstrate these attributes:


//
// To compile:
// clang -o constructor constructor.c
//

#include <stdio.h>
 
void constructor() __attribute__((constructor));
void destructor() __attribute__((destructor));

int main()
{
	printf ("main called\n");
	return 0;
}

void constructor()
{
	printf ("constructor called\n");
}

void destructor()
{
	printf ("destructor called\n");
}

When running this application, you will see the following output logs as you would expect:

constructor called
main called
destructor called

 
 
How does it work under the hood?

When you mark functions with these attributes, the compiler will create in your binary the sections called __mod_init_func for the constructors and __mod_term_func for the destructors. These sections contain the list of function pointers. You can use the excellent MachOView to see these sections:


ACTION

When your application is launched, dyld will call the constructors before your main() function is called. This is handled by the following dyld function:

void ImageLoaderMachO::doModInitFunctions(const LinkContext& context)

The destructors are handled by the dyld function:

void ImageLoaderMachO::doTermination(const LinkContext& context)

Since dyld is open source you can look at the implementation in the file ImageLoaderMachO.cpp of dyld. The source code for macOS 10.11.4 is available here.

 
 
Example of use

  • The first obvious usage is to be able to initialize some global variables with a constructor and do some cleanup with a destructor. It could be used to initialize some libraries too.
  •  

  • Another usage is code injection. In a previous post ‘Simple code injection using DYLD_INSERT_LIBRARIES’ I wrote code to replace some methods with an Objective-C +(void)load class method. Using a constructor would allow to inject code earlier in the process.
  •  

  • A constructor attribute could be used to implement a software protection. You could encrypt your executable with a custom encryption and use a constructor function to decrypt the binary just before it is loaded.

Blowfish operations with key size longer than 448 bits in macOS 10.11.5 / iOS 9.3.2

Posted: July 10th, 2016 | Author: | Filed under: iOS, MacOSX, OS X, Programming | Tags: , , , , | No Comments »

Until macOS 10.11.4 and iOS 9.3.1 CommonCrypto/corecrypto supported Blowfish operations with key sizes longer than 448 bits. Starting with macOS 10.11.5 and iOS 9.3.2 this is no longer the case: the minimum and maximum key sizes are now enforced (respectively kCCKeySizeMinBlowfish 8 bytes and kCCKeySizeMaxBlowfish 56 bytes).

This is probably the fix for CVE-2016-1802:

ACTION

If you perform a Blowfish operation with a key length longer than 448 bits, it will now fail with an error kCCParamError. Below is an example of code using a 64 bytes Blowfish key that works on macOS 10.11.4 / iOS 9.3.1 but returns an error kCCParamError on newer systems:


#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonCrypto.h>

int main(int argc, const char * argv[])
{
	@autoreleasepool
	{
		uint8_t keyData[64] =
		{
			0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
            0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
			0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
			0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
		};
		
		CCCryptorRef cryptorRef;
		CCCryptorStatus status = CCCryptorCreate(kCCDecrypt, kCCAlgorithmBlowfish, 0, keyData, sizeof(keyData), NULL, &cryptorRef);
		
		NSLog(@"CCCryptorCreate result: %d", status);
		if(status != kCCSuccess)
		{
			NSLog(@"*** CCCryptorCreate failed!!!");
		}
	}
	
    return 0;
}

If you have to support Blowfish with a key longer than 448 bits, you can’t use anymore CommonCrypto and should switch to a different implementation. Note that using Blowfish with a key longer than 448 bits is not recommended as it weakens the security guaranteed by the algorithm.


State Preservation and Restoration Debug Logs

Posted: July 8th, 2016 | Author: | Filed under: Debugging, iOS, OS X, Programming | Tags: , , , , , | No Comments »

The State Preservation and Restoration system is well documented here:
Preserving Your App’s Visual Appearance Across Launches.

But what is not well known is that there is a secret preference to enable debug logs. You can set the preference UIStateRestorationDebugLogging to YES in your main function before the call to UIApplicationMain:

[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"UIStateRestorationDebugLogging"];

There is also a less useful ‘Developer Mode’ secret preference which will skip the deletion of the restoration archive when the app crashes. To enable this mode set the preference UIStateRestorationDeveloperMode to YES in your main function before the call to UIApplicationMain:

[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"UIStateRestorationDeveloperMode"];

Identifying the type of build (Build, Archive) at compile time in Xcode

Posted: June 23rd, 2016 | Author: | Filed under: iOS, OS X, Programming, Xcode | Tags: , , , , , | No Comments »

Let’s say you want to have a different behavior in your app depending on whether you build it in Xcode or you perform an Archive. And you want this behavior to be done at compile time. Note that the use of different configurations is not what is wanted.

Here is a solution using the ‘ACTION’ Xcode property build setting. This property is documented in the Xcode Build Setting Reference:


ACTION

The ‘ACTION’ environment variable has 2 interesting values:

  • build: when the app is built
  • install: when the app is archived

Here is what you can do to identify the type of build (Build, Archive) at compile time in Xcode:

  • In the ‘Preprocessor Macros’ (GCC_PREPROCESSOR_DEFINITIONS) in the Builds Settings of your project, add:
     XCODE_ACTION_${ACTION}=1
    
  • In your precompiled prefix header for example, you can now create a define IS_ARCHIVE_BUILD:
    #if XCODE_ACTION_install
    	#define IS_ARCHIVE_BUILD	1
    #else
    	#define IS_ARCHIVE_BUILD	0
    #endif
    

You can then use the define IS_ARCHIVE_BUILD to have a different behavior at compile time. This solution works fine with Xcode 7.3.1 as well as Xcode 8.0b1. It hasn’t been tested with other Xcode versions.


Programmatically lock the screen

Posted: June 5th, 2016 | Author: | Filed under: MacOSX, OS X, Programming | Tags: , , , | No Comments »

The Keychain Access application has a preference to display a “Lock Screen” menu item in the menubar:


Keychain Access Preferences

After enabling the checkbox ‘Show keychain status in menu bar’, this menu will appear in the menubar:


Lock Screen in Menubar

This menu is located here:

/Applications/Utilities/Keychain Access.app/Contents/Resources/Keychain.menu

and it is fairly easy to find the method
-[AppleKeychainExtra _lockScreenMenuHit:].


-[AppleKeychainExtra _lockScreenMenuHit:]

That’s this simple! The method -[AppleKeychainExtra _lockScreenMenuHit:] simply calls the private method ‘SACLockScreenImmediate’ from the Login private framework. The Login framework takes care of all the hard work.

Now we can create a simple application to lock the screen. Here is the whole source code:

extern void SACLockScreenImmediate();

int main()
{
    SACLockScreenImmediate();
    return 0;
}

To compile it:

clang -F /System/Library/PrivateFrameworks -framework login -o LockScreen LockScreen.c

You can download the precompiled binary here: LockScreen.zip


Disable swipe to delete in Mail.app on OS X 10.11

Posted: May 10th, 2016 | Author: | Filed under: code injection, MacOSX, Mail, OS X | 9 Comments »

OS X 10.11 ‘El Capitan’ added a new feature to Mail.app ‘Swipe to manage your inbox’:

Swipe to manage your inbox.
Now you can take care of your email with a swipe, just like on your iOS devices. Need to triage your inbox? Swipe right to mark an email as read or unread, or swipe left to delete. You’ll be focused on what’s important in no time.


Swipe To Delete

 

I find this new feature extremely annoying as I keep triggering it by accident. Sadly it seems that there is no preference (even secret preference) to disable this feature. But the good news is that Mail.app supports plugins.

To disable this feature, I created a simple Mail.app plugin. A precompiled version for Mail 9.3 (3124)
(OS X 10.11.4) can be downloaded here: DisableSwipeGesture.mailbundle.zip

 

You can download the source code here : Download ‘DisableSwipeGesture’ Source Code

 

Installation using the precompiled version for Mail 9.3 (3124) – OS X 10.11.4:

  • Download the precompiled version
  • Unzip
  • Copy the file into ~/Library/Mail/Bundles/
  • Relaunch Mail.app

 

Installation for other versions of Mail.app:

  • Download the DisableSwipeGesture source code
  • Open the project in Xcode
  • Build
  • Relaunch Mail.app

 

How does it work?

Mail.app uses a standard NSTableView to support the swipe to delete gesture. It implements the AppKit -tableView:rowActionsForRow:edge: delegate method to add the swipe to delete feature.

Before handling a swipe event, AppKit checks if swipe to delete is supported with the internal method -(BOOL)[NSTableView _allowSwipeToDeleteForEvent:]. The default implementation checks if the NSTableView is a view based tableview and if there is a delegate. The ‘DisableSwipeGesture’ Mail plugin overrides this internal method to always return NO i.e. to never allow swipe to delete. Note that this plugin only changes the behavior of Mail.app, it does not affect any other app. However the same mechanism could be used to disable the swipe to delete feature for any OS X app supporting plugins.

 

Mail.app plugin compatibility

Before loading any plugin, Mail.app checks if the plugin’s Info.plist contains the current Mail.app ‘PluginCompatibilityUUID’ value. If this is not the case, Mail.app will refuse to load the plugin and you will see an alert:


Incompatible Plugin

If you use this ‘DisableSwipeGesture’ plugin and you update Mail.app though an OS X update, you will need to update the PluginCompatibilityUUID value in the Info.plist of the ‘DisableSwipeGesture’ plugin. The simplest solution is to recompile the plugin using the steps provided in ‘Installation for other versions of Mail.app’. The Xcode project has a build phase that will extract the PluginCompatibilityUUID from /Application/Mail.app and copy it into the Info.plist.


Checking if Reduced Motion is enabled on iOS 7

Posted: May 20th, 2014 | Author: | Filed under: Debugging, iOS, Programming | Tags: , , , | No Comments »

Apple introduced in iOS 7.0.3 a setting to reduce motion ( http://support.apple.com/kb/HT5595 ) :
Settings -> General -> Accessibility -> Reduce Motion


Reduced Motion Setting

Sadly there is no public API to know if the user enabled “Reduce motion”.
Here is how to get the value of this setting using a private API. Note that you should not use this code for applications submitted to the App Store.


#include <dlfcn.h>

+ (BOOL) reduceMotionEnabled
{
	BOOL (*_UIAccessibilityReduceMotionFunction)(void) = (BOOL (*)(void)) dlsym(RTLD_DEFAULT, "_UIAccessibilityReduceMotion");
	if(_UIAccessibilityReduceMotionFunction != NULL)
	{
		return _UIAccessibilityReduceMotionFunction();
	}
	else
	{
		NSLog(@"Unsupported: _UIAccessibilityReduceMotion does not exist on this iOS version");
		return NO;
	}
}

Edit: Apple added a public API on iOS 8:

// Returns whether the system preference for reduce motion is enabled
UIKIT_EXTERN BOOL UIAccessibilityIsReduceMotionEnabled() NS_AVAILABLE_IOS(8_0);