一个壳代码乱序重构

来源:互联网 发布:单纯性算法c代码 编辑:程序博客网 时间:2024/04/30 01:55
一个壳代码乱序重构

/*
Coder: dummyz@126.com
2008/01/15
*/

#include <Windows.h>
#include <fstream>
#include <memory>
#include <list>
#include <algorithm>
#include "xde.h"

using namespace std;

typedef unsigned char ubyte;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;

ubyte* load_pefile(const char* fname, ulong& size)
{
    IMAGE_DOS_HEADER dosheader;
    IMAGE_NT_HEADERS ntheader;
    ifstream ifile(fname, ios::binary);

    if ( !ifile )
        return NULL;

    ifile.read((char*)&dosheader, sizeof (IMAGE_DOS_HEADER));
    if ( dosheader.e_magic != IMAGE_DOS_SIGNATURE )
        return NULL;

    ifile.seekg(dosheader.e_lfanew, ios::beg);

    ifile.read((char*)&ntheader, sizeof (IMAGE_NT_HEADERS));
    if ( ntheader.Signature != IMAGE_NT_SIGNATURE ||
        ntheader.FileHeader.NumberOfSections == 0 )
        return NULL;

    size = ifile.seekg(0, ios::end).tellg();
    ifile.seekg(0, ios::beg);

    auto_ptr<ubyte> buf(new ubyte[size]);
    ifile.read((char*)buf.get(), size);

    return buf.release();
}

typedef struct _instr
{
    ubyte* old_ip;
    ubyte* new_ip;
    xde_instr instr;
} instr_t;

bool is_hasip(list<instr_t>& instr_lst, ubyte* ip)
{
    list<instr_t>::iterator i = instr_lst.begin();
    while ( i != instr_lst.end() )
    {
        instr_t& p = *i++;
        if ( p.old_ip == ip )
        {
            return true;
        }
    }

    return false;
}

int main(int argc, char* argv[])
{
    if ( argc < 2 )
    {
        return -1;
    }
   
    ulong file_size;
    auto_ptr<ubyte> file_buf(load_pefile(argv[1], file_size));
    ubyte* base = file_buf.get();
    if ( base == NULL )
    {
        return -2;
    }
   
    list<instr_t> instr_lst; // 指令表
    list<ubyte*> ep_list; // 入口表
    instr_t instr;

    PIMAGE_DOS_HEADER dosheader = (PIMAGE_DOS_HEADER)base;
    PIMAGE_NT_HEADERS ntheader = (PIMAGE_NT_HEADERS)(base + dosheader->e_lfanew);
    PIMAGE_SECTION_HEADER sectheader = IMAGE_FIRST_SECTION(ntheader);
   
    ulong code_size = ntheader->OptionalHeader.SizeOfCode;
    ulong code_va = ntheader->OptionalHeader.ImageBase + sectheader->VirtualAddress;
    ulong oep_va = ntheader->OptionalHeader.ImageBase + ntheader->OptionalHeader.AddressOfEntryPoint;

    ubyte* code = base + sectheader->VirtualAddress;

    instr.old_ip = base + ntheader->OptionalHeader.AddressOfEntryPoint - /
        sectheader->VirtualAddress + sectheader->PointerToRawData;
   
    auto_ptr<byte> code_buf(new byte[code_size * 2]);
    memset(code_buf.get(), 0x90, code_size * 2);

    instr.new_ip = code_buf.get() + ntheader->OptionalHeader.AddressOfEntryPoint - /
        sectheader->VirtualAddress;
   
    // @1 重构串行指令序
    ep_list.push_back(instr.old_ip);
    while ( true )
    {
        list<ubyte*>::iterator it;
        
        printf("/r/bPasering eip = %08X...", instr.old_ip - code + code_va);
        
        if (
            instr.old_ip > code + code_size ||
            is_hasip(instr_lst, instr.old_ip) // 检查是否已经处理过了, 从入口表中取出新的地址
            )
        {
            if ( ep_list.empty() )
                break;

            instr.old_ip = ep_list.front();
            ep_list.erase(ep_list.begin());
        }

        if ( 0 == xde_disasm(instr.old_ip, &instr.instr) )
        {
            printf("xde_disasm error!/n");
            break;
        }

        /*
0040102C > $ C705 00104000>mov     dword ptr [401000], 00401333
00401036   . FF25 00104000 jmp     dword ptr [401000]
        */
        if ( instr.instr.opcode == 0xc7 &&
            instr.instr.modrm == 0x05 &&
            (instr.instr.addr_l[0] >= code_va && instr.instr.addr_l[0] < oep_va)
            )
        {
            ubyte* next_ep_ip = instr.old_ip + instr.instr.len;
            if ( *(ushort*)next_ep_ip == 0x25ff &&
                *(ulong*)(next_ep_ip + 2) == instr.instr.addr_l[0]
                )
            {
                next_ep_ip += 6;
                if ( ep_list.end() == find(ep_list.begin(), ep_list.end(), next_ep_ip) &&
                    !is_hasip(instr_lst, next_ep_ip)
                    )
                {
                    ep_list.push_back(next_ep_ip);
                }
               
                instr.old_ip = instr.instr.data_l[0] - code_va + code;
                continue;
            }
        }

        if ( instr.instr.flag & C_REL )
        {
            ubyte* next_ep_ip = instr.old_ip + instr.instr.len;
            switch ( instr.instr.datasize )
            {
            case 1: next_ep_ip = (ubyte*)((ulong)next_ep_ip + (long)instr.instr.data_c[0]); break;
            case 4: next_ep_ip = (ubyte*)((ulong)next_ep_ip + (long)instr.instr.data_l[0]); break;
            default: printf("error datasize!/n");   
            }

            if ( ep_list.end() == find(ep_list.begin(), ep_list.end(), next_ep_ip) &&
                !is_hasip(instr_lst, next_ep_ip)
                )
            {
                ep_list.push_back(next_ep_ip);
            }

            if ( instr.old_ip[0] == 0x8a )
            {
                instr.old_ip[0] = 0x8a;
            }
        }
        
        it = find(ep_list.begin(), ep_list.end(), instr.old_ip);
        if ( ep_list.end() != it ) // 从入口表中踢出
        {
            ep_list.erase(it);
        }

        instr_lst.push_back(instr);
        instr.new_ip += instr.instr.len;

        if ( instr.old_ip[0] == 0xc3 ||
            instr.old_ip[0] == 0xc2
            )
        {
            if ( ep_list.empty() )
                break;

            instr.old_ip = ep_list.front();
            ep_list.erase(ep_list.begin());
        }
        else
        {
            instr.old_ip += instr.instr.len;
        }
    }
   
    printf("/ninstr sum = %d/n", instr_lst.size());
   
    // @2 拷贝 & 校正偏移
    list<instr_t>::iterator instr_lst_i = instr_lst.begin();
    while ( instr_lst_i != instr_lst.end() )
    {
        instr_t& instr1 = *instr_lst_i++;
        
        printf("/r/bRelocing eip = %08X...", instr1.new_ip - code_buf.get() + code_va);

        if ( instr1.instr.flag & C_REL )
        {
            ubyte* jmp_ip = instr1.old_ip + instr1.instr.len;
            switch ( instr1.instr.datasize )
            {
            case 1: jmp_ip = (ubyte*)((ulong)jmp_ip + (long)instr1.instr.data_c[0]); break;
            case 4: jmp_ip = (ubyte*)((ulong)jmp_ip + (long)instr1.instr.data_l[0]); break;
            default: printf("error datasize!/n");
            }
            
            do
            {
                if ( jmp_ip[0] == 0xc7 && jmp_ip[1] == 0x05 &&
                    *(ulong*)(jmp_ip + 2) >= code_va && *(ulong*)(jmp_ip + 2) < oep_va
                    )
                {
                    if ( *(ushort*)(jmp_ip + 2 + 4 + 4) == 0x25ff &&
                        *(ulong*)(jmp_ip + 2 + 4 + 4 + 2) == *(ulong*)(jmp_ip + 2) )
                    {
                        jmp_ip = *(ulong*)(jmp_ip + 2 + 4) - code_va + code;
                        continue;
                    }
                }

                break;
            } while( true );
            
            list<instr_t>::iterator instr_lst_j = instr_lst.begin();
            while ( instr_lst_j != instr_lst.end() )
            {
                instr_t& instr2 = *instr_lst_j;
                if ( instr2.old_ip == jmp_ip )
                {
                    xde_instr tmp = instr1.instr;

                    tmp.data_l[0] = instr2.new_ip - instr1.new_ip + instr1.instr.len;
                    xde_asm(instr1.new_ip, &tmp); // 汇编
                    break;
                }

                instr_lst_j++;
            }

            if ( instr_lst_j == instr_lst.end() )
            {
                printf("reloc jmp error!/n");
                break;
            }
        }
        else
        {
            memcpy(instr1.new_ip, instr1.old_ip, instr1.instr.len);
        }
    }
   
    ofstream ofile("1.bin", ios::binary);
    ofile.write((char*)code_buf.get(), code_size);
   
    printf("/nFinished!/n");

    return 0;
}