mirror of
https://github.com/BishopFox/bfdecrypt.git
synced 2026-11-07 09:46:06 -10:00
Easier ways to get the decrypted IPA off a device
This commit is contained in:
1 parent
dc6f9d4006
commit
351f065780
12 files changed
+271
-12
No files matched your search
+7
-3
@@ -8,8 +8,12 @@
|
||||
@property (assign) NSString *appPath;
|
||||
@property (assign) NSString *docPath;
|
||||
|
||||
- (id)initWithPathToBinary:(NSString *)pathToBinary;
|
||||
- (void)createIPAFile;
|
||||
-(id)initWithPathToBinary:(NSString *)pathToBinary;
|
||||
-(void)createIPAFile;
|
||||
-(BOOL)dumpDecryptedImage:(const struct mach_header *)image_mh fileName:(const char *)encryptedImageFilenameStr image:(int)imageNum;
|
||||
-(NSString *)IPAPath;
|
||||
-(void)IPAServer:(int)listenPort;
|
||||
-(int)getSocketForPort:(int)listenPort;
|
||||
-(NSString *)getIPAddress;
|
||||
|
||||
@end
|
||||
@end
|
||||
+154
-6
@@ -24,14 +24,27 @@
|
||||
#include <objc/runtime.h>
|
||||
#include <mach/mach.h>
|
||||
#include <err.h>
|
||||
#include <sys/param.h>
|
||||
#include <mach-o/ldsyms.h>
|
||||
#include <libkern/OSCacheControl.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/uio.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <errno.h>
|
||||
#import "SSZipArchive.h"
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#include <libkern/OSCacheControl.h>
|
||||
#include <sys/stat.h>
|
||||
#include "DumpDecrypted.h"
|
||||
#import "SSZipArchive.h"
|
||||
|
||||
//#define DEBUG(...) NSLog(__VA_ARGS__);
|
||||
#define DEBUG(...) {}
|
||||
|
||||
#define swap32(value) (((value & 0xFF000000) >> 24) | ((value & 0x00FF0000) >> 8) | ((value & 0x0000FF00) << 8) | ((value & 0x000000FF) << 24) )
|
||||
|
||||
@@ -263,6 +276,7 @@
|
||||
NSLog(@"[+] Close files.\n");
|
||||
close(fd);
|
||||
close(outfd);
|
||||
sync();
|
||||
NSLog(@"[+] Dump complete.\n");
|
||||
|
||||
return true;
|
||||
@@ -304,9 +318,114 @@
|
||||
return true;
|
||||
}
|
||||
|
||||
-(NSString *)IPAPath {
|
||||
return [NSString stringWithFormat:@"%@/decrypted-app.ipa", [self docPath]];
|
||||
}
|
||||
|
||||
// Based on code taken from Bishop Fox Firecat
|
||||
-(int)getSocketForPort:(int)listenPort {
|
||||
struct sockaddr_in a;
|
||||
int IPAServerSock, clientSock;
|
||||
int yes = 1;
|
||||
|
||||
// get a fresh juicy socket
|
||||
DEBUG(@"[dumpDecrypted] socket()");
|
||||
if((IPAServerSock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
NSLog(@"ERROR: socket()");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// make sure it's quickly reusable
|
||||
DEBUG(@"[dumpDecrypted] setsockopt()");
|
||||
if(setsockopt(IPAServerSock, SOL_SOCKET, SO_REUSEADDR, (char *) &yes, sizeof(yes)) < 0) {
|
||||
NSLog(@"ERROR: setsockopt()");
|
||||
close(IPAServerSock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// listen on all of the hosts interfaces/addresses (0.0.0.0)
|
||||
DEBUG(@"[dumpDecrypted] bind()");
|
||||
memset(&a, 0, sizeof(a));
|
||||
a.sin_port = htons(listenPort);
|
||||
a.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
a.sin_family = AF_INET;
|
||||
if(bind(IPAServerSock, (struct sockaddr *) &a, sizeof(a)) < 0) {
|
||||
NSLog(@"ERROR: bind()");
|
||||
close(IPAServerSock);
|
||||
return 0;
|
||||
}
|
||||
DEBUG(@"[dumpDecrypted] listen()");
|
||||
listen(IPAServerSock, 10);
|
||||
|
||||
return IPAServerSock;
|
||||
}
|
||||
|
||||
-(void)IPAServer:(int)listenPort {
|
||||
unsigned int i;
|
||||
struct sockaddr_in clientAddr;
|
||||
int serverSock, clientSock;
|
||||
|
||||
// get a fresh juicy socket
|
||||
DEBUG(@"[dumpDecrypted] getSocketForPort()");
|
||||
if( ! (serverSock = [self getSocketForPort:listenPort])) {
|
||||
NSLog(@"ERROR: socket()");
|
||||
return;
|
||||
}
|
||||
|
||||
i = sizeof(clientAddr);
|
||||
|
||||
NSLog(@"[bfdecrypt] Waiting for connection on port %d\n",listenPort);
|
||||
if((clientSock = accept(serverSock, (struct sockaddr *)&clientAddr, &i)) == -1) {
|
||||
NSLog(@"ERROR: accept(): %s", strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
NSLog(@"[bfdecrypt] Got connection from remote target %s\n", inet_ntoa(clientAddr.sin_addr));
|
||||
int fd = open([[self IPAPath] UTF8String], O_RDONLY);
|
||||
if(!fd) {
|
||||
NSLog(@"[bfdecrypt] Failed to open the IPA file %@!", [self IPAPath]);
|
||||
return;
|
||||
}
|
||||
|
||||
// I wanted to use sendfile(2), but it's sandboxed by the kernel.
|
||||
char buffer[65535];
|
||||
int loopCount=0, totalBytes=0;
|
||||
DEBUG(@"[bfdecrypt] Entering loop");
|
||||
while (1) {
|
||||
int bytes_read = read(fd, buffer, sizeof(buffer));
|
||||
totalBytes += bytes_read;
|
||||
DEBUG(@"[bfdecrypt] %d: Read %d (%d total) bytes from IPA file", loopCount++, bytes_read, totalBytes);
|
||||
if(bytes_read == 0) // We're done reading from the file
|
||||
break;
|
||||
|
||||
if(bytes_read < 0) {
|
||||
NSLog(@"[bfdecrypt] Failed to read() from IPA file");
|
||||
break;
|
||||
}
|
||||
|
||||
void *p = buffer;
|
||||
while(bytes_read > 0) {
|
||||
DEBUG(@"[bfdecrypt] Sending %d bytes", bytes_read);
|
||||
int bytes_written = send(clientSock, p, bytes_read, 0);
|
||||
if (bytes_written <= 0) {
|
||||
// handle errors
|
||||
NSLog(@"[bfdecrypt] Error sending!");
|
||||
break;
|
||||
}
|
||||
bytes_read -= bytes_written;
|
||||
p += bytes_written;
|
||||
}
|
||||
}
|
||||
|
||||
close(fd);
|
||||
shutdown(clientSock, SHUT_RDWR);
|
||||
shutdown(serverSock, SHUT_RDWR);
|
||||
close(clientSock);
|
||||
close(serverSock);
|
||||
}
|
||||
|
||||
-(void) createIPAFile {
|
||||
NSString *IPAFile = [NSString stringWithFormat:@"%@/decrypted-app.ipa", [self docPath]];
|
||||
NSString *IPAFile = [self IPAPath];
|
||||
NSString *appDir = [self appPath];
|
||||
NSString *appCopyDir = [NSString stringWithFormat:@"%@/ipa/Payload/%s", [self docPath], self->appDirName];
|
||||
NSString *zipDir = [NSString stringWithFormat:@"%@/ipa", [self docPath]];
|
||||
@@ -355,8 +474,37 @@
|
||||
// Clean up. Leave only the .ipa file.
|
||||
[fm removeItemAtPath:zipDir error:nil];
|
||||
|
||||
NSLog(@"[dumpdecrypted] Wrote %s/decrypted-app.ipa", [[self docPath] UTF8String]);
|
||||
NSLog(@"[dumpdecrypted] Wrote %@", [self IPAPath]);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// https://stackoverflow.com/questions/6807788/how-to-get-ip-address-of-iphone-programmatically
|
||||
- (NSString *)getIPAddress {
|
||||
|
||||
NSString *address = @"error";
|
||||
struct ifaddrs *interfaces = NULL;
|
||||
struct ifaddrs *temp_addr = NULL;
|
||||
int success = 0;
|
||||
// retrieve the current interfaces - returns 0 on success
|
||||
success = getifaddrs(&interfaces);
|
||||
if (success == 0) {
|
||||
// Loop through linked list of interfaces
|
||||
temp_addr = interfaces;
|
||||
while(temp_addr != NULL) {
|
||||
if(temp_addr->ifa_addr->sa_family == AF_INET) {
|
||||
// Check if interface is en0 which is the wifi connection on the iPhone
|
||||
if([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"]) {
|
||||
// Get NSString from C String
|
||||
address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
|
||||
}
|
||||
}
|
||||
temp_addr = temp_addr->ifa_next;
|
||||
}
|
||||
}
|
||||
// Free memory
|
||||
freeifaddrs(interfaces);
|
||||
return address;
|
||||
}
|
||||
|
||||
@end
|
||||
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
Regular → Executable
BIN
Binary file not shown.
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.apple.xcode.dsym.bfdecrypt.dylib</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>dSYM</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</plist>
|
||||
Binary file not shown.
+90
-3
@@ -11,20 +11,107 @@
|
||||
#include <stdlib.h>
|
||||
#include <dlfcn.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#include <stdint.h>
|
||||
#include "DumpDecrypted.h"
|
||||
|
||||
#define PORT 31336
|
||||
//#define DEBUG(...) NSLog(__VA_ARGS__);
|
||||
#define DEBUG(...) {}
|
||||
|
||||
// The dylib constructor sets decryptedIPAPath, spawns a thread to do the app decryption, then exits.
|
||||
__attribute__ ((constructor)) static void bfinject_rocknroll() {
|
||||
NSLog(@"[bfdecrypt] Spawning thread to do decryption in the background...");
|
||||
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
NSLog(@"[bfdecrypt] Inside decryption thread");
|
||||
const char *fullPathStr = _dyld_get_image_name(0);
|
||||
|
||||
NSLog(@"[bfdecrypt] Inside thread. Full path to app: %s", fullPathStr);
|
||||
DumpDecrypted *dd = [[DumpDecrypted alloc] initWithPathToBinary:[NSString stringWithUTF8String:fullPathStr]];
|
||||
if(!dd) {
|
||||
NSLog(@"[bfdecrypt] ERROR: failed to get DumpDecrypted instance");
|
||||
return;
|
||||
}
|
||||
|
||||
NSLog(@"[bfdecrypt] Full path to app: %s /// IPA File: %@", fullPathStr, [dd IPAPath]);
|
||||
|
||||
// Show a "Decrypting!" alert on the device and block the UI
|
||||
UIAlertController *alertController = [UIAlertController
|
||||
alertControllerWithTitle:@"Decrypting"
|
||||
message:@"Please wait, this will take a few seconds..."
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
UIViewController *root = [[[UIApplication sharedApplication] keyWindow] rootViewController];
|
||||
[root presentViewController:alertController animated:YES completion:nil];
|
||||
|
||||
// Do the decryption
|
||||
[dd createIPAFile];
|
||||
|
||||
// Dismiss the alert box
|
||||
[alertController dismissViewControllerAnimated:NO completion:nil];
|
||||
|
||||
// Would the user like to host the IPA on a port for easy retrieval with NetCat?
|
||||
NSString *message = [NSString stringWithFormat:@"Would you like to serve the IPA on %@:31336 for retrieval with NetCat?\nYou can use nc %@:31336 > /tmp/decrypted.ipa.", [dd getIPAddress], [dd getIPAddress]];
|
||||
alertController = [UIAlertController
|
||||
alertControllerWithTitle:@"Decryption Complete!"
|
||||
message:message
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
UIAlertAction *cancelAction = [UIAlertAction
|
||||
actionWithTitle:NSLocalizedString(@"No", @"Cancel action")
|
||||
style:UIAlertActionStyleCancel
|
||||
handler:^(UIAlertAction *action)
|
||||
{
|
||||
NSLog(@"Cancel action");
|
||||
[alertController dismissViewControllerAnimated:NO completion:nil];
|
||||
}];
|
||||
|
||||
UIAlertAction *okAction = [UIAlertAction
|
||||
actionWithTitle:NSLocalizedString(@"Yes", @"OK action")
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction *action)
|
||||
{
|
||||
NSLog(@"OK action");
|
||||
|
||||
// Removing the "Decryption Complete!" alert
|
||||
[alertController dismissViewControllerAnimated:NO completion:nil];
|
||||
|
||||
// Spawn server on port 31336 by default
|
||||
// Connections to this port will be sent a raw copy of the IPA file.
|
||||
NSLog(@"[bfdecrypt] Checking we can start the server...");
|
||||
int s;
|
||||
if( ! (s = [dd getSocketForPort:PORT])) {
|
||||
// Port 31336 isn't available. Something listening?
|
||||
NSLog(@"[bfdecrypt] Couldn't listen on port %d, is another decrypted app still running?", PORT);
|
||||
UIAlertController *errorController = [UIAlertController
|
||||
alertControllerWithTitle:@"Error!"
|
||||
message:@"Could not start server on port 31336, perhaps there's another decryption server already listening?"
|
||||
preferredStyle:UIAlertControllerStyleAlert
|
||||
];
|
||||
[errorController addAction:[UIAlertAction
|
||||
actionWithTitle:NSLocalizedString(@"Ok", @"Ok")
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction *action)
|
||||
{
|
||||
NSLog(@"Cancel action");
|
||||
[errorController dismissViewControllerAnimated:NO completion:nil];
|
||||
}]
|
||||
];
|
||||
[root presentViewController:errorController animated:YES completion:nil];
|
||||
} else {
|
||||
close(s);
|
||||
NSLog(@"[bfdecrypt] Yes we can, starting now.");
|
||||
[dd IPAServer:PORT];
|
||||
NSLog(@"[bfdecrypt] IPAServer finished.");
|
||||
}
|
||||
}];
|
||||
|
||||
[alertController addAction:cancelAction];
|
||||
[alertController addAction:okAction];
|
||||
[root presentViewController:alertController animated:YES completion:nil];
|
||||
|
||||
NSLog(@"[bfdecrypt] Over and out.");
|
||||
while(1)
|
||||
sleep(9999999);
|
||||
});
|
||||
|
||||
NSLog(@"[bfdecrypt] Exiting constructor.");
|
||||
NSLog(@"[bfdecrypt] All done, exiting constructor.");
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user