Tuesday, September 25, 2012

A PRIVATE HEX EDITOR CODED ON C++

A PRIVATE HEX EDITOR CODED ON C++

COMPILE AND RUN


1. Main.cpp
Code:
    #include "Editor.hpp"
     
    Console console;
    HexEditor hexedit;
    bool quit = false;
    void draw();
    void loop();
    void processInput(char key);
     
    int main() {
        loop();
        return 0;
    }
     
    void loop() {
        console.init("Psych Hex Editor - Created by Psych.gs");
        draw();
        char input;
        while (!quit) {
            input = getch();
            processInput(input);
            draw();
        }
    }
     
    void draw() {
        console.clear();
        console.write(0,23,"Keys: ESC = Exit  ENTER = Open File  WASD = Navigate Tab = Edit  Z = Save",FOREGROUND_GREEN|BACKGROUND_BLUE);
        console.write(0,24,"Q = Scrolldown E = Scrollup Space = Switch View F = Find",FOREGROUND_BLUE|BACKGROUND_GREEN);
        hexedit.draw(&console);
        console.render();
    }
     
    void processInput(char key) {
        if (key == VK_TAB) {
            hexedit.go_edit(&console);
        }
        if (key == VK_ESCAPE) {
            quit = true;
        }
        if (key == VK_RETURN) {
            hexedit.load_file();
        }
        if (key == 'd' || key == 'D') {
            hexedit.select(1);
        }
        if (key == 'a' || key == 'A') {
            hexedit.select(-1);
        }
        if (key == 's' || key == 'S') {
            hexedit.select(16);
        }
        if (key == 'w' || key == 'W') {
            hexedit.select(-16);
        }
        if (key == 'q' || key == 'Q') {
            hexedit.scroll(1);
        }
        if (key == 'e' || key == 'E') {
            hexedit.scroll(-1);
        }
        if (key == 'z' || key == 'Z') {
            hexedit.save();
        }
        if (key == 'f' || key == 'F') {
            hexedit.find(&console);
        }
        if (key == VK_SPACE) {
            hexedit.switchmodes();
        }
    }
    
2. Editor.hpp

Code:
    #include 
    #include 
    #include 
    #include 
     
    void error(const char *msg);
     
    class Console {
    private:
        CHAR_INFO console_buffer[25][80];
        HANDLE cHandle;
    public:
        void init(const char *title);
        void write(int x, int y, const char *c, WORD attributes);
        void render();
        void clear();
    };
     
    struct Editable {
        short x;
        int y;
        char data;
    };
     
    class HexEditor {
    private:
        char fname[64];
        char completePath[255];
        long fsize;
        bool hasFile;
        char *fileByte;
        Editable *edit;
        Editable *strEdit;
        long selected,lc;
        int sTimes;
        long scrollAmount;
        void gen_edit();
        void grab_file_info();
        void findandselect(const char *find);
        void findtext(Console *g);
        void findbytes(Console *g);
        void converttobytes(char *bytebuf, const char *text);
        bool startsWith(const char *c1,const char *c2);
        short mode;
    public:
        void draw(Console *g);
        void load_file();
        void select(int add);
        void scroll(int add);
        void switchmodes();
        void go_edit(Console *g);
        void save();
        void find(Console *g);
        bool editMode;
    };
    

3. Editor.cpp

Code:
    #include "Editor.hpp"
     
    void m(const char *m) {
        MessageBoxA(0,m,m,0);
    }
     
    void error(const char *msg) {
        MessageBoxA(0,msg,"Psych Hex Editor|Error",0);
    }
     
    void Console::init(const char* title) {
        cHandle = (HANDLE)GetStdHandle(STD_OUTPUT_HANDLE);
        if (cHandle == INVALID_HANDLE_VALUE) {
            error("Invalid handle value of std output handle.");
        }
        SetConsoleTitle(title);
    }
     
    void Console::clear() {
        for (int x = 0; x < 80; x++) {
            for (int y = 0; y < 25; y++) {
                console_buffer[y][x].Char.AsciiChar = '\0';
                console_buffer[y][x].Attributes = FOREGROUND_GREEN | BACKGROUND_BLUE;
            }
        }
    }
     
    void Console::write(int x, int y, const char *c, WORD attributes) {
        int len = strlen(c);
        for (int i = 0; i < len; i++) {
            console_buffer[y][x+i].Char.AsciiChar = c[i];
            console_buffer[y][x+i].Attributes = attributes;
        }
    }
     
    void Console::render() {
        COORD size = {80,25};
        COORD pos = {0,0};
        SMALL_RECT region = {0,0,79,24};
        WriteConsoleOutput(cHandle,(CHAR_INFO*)console_buffer,size,pos,&region);
    }
     
    void HexEditor::draw(Console *g) {
        char outBuf[80];
        if (hasFile) {
            sprintf(outBuf,"%s %f kb",fname,(float)fsize/1024);
        } else {
            sprintf(outBuf,"No File Loaded");
        }
        g->write(0,0,outBuf,FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY|BACKGROUND_BLUE);
        char out[4];
        scrollAmount = sTimes*16;
        if (hasFile) {
            for (lc = 0; lc < fsize; lc++) {
                if (lc < 304 && lc+scrollAmount < fsize) {
                    switch (mode) {
                        case 0:
                            sprintf(out,"x%x",edit[lc+scrollAmount].data);
                            break;
                        case 1:
                            sprintf(out,"%c",edit[lc+scrollAmount].data);
                            break;
                    }
                    if (selected == lc+scrollAmount) {
                        if (editMode) {
                            g->write(edit[lc+scrollAmount].x,edit[lc+scrollAmount].y-sTimes,out,FOREGROUND_BLUE|FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_INTENSITY);
                        } else {
                            g->write(edit[lc+scrollAmount].x,edit[lc+scrollAmount].y-sTimes,out,FOREGROUND_BLUE|FOREGROUND_RED|FOREGROUND_GREEN);
                        }
                    } else {
                        g->write(edit[lc+scrollAmount].x,edit[lc+scrollAmount].y-sTimes,out,BACKGROUND_BLUE|BACKGROUND_RED|BACKGROUND_GREEN);
                    }
                }
            }
        }
    }
     
    void HexEditor::select(int add) {
        if (selected+add < 0 || selected+add == fsize || selected+add > fsize) {
            return;
        }
        selected += add;
    }
     
    void HexEditor::scroll(int add) {
        if (sTimes+add < 0 || sTimes+add > (fsize-288)/16) {
            return;
        }
        sTimes += add;
    }
     
    void HexEditor::switchmodes() {
        if (mode != 1 || mode > 1) {
            mode++;
        } else {
            mode = 0;
        }
        gen_edit();
    }
     
    void HexEditor::load_file() {
        OPENFILENAME ofn;
        ZeroMemory(&ofn,sizeof(ofn));
        ofn.lStructSize = sizeof(OPENFILENAME);
        ofn.lpstrFilter = "All Files (*.*)\0*.*\0";
        ofn.lpstrFile = completePath;
        ofn.nMaxFile = 255;
        ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST;
        ofn.lpstrDefExt = "";
       
        if (GetOpenFileName(&ofn)) {
            hasFile = true;
            grab_file_info();
        }
    }
     
    void HexEditor::grab_file_info() {
        SHFILEINFOA sfi = {0};
        SHGetFileInfo(completePath,-1,&sfi,sizeof(sfi),SHGFI_DISPLAYNAME);
        sprintf(fname,"%s",sfi.szDisplayName);
        FILE *fp = fopen(completePath,"rb");
        fseek(fp,0,SEEK_END);
        fsize = ftell(fp);
        fseek(fp,0,SEEK_SET);
        fileByte = (char*)malloc(sizeof(char)*fsize);
        fread(fileByte,1,fsize,fp);
        fclose(fp);
        gen_edit();
    }
     
    void HexEditor::gen_edit() {
        edit = (Editable*)malloc(sizeof(Editable)*fsize);
        short currX = 0;
        int currY = 3;
        for (lc = 0; lc < fsize; lc++) {
            if (fileByte[lc] < 0x20 && mode == 1) {
                edit[lc].data = ' ';
            } else {
                edit[lc].data = fileByte[lc];
            }
            edit[lc].x = currX;
            edit[lc].y = currY;
            if (currX != 75) {
                currX += 5;
            } else {
                currY++;
                currX = 0;
            }
        }
    }
     
    void HexEditor::go_edit(Console *g) {
        editMode = true;
        if (mode == 0) {
            g->clear();
            g->write(0,24,"Please enter a valid hexadecimal number-",FOREGROUND_GREEN|BACKGROUND_BLUE);
            draw(g);
            g->render();
            short hex;
            char c[4];
            c[0] = '0';
            c[1] = 'x';
            c[2] = getch();
            if ((c[2] > 0x29 && c[2] < 0x3A) || (c[2] > 0x60 && c[2] < 0x67) || (c[2] > 0x40 && c[2] < 0x47)) {
                sscanf(c,"%x",&hex);
                edit[selected].data = (char)hex;
                g->clear();
                g->write(0,24,"Please enter a valid hexadecimal number-",FOREGROUND_GREEN|BACKGROUND_BLUE);
                draw(g);
                g->render();
                c[3] = getch();
                if ((c[3] > 0x29 && c[3] < 0x3A) || (c[3] > 0x60 && c[3] < 0x67) || (c[2] > 0x40 && c[2] < 0x47)) {
                    sscanf(c,"%x",&hex);
                    edit[selected].data = (char)hex;
                    fileByte[selected] = (char)hex;
                    editMode = false;
                    return;
                } else {
                    editMode = false;
                    return;
                }
            } else {
                editMode = false;
                return;
            }
        }
        if (mode == 1) {
            g->clear();
            g->write(0,24,"Please enter a new character-",FOREGROUND_GREEN|BACKGROUND_BLUE);
            draw(g);
            g->render();
            char c = getch();
            if (c > 0x19 && c < 0x7F) {
                edit[selected].data = c;
                fileByte[selected] = c;
                editMode = false;
                return;
            } else {
                editMode = false;
                return;
            }
        }
    }
     
    void HexEditor::save() {
        OPENFILENAME ofn;
        char sfilePath[255];
        ZeroMemory(&ofn,sizeof(ofn));
        ofn.lStructSize = sizeof(OPENFILENAME);
        ofn.lpstrFilter = "All Files (*.*)\0*.*\0";
        ofn.lpstrFile = sfilePath;
        ofn.nMaxFile = 255;
        ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST;
        ofn.lpstrInitialDir = completePath;
        ofn.lpstrDefExt = "";
        if (GetSaveFileName(&ofn)) {
            FILE *fp = fopen(sfilePath,"wb");
            fwrite(fileByte,fsize,1,fp);
            fclose(fp);
        }
    }
     
    void HexEditor::findbytes(Console *g) {
        char texBuf[255],text[64],bytes[24];
        memset(text,'\0',64);
        short currLen = 0;
        sprintf(texBuf,"Please enter bytes to find(FORMAT=0x??,0x??)->");
        g->clear();
        g->write(0,23,"Press escape to exit find",FOREGROUND_GREEN|BACKGROUND_BLUE);
        g->write(0,24,texBuf,FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY|BACKGROUND_BLUE);
        draw(g);
        g->render();
        bool end = false;
        char in;
        while (!end) {
            in = getch();
            if (in == VK_ESCAPE) {
                end = true;
            } else {
                if (in == VK_BACK) {
                    if (currLen != 0) {
                        text[currLen-1] = '\0';
                        currLen--;
                    }
                } else {
                    if (in != VK_RETURN) {
                        text[currLen] = in;
                        currLen++;
                    }
                }
                sprintf(texBuf,"Please enter bytes to find(FORMAT=0x??,0x??)->%s",text);
                if (currLen%5 == 0) {
                    converttobytes(bytes,text);
                    findandselect(bytes);
                }
                g->clear();
                g->write(0,23,"Press escape to exit find",FOREGROUND_GREEN|BACKGROUND_BLUE);
                g->write(0,24,texBuf,FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY|BACKGROUND_BLUE);
                draw(g);
                g->render();
            }
        }
    }
     
    void HexEditor::converttobytes(char *bytebuf, const char* text) {
        short currByte = 0,currBB = 0;
        char currBytebuf[4];
        int sLen = strlen(text);
        for (int i = 0; i < sLen; i++) {
            if (text[i] != ',') {
                currBytebuf[currByte] = text[i];
            } else {
                currByte = 0;
                int in;
                sscanf(text,"%x",&in);
                bytebuf[currBB] = (char)in;
                currBB++;
            }
        }
    }
     
    void HexEditor::findtext(Console *g) {
        char texBuf[255],text[64];
        memset(text,'\0',64);
        short currLen = 0;
        sprintf(texBuf,"Please enter text to find->");
        g->clear();
        g->write(0,23,"Press escape to exit find",FOREGROUND_GREEN|BACKGROUND_BLUE);
        g->write(0,24,texBuf,FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY|BACKGROUND_BLUE);
        draw(g);
        g->render();
        bool end = false;
        char in;
        while (!end) {
            in = getch();
            if (in == VK_ESCAPE) {
                end = true;
            } else {
                if (in == VK_BACK) {
                    if (currLen != 0) {
                        text[currLen-1] = '\0';
                        currLen--;
                    }
                } else {
                    if (in != VK_RETURN) {
                        text[currLen] = in;
                        currLen++;
                    }
                }
                sprintf(texBuf,"Please enter text to find->%s",text);
                findandselect(text);
                g->clear();
                g->write(0,23,"Press escape to exit find",FOREGROUND_GREEN|BACKGROUND_BLUE);
                g->write(0,24,texBuf,FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY|BACKGROUND_BLUE);
                draw(g);
                g->render();
            }
        }
    }
     
    void HexEditor::find(Console* g) {
        switch (mode) {
            case 0:
                findbytes(g);
                break;
            case 1:
                findtext(g);
                break;
        }
    }
     
    void HexEditor::findandselect(const char *find) {
        char fBuf[64];
        memset(fBuf,'\0',64);
        int flen = strlen(find);
        for (lc = selected; lc < fsize; lc++) {
            for (int i = 0; i < flen; i++) {
                fBuf[i] = fileByte[lc+i];
            }
            if (!strcmp(fBuf,find)) {
                selected = lc;
                if ((lc-288)/16 < 0) {
                    sTimes = 0;
                } else {
                    sTimes = (lc-288)/16;
                }
                return;
            }
        }
    }