Skip to content

Instantly share code, notes, and snippets.

@eybisi
Created June 28, 2022 18:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eybisi/c589ab1a40a2faf701750cad74658960 to your computer and use it in GitHub Desktop.
Save eybisi/c589ab1a40a2faf701750cad74658960 to your computer and use it in GitHub Desktop.

CFF definition (Sample : 92ae23580c83642ad0e50f19979b9d2122f28d8b3a9d4b17539ce125ae8d93eb)

cff blocks is equal to number of sparse-switch-payload count

  • first bytecode of function is initialization for cff which sets str
1a00(switch reg) ????(strId) -> const string v0, "xxxx"string@strId 
  • each block dispatcher startswith
6e10 ????(methodId) 0000(switch reg) -> invoke-virtual      {v0}, Ljava/lang/String;->hashCode()I # method@d71d

v0 holds object to be hashCode'd.

  • block dispatcher ends with sparse-switch instruction:
2c 01(reg that holds calculated value) 1600 0000(offset to sparse-switch-payload) -> sparse-switch v1, :s_switch_t 

0x8ca750+(0x16*2) = 0x8ca77c payload table

  • hashCode object is always stored at register switch reg. Therefore each block ends with:
1a00(switch reg) ???? -> const v0, "xxxx"`
28?? -> goto :current_block_dispatcher

example cff'ed function:


Class: Lcom/plus/currencyconverter/virtual/model/VirtualRatesModel;
.method public b(Lretrofit2/d;Ljava/lang/Throwable;)V
    .registers 7
    
    .param p1, "":Lretrofit2/d;
    .param p2, "":Ljava/lang/Throwable;
    
    008ca72c: 1a00 9db7               0000: const-string        v0, "ۜۗۛۘۡۨۘۙۜۧۘۜۙ۠ۛۧۢۥۢۚ۬۬ۥۘۦۥۦۘ۫۠ۤۤۧۡۘ۟۫ۦۘۗۙۖۘ۟ۗ۠ۜۨۢۢ۫ۢۚۡۚ" # string@b79d
                            goto_0002: # 5 refs
    008ca730: 6e10 1dd7 0000          0002: invoke-virtual      {v0}, Ljava/lang/String;->hashCode()I # method@d71d
    008ca736: 0a01                    0005: move-result         v1
    008ca738: 1302 c001               0006: const/16            v2, 0x1c0
    008ca73c: b721                    0008: xor-int/2addr       v1, v2
    008ca73e: d711 b302               0009: xor-int/lit16       v1, v1, 0x2b3
    008ca742: 1302 c100               000b: const/16            v2, 0xc1
    008ca746: 1403 3623 0e8d          000d: const               v3, -1928453322
    008ca74c: b721                    0010: xor-int/2addr       v1, v2
    008ca74e: b731                    0011: xor-int/2addr       v1, v3
    008ca750: 2c01 1600 0000          0012: sparse-switch       v1, :s_switch_0028
    008ca756: 28ed                    0015: goto                :goto_0002
                          s_case_0016: # case 1952522358
    008ca758: 1a00 6ebd               0016: const-string        v0, "۟ۥۦۘ۠ۧۨۘۡۤ۟ۗۧۥۘۛۨۖۘۤۢۜۦۗ۬ۧۦ۬ۚ۟ۤۤۜۨۚۛۖۧۧۡۘۡۡۚ۠ۦۚۡ۬ۚ۟ۖۙ" # string@bd6e
    008ca75c: 28ea                    0018: goto                :goto_0002
                          s_case_0019: # case 680223507
    008ca75e: 1a00 3ba3               0019: const-string        v0, "ۖ۟ۡ۬ۛۗۦۥۨۘۛۧۘۘۚۤۥ۟۠ۚۢ۟ۧۦۦۡۘ۟ۛ۬۠ۤۤ" # string@a33b
    008ca762: 28e7                    001b: goto                :goto_0002
                          s_case_001c: # case -1353228980
    008ca764: 1a00 7ad4               001c: const-string        v0, "ۧۗۤۨۡۢ۫۠ۘ۫ۙۡۘۛۨ۬ۛ۟ۡۘۥۦۨۘ۫ۨۡۘۡۚ۠ۥ۬" # string@d47a
    008ca768: 28e4                    001e: goto                :goto_0002
                          s_case_001f: # case 1753120390
    008ca76a: 5440 1866               001f: iget-object         v0, p0, Lcom/plus/currencyconverter/virtual/model/VirtualRatesModel$a;->a:Lcom/plus/currencyconverter/d/b$a; # field@6618
    008ca76e: 7210 87c8 0000          0021: invoke-interface    {v0}, Lcom/plus/currencyconverter/d/b$a;->b()V # method@c887
    008ca774: 1a00 25cf               0024: const-string        v0, "ۥۢ۫ۜ۬۫۬ۤۢۡۛۜۘۘۡۜۦۨۘۧۤۖۥۡۜۗۥۢۚۤ۟ۨۦۘ۟ۜۢۦۦ۫۬۫۟ۚ۫ۙ۟ۢۙۤۤۜۥۥ" # string@cf25
    008ca778: 28dc                    0026: goto                :goto_0002
                          s_case_0027: # case -818024012
    008ca77a: 0e00                    0027: return-void         
                        s_switch_0028:
    008ca77c: 0002 0500 4c5d 57af ... 0028: sparse-switch-payload
                                                case -1353228980: -> :s_case_001c
                                                case -818024012: -> :s_case_0027
                                                case 680223507: -> :s_case_0019
                                                case 1753120390: -> :s_case_001f
                                                case 1952522358: -> :s_case_0016
                                            .end payload

how to fix it

  • Identify init, dispatcher and blocks.
  • Extract switch function (dispatcher)
  • Start from init, store each sparse-switch-payload
  • remove reduntant codes (const string and goto) and add block codes to each other
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment