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.

4
  • 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, 2016 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, 2016 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, 2016 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, 2016 at 3:19

2 Answers 2

2

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
  • 1
    Wow that's awesome! Thanks so much for making the script. This is an excellent base to build upon.
    – wmjdgla
    Sep 24, 2016 at 3:31
6

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;
}
1
  • 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, 2016 at 3:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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