2014年4月8日 星期二

AES-128 JPG 解碼


這兩天愛上學習 iOS 應用程式的保安知識。越學越感受到 iOS 及 Objective-C 的強大;也越來越覺得「道高一尺,魔高一丈」,難怪 iOS 一直都能被 Jailbreak...。圖中是被加密的 JPG,一直都解不開。但利用這兩天學到的工具:Snoop-it,很容易便得出是 AES-128 加密的結果。再配合編寫 Objective-C 程式,便能順利還回 JPG 的原貌。
//
//  main.m
//  AESDecode
//
//  Created by Pacess on 8/4/14.
//  Copyright (c) 2014 Pacess. All rights reserved.
//

#include <CommonCrypto/CommonCryptor.h>
#include <Foundation/Foundation.h>
#include <unistd.h>
#include <fcntl.h>

@interface NSData(AES)
- (NSData *)decryptedDataUsingAESKey:(NSData *)key;
@end

@implementation NSData(AES)

- (NSData *)decryptedDataUsingAESKey:(NSData *)key  {
   const uint8_t *bytePointer = [self bytes];
   size_t length = [self length];
   if (length < kCCBlockSizeAES128)  {return nil;}

   size_t decodeSize = 0;
   CCCryptorStatus result = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                    [key bytes], [key length],
                                    bytePointer,
                                    bytePointer+kCCBlockSizeAES128, length-kCCBlockSizeAES128,
                                    NULL, 0,
                                    &decodeSize);
   if (result != kCCBufferTooSmall)  {return nil;}

   void *decodePointer = malloc(decodeSize);
   if (decodePointer == nil)  {return nil;}

   result = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                    [key bytes], [key length],
                    bytePointer,
                    bytePointer+kCCBlockSizeAES128, length-kCCBlockSizeAES128,
                    decodePointer, decodeSize,
                    &decodeSize);
   if (result != kCCSuccess)  {free(decodePointer);  return nil;}
   
   NSData *decodedData = [NSData dataWithBytesNoCopy:decodePointer length:decodeSize];
   if (decodedData == nil)  {free(decodePointer);  return nil;}
   return decodedData;
}

@end

int main(int argc, char * argv[])  {
   @autoreleasepool {

      char *aes128Key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
      NSData *key = [NSData dataWithBytesNoCopy:(aes128Key) length:sizeof(aes128Key)-1 freeWhenDone:0];
      int pages[] = {0, 32, 104, 105, 106, 108, -1};

      NSString *applicationDirectory = [[NSBundle mainBundle] bundlePath];
      NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
      NSString *documentsDirectory = [paths objectAtIndex:0];

      int index = 0;
      while (pages[index] >= 0)  {

         int pageID = pages[index++];
         NSString *filename = [NSString stringWithFormat:@"%03d.jpg", pageID];
         NSString *filePath = [applicationDirectory stringByAppendingPathComponent:filename];
         NSData *aes128Data = [NSData dataWithContentsOfFile:filePath];

         NSData *jpgData = [aes128Data decryptedDataUsingAESKey:key];
         filename = [@"Decoded_" stringByAppendingString:filename];
         filePath = [documentsDirectory stringByAppendingPathComponent:filename];
         [jpgData writeToFile:filePath atomically:NO];
      }
      return 0;
   }
}

2 則留言:

Benny 提到...

你好,最近我也遇到需將iOS的APP的資料進行加密的問題,可以請問一下,你是如何找出AES的key值?感謝。

Pacess HO 提到...

Benny 你好。Snoop-it 會一直監測所有加密動作,所以當發生 AES 解碼時,它連 AES Key 也記錄了。在加密介面已經可以方便查閱,不用自行去尋找。