<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    黑盒破解

    這個題目比較硬核,輸入的地方通過比較字符串來選擇函數。首先通過構造函數找到整個數據結構的定義

    偏移 類型 長度 備注
    a1 sth_p q 0x100
    a1+8 char_table_0_p q 0x100 0x6030e0
    a1+16 input c 100
    a1+272 rand%50
    a1+280 char_table_0_p-sth_p q
    a1+288+8 char_table_2 d 8 (a1+8)[72+l] 6030e0[l+255]
    a1+408 char_table_1 b 255 0x603700
    a1+672 func_addr q 255 (a1+8)[84+i] 603200+i(+=)
    a1+672+8 func_table q 8 (a1+8)[84+6030e0[l+255]]

    輸入函數形式為:

    for i in range(len(input)):
        *(a1+664) = input[i+1]
        for j in range(8):
            if(f[input[i]] == (a1 + 408)[(a1+8)[72+j]]):
                call (a1+8)[84 + (a1+8)[j+72]] ( a1 )

    可以看到,實際上就是令Input[i]作為下標取數組f的值,然后遍歷char_table_1中的8個值,如有相等的則取func_addr中對應的函數來調用。

    一共8個函數,根據提示語可以定位到其中的一個函數,查看交叉引用則能找到另外8個函數的函數表:

    逐個反編譯發現:

    函數名 執行條件 表達式 功能
    func_0 (a1+288)<(a1+292) (a1+665) = char_table[a1+288] m=c[index]
    func_1 (a1+288)<(a1+292) char_table[a1+288] = (a1+665) c[index]=m
    func_2 (a1+665) = (a1+665) + (a1+664) – 33 m+=[next]-33
    func_3 (a1+665) = (a1+665) – ((a1+664) – 33) + 1 m-=[next]-33
    func_4 (a1+288)++ index++
    check_func *(a1+664)==’s’ s = char_table_0[(a1+288)], len=20,puts(s) check(s)
    func_6 (a1+288)– index–
    func_7 后一個參<=0x59 char_table_0[a1+288] = input[*(a1+288) + *(a1+664) – 48] – 49

    其中用到的變量一共有4個:

    a1+292 = 255
    a1+664 = [next](即input[i+1])
    a1+665 = m(臨時變量)
    a1+288 = index

    在check_func中會輸出s,s是從char_table_0中以index為起點取的0x20個值。如果s滿足三個方程則通過校驗,返回成功。

    而實際上那三個方程是不需要逆的—題目中明示了只要輸出“Binggo”即可得到flag。因此目標顯然是在char_table_0中獲得Binggo的字符串,將其dump出來輸出了一下發現并字符順序并沒有合適的,甚至上述5個字母都不齊。以及一個最關鍵的問題,check_func中取了0x20個值賦給s,這顯然不符合”Binggo”的要求,因此第七個字符必須給上”使其截斷才行。

    分析其余7個函數,發現0和1可以交換char_table_0中的字符的位置,2、3和7則可以修改char_table_0中字符的值,4和6則是用來移動下標的,最后check_func加’s’來結束并輸出。在構造輸入之前,先要找到函數對應的輸入值。

    逆向一下發現char_table中還被更改了值,IDA動態調試斷在函數調用處調用idc腳本,即可得到對應值:

    auto i, j, v14, p, q;
    for(i=0;i<8;i++)
    {
        p = Byte(0x6030e0+255+i);
        v14 = 0x400dc1;
        //for ( j = 0; j <= p; ++j )
        {
          v14 = Dword(0x91d440+8+8*(p+0x54));
        }
        for(j=0;j<255;j++)
        {
            if(Byte(0x603900+j)==Byte(0x91d5d8+p))
            {
                q = j;
                break;
            }
            //Message("Not Found : %x", Byte(0x603700+p));
        }
        Message("%xt%ct%xn",q , q, v14);
    }
    24  $   400dc1  
    38  8   400e7a  
    43  C   400f3a  
    74  t   401064  *  
    30  0   4011c9  
    45  E   40133d  
    75  u   4012f3  *  
    23  #   4014b9  

    得到這8個輸入字符即可開始構造了。

    由于函數功能很多樣,因此構造方法很多,在此僅表述我的構造方法:

    由于輸入buffer有限,因此不適合向右移動指針太多來找尋合適的字符。所以我就原地變換—畢竟將一個字符變成另一個字符滿打滿算也只要4個輸入,移動指針可就輕而易舉幾十上百了。

    下列計劃中push表示將char_table中的值取入m,A->B表示將A通過func_2和3變換成B,->1表示指針后移1位

    push P    # $
    P->B    # t/
    pop B    # 8
    #111(用于填充make,其實1個就夠,懶得算了233)
    B->i    # CH
    ->1        # 0
    pop i    # 8
    i->n    # C&
    ->1        # 0
    pop n    # 8
    ->1        # 0
    n->g    # t(
    pop g    # 8
    ->1        # 0
    pop g    # 8
    g->o    # C)
    ->1        # 0
    pop o    # 8
    ->1        # 0
    make x00    # #0
    <-6        # uuuuuu
    End        # Es

    其中的111是為了make x00,在指針指向第七個字符時直接構造,提交給服務器即可獲得flag。相對而言我覺得這題是所有(re和安卓)題目中質量最高和最(逆向過程中)有趣的~

    本文章首發在 網安wangan.com 網站上。

    上一篇 下一篇
    討論數量: 0
    只看當前版本


    暫無話題~
    亚洲 欧美 自拍 唯美 另类