Afkayas.1/AfKayAs.2分析
第二個和第三個的分析。
Afkayas.1
第二個也是找名稱序列號。查殼後無殼,是VB寫的。照舊先執行下。
VB的彈窗函式是rtcMsgBox,或者通過搜字串"You GetWrong"來定位呼叫位置。
定位到函式內部,然後就找對比的地方,je跳轉就是錯誤的對話方塊
往上翻,vb的一些函式我不太理解做什麼的,通過單步跟,找到了輸入字串以後的一些操作
輸入字串以後,會檢查字串的長度,然後字串長度*0x17CFB計算出一個數Num,這個數加上輸入字串的第一個位元組。這裡需要注意的是,如果是字母或者是數字的話,轉換成ASSIC都是一個位元組就可以,但是如果輸入的是漢字,一個漢字是2個位元組,所以準確來說它取的是輸入的第一個字元。取出第一個字元後,和Num相加,然後呼叫__vbaStrI4這個函式,將數字轉換成字串。__vbaStrl4所在的dll是Msvbvm50.dll。稍後可能用到。這一步就算出了序列號中數字的那一部分。
然後序列號前面要加一個字串"AKA-",拼接好後,和輸入的序列號做比較,正確就彈對的框。
然後嘗試寫了下注冊機
#include<Windows.h> #include<stdio.h> #include<stdlib.h> //#pragma comment(lib,"Msvbvm50.dll") HMODULE g_hMod = NULL; //AKA-XXXXX //字串的長度*0x17CFB //第一個位元組的ASSIC+計算出的數 //Msvbvm50.dll //呼叫__vbaStrI4 //函式型別 (*指標變數名)(形參列表) 函式指標的定義 //typedef int(_stdcall * DLLFUNC)(int ,int) typedef WCHAR*(_stdcall*vbStrCalc)(DWORD num); char g_ret[30]{}; // 寬字元轉換為多字元(Unicode --> ASCII) #define WCHAR_TO_CHAR(lpW_Char, lpChar) \ WideCharToMultiByte(CP_ACP, NULL, lpW_Char, -1, lpChar, _countof(lpChar), NULL, FALSE); // 多字元轉換為寬字元(ASCII --> Unicode) #define CHAR_TO_WCHAR(lpChar, lpW_Char) \ MultiByteToWideChar(CP_ACP, NULL, lpChar, -1, lpW_Char, _countof(lpW_Char)); //str,輸入的字串 //len,字串長度 //flag 用來判斷輸入的是字母數字(true),還是漢字(false) void calcSerial(char *str,int len,bool flag) { vbStrCalc p_Fun = (vbStrCalc)GetProcAddress(g_hMod, "__vbaStrI4"); DWORD Tmp = 0; Tmp = len * 0x17CFB; if(flag==true) { int NumAndAlph = (int)str[0]; NumAndAlph += Tmp; WCHAR* ss = p_Fun(NumAndAlph); WCHAR_TO_CHAR(ss, g_ret); } else { //漢字要取兩個位元組 int chinese = 0; int aa = str[0]; int bb = str[1] & 0xFF; chinese |= aa; chinese <<= 8; chinese |= bb; chinese += Tmp; WCHAR* ss = p_Fun(chinese); WCHAR_TO_CHAR(ss, g_ret); } } int main() { g_hMod = LoadLibrary(L"Msvbvm50.dll"); char buf[100]{}; WCHAR bufTmp[100]{}; printf("Enter Name: "); scanf("%s", buf); if ((buf[0] & 0x80) == 0) //判斷漢字還是字母,看第一個位元組最高位是1還是0,0就是漢字母 { calcSerial(buf, strlen(buf),true); } else { CHAR_TO_WCHAR(buf, bufTmp); calcSerial(buf, wcslen(bufTmp),false); } printf("Serial is:AKA-%s\n", g_ret); system("pause"); return 0; }
測試
AfKayAs.2
這個第一個是要去一個neg,彈出來的時候,感覺不是messagebox,停留幾秒後這個彈窗自己消失,然後彈出輸序列號的視窗。首先我想既然不是messagebox,那彈出這個東西,再怎麼它也應該是個視窗,建立一個視窗,貼一張圖,然後把視窗邊框都去掉,顯示出來應該就是這樣子。然後我就給createwindows下斷,可一想也不太對,vb建立視窗用的什麼函式呢?查了下也沒查出個所以然,沒招,單步跟跟看。跟了一頓,全在Msvbvm50.dll中
調到F0260c6的時候,F8了一下直接彈出了序列號的那個框,感覺不太對,單步跟進去,果然再單步下去那個neg又出來了,
在F0260C6裡面,看到了這三個函式,視窗的訊息迴圈用的,
通過這些訊息後,到WM_PAINT,彈窗出現
看視窗的情況,Form1就是上面這個視窗,它上面的那個視窗應該就是那個序列號的視窗
WS_CLIPSIBLINGS用於子視窗,設定子視窗不重繪被覆蓋部分.
WS_CLIPCHILDREN樣式主要是用於父視窗,也就是說當在父視窗繪製的時候,父視窗上還有一個子視窗,那麼設定了這個樣式的話,子視窗區域父視窗就不負責繪製。
樣式什麼的慢慢查。在這個視窗下還有一個視窗有WM_POPUP的屬性的視窗,然後接著執行
又建立了一個子視窗。注意有一個ThunderRT5Timer的東西
執行這個程式的時候,彈出這個neg以後,要等幾秒,它才消失,那麼這裡這個Timmer類就值得注意了,除錯過程中當傳送這個訊息後,視窗消失。可以假設一下,程式執行起來,彈出視窗,定時器設定時間,到時間傳送WM_TIMMER,關閉視窗。開始這個視窗可能就是這麼來的。事實上當視窗退出後,視窗列表這個視窗Form1以及定時器那個東西也一併消失。
SetTimer(m_hWnd,1,1000,NULL)
定時器的函式bp SetTimer試了下,我這裡是想找定時器SetTimmer的那個時間,但是沒有思路,只能找到那個時間到達後,傳送的WM_TIMMER訊息,傳送完這個訊息後,這個neg就會消失,如果找到那個時間,也就是定時器時長,把它改成0,那麼效果就是這個彈窗剛出來,定時器時間很短,基本上一出來就傳送WM_TIMER,然後立刻關閉這個視窗,那麼看起來這個視窗好像沒出現一樣,因為這個視窗是在DLL中的程式碼建立的,沒辦法修改,這裡能力有限,暫時是真找不到,有思路求指教。不勝感激
然後就是輸入名稱序列號,來判斷輸入正確。按一貫思路,輸入字串後點擊,會彈MessageBox,那麼就開始找。首先執行它預設有輸入,什麼也不輸就跑一下,結果發現直接彈出這個窗,點選直接退出。
可以看到不同的輸入,出錯的形式不同,執行時錯誤13 型別不匹配 ,執行時錯誤5 無效的呼叫過程或引數。這兩個都算是錯誤輸入問題導致,所以按正常輸入去找名稱和序列號的關係。
正常輸入以後,斷在rtcMsgBox函式開頭,還是棧中返回地址跟隨,進到了呼叫處。引數正是彈窗裡的顯示
而分支的跳轉在上面
然後就看這個je是什麼比較後的判斷,結果並沒有什麼比較,這裡esi做了一個test,改變了zf的值,完成了判斷。
那到這裡,要想知道esi裡面是什麼的值,只能往上繼續找,上面的程式碼很多,我直接找到了函式的開始處位置,一步一步看。
整個序列號的判斷我全截圖了,VB中一些函式意思不太清楚,有些地方不太懂意思
>先計算輸入name的長度
>ret=長度*0x15B38
>取輸入字串第一個字元的值(十六進位制),值+ret
>呼叫__vbaStrI4轉成字串,儲存str0
>呼叫函式檢測不知道什麼東西
>把上面求得字串str0呼叫__vbaR8Str轉化成浮點數 fNum,入棧st0
>記憶體中取一個浮點數10入棧,然後st0=10/5=2
>檢測狀態暫存器的一個值,意義不懂
>st0=fNum+2 是計算後的值,然後呼叫__vbaStrR8將浮點數轉換成字串儲存,字串記作str1
>記憶體清理
>str1呼叫__vbaR8Str轉浮點數 fNum1 入棧
>fNum1=fNum1*3 fNum1=fNum1-2
>fNum1呼叫__vbaStr8轉化成字串str2
>記憶體清理
>str2 呼叫__vbaR8Str轉成浮點數fNum2
>fNum2=fNum2-(-15.000)
>fNum2呼叫__vbaStrR8轉字串str3,儲存
>記憶體清理
>取自己輸入的序列號,__vbaR8Str轉浮點數f_input入棧st0,然後彈出到棧[ebp-0xE4]上儲存
>正確的序列號字串str3 轉浮點數fNum3
>f_input/fNum,計算出結果 f_ret,f_ret和常數1比,FST暫存器的值給eax,檢測ah是否為0,為0就彈錯誤框,
>否則,esi=1,之前檢測esi的值到這裡也就清楚了。
描述過程可能不清楚,但總的來說就是輸入的字串進行一系列浮點數操作得出一個浮點數,輸入的序列號也計算出一個浮點數,然後輸入的除以正確的,算出一個結果,改變了FST暫存器,把FST暫存器的值給eax,如果ah的值為0,則輸入的序列號就錯,非0,輸入的序列號就正確。
第二個的註冊機就不寫了,那個浮點數轉字串的函式不太會用,涉及到浮點數的一些操作還不是很懂。然後輸入一個名稱,找了一下它的序列號作為檢測。證明是對的。
總結下,那個neg最後還是沒去掉,然後第二個的註冊機感覺寫起來有點繁瑣,轉化成程式碼的能力有待練習吧。
最後分析過程中找到的一些資料
浮點數除法
協處理指令
http://blog.sina.com.cn/s/blog_7753c5fa0100q96l.html
VB逆向一些常用的函式