什么是mfc?
MFC庫是開發Windows應用程序的C++接口。MFC提供了面向對象的框架,采用面向對象技術,將大部分的Windows API 封裝到C++類中,以類成員函數的形式提供給程序開發人員調用。
簡單來說,MFC是一種面向對象,用于開發windows應用程序的框架,突出特點是封裝了大部分windows API,便于開發人員使用(寫win掛方便)。
MFC程序的運行過程分為以下四步:
那么問題來了,我們如何逆向mfc程序呢?因為其封裝了大部分windows API,逆向起來也復雜了不少,因為需要了解大量的windows api 并且熟悉windows編程。下面進行講解。
如下圖,是MFC框架軟件的基本界面,可以看到,就是一堆button,主要逆向也是check button。
那么,對于MFC逆向,我們主要需要知道的是,當我們執行某個操作(點擊某個按鈕)的時候,程序會執行什么處理函數。在mfc中,程序是使用消息機制來實現操作響應的,這個是消息映射表的代碼:
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)
}
其中這個AFX_MSGMAP_ENTRY中的最后一個成員AFX_PMSG就是一個函數指針,指向了當前控件綁定的函數。同時,這個nID成員描述的是當前控件的ID,利用這個ID就能確定我們所尋找的控件。然后這個AFX_MSGMAP結構體則會記錄一個指向AFX_MSGMAP_ENTRY的指針,于是查找控件的注冊函數的思路可以縮小為:
那么,我們又該怎么找到控件ID呢,俗話說“工欲善其事,必先利其器”,作為逆向分析人員,肯定要選擇好分析的工具了,很慶幸,我們站在巨人的肩膀上,針對mfc軟件程序的逆向分析,前輩們已經開發了一些非常好用的小工具,我們可以直接使用它們。例如:
其中我們主要用的是xspy,mfc分析利器如下圖所示
打開程序軟件
程序的標題Flag就在控件中,然后界面內容是讓我們找一個key。很明顯,我們需要找到兩個東西
根據這些內容,告訴我們我們去找控件,然后這時候就要掏出xspy了。不然的話,我們如果使用老一套經典分析流程,die+ida對用架構分析,會發生下面這樣的事。首先die查個架構,查個殼
好家伙,VMP殼,PE32ida走起,如下圖,emmm....
這樣的話,我們很難繼續往下分析,所以我們使用xspy分析。使用方法如下圖
首先我們找到了Flag_enc(944c8d100f82f0c18b682f63e4dbaa207a2f1e72581c2f1b)我們知道特定的,窗口句柄叫 HWND
然后我們可以發現一條特殊的onMsgOnMsg:0464,func=0x00402170(MFC1.exe+ 0x002170 )為什么特殊呢,因為只有它并不是以宏的形式出現,應該是作者自定義的消息,沒有button等東西,所以程序怎么點擊都無法觸發任何效果;并且傳入一個特殊數字0464,來觸發效果。
那么,我們需要去發送這條消息來出發func函數以獲取我們需要的key
#include<Windows.h>
#include<stdio.h>
int main()
{
HWND h=FindWindowA(NULL, "Flag就在控件里");
if (h)
{
SendMessage(h, 0x0464, 0, 0);
printf("success");
}
else printf("failure");
}
使用 API FindWindow 獲取窗口句柄,SendMessage發送消息,得到了key{I am a Des key}
最后DES解密即可
flag{thIs_Is_real_kEy_hahaaa}
【----幫助網安學習,需要網安學習資料關注我,私信回復“資料”免費獲取----】
① 網安學習成長路徑思維導圖
② 60+網安經典常用工具包
③ 100+SRC漏洞分析報告
④ 150+網安攻防實戰技術電子書
⑤ 最權威CISSP 認證考試指南+題庫
⑥ 超1800頁CTF實戰技巧手冊
⑦ 最新網安大廠面試題合集(含答案)
⑧ APP客戶端安全檢測指南(安卓+IOS)
下面,再講解一道大型比賽的賽題來實驗打開,看到這個樸素的界面可以鑒定是MFC框架。
我們看到了一個input,還有一個check button,很明顯,我們首先就需要去找check button的id&注冊函數。
check按鈕的id為03e9,同時窗口存在OnCommand: notifycode=0000 id=03e9,func=0x00C72420(Junk_Instruction.exe+ 0x002420 )函數。那么對應的check邏輯肯定在基址+偏移0x002420處。打開ida,找到check函數 sub_402420 ,如下圖
可以看到有一個條件判斷:if ( (unsigned __int8)sub_402600(v2 + 16) )。一眼頂針,兩個分支分別是彈出正確和錯誤的對話框,為什么呢?if else函數體內容基本一樣。當然我們還是動態調試一下
所以enc函數很明顯就是sub_402600這個函數中就出現了很多垃圾指令了,也就對應上題目名稱Junk_instruction了。
爆紅
花指令,經典call $+5起手,就是先用一個call壓好返回地址,再把棧里的返回地址彈出來,改一下,壓回去,如此反復。去掉也很簡單,我們把下述累死指令塊全部nop掉即可,有好幾處,一模一樣。
當然,我們使用idapython腳本自動去花
from ida_bytes import get_bytes, patch_bytes
import re
addr=0x402600
end=0x402fe3
buf=get_bytes(addr, end-addr)
def nopp(s):
s=s.group(0)
print("".join(["%02x"%i for i in s]))
s=b"\x90"*len(s)
return s
pattern=b"\xe8\x00\x00\x00\x00\x58\x89.*?\xc3.*?\x22"
buf=re.sub(pattern , nopp, buf, flags=re.I)
patch_bytes(addr, buf)
print("Done")
去除花指令,簡單審計發現是對程序進行RC4加密,最后還對輸入進行了個倒敘
去花后,整理一下,代碼如下
char __thiscall sub_402600(void *this, int a2)
{
const WCHAR *v2; // eax
void *v3; // eax
char v5[511]; // [esp+9h] [ebp-4BBh] BYREF
int v6; // [esp+208h] [ebp-2BCh]
char *v7; // [esp+20Ch] [ebp-2B8h]
int v8; // [esp+210h] [ebp-2B4h]
size_t Count; // [esp+214h] [ebp-2B0h]
int v10; // [esp+218h] [ebp-2ACh]
size_t v11; // [esp+21Ch] [ebp-2A8h]
char *v12; // [esp+220h] [ebp-2A4h]
char *v13; // [esp+224h] [ebp-2A0h]
int v14; // [esp+228h] [ebp-29Ch]
char v15[4]; // [esp+22Ch] [ebp-298h] BYREF
char *Source; // [esp+230h] [ebp-294h]
void *v17; // [esp+234h] [ebp-290h]
char cipher[32]; // [esp+238h] [ebp-28Ch]
const char *v19; // [esp+258h] [ebp-26Ch]
char *v20; // [esp+25Ch] [ebp-268h]
int i; // [esp+260h] [ebp-264h]
char *p_Destination; // [esp+264h] [ebp-260h]
char v23; // [esp+26Dh] [ebp-257h]
char v24; // [esp+26Eh] [ebp-256h]
char v25; // [esp+26Fh] [ebp-255h]
char v26[28]; // [esp+270h] [ebp-254h] BYREF
char v27[256]; // [esp+28Ch] [ebp-238h] BYREF
char key[256]; // [esp+38Ch] [ebp-138h] BYREF
char Destination; // [esp+48Ch] [ebp-38h] BYREF
char v30[39]; // [esp+48Dh] [ebp-37h] BYREF
int v31; // [esp+4C0h] [ebp-4h]
v17=this;
v31=3;
cipher[0]=91;
cipher[1]=-42;
cipher[2]=-48;
cipher[3]=38;
cipher[4]=-56;
cipher[5]=-35;
cipher[6]=25;
cipher[7]=126;
cipher[8]=110;
cipher[9]=62;
cipher[10]=-53;
cipher[11]=22;
cipher[12]=-111;
cipher[13]=125;
cipher[14]=-1;
cipher[15]=-81;
cipher[16]=-35;
cipher[17]=118;
cipher[18]=100;
cipher[19]=-80;
cipher[20]=-9;
cipher[21]=-27;
cipher[22]=-119;
cipher[23]=87;
cipher[24]=-126;
cipher[25]=-97;
cipher[26]=12;
cipher[27]=0;
cipher[28]=-98;
cipher[29]=-48;
cipher[30]=69;
cipher[31]=-6;
v2=(const WCHAR *)sub_401570(&a2);
v14=sub_4030A0(v2);
v10=v14;
v3=(void *)sub_401570(v14);
sub_403000(v3);
sub_4012A0(v15);
Source=(char *)unknown_libname_1(v26);
v20=Source;
v13=Source + 1;
v20 +=strlen(v20);
v11=++v20 - (Source + 1);
Count=v11;
Destination=0;
memset(v30, 0, sizeof(v30));
strncpy(&Destination, Source, v11);
if ( sub_402AF0(&Destination) )
{
v23=0;
v25=0;
LABEL_7:
v24=v25;
}
else
{
strcpy(key, "qwertyuiop"); // key
memset(&key[11], 0, 0xF5u);
memset(v27, 0, sizeof(v27));
memset(v5, 0, sizeof(v5));
v19=key;
v7=&key[1];
v19 +=strlen(v19);
v6=++v19 - &key[1];
RC4_init((int)v27, key, v19 - &key[1]); // RC4_init
p_Destination=&Destination;
v12=v30;
p_Destination +=strlen(p_Destination);
v8=++p_Destination - v30;
RC4_crypt((int)v27, (int)&Destination, p_Destination - v30);// RC4_crypto
for ( i=31; i >=0; --i )
{
if ( v30[i - 1] !=cipher[i] ) // 倒敘
{
v25=0;
goto LABEL_7;
}
}
v24=1;
}
LOBYTE(v31)=0;
sub_403060(v26);
v31=-1;
sub_4012A0(&a2);
return v24;
}
首先提取密文,利用插件Lazy_ida 5BD6D026C8DD197E6E3ECB16917DFFAFDD7664B0F7E58957829F0C009ED045FA
key-->qwertyuiop
cyberchef 得解
flag{973387a11fa3f724d74802857d3e052f}
IT之家 7 月 16 日消息 今天微軟發布了 Windows 10 21H1 Build 19043.1147 (KB5004296) 更新,面向 Release Preview 發布預覽頻道推送。
微軟表示,“注意:21H1 的 Beta 通道中的 Windows Insiders 將不會收到這個更新。我們將很快向這些內測人員推送 Windows 11 Insider Preview 構建版本。”
Windows 10 Build 19043.1147 (21H1) 預覽版包括以下改進修復:
修復了搜索索引器的一個問題。在你退出后,搜索索引器繼續持有每個用戶搜索數據庫的句柄,在配置文件路徑“C:\Users\username\AppData\Roaming\Microsoft\SearchData\Applications\”上存在。因此,搜索索引器停止工作,并創建了重復的配置文件名稱。
修復了阻止游戲服務為桌面用戶打開某些游戲的問題 Bug。
修復了使你無法使用輸入法編輯器(IME)輸入文本的問題。例如,在啟動后,如果你設置了電源選項,通過關閉筆記本電腦的蓋子來關閉筆記本電腦,這可能會發生問題。
改變了將新活動上傳至時間線的功能。如果你使用微軟賬戶(MSA)在設備上同步活動歷史,你不能把新的活動上傳到時間線。但你仍然可以使用時間線,在本地設備上看到活動歷史(關于最近的應用程序、網站和文件的信息)。這并不影響 Azure Active Directory(AAD)賬戶。要查看網絡歷史,微軟 Edge 和其他瀏覽器提供了查看最近網絡活動的選項。你也可以使用微軟 OneDrive 和 Office 查看最近使用的文件。
修復了當你在映射網絡驅動器時,可能會導致文件資源管理器窗口失去焦點的問題。
修復了當你刪除映射的網絡驅動器上的許多文件時,會導致文件資源管理器在達到 99% 的完成度后停止工作的問題。
修復了組策略注冊表遙測中的時間問題,會導致組策略擴展處理失敗。
修復了重復重建 Windows 過濾平臺(WFP)過濾器的問題。當設備被注冊到移動設備管理(MDM)服務并且且“MDMWinsOverGP”被設置時,這個問題就會發生。
修復了 MDM 服務的問題,未能正確應用某些垃圾郵件規則。
修復了在向 MDM 服務注冊期間,設備上的更新構建修訂(UBR)總是報告為零(0)的問題。
修復了導致橢圓曲線數字簽名算法(ECDSA)證書注冊失敗,出現錯誤“0x80090027 NTE_INVALID_PARAMETER”的問題。這個問題發生在可信平臺模塊(TPM)提供者(微軟軟件密鑰存儲提供者)存儲密鑰時。
修復了審核事件 4624 和 5142 的問題,當荷蘭語是顯示語言時,會顯示錯誤的事件模板。
修復了導致 System Integrity 泄漏內存的問題。
修復了當你按下游戲控制手柄上的觸發按鈕時,會大聲播放在游戲中選擇東西的聲音的問題。
修復了使電源計劃和游戲模式無法按預期工作的問題。這將導致游戲時幀率降低和性能下降。
修復了即在從某些域訪問互聯網的系統上,任務欄網絡圖標上出現“網絡內部訪問”的問題。
修復了即在你連接到虛擬專用網絡后,網絡連接狀態指示器(NCSI)無法檢測到互聯網連接的問題。
修復了導致打印停止或打印錯誤輸出的問題。這個問題發生在更新到 Windows 10 2004 版本或更高版本后使用 USB 連接打印時。
修復了可能會降低應用程序的性能的罕見問題,這些應用程序在每次調用 Gdiplus.dll!GdipMeasureString 時都會有一個新字體的緊密循環。這個問題發生在安裝 2021 年 2 月及以后發布的 Windows 更新之后。
修復了即當使用某些固定的通道布局進行流媒體時,會錯誤地路由一些音頻通道的問題。
修復了即 Set-RDSessionCollectionConfiguration 沒有設置 camerastoredirect:s:value 自定義屬性的問題。
修復了特權訪問管理(PAM)部署中報告的本地安全授權子系統服務(LSASS)域控制器內存泄漏問題。
修復了在簽出后無法訪問映射到分布式文件系統(DFS)根的網絡驅動器的問題。
修復了在登錄后無法重新連接到映射的網絡驅動器,并顯示拒絕訪問的錯誤的問題。如果你使用 net use /deep 選項在同一個加密文件共享上創建多個驅動器映射到不同的路徑,就會出現這個問題。
修復了 Windows 網絡文件系統(NFS)客戶端中中可能會阻止你在掛載 NFS 共享后重命名文件的問題。如果你使用文件資源管理器重命名文件,這個問題會發生,但如果你使用命令行重命名文件,則不會發生。
修復了關于未處理的“打開文件”對話框關鍵異常的問題。因此,微軟基礎類(MFC)應用程序可能會意外地關閉。
修復了即設置中的“存儲感知”頁面可能會錯誤地報告某些使用 GUID 分區表(GPT)的存儲設備的大小的問題。受影響的設備會在 Storage Sense 中錯誤地報告,其大小是文件資源管理器中報告大小的兩倍。注意:這個問題不影響使用主引導記錄(MBR)的存儲設備。