鍍金池/ 教程/ iOS/ 鍵盤緩存與安全鍵盤
Hack 實(shí)戰(zhàn)——支付寶 App 手勢密碼校驗(yàn)欺騙
使用 Reveal 分析他人 App
后臺 daemon 非法竊取用戶 iTunesstore 信息
使用 iNalyzer 分析應(yīng)用程序
越獄檢測的攻與防
使用 introspy 追蹤分析應(yīng)用程序
廢除應(yīng)用程序的 ASLR 特性
使用 Cycript 修改支付寶 App 運(yùn)行時(shí)
敏感邏輯的保護(hù)方案
Fishhook
使用 class-dump-z 分析支付寶 App
static 和被裁的符號表
iOS7 的動態(tài)庫注入
二進(jìn)制和資源文件自檢
Hack 實(shí)戰(zhàn)——探究支付寶 App 手勢密碼
使用 Keychain-Dumper 導(dǎo)出 keychain 數(shù)據(jù)
數(shù)據(jù)擦除
Hack 實(shí)戰(zhàn)——解除支付寶 App 手勢解鎖錯(cuò)誤次數(shù)限制
Objective-C 代碼混淆
阻止 GDB 依附
基于腳本實(shí)現(xiàn)動態(tài)庫注入
Hack 必備的命令與工具
鍵盤緩存與安全鍵盤
數(shù)據(jù)保護(hù) API

鍵盤緩存與安全鍵盤

大部分中文應(yīng)用彈出的默認(rèn)鍵盤是簡體中文輸入法鍵盤,在輸入用戶名和密碼的時(shí)候,如果使用簡體中文輸入法鍵盤,輸入英文字符和數(shù)字字符的用戶名和密碼時(shí),會自動啟動系統(tǒng)輸入法自動更正提示,然后用戶的輸入記錄會被緩存下來。

系統(tǒng)鍵盤緩存最方便拿到的就是利用系統(tǒng)輸入法自動更正的字符串輸入記錄。 緩存文件的地址是:
/private/var/mobile/Library/Keyboard/dynamic-text.dat

導(dǎo)出該緩存文件,查看內(nèi)容,欣喜的發(fā)現(xiàn)一切輸入記錄都是明文存儲的。因?yàn)橄到y(tǒng)不會把所有的用戶輸入記錄都當(dāng)作密碼等敏感信息來處理。 一般情況下,一個(gè)常規(guī) iPhone 用戶的 dynamic-text.dat 文件,高頻率出現(xiàn)的字符串就是用戶名和密碼。

所以,一般銀行客戶端 app 輸入密碼時(shí)都不使用系統(tǒng)鍵盤,而使用自己定制的鍵盤,原因主要有 2 個(gè):

1)避免第三方讀取系統(tǒng)鍵盤緩存

2)防止屏幕錄制 (自己定制的鍵盤按鍵不加按下效果)

那么,如何實(shí)現(xiàn)自定義安全鍵盤呢?大致思路如下:

1)首先捕獲系統(tǒng)鍵盤的彈出、收回通知
2)創(chuàng)建一個(gè)更高級別的 window 擋住系統(tǒng)鍵盤
3)需要拋出一個(gè) idtextInput 的弱引用切換焦點(diǎn)

下面給出一個(gè)簡單的安全鍵盤模型:

@interface WQSafeKeyboard : UIWindow  

@property (nonatomic, weak, setter = focusOnTextFiled:) UITextField *textFiled;  
+ (WQSafeKeyboard *)deploySafeKeyboard;  
@end  

@interface WQSafeKeyboard()  

@property (nonatomic, strong)WQInterKeyboard *keyboard;  
@end  

@implementation WQSafeKeyboard  

+ (WQSafeKeyboard *)deploySafeKeyboard  
{  
    WQSafeKeyboard *kb = [[WQSafeKeyboard alloc]init];  
    [kb addObserver];  
    return kb;  
}  

- (instancetype)init  
{  
    if (self = [super init]) {  
        self.windowLevel = UIWindowLevelAlert;  
        self.frame = CGRectZero;  
        self.rootViewController = self.keyboard;  
    }  
    return self;  
}  

- (void)dealloc  
{  
    [[NSNotificationCenter defaultCenter] removeObserver:self];  
}  

- (WQInterKeyboard *)keyboard  
{  
    if (!_keyboard) {  
        _keyboard = [[WQInterKeyboard alloc]init];  
    }  
    return _keyboard;  
}  

- (void)focusOnTextFiled:(UITextField *)textFiled  
{  
    _textFiled = textFiled;  
    self.keyboard.textField = _textFiled;  
}  

- (void)addObserver  
{  
    [[NSNotificationCenter defaultCenter]addObserver:self  
                                            selector:@selector(keyboardWillShow:)  
                                                name:UIKeyboardWillShowNotification  
                                              object:nil];  
    [[NSNotificationCenter defaultCenter]addObserver:self  
                                            selector:@selector(keyboardWillHide:)  
                                                name:UIKeyboardWillHideNotification  
                                              object:nil];  
}  

- (void)keyboardWillShow:(NSNotification *)notification  
{  
    if (![self.textFiled isFirstResponder]) {  
        return;  
    }  
    [self keyboardAnimationWithNotification:notification];  
}  

- (void)keyboardWillHide:(NSNotification *)notification  
{  
    if (![self.textFiled isFirstResponder]) {  
        return;  
    }  
    [self keyboardAnimationWithNotification:notification];  
}  

- (void)keyboardAnimationWithNotification:(NSNotification *)notification  
{  
    [self makeKeyAndVisible];  
    NSDictionary *userInfo = [notification userInfo];  
    CGRect kbFrame_end,kbFrame_begin;  
    NSTimeInterval animationDuration;  
    UIViewAnimationCurve animationCurve;  
    [userInfo[UIKeyboardFrameEndUserInfoKey] getValue:&kbFrame_end];  
    [userInfo[UIKeyboardFrameBeginUserInfoKey] getValue:&kbFrame_begin];  
    [userInfo[UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];  
    [userInfo[UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];  

    self.frame = [self resizeFrameToAdjust:kbFrame_begin];  
    [UIView animateWithDuration:animationDuration  
                          delay:0  
                        options:(animationCurve<<16)  
                     animations:^{  
                         self.frame = [self resizeFrameToAdjust:kbFrame_end];  
                     }completion:^(BOOL finished) {  

                     }];  
    if ([notification.name isEqualToString:UIKeyboardWillHideNotification]) {  
        [self resignKeyWindow];  
    }  
}  

- (CGRect)resizeFrameToAdjust:(CGRect)frame  
{  
    if ([[UIApplication sharedApplication] isStatusBarHidden] )  
        return frame;  

    if (SYSTEM_VERSION_LESS_THAN(@"7.0")) {  
        frame = CGRectMake(frame.origin.x,  
                           frame.origin.y - STATUSBAR_HEIGHT,  
                           frame.size.width,  
                           frame.size.height);  
    }  
    return frame;  
}  

@end