2

I'm not asking for a decompiler, as I'm aware that it does not produce accurate results all the time. I've tried Googling but all I found were decompilers.

Problem

I found it extremely inefficient to be continuously referring to the instruction set manual to find out what various uncommon instructions do. Furthermore I deal only infrequently with assembly and I found I have to continuously make a conscious effort to interpret the mnemonic syntax, which slows things down tremendously.

Requirement

A per-line translation of the assembly instructions. As a very simple example, replacing add eax, ebx with eax += ebx in the disassembly view, or just commenting the instruction with the pseudocode. Be it replacement or commenting, having the pseudocode inline would help to preserve the graph view and other convenient functionalities provided by IDA.

  • 2
    Many instructions have a whole load of side effects e.g. ret, push... even your simple add example implicitly calculates all eflags registers. If you would translate all of this to pseudocode, you would end up with an intermediate representation (Vex, REIL, ESIR, ...). There are lots of them out there and I would advice to have a look at them, since they feature RISC instruction sets. – Nordwald Sep 16 '16 at 8:57
  • @Nordwald Side effects is another reason why I would prefer to have pseudocode. Trying to keep track of all of them and to figure out what flags the conditional instructions are checking for is simply not practical for me. – wmjdgla Sep 16 '16 at 9:07
  • 3
    Have you considered purchasing HexRay's decompiler? It'll provide a function level decompilation, far superior to any instruction level decompilation – NirIzr Sep 16 '16 at 9:26
  • @Nirlzr Nope I'm not looking into decompilers as they do not produce accurate results all the time, at least based on what I've learned so far. How well can they handle obfuscation and anti-analysis? Also can graph view be used on the decompiled code? – wmjdgla Sep 24 '16 at 3:19
1

Here's an incomplete script to do this, for x86:

#include <idc.idc>
/*
    Project name: Pseudo instruction adder 1.0

    Author: fastman92
*/

#define true 1
#define false 0


#define ARCHITECTURE_TYPE_X86 1
#define ARCHITECTURE_TYPE_X64 2

extern architectureType;
extern pointerSize;

static MakeInstructionComment_x86(ea)
{
    auto mnem = GetMnem(ea);

    auto op0 = GetOpnd(ea, 0);
    auto op1 = GetOpnd(ea, 1);

    auto comment = "";

    if(mnem == "push")
        comment = sprintf("ESP -= 4; *(int32_t*)ESP = %s;", op0);
    else if(mnem == "mov")
        comment = sprintf("%s = %s;", op0, op1);
    else if(mnem == "lea")
        comment = sprintf("%s = address(%s);", op0, op1);
    else if(mnem == "jmp")
        comment = sprintf("goto %s;", op0);
    else if(mnem == "pop")
        comment = sprintf("%s = *(int32_t*)ESP; ESP += 4;", op0);
    else if(mnem == "leave")
        comment = "EBP = *(int32_t*)ESP; ESP += 4;";
    else if(mnem == "retn")
        comment = "return;";
    else if(mnem == "sub")
        comment = sprintf("%s -= %s;", op0, op1);
    else if(mnem == "shr")
        comment = sprintf("%s = %s >> %s;", op0, op0, op1);
    else if(mnem == "shl")
        comment = sprintf("%s = %s << %s;", op0, op0, op1); 
    else if(mnem == "and")
        comment = sprintf("%s &= %s;", op0, op1);
    else if(mnem == "or")
        comment = sprintf("%s |= %s;", op0, op1);
    else if(mnem == "xor")
        comment = sprintf("%s ^= %s;", op0, op1);
    else if(mnem == "not")
        comment = sprintf("%s = ~%s;", op0, op0);
    else if(mnem == "cmp")
        comment = sprintf("EFL = cmp(%s, %s);", op0, op1);
    else if(mnem == "test")
        comment = sprintf("EFL = test(%s, %s);", op0, op1);

    else if(mnem == "jnb")
        comment = "goto, if A >= B;";
    else if(mnem == "jz")
        comment = "goto, if A == B;";
    else if(mnem == "jnz")
        comment = "goto, if A != B;";
    else if(mnem == "jb")
        comment = "goto, if A < B;";
    else if(mnem == "jbe")
        comment = "goto, if A <= B;";
    else if(mnem == "jl")
        comment = "goto, if A < B;";
    else if(mnem == "ja")
        comment = "goto, if A > B;";
    else if(mnem == "js")
        comment = "goto, if A < 0;";


    else if(mnem == "pusha")
        comment = "saveAllGeneralRegisterValues()";
    else if(mnem == "popa")
        comment = "restoreAllGeneralRegisterValues()";

    else if(mnem == "stc")
        comment = "setCarryFlag();";
    else if(mnem == "clc")
        comment = "clearCarryFlag();";
    else if(mnem == "cmps")
        comment = "memcmp;";
    else if(mnem == "movs")
        comment = "memset;";

    else if(mnem == "nop")
        comment = ";";

    else if(mnem == "call")
        comment = sprintf("call %s", op0);  
    else if(mnem == "inc")
        comment = sprintf("%s++;", op0);
    else if(mnem == "dec")
        comment = sprintf("%s--;", op0);
    else if(mnem == "add")
        comment = sprintf("%s += %s;", op0, op1);
    else
    {
        // Message("unknown: 0x%X mnem: %s\n", ea, mnem);
        return true;
    }

    MakeComm(ea, comment);

    // Message("0x%X: %s\n", ea, comment);
    return true;
}

static MakeInstructionComment(ea)
{
    if(architectureType == ARCHITECTURE_TYPE_X86)
        return MakeInstructionComment_x86(ea);      
}

static main()
{
    architectureType = ARCHITECTURE_TYPE_X86;

    if(architectureType == ARCHITECTURE_TYPE_X86)
    {
        pointerSize = 4;
    }


    Message("Start of pseudo instruction adder by fastman92\n");

    auto seg, loc;

    Message("========================================\n");

    seg = FirstSeg();   // Get address pointed by a first segment

    auto shouldBreak = false;

    while(seg != BADADDR )
    {   
        Message("----------------------------------------\n");

        loc = SegStart(seg);        

        Message("Adding pseudo code comments in segment %s\n", SegName(seg));


        while(loc != BADADDR && loc < SegEnd(seg))
        {                           
            if(isCode(GetFlags(loc)))
            {
                shouldBreak = !MakeInstructionComment(loc);

                if(shouldBreak)
                    break;
            }

            loc = NextHead(loc, BADADDR);           
        }


        if(shouldBreak)
            break;

        seg = NextSeg(seg);     // get address of the next segment
    }

    Message("End of pseudo instruction adder by fastman92\n");
}
  • 1
    Wow that's awesome! Thanks so much for making the script. This is an excellent base to build upon. – wmjdgla Sep 24 '16 at 3:31
5

You can enable the auto-comment option in IDA, to have something like this:

enter image description here

Or also give a try to snowman, a free decompiler for IDA Pro, that is able to transform this compiled program:

#include <stdio.h>

int main() {
        printf("Hello, World!\n");
        return 0;
}

into

int64_t main() {
    puts("Hello, World!");
    return 0;
}
  • Unfortunately the auto-comments do not go far enough, and I'm not looking for decompilers as they do not produce accurate results all the time, at least based on what I've learned so far. – wmjdgla Sep 24 '16 at 3:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.