Android 逆向 | 不是加密的 Base64

2021-02-15 鹹魚學Python

Base64 就是一種基於 64 個可列印字符來表示二進位數據

Base64,就是說選出64個字符----小寫字母a-z、大寫字母A-Z、數字0-9、符號"+"、"/"(再加上作為墊字的"=",實際上是65個字符)作為一個基本字符集。然後,其他所有符號都轉換成這個字符集中的字符
                                                                       -- 選自《阮一峰老師的博客》

Base 系列還有 16/32/62/64/85/36/58/91/92 等,分別表示用不同個數的可列印字符表示二進位數據

那麼為什麼會用 Base 系列算法?

有的字符在一些環境中是不能顯示或使用的,比如 &, = 等字符在 URL 被保留為特殊作用的字符;

比如描述一張圖片,而圖片中的二進位碼如果轉成對應的字符的話,會有很多不可見字符和控制符(如換行、回車之類),這時就需要對進行編碼。

Base 系列的就是用來將字節編碼為 ASCII 中的可見字符的。

這個在之前也有一篇文章用來描述關於請求中傳遞驗證碼使用的就是base64

文末彩蛋 | 這個 Request URL 長得好不一樣

他的本質其實就是把原本不好顯示的字符切片分組後用好顯示的ascii碼來展示

今天就講講base64對字符做了啥?

第一種

待轉換的字符串長度正好是 3 的整數倍

三個字符Man,轉換示意圖如下

1、把待轉換的字符串,分割成 3 個一組,並且轉換為共 24 個的二進位位2、將轉換好的二進位位再按照每 6 個一組整成 4 組4、將補成的 8 位的二進位數據轉化為 10 進位數5、將轉化為的 10 進位數對照 Base64 的碼錶注意轉化為碼錶中的字符,得出Base64的編碼

如果一個編碼後的 base64 編碼是沒有等號填充的,那麼說明原字符的長度是 3 的整數倍

第二種

待轉換的字符串長度正好比 3 的整數倍多 1 個字節或 2 個字節

像單個字符A,轉換示意圖如下

一個字節:一個字節共 8 個二進位位,依舊按照規則進行分組。此時共 8 個二進位位,每 6 個一組,則第二組缺少 4 位後面用 0 補齊得,得到兩個 Base64 編碼,而後面兩組沒有對應數據,都用 「 = 」 補上。

像兩個字符AB,轉換示意圖如下

兩個字節:兩個字節共 16 個二進位位,依舊按照規則進行分組。此時總共 16 個二制位,每 6 個一組,則第三組缺少 2 位,用 0 補齊,得到三個 Base64 編碼,第四組完全沒有數據則用 「 = 」 補上。

按照上面的算法,我們可以得到以下規律

如果後面填充一個=那麼原文長度是 3n + 2 的長度

如果後面填充的是兩個=,那麼原文長度是 3n + 1 長度

逆向反推快速識別

知道原理之後,快速用代碼實現以下:

Python 無中文字符版:

import base64
str_encrypt="aaaa"
# 不要使用 base64.encodebytes(rq_time.encode()).decode()
base64_encrypt=base64.b64encode(str_encrypt.encode('utf-8')).decode()
print(base64_encrypt)

Python 含中文字符版:

"""
base64實現
"""

import base64
import string

# base 字符集

base64_charset = string.ascii_uppercase + string.ascii_lowercase + string.digits + '+/'


def encode(origin_bytes):
    """
    將bytes類型編碼為base64
    :param origin_bytes:需要編碼的bytes
    :return:base64字符串
    """

    # 將每一位bytes轉換為二進位字符串
    base64_bytes = ['{:0>8}'.format(str(bin(b)).replace('0b', '')) for b in origin_bytes]

    resp = ''
    nums = len(base64_bytes) // 3
    remain = len(base64_bytes) % 3

    integral_part = base64_bytes[0:3 * nums]
    while integral_part:
        # 取三個字節,以每6比特,轉換為4個整數
        tmp_unit = ''.join(integral_part[0:3])
        tmp_unit = [int(tmp_unit[x: x + 6], 2) for x in [0, 6, 12, 18]]
        # 取對應base64字符
        resp += ''.join([base64_charset[i] for i in tmp_unit])
        integral_part = integral_part[3:]

    if remain:
        # 補齊三個字節,每個字節補充 0000 0000
        remain_part = ''.join(base64_bytes[3 * nums:]) + (3 - remain) * '0' * 8
        # 取三個字節,以每6比特,轉換為4個整數
        # 剩餘1位元組可構造2個base64字符,補充==;剩餘2位元組可構造3個base64字符,補充=
        tmp_unit = [int(remain_part[x: x + 6], 2) for x in [0, 6, 12, 18]][:remain + 1]
        resp += ''.join([base64_charset[i] for i in tmp_unit]) + (3 - remain) * '='

    return resp


def decode(base64_str):
    """
    解碼base64字符串
    :param base64_str:base64字符串
    :return:解碼後的bytearray;若入參不是合法base64字符串,返回空bytearray
    """
    if not valid_base64_str(base64_str):
        return bytearray()

    # 對每一個base64字符取下標索引,並轉換為6為二進位字符串
    base64_bytes = ['{:0>6}'.format(str(bin(base64_charset.index(s))).replace('0b', '')) for s in base64_str if
                    s != '=']
    resp = bytearray()
    nums = len(base64_bytes) // 4
    remain = len(base64_bytes) % 4
    integral_part = base64_bytes[0:4 * nums]

    while integral_part:
        # 取4個6位base64字符,作為3個字節
        tmp_unit = ''.join(integral_part[0:4])
        tmp_unit = [int(tmp_unit[x: x + 8], 2) for x in [0, 8, 16]]
        for i in tmp_unit:
            resp.append(i)
        integral_part = integral_part[4:]

    if remain:
        remain_part = ''.join(base64_bytes[nums * 4:])
        tmp_unit = [int(remain_part[i * 8:(i + 1) * 8], 2) for i in range(remain - 1)]
        for i in tmp_unit:
            resp.append(i)

    return resp


def valid_base64_str(b_str):
    """
    驗證是否為合法base64字符串
    :param b_str: 待驗證的base64字符串
    :return:是否合法
    """
    if len(b_str) % 4:
        return False

    for m in b_str:
        if m not in base64_charset:
            return False
    return True


if __name__ == '__main__':
    s = '我的目標是星辰大海. One piece, all Blue'.encode()
    local_base64 = encode(s)
    print('使用本地base64加密:', local_base64)
    b_base64 = base64.b64encode(s)
    print('使用base64加密:', b_base64.decode())

    print('使用本地base64解密:', decode(local_base64).decode())
    print('使用base64解密:', base64.b64decode(b_base64).decode())

Java 版快速實現:

import sun.misc.BASE64Encoder;
public class Base64Utils {

 public static void main(String[] args) {
  String man = "Man";
  String a = "A";
  String bc = "BC";

  BASE64Encoder encoder = new BASE64Encoder();
  System.out.println("Man base64結果為:" + encoder.encode(man.getBytes()));
  System.out.println("BC base64結果為:" + encoder.encode(bc.getBytes()));
  System.out.println("A base64結果為:" + encoder.encode(a.getBytes()));
 }
}

這裡為什麼強調有中文版和無中文版的 base64 算法呢?

因為按照上面的的示意圖可以知道,我們第一步是將代碼轉化為ascii碼之後再轉化為二進位的,但是ascii碼中並沒有包含中文

所以其他的字符集就需要統一轉化為二進位之後再分割,中文就是要同一編碼方式,例如同一使用utf-8字符集轉化為二進位之後分割

知道算法原理和規律有什麼用?

知道算法原理和規律有助於我們快速識別這個編碼方式是不是簡單常用的算法,一定程度上減輕 app 逆向的工作量

我們主要需要快速識別下面幾個要素,就能幫助我們在判斷 APP 加密/編碼方式的時候減少工作量:

Love&Share 

[ 完 ]

對了,看完記得一鍵四連,這個對我真的很重要。

相關焦點

  • 一文讀懂base64
    二、什麼是 base64Base64 是一種基於 64 個可列印字符來表示二進位數據的表示方法。由於 2⁶ = 64 ,所以每 6 個比特為一個單元,對應某個可列印字符。3 個字節有 24 個比特,對應於 4 個 base64 單元,即 3 個字節可由 4 個可列印字符來表示。
  • 網絡安全加密——DES、AES、RSA、Base64、MD5加密原理介紹,代碼實現
    :(NSData *)key;#pragma mark - DES解密/* DES解密,字符串必須為base64格式,key為字符串形式 */- (NSString *)desDecryptWithKey:(NSString *)key;/* DES解密 *
  • 【拓展】868- 一文讀懂base64
    二、什麼是 base64Base64 是一種基於 64 個可列印字符來表示二進位數據的表示方法。由於 2⁶ = 64 ,所以每 6 個比特為一個單元,對應某個可列印字符。3 個字節有 24 個比特,對應於 4 個 base64 單元,即 3 個字節可由 4 個可列印字符來表示。
  • Android逆向之旅--「最右」籤名算法解析(ARM指令學習噁心篇)
    這裡有一段初始化代碼,不過我們通過簡單分析之後發現其實沒那麼難,這一段可以直接閱讀以下,這裡會判斷當前字符串的信息是否大於64,如果小於64就把後面的數據補0,這裡可以看到是分組進行數據操作的,一組數據是64個字節,會把加密數據用分組的形式進行操作
  • 一次逆向解密的解讀
    前提       本文為攻防世界的CTF題目web分項裡面的一道逆向解密題目
  • SpyNote5.0 Client_APK逆向分析
    準備工具對於SpyNote5.0 Client_APK的逆向分析卻鮮有人問津,下面我簡單介紹使用工具,然後開始進入逆向分析環節。開始逆向分析咱們開始對於Client_APK進行分析,通常喜歡將客戶端生成的APK程序拖入androidkiller。(如何生成客戶端請見上文的幾篇文章) 拖入程序後androidkiller會自動進行反彙編,然後有程序分析結果。
  • 爬蟲js逆向之加密參數破解--抖音第三方數據分析平臺的坑
    爬蟲js逆向系列我會把做爬蟲過程中,遇到的所有js逆向的問題分類展示出來,以現象,解決思路,以及代碼實現
  • 【Android 原創】從OWASP CrackMe學Android逆向(二)
    作者論壇帳號:Se8s0n前言從OWASP CrackMe學Android逆向(一)感覺用題目來學習會比之前學得內容多很多
  • 記一次APP的java層算法逆向(六)
    「 前言:初學逆向 請多多指教,然後這些都只是做個學習筆記給自己學習,順便分享給大家,並不是個人原創!
  • 好課資源共享:android逆向
    android逆向511.Java版)尚學堂2020java全套視頻教程200G(每月更新)軟體破解逆向工程實戰 - 第六期  DLL黑客 作弊開發訓練營巧匠電商視覺實戰設計視頻教程28期前端Vue3.0從0到1手把手擼碼搭建管理後臺系統暖石100 零基礎入職網際網路運營(完結)逆冬2020權重站教程黑馬·C++ 24期就業班(高清不加密
  • 【小程序】某小程序應用請求頭籤名校驗逆向
    小程序請求頭籤名校驗逆向破解渣男說,他最近需要對一個小程序做爬蟲,但是這個小程序有請求頭籤名校驗,於是撿來分析一下root手機抓包使用root手機得到首頁的請求信息如下,一看就知道其中souche-sign、mini-app-token、sso-token是重點分析對象GET /
  • android so逆向專題及常見問題 - CSDN
    Bcc signed_immed_81101 1111 vvvv vvvv -- SWI immed_81110 0vvv vvvv vvvv -- B   signed_immed_11111h hvvv vvvv vvvv -- BL(X) immed_11複製代碼0x02 示例先對上篇文章中的switch分支進行逆向
  • 小生淺談Java層逆向,【Android逆向技術】
    我們都知道安卓應用是可以用多種語言來進行開發的,而且根據不同的語言我們也有不同的逆向方式,今天小生就給大家介紹介紹在眾多語言中相對簡單一點的java,我們稱之為java層逆向
  • Android算法逆向學習筆記之2016騰訊遊戲安全移動賽題Tencent2016A(含註冊機)
    printf("密碼是:%s",pwd); system("pause"); return 0;}base64.hstd::string base64_decode(std::string const& s);base64.cpp#include "base64.h"#include <iostream>
  • InjuredAndroid 1-5
    : null  b3nac.injuredandroid.b25lActivity    Permission: null  b3nac.injuredandroid.TestBroadcastReceiver    Permission: null  com.google.firebase.auth.internal.FederatedSignInActivity
  • php幾種常用的加密解密算法
    "\n";可逆轉的加密為:base64_encode()、urlencode() 、mcrypt_encrypt()、rawurlencode()相對應的解密函數:base64_decode() 、urldecode() 、mcrypt_decrypt()、rawurldecode()mcrypt_encrypt()—使用給定參數加密明文
  • 【安卓逆向之密碼學】從一個簡單的AES-256-CBC開始
    很久沒寫文章了,我又回來了,這回開始,應該會慢慢更新一些有關安卓逆向中的學習記錄,主要的目的還是鞏固自己的學習,不做筆記學習的東西容易忘記,當然,如果給大家帶來了收穫,別忘了點讚、收藏和轉發,哈哈哈今天要帶來的是一個有關AES加密相關的APP分析,如果參加了看雪高研安卓班的話,應該就知道我說的是哪個了。話不多說,直接開始。
  • Coinbase攜手WeGift推出數字禮品卡 支持加密貨幣支付
    近日,加密貨幣服務商Coinbase宣布與數字禮品卡提供商WeGift合作提出一個數字禮品卡服務,滿足加密貨幣用戶日常購物的需求。加密貨幣反對人士的一個觀點就是一般商店不會接受這種虛擬貨幣,而Coinbase這次的服務就是要解決這個問題。
  • 加密貨幣信用卡來了!VISA 金融卡「Coinbase Card」在德法意等國...
    所有擁有 Coinbase 帳戶的用戶,都可以在任何接受 Visa 付款的實體或線上商家使用 Coinbase Card,並以比特幣(BTC)、以太幣(ETH)和萊特幣(LTC)等加密貨幣支付。Coinbase 於 4 月首次推出「Visa 加密貨幣金融卡」,與英國支付處理商 PaySafe 合作發行。當時僅在英國發行,如今他們履行了承諾,將版圖擴展到另外六個國家。
  • 好課分享:易錦大學安卓逆向第2期125講-無key
    .mp4  125.35M|   |   ├──020課 冒泡排序算法分析.mp4  137.20M|   |   ├──021課 關鍵android_server文件檢測.mp4  67.03M|   |   ├──022課 IDA調試埠檢測.mp4  70.75M|   |   ├──023課 ELF可執行程序加載so庫.mp4  129.77M