1. 程式人生 > >記錄一次手動脫殼 Jarvisoj Reverse Evil.exe

記錄一次手動脫殼 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.