攻防世界逆向高手题之crazy
攻防世界逆向高手題之crazy
繼續(xù)開啟全棧夢想之逆向之旅~
 這題是攻防世界逆向高手題的crazy
 
下載附件,照例扔入exeinfope中查看信息:
 
64位ELF文件,扔入對應(yīng)IDA中查看信息,有main函數(shù)看main函數(shù):
 
可以看到,一堆眼花繚亂的系統(tǒng)函數(shù),有些則是用類名調(diào)用的普通C++函數(shù)。
 這里積累第一個經(jīng)驗:(別人博客的一句話)
代碼看著很亂,有很多很長的命令,解決辦法:依據(jù)英文意思去猜測。
 找關(guān)鍵變量的方法:從后往前找,看flag和輸入關(guān)系。復(fù)雜代碼本質(zhì)應(yīng)該是簡潔的,這樣才叫出題。
但是從后往前找與flag的有關(guān)變量還是很麻煩,所以我們用運行程序方法不斷查看顯示信息,鎖定關(guān)鍵位置。(調(diào)試的話不知道斷點下在那里可能要遍歷很長時間)
 。
 。
 。
 第一次亂輸入:
 
.
 .
 可以看到運行到checking…后顯示too short or too long處,還有就是用戶輸入在字符串輸出之前。返回IDA查看代碼:
 
這里有個cin,也是主函數(shù)中在其它字符串之前的,cin是c++的輸入函數(shù),從這里積累第二個經(jīng)驗:該程序的長字符傳命令中最后一個才是我們要關(guān)注的命令,比如這里的cin函數(shù),像下面截圖中字符串前面也有cout函數(shù)。
 
.
 .
 .
 看check…字符串之后的函數(shù):
 
可以看到checking到if判斷語句之間還是有很多函數(shù)的,可以用前面的依據(jù)英文意思猜測的方法去看函數(shù),也可以在strings窗口查找too short or too long處的函數(shù)位置:(我選擇后者)
 
這里跟蹤到HighTemplar::calculate函數(shù),根據(jù)英文名是計算函數(shù),但是我看不懂這里的this+16,憑借意思我推測是我們輸入flag的地址,把我們輸入的flag經(jīng)過兩個簡單的循環(huán)異或加密后輸出:
bool __fastcall HighTemplar::calculate(HighTemplar *this) {__int64 v1; // rax_BYTE *v2; // rbxbool result; // al_BYTE *v4; // rbxint i; // [rsp+18h] [rbp-18h]int j; // [rsp+1Ch] [rbp-14h]if ( std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::length((char *)this + 16) != 32 ){v1 = std::operator<<<std::char_traits<char>>(&std::cout, "Too short or too long");std::ostream::operator<<(v1, std::endl<char,std::char_traits<char>>);exit(-1);}for ( i = 0;i <= (unsigned __int64)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::length((char *)this + 16);++i ){v2 = (_BYTE *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[]((char *)this + 16, // 這里積累第三個經(jīng)驗:這是一個兩步操作,v2取的是對應(yīng)字符的地址,*v2是指在原v2地址上修改。把修改input_flag字符分成了兩步做,讓不熟悉的我載了跟頭。i);*v2 = (*(_BYTE *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[]((char *)this + 16,i) ^ 80)+ 23;}for ( j = 0; ; ++j ){result = j <= (unsigned __int64)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::length((char *)this + 16);if ( !result )break;v4 = (_BYTE *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[]((char *)this + 16,j);*v4 = (*(_BYTE *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[]((char *)this + 16,j) ^ 19)+ 11;}return result; }.
 .
 .然后由于HighTemplar::calculate函數(shù)的下一個就是if判斷函數(shù),所以我們只能跟蹤if判斷函數(shù)的HighTemplar::getSerial了。
 
.
 .
 前面this+16我推測是我們輸入flag的地方,但是這個this+80存了什么東西我是真不知道了。雙擊跟蹤堆棧也是未賦值的狀態(tài)。這里積累第四個經(jīng)驗,逆向中不符合預(yù)期帶份運算結(jié)果基本都是中間做了其它操作,如之前遇到的HOOK,這里很多函數(shù)我還沒跟蹤,那說明的確會有未發(fā)現(xiàn)的操作。
 .
 .
 回到一開始cin函數(shù)的地方,表黃輸入變量,看哪里還引用過該變量:
 
可以看到在checking前面還引用了一下,而該函數(shù)我們并沒有分析,雙擊跟蹤分析:
unsigned __int64 __fastcall HighTemplar::HighTemplar(DarkTemplar *a1, __int64 input_flag) {char v3; // [rsp+17h] [rbp-19h] BYREFunsigned __int64 v4; // [rsp+18h] [rbp-18h]v4 = __readfsqword(0x28u);DarkTemplar::DarkTemplar(a1);*(_QWORD *)a1 = &off_401EA0;*((_DWORD *)a1 + 3) = 0;std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string((char *)a1 + 16, // C++函數(shù),basic_string(字符串類模板),不是復(fù)制就是比較,這里是復(fù)制輸入字符串給a1+16開始的地址的數(shù)組中input_flag);std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string((char *)a1 + 48, // C++函數(shù),basic_string(字符串類模板),不是復(fù)制就是比較,這里是復(fù)制輸入字符串給a1+48開始的地址的數(shù)組中,與前面隔了32個字符input_flag);std::allocator<char>::allocator(&v3);std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string((char *)a1 + 80,"327a6c4304ad5938eaf0efb6cc3e53dc", // C++函數(shù),basic_string(字符串類模板),不是復(fù)制就是比較,這里是復(fù)制輸入字符串給a1+80開始的地址的數(shù)組中,與前面還是隔了32個字符,這個v3不清楚&v3);std::allocator<char>::~allocator(&v3);return __readfsqword(0x28u) ^ v4; }這里我們可以看到把輸入的flag分別給了this+16和this+48地址處,在this+80地址處給了327a6c4304ad5938eaf0efb6cc3e53dc這個字符串,那么前面對this+80的疑惑就解釋得通了。
 .
 .
 回過頭去看this+80的那個HighTemplar::calculate函數(shù):
.
 .
 簡單的加密邏輯,直接寫腳本逆向邏輯即可:
.
 .
 結(jié)果:(這里積累第5個經(jīng)驗:現(xiàn)在的flag真的是越來越古靈精怪了,還有花括號,我一開始都以為我寫錯腳本了,現(xiàn)在看來,什么類型的flag都可以!一次不行就修改再交幾次)
 
.
 .
 .
 最后,下面這三個函數(shù)有什么用呢,我判斷它是沒什么用的,因為參數(shù)沒有傳入我輸入的flag,跟蹤里面也沒有我輸入的flag地址,除非是偏移地址間接引用我輸入的flag,不過那樣的話題就很難了!
 
 .
 .
 .
 總結(jié):
1:這里積累第一個經(jīng)驗:(別人博客的一句話)
 代碼看著很亂,有很多很長的命令,解決辦法:依據(jù)英文意思去猜測。
 找關(guān)鍵變量的方法:從后往前找,看flag和輸入關(guān)系。復(fù)雜代碼本質(zhì)應(yīng)該是簡潔的,這樣才叫出題。
但是從后往前找與flag的有關(guān)變量還是很麻煩,所以我們用運行程序方法不斷查看顯示信息,鎖定關(guān)鍵位置。(調(diào)試的話不知道斷點下在那里可能要遍歷很長時間)
2:
 這里積累第二個經(jīng)驗:該程序的長字符傳命令中最后一個才是我們要關(guān)注的命令,比如這里的cin函數(shù),像下面截圖中字符串前面也有cout函數(shù)。
3:
 這里積累第三個經(jīng)驗:這是一個兩步操作,v2取的是對應(yīng)字符的地址,*v2是指在原v2地址上修改。把修改input_flag字符分成了兩步做,讓不熟悉的我載了跟頭。
4:
 這里積累第四個經(jīng)驗,逆向中不符合預(yù)期帶份運算結(jié)果基本都是中間做了其它操作,如之前遇到的HOOK,這里很多函數(shù)我還沒跟蹤,那說明的確會有未發(fā)現(xiàn)的操作。
5:
 這里積累第5個經(jīng)驗:現(xiàn)在的flag真的是越來越古靈精怪了,還有花括號,我一開始都以為我寫錯腳本了,現(xiàn)在看來,什么類型的flag都可以!一次不行就修改再交幾次
解畢!敬禮!
總結(jié)
以上是生活随笔為你收集整理的攻防世界逆向高手题之crazy的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: dya50 javascript
 - 下一篇: U盘安装CentOS7黑屏