记录一次手动脱壳 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.

猜你喜欢

转载自blog.csdn.net/caobo_lq666/article/details/83211242
今日推荐