記錄一次手動脫殼 Jarvisoj Reverse Evil.exe
這個題目的分值是200,對我來說是個不小的挑戰啊。
查了一下殼,沒有發現什麼
真的這麼簡單?拖入IDA觀察:
呃呃呃,果然不簡單;在IDA裡面沒有任何函式的痕跡。只有一個.text段。
猜測,應該是加了某種殼對源程式加密過。用OD載入。
看到OD的提示,再看到這裡的迴圈pushad,看來應該是有殼,可是工具又查不出來,手動?
這時想到了ESP定律,記錄個大佬的ESP定律講解連結:https://blog.csdn.net/D_R_L_T/article/details/74625872
將的很詳細具體。
我就抱著試一試的態度開始了ESP大法的操作。
1、先F8到pushad下一條指令,找到此時的ESP
2、轉到ESP地址出的資料,下硬體記憶體訪問斷點。
3、F9到popad附近
4、F8單步尋找popad
5、附近找到jmp指令(一般是大的jmp)
6、跳過去就是OEP啦
嗯哼,接下來就可以用OD的外掛Ollydump脫殼dump下來啦:
到底是不是呢?我們將dump下來的程式拖進IDA檢視,會發現已經建立了函式。
接下來就是F5啦:
對這些函式逐個檢視(詳細的就不講了)。
每個函式的功能:
sub_4018F0 下載一張圖片,得到圖片的位元組數,返回儲存圖片資料的緩衝區的首地址。
sub_401740 初始化一個byte陣列 KEY[264]
sub_401800 一個演算法,得到與檔案等長一段資料存在緩衝區buffer
sub_401220 對上述得到的緩衝區的資料進行一個簡單的異或
紀錄下自己的掉進的坑:在初始化陣列時,自己沒有注意到移位運算的優先順序低於 加減 ,導致得到了亂碼,半天才找到錯誤(長記性)。
附送逆向get的程式碼(C++):
#include<bits/stdc++.h> using namespace std; int main() { FILE *fp,*dump; fp =fopen("x.jpg","rb"); dump = fopen("shell.txt","wb"); fseek(fp,0,SEEK_END); int file_len = ftell(fp);//檔案的長度 fseek(fp,0,SEEK_SET); cout<<file_len<<endl; char file[file_len]; fread(file,file_len,1,fp); fclose(fp); unsigned char key[264]; long long first = 0x4A8754F5745174; for(int i=0;i<8;i++) { key[i] = 0; } for(int i=0;i<256;i++) key[i+8] = ((i + (first >>(i % 8 * 8)))&0xff);//運算子的優先順序 int len = 264; int dkey[len/4]; int temp; unsigned char temp4,temp5; for(int i=0;i<len/4;i++) { temp = 0; for(int j=3;j>-1;j--) { temp = (temp<<8) + key[4 * i + j]; } dkey[i] = temp; } char flag[file_len]; for(int i=0;i<file_len;i++) { dkey[0] = (dkey[0]+ 1)%256; dkey[1] = (key[dkey[0] + 8] + dkey[1])%256; temp4 = key[dkey[0] + 8]; temp5 = key[dkey[1] + 8]; key[dkey[0] + 8] = temp5; key[dkey[1] + 8] = temp4; flag[i] = (key[(temp4 + temp5 )%256 + 8] ^ file[i] ^ i)%256; fputc(flag[i],dump); } fclose(dump); /* for(int i=file_len-1;i>=4;i --) { if(flag[i]==0x68) { printf("%c%c%c%c",flag[i-4],flag[i-3],flag[i-2],flag[i-1]); i -= 4; } } cout<<endl; */ return 0; }
可以用16進位制編輯器開啟得到的檔案
可以看到很多字元,但好像是無序的;檢視大佬的WP知道這是shellcode(驚)。
自己在OD找段空白,copy進去:
啊哈哈,剛好最近看書看到這段類似的程式碼實現;
PEB-> PEB_LAR_DATA-> InInitalizationOrderMouduleList->DLL->API
繼續往下看;
push一段字串
注意小端序,即可得到了flag.