// ZFasConv v 1.0.0.1
// Purpose: converts fas files to OllyDbg
// by Z3N

// VERY IMPORTANT NOTICE: COMPILE THIS DLL WITH BYTE ALIGNMENT OF STRUCTURES
// AND UNSIGNED CHAR!

#include <windows.h>
#include <stdio.h>
#include <string.h>

#include "plugin.h"
#include "fas.h"

DWORD GetCurrentEIP(void);
void  LoadFas(void);


HINSTANCE       hinst;                // DLL instance
HWND            hwmain;               // Handle of main OllyDbg window
byte            usecomment, uselabel;
t_module        *pmodule;
int		        mem, prepsrc, strtable, symtlen, i;
int		        *modbase, *stroffset;
header	        *fhead;
fsymbol	        *sym;
char            path[255];


BOOL WINAPI 
DllEntryPoint   (HINSTANCE  hi,
                DWORD       reason,
                LPVOID      reserved)
{
    if (reason==DLL_PROCESS_ATTACH)
        hinst=hi;       // Mark plugin instance
    return 1;           // Report success
};


int _export cdecl 
ODBG_Plugindata (char shortname[32])
{
    strcpy( shortname,"FasConv" );    // Name of plugin
    return PLUGIN_VERSION;
};


int _export cdecl 
ODBG_Plugininit (int     ollydbgversion,
                HWND    hw,
                ulong   *features) 
{
    if (ollydbgversion < PLUGIN_VERSION)
    {
        return -1;
    }
    
    hwmain=hw;
    Addtolist(0,0,"FasConvertor by Z3N, Thx to wasm");
    return 0;
};


int _export cdecl 
ODBG_Pluginmenu(int     origin,
                char    data[4096],
                void    *item)
{
    //int i,n;
    //t_dump *pd;
    switch (origin) {
    case PM_MAIN:                      // Plugin menu in main window
        strcpy(data,"0 Get labels,1 &About");
        return 1;
        
    default: 
        break;                         // Any other window
  };
  return 0;                            // Window not supported by plugin
};


void 
information(char *message)
{
    MessageBox( hwmain, message, "FasConvertor v1.0.0.1", MB_OK|MB_ICONINFORMATION);
}


DWORD 
GetCurrentEIP(void)
{
    t_thread* t2;   // t_thread
    
    t2=Findthread( Getcputhreadid() );
    return t2->reg.ip;
}


void _export cdecl 
ODBG_Pluginaction   (int    origin,
                    int     action,
                    void    *item) 
{
    if (origin==PM_MAIN) {
        switch (action) {
        case 0:
            LoadFas();
            break;
            
        case 1:
            // Menu item "About", displays plugin info.
            information("FasConvertor v0.01 by Z3N\nThx to wasm\n You can mail me on this site");
            break;
            
        default: 
            break;
        }; 
    };
};


void 
LoadFas(void)
{
    HANDLE	in;
    
    #define WAS_DEFINED			1
    #define ASS_TIME_VARIABLE	2
    #define	IN_STRING_TABLE		0x80000000
    
    char *str2 = Plugingetvalue(VAL_PROCESSNAME);    //some checks
    if (strlen(str2) == 0)
    {
        Addtolist (0,1,"FasConvertor ERROR: No process to add fas info");
        information ("Well - if you don't debug anything - you don't need .fas file ;-)");
        return;
    }
    //__asm _emit 0xCC;
    modbase = Plugingetvalue(VAL_EXEFILENAME);
    strcpy( path, modbase );
    strcpy( strrchr( path, '.' ) ,".fas");
    
    in = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING, NULL);
    if (in==INVALID_HANDLE_VALUE)
    {
        Browsefilename("Select map file", path, ".fas", 0);
    }
    
    in = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (in==INVALID_HANDLE_VALUE)
    {
        Addtolist (0,1,"FasConvertor ERROR: Cannot open %s", path);
        return;
    };
    
    mem = VirtualAlloc(NULL, GetFileSize(in, NULL), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    if(!mem)
    {
        Addtolist (0,1,"FasConvertor ERROR: Cannot Alloc mem ");
        return;
    }
    
    if(ReadFile(in, mem, GetFileSize(in,NULL), &modbase, NULL))
    {
        fhead = mem;
        sym = fhead->offset_symbol_table+mem;
        prepsrc = fhead->offset_preprocessed_source+mem;
        strtable = fhead->offset_string_table+mem;
        symtlen = fhead->length_symbol_table;
        pmodule = Findmodule( (ulong)GetCurrentEIP() );
        modbase = pmodule->base;
        //__asm _emit 0xCC;
        for (i=0; i!=symtlen; i+=32)
        {
            if(sym->flags & WAS_DEFINED)
            {
                if((!(sym->flags & ASS_TIME_VARIABLE)))
                {
                    if (  (int)sym->value>=modbase  &&  
                          (sym->symb_name_prep_offset!=0)  &&  
                          ( !( (int)sym->value & IN_STRING_TABLE ) )  
                       )
                    {
                        if (sym->symb_name_prep_offset & IN_STRING_TABLE)
                        {
                            // if we are in string table
                            //__asm _emit 0xCC;
                            Insertname( (int)sym->value, NM_LABEL, strtable + (sym->symb_name_prep_offset ^ IN_STRING_TABLE) );
                        }
                        else
                        {
                            //if in prep source
                            stroffset = prepsrc+sym->symb_name_prep_offset;
                            memcpy( &path, (byte*)stroffset+1, (byte)*stroffset);
                            memset( (byte*)path+(byte)*stroffset, 0, 4);
                            Insertname( (int)sym->value , NM_LABEL, &path);
                        }
                    }
                }
            }
            sym++;
        }
        Infoline( "Fas file successfuly imported - comments updated" );
    }
    VirtualFree( mem, NULL, MEM_RELEASE );
    CloseHandle( in );
    Setcpu(0,0,0,0,CPU_ASMFOCUS);
};



