1

I'm trying to reverse engineer a proprietary scripting "compiled bytecode" So I can recover source codes of contractor who has gone.

While I worked out the majority of it, I'm trying to work out how to translate expressions back into code. Wondering if anyone may have some ideas from the patterns below the sort of logic that might be used to rebuild the equations. In particular how operators may be applied back to the components of the expression.

Specifically I'm trying to work out how to decompile these two expressions:

A = B * C+D/E-F
A = B * (C+D)/E-F

Operation Codes ,this was worked out from examples provided below

22 04 >
2B 04 <
32 04 *
01 04 +
17 04 /
55 04 -
25 00 AND
27 00 OR
26 04 end of statement

Type of assignment:

3D 40 xx xx       = Variable xx xx 
3D 45 xx xx xx xx = 4 byte number
4B xx             = One byte value
48 xx             = One byte value
38 40 xx xx       = Assign result to variable xx xx

In this example the variables are:

A = 00 00
B = 00 04
C = 00 08
D = 00 0C
E = 00 10
F = 00 14

Example:

A = 10*20+30/40-50/2

4B AF       ; 175 
38 40 00 00 ; Assign result to A

A = 10*B+30/40-50/2

48 0A       ; 10
3D 40 00 04 ; B 
32 04       ; *
48 00       ; 0
01 04       ; +
48 19       ; 25
55 04       ; -
38 40 00 00 ; assign result to A

A = B+C

3D 40 00 04 ; B
3D 40 00 08 ; C
01 04       ; +
38 40 00 00 ; assign result to A

A = B*C

3D 40 00 04 ; B
3D 40 00 08 ; C
32 04       ; *
38 40 00 00 ; assign result to A

A = B-C

3D 40 00 04 ; B
3D 40 00 08 ; C
55 04       ; -
38 40 00 00 ; Assign result to A

A = B/C

3D 40 00 04 ; B
3D 40 00 08 ; C
17 04       ; / 
38 40 00 00 ; Assign result to A

A = B*C+D-E/F

3D 40 00 04 ; B
3D 40 00 08 ; C
32 04       ; *
3D 40 00 0C ; D
01 04       ; +
3D 40 00 10 ; E
3D 40 00 14 ; F
17 04       ; /
55 04       ; -
38 40 00 00 ; Assign result to A

A = B*C+D/E-F

3D 40 00 04 ; B
3D 40 00 08 ; C
32 04       ; *
3D 40 00 0C ; D
3D 40 00 10 ; E
17 04       ; / 
01 04       ; +
3D 40 00 14 ; F
55 04       ; -
38 40 00 00 ; Assign result to A

A = B*(C+D)/E-F

3D 40 00 04 ; B
3D 40 00 08 ; C
3D 40 00 0C ; D
01 04       ; +
32 04       ; *
3D 40 00 10 ; E
17 04       ; /
3D 40 00 14 ; F
55 04       ; -
38 40 00 00 ; Assign result to A

A = B+C * D

3D 40 00 04 ; B
3D 40 00 08 ; C 
3D 40 00 0C ; D
32 04       ; * 
01 04       ; +
38 40 00 00 ; assign result to A

A=(B+C) * D

3D 40 00 04 ; B
3D 40 00 08 ; C
01 04       ; +
3D 40 00 0C ; D
32 04       ; *
38 40 00 00 ; assign result to A

A=B+C+D * E

3D 40 00 04 ; B
3D 40 00 08 ; C
01 04       ; +
3D 40 00 0C ; D
3D 40 00 10 ; E
32 04       ; *
01 04       ; +
38 40 00 00 ; assign result to A

A=(B+C+D) * E

3D 40 00 04 ; B
3D 40 00 08 ; C
01 04       ; +
3D 40 00 0C ; D
01 04       ; +
3D 40 00 10 ; E
32 04       ; *
38 40 00 00 ; assign result to A

A=A+B * C+D+E * F

3D 40 00 00 ; A
3D 40 00 04 ; B
3D 40 00 08 ; C
32 04       ; *
01 04       ; +
3D 40 00 0C ; D
01 04       ; +
3D 40 00 10 ; E
3D 40 00 14 ; F
32 04       ; *
01 04       ; +
38 40 00 00 ; Assign result to A

A=(A+B) * (C+D)+E * F

3D 40 00 00 ; A
3D 40 00 04 ; B
01 04       ; + 
3D 40 00 08 ; C
3D 40 00 0C ; D
01 04       ; +   
32 04       ; *
3D 40 00 10 ; E
3D 40 00 14 ; F
32 04       ; *
01 04       ; +
38 40 00 00 ; Assign result to A

A=A+B+(C * D)+E

3D 40 00 00 ; A
3D 40 00 04 ; B
01 04       ; +
3D 40 00 08 ; C
3D 40 00 0C ; D
32 04       ; *
01 04       ; +
3D 40 00 10 ; E
01 04       ; + 
38 40 00 00 ; assign result to A

A=A+B+(C* D *E)+F

3D 40 00 00 ; A
3D 40 00 04 ; B
01 04       ; +
3D 40 00 08 ; C
3D 40 00 0C ; D
32 04       ; *
3D 40 00 10 ; E
32 04       ; *
01 04       ; +
3D 40 00 14 ; F
01 04       ; +
38 40 00 00 ; assign result to A

A=B-C

3D 40 00 04 ; B
3D 40 00 08 ; C
55 04       ; -
38 40 00 00 ; assign result to A

A=B*C+D-E/F

3D 40 00 04 ; B
3D 40 00 08 ; C
32 04       ; *
3D 40 00 0C ; D
01 04       ; +
3D 40 00 10 ; E
3D 40 00 14 ; F
17 04       ; -
55 04       ; /
38 40 00 00 ; Assign result to A

Boolean Expressions

512 < A

3D 45 00 00 02 00 ; 512
3D 40 00 00       ; variable A
2B 04             ; <
26 00             ; end of expression
00 7E             ; ?

a>B and b128 or d>1024 or e>128

3D 40 00 00 ; A
3D 40 00 04 ; B
22 04       ; >
25 00       ; AND
00 CC       ;
3D 40 00 04 ; B
3D 40 00 08 ; C
2B 04       ; <
25 00       ; AND
00 CC       ;
3D 40 00 08 ; C
4B 80       ; 128
22 04       ; >
27 00       ; OR 
00 E8       ;
3D 40 00 0C ; D 
3D 45 00 00 04 00 ; 1024
22 04       ; >
27 00       ; OR 
00 E8       ; 
3D 40 00 10 ; E
4B 80       ; 128
22 04       ; >
26 00       ; end of expression
01 14       ; ?
2
  • 5
    Your notation is stack based Polish notation – "postfix". The form you want to convert it to is called "infix". Adding those two together, you may want to read the answers in Converting from postfix to infix.
    – Jongware
    Jun 29, 2015 at 0:08
  • Isn't your example for A=B*C+D-E/F incorrect? It should have been B C * D + E F / - instead of B C * D + E F - / Jun 29, 2015 at 5:22

1 Answer 1

2

Thanks to response from Jongware who correctly identified this as reverse polish notation, which needed to be converted to "infix"

Tested on some samples

Original:

1) A=B * C+D-E/F

2) A=B * C+D/E-F

3) A=B * (C+D)/E-F

Decompiled:

1) A=(((B * C)+D)-(E/F))

2) A=(((B * C)+(D/E))-F)

3) A=(((B* (C+D))/E)-F)

If this helps anyone else this is the prototype processing code in C#, which I've verified works correctly. This code needs further improvement, but it does work for this scenario described.

    // instruction is a byte[] array containing the code to decode
    Stack<string> stack = new Stack<string>();
    string op;
    byte[] bit32=new byte[4];
    string result;

    for (int i = 0; i < instruction.Length;i++ )
    {
        op="";
        switch (instruction[i])
        {
            case 0x22:
                op=">";
                i++;
                break;
            case 0x2B:
                op="<";
                i++;
                break;
            case 0x32:
                op="*";
                i++;
                break;
        case 0x01:
            op="+";
            i++;
            break;
        case 0x17:
            op="/";
            i++;
            break;
        case 0x55:
            op="-";
            i++;
            break;
        case 0x38:
            i++;

            if (instruction[i]==0x40)
            {
                // builds the final result, and adds it to textboxDecompiledText
                i++;
                result = string.Format("{0}={1}", string.Format("S{0:X2}{1:X2}", instruction[i], instruction[i + 1]),
                stack.Pop());

                i++;

                textBoxDecompiled.Text += result;
                break;

            }
            break;
        case 0x4B: // 1 byte integer
        case 0x48:
            i++;
            stack.Push(((int)instruction[i]).ToString());
            break;
        case 0x3D:
            i++;
            switch (instruction[i])
            {
                case 0x40: // variable
                    i++;
                    string currentVariable= string.Format("S{0:X2}{1:X2}", instruction[i], instruction[i + 1]);
                    stack.Push(currentVariable);
                    i += 1;
                    break;
                case 0x45: // 4 byte integer
                    i++;
                    Buffer.BlockCopy(instruction,i,bit32,0,4);
                    Array.Reverse(bit32);
                    int bit32result = BitConverter.ToInt32(instruction, 0);
                    stack.Push(bit32result.ToString());
                    i+=3;
                    break;


            }
            break;

    }

    // check if we have an operator
    if (!string.IsNullOrEmpty(op))
    {
        if (stack.Count >= 2)
        {
            string op2 = stack.Pop();
            string op1 = stack.Pop();
            stack.Push(string.Format("({0}{1}{2})", op1, op, op2));
        }
        else
        {
            // something wrong here!
            throw new InvalidOperationException();
        }
    }
}

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.