吾愛破解 - LCG - LSG |安卓破解|病毒分析|huihengkj.com

 找回密碼
 注冊[Register]

QQ登錄

只需一步,快速開始

搜索
查看: 2572|回復: 17

[CTF] XNUCA2020-RE-UnravelMFC復現

  [復制鏈接]
樓主
多喝咖啡 發表于 2020-11-5 14:58 回帖獎勵
本帖最后由 多喝咖啡 于 2020-11-7 22:32 編輯

當時做這題一步步動態調,花了7 8個小時做出來了...
用的是x32dbg調試,為了跟動態調試的時候一致,把基址改為了0xA90000。

如何找按鈕對應的函數

如何找到這些按鈕按下時對應的消息處理函數呢?

在MFC中,程序是使用消息機制來實現操作響應的,下面是消息映射表的結構。其中我們想要的某個控件的消息處理函數,就存放在該結構體的pfn中。nID與控件的ID相同。

struct AFX_MSGMAP{
    AFX_MSGMAP * pBaseMessageMap;
    AFX_MSGMAP_ENTRY * lpEntries;
}

struct AFX_MSGMAP_ENTRY{
    UINT nMessage;    //Windows Message
    UINT nCode        //Control code or WM_NOTIFY code
    UINT nID;         //control ID (or 0 for windows messages)
    UINT nLastID;     //used for entries specifying a range of control id's
    UINT nSig;        //signature type(action) or pointer to message 
    AFX_PMSG pfn;     //routine to call (or specical value)
}


用resource hacker查找資源。得到資源對應的編號。
例如:確定對應1,取消對應2,輸入框對應1000。
于是我們在IDA中搜索立即數1000。

在.rdata段里找一找。符合上述結構體的數據

struct AFX_MSGMAP_ENTRY
{
        UINT nMessage;
        UINT nCode;
        UINT nID;
        UINT nLastID;
        UINT_PTR nSig;
        void (*pfn)(void);
};

struct AFX_MSGMAP
{
  const AFX_MSGMAP *(__stdcall *pfnGetBaseMap)();
  const AFX_MSGMAP_ENTRY *lpEntries;
};

將上面兩個結構體插入到Local Types。再同步到idb。


在edit-struct var中,將上述數據組織成結構體。
于是,我們找到了按鈕對應的函數。

確認鍵按不了?


500彩票邀请码 在消息框對應的函數中,有一個與66的比較。可以猜測,我們需要讓輸入長度為66。果然可以按下確定了。

兩個藏得很深的函數

sub_C29C80 SMC函數
在生成消息框之前會運行

500彩票邀请码sub_C29E40 改變check1里面的cmp_str

#include <stdio.h>
#include <string.h>
int main(int argc, char const *argv[])
{
        char key[] = "fuck";
        char plain[45] = "B=.NI;&3JBZ;$;?(I72x0&4GLZDS2V6&%AF.!5#+J[F^";
        plain[19] = 0x27;

        for(int i =0;i<0x2c;i++)
        {
                plain[i] ^= key[i%4];
                printf("%c",plain[i] );
        }
        printf("\n");
        return 0;
}

所以check1里面的cmp_str = $HM%/NEX,79PBN\C/BQLVSW,*/'8T#UMC4%EG@@@,.%5

按下確認鍵會發生的事情


之前一大堆函數大概就是在獲取消息框的內容、檢查有沒有是否有輸入之類的。值得注意的一個函數是sub_C017A9,拿ida自己命名的參數(lpMultiByteStr, lpWideCharStr, 2 * v17, CodePage)去搜了下,發現神似WideCharToMultiByte這個函數。作用:因為我們的輸入存到內存中都是一個字符兩字節,會把兩字節的字符轉換為一字節。經過動態調試,確實是這個函數。

sub_BFDD48這個是個strlen,emmmmm如果不動調的話,真的看不出來。


然后分別check輸入的前33個和后33個字符。

一個魔改了的RC4

sub_C0971F對輸入的前33位做了一個魔改的rc4加密

int main()
{
        char key[] = "sorry_you_are_wrong";
        unsigned char T[256]={0};
        unsigned char S[] = {196, 120, 53, 239, 86, 152, 45, 254, 98, 81, 138, 177, 186, 121, 127, 37, 169, 181, 73, 189, 137, 159, 19, 228, 60, 235, 26, 90, 204, 174, 191, 212, 243, 106, 203, 83, 35, 117, 236, 149, 247, 221, 88, 51, 31, 193, 151, 249, 94, 58, 77, 207, 146, 142, 14, 126, 54, 136, 76, 165, 24, 158, 5, 124, 1, 44, 49, 194, 209, 199, 55, 104, 132, 229, 180, 178, 216, 72, 8, 41, 198, 114, 108, 128, 139, 46, 231, 79, 52, 99, 131, 100, 224, 154, 57, 34, 237, 129, 80, 43, 17, 222, 233, 238, 48, 11, 170, 230, 59, 96, 242, 150, 195, 42, 119, 12, 173, 0, 18, 68, 97, 252, 167, 140, 118, 47, 182, 160, 219, 6, 25, 208, 107, 226, 187, 102, 2, 15, 232, 153, 40, 29, 10, 190, 141, 255, 69, 103, 143, 71, 27, 163, 50, 33, 234, 161, 157, 225, 112, 245, 211, 125, 188, 122, 3, 135, 145, 240, 38, 65, 113, 7, 93, 168, 22, 16, 179, 36, 223, 87, 95, 162, 23, 200, 192, 171, 213, 148, 116, 185, 214, 70, 155, 220, 244, 101, 202, 156, 201, 32, 197, 85, 215, 175, 30, 246, 206, 130, 218, 164, 205, 62, 9, 241, 133, 183, 91, 67, 134, 75, 210, 105, 82, 250, 217, 20, 63, 61, 64, 115, 84, 166, 28, 39, 227, 110, 147, 66, 74, 123, 13, 78, 184, 111, 4, 172, 92, 89, 144, 109, 251, 176, 21, 248, 56, 253};
        int j=0;
        int i=0;
        int temp;
        for(i=0; i< 256; i++)
        {
                T[i] = key[i % 19];
        }

        for(i=0; i<256;i++)
        {
                j = (T[i] + j +S[i])%256;
                temp = S[i];
                S[i] = S[j];
                S[j] = temp;
        }

        i = j = 0;
        int t;
        for(int r=0; r<0x21;r++)
        {
                i = (i+1) % 256;
                j = (j+S[i]) % 256;
                temp = S[i];
                S[i] = S[j];
                S[j] = temp;
                t = (S[j]+S[i]) % 256;
                printf("key = %x %d\n",S[t],S[t]);
        }
        return 0;

}

所以輸入會與0x40,0x28,0xb6,0x5c,0xd3,0x84,0x5c,0x1a,0xe0,0x18,0xfd,0x3f,0x5d,0xce,0xf6,0xbb,0x3d,0x46,0x43,0x82,0x7a,0xa9,0x5c,0xe3,0xe4,0x48,0xfd,0xa5,0xb9,0x39,0x7b,0xd4,0xfe進行異或。

類BASE32

經過rc4加密后,來到0xF05188。在內存中dump出真正的代碼,再寫腳本patch。雖然這個函數經過了混淆(各種jmp)但是ida還是能F5出結果。


(其中參數a1為dest,a2為src,a3為src的length)
這左移右移的,加3加4的,再聯系到輸入長度33,cmp_str的長度44,這不就是base系列嗎。

#include <stdio.h>
int main(int argc, char const *argv[])
{
        unsigned char encoded[] ="$HM%/NEX,79PBN\\C/BQLVSW,*/'8T#UMC4%EG@@@,.%5";
        unsigned char result[44];
        int xor_arr[] = {0x40,0x28,0xb6,0x5c,0xd3,0x84,0x5c,0x1a,0xe0,0x18,0xfd,0x3f,0x5d,0xce,0xf6,0xbb,0x3d,0x46,0x43,0x82,0x7a,0xa9,0x5c,0xe3,0xe4,0x48,0xfd,0xa5,0xb9,0x39,0x7b,0xd4,0xfe};

        int result_ptr = 0;
        int encoded_ptr = 0;
        for(int i = 0; i <44;i++)
        {
                encoded[i] -= 0x23;
        }

        for(int i=0;i<11;i++)
        {
                result[result_ptr] = ((unsigned char)encoded[encoded_ptr] <<2) | ((unsigned char)encoded[encoded_ptr+1] >>4);
                result[result_ptr+1] = ((unsigned char)encoded[encoded_ptr+1] <<4) | ((unsigned char)encoded[encoded_ptr+2] >>2);
                result[result_ptr+2] = ((unsigned char)encoded[encoded_ptr+2] <<6) | ((unsigned char)encoded[encoded_ptr+3]);
                encoded_ptr += 4;
                result_ptr += 3;
        }
        for(int i = 0; i <33;i++)
        {
                printf("%c",(result[i]^xor_arr[i]));

        }
        printf("\n");
        return 0;
}
//Fr4nk1y_MfC_l5_t0O_ComPIeX_4nd_dl

魔改的TEA

check2里面有一個改了delta的TEA加密算法。
首先會驗證flag[33]=='f'
sub_C051B5的作用是將8個字符組成2個32位的int。
sub_F05420便是TEA加密了。密鑰存在dword_F05048中。


500彩票邀请码 for循環剩下的內容沒看太懂,經過動態調試得知是交換密文c0,c1的位置。

#include <stdio.h>  
#include <stdint.h>  
//解密函數  
void decrypt (uint32_t* v, uint32_t* k) {  
    uint32_t x0=v[0], x1=v[1], sum=0x86772b40, i;  /* set up */  
    uint32_t delta=0x2433B95A;                     /* a key schedule constant */  
    uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3];   /* cache key */  
    for (i=0; i<32; i++) {                         /* basic cycle start */  
        x1 -= ((x0<<4) + k2) ^ (x0 + sum) ^ ((x0>>5) + k3);  
        x0 -= ((x1<<4) + k0) ^ (x1 + sum) ^ ((x1>>5) + k1);  
        sum -= delta;  
    }                                              /* end cycle */  
    v[0]=x0; v[1]=x1;  
}  

int main()  
{  
    uint32_t v[2]={0x2d46347f,0x5e79f6f4},k[4]={0x0D9610D02,0x2AADA57D,0x0A37537F1,0x0C29E3913};  
    // k為加密解密密鑰,為4個32位無符號整數,即密鑰長度為128位
    printf("原始數據:%x %x\n",v[0],v[1]);  
    decrypt(v, k);  
    printf("解密后的數據:%x %x\n",v[0],v[1]);  
    return 0;  
}  

妙用Z3

這個方程涉及到了進位和借位的操作?手算算不出來,經過了2個小時,想到了z3,直接秒出...

from z3 import *

c54 = BitVec('c54',64)
c10 = BitVec('c10',64)
c76 = BitVec('c76',64)

s = Solver()
s.add(c54 - c10 == 0x3F66B755B4490579)
s.add(c10 + c76 == 0x162F924623D2CAE0)
s.add(c76 - c54 == 0x7C3C71F1B295D77F)
s.check()
print(s.model())

[c54 = 7830893152465779821,
c10 = 3262352701727045364,
c76 = 16783048594668704748]

再加上c3 = 0x2F9970FF
c2 = 0xDF3634AE
用TEA解密就得到flag。注意字節序。

flag

500彩票邀请码Fr4nk1y_MfC_l5_t0O_ComPIeX_4nd_dlff1cUlt_foR_THe_r0Ok1E_t0_REver5e



更新題目鏈接
鏈接: http://pan.baidu.com/s/1cY2XeP7CYq0JluTUT6hkBg 提取碼: 4seg

DDF58320-F597-4247-98CF-7630DDB01428.png (8.8 KB, 下載次數: 1)

DDF58320-F597-4247-98CF-7630DDB01428.png

免費評分

參與人數 9威望 +2 吾愛幣 +109 熱心值 +8 收起 理由
七個漲停一倍 + 1 我很贊同!
新手12138 + 1 + 1 我很贊同!
evill + 1 + 1 用心討論,共獲提升!
0615 + 1 + 1 熱心回復!
gaosld + 1 + 1 謝謝@Thanks!
Hmily + 2 + 100 + 1 感謝發布原創作品,吾愛破解論壇因你更精彩!
fengbolee + 1 + 1 用心討論,共獲提升!
LittleMatch + 1 + 1 lsggtql
二娃 + 2 + 1 謝謝@Thanks!

查看全部評分

發帖前要善用論壇搜索功能,那里可能會有你要找的答案或者已經有人發布過相同內容了,請勿重復發帖。

推薦
 樓主| 多喝咖啡 發表于 2020-11-7 22:33 |樓主

已更新在正文末尾
沙發
斌斌A 發表于 2020-11-5 16:46
3#
alibunny 發表于 2020-11-6 00:03
4#
LittleMatch 發表于 2020-11-6 00:11
感謝樓主分享
5#
碎步流年 發表于 2020-11-6 10:50
學習了,感謝分享
6#
wanshiz 發表于 2020-11-6 11:05
樓主本事高。
7#
re1wn 發表于 2020-11-6 20:49
膜一波師傅
8#
chenyanwjf 發表于 2020-11-7 08:56
學習下,感謝。!!
9#
Li1y 發表于 2020-11-7 10:44
求個原文件
您需要登錄后才可以回帖 登錄 | 注冊[Register]

本版積分規則 警告:本版塊禁止灌水或回復與主題無關內容,違者重罰!

快速回復 收藏帖子 返回列表 搜索

RSS訂閱|小黑屋|處罰記錄|聯系我們|吾愛破解 - LCG - LSG ( )

GMT+8, 2020-11-24 20:07

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回復 返回頂部 返回列表

500彩票邀請碼-彩經網