Tag Archives: decompilation

Naive x86 Re-targeter

Here’s the complete, do-it-yourself instructions and code for that re-targeting experiment. First, the files:

The re-targeter wants to process code like that found in function.txt. This is the disassembly format output by my favorite Win32 PE disassembler, Sang Cho’s Disassembler. I knew in advance that the function expects 4 parameters, and that fact is hardcoded in the re-targeter along with the file name. The testbench.c file contains the opcodes for the original function and allows the programmer to switch between the original opcodes and the re-targeted code for verification.

To run this experiment:

  • download all 5 files into one (Unix, x86) directory
  • ./unnamed-re-project.py > bitreader.c
  • gcc *.c -o testbench

The testbench.c program simulates the data structure that the re-targeted bitreading function expects, along with a bitstream that looks like 0xA5, 0x5A repeated. Running the program should result in:

 12 bits = A55
  4 bits = A

If compiling on x86_32, you can switch the “#if 0” to “#if 1” in order to test the original opcodes.

I took a stab at making the re-targeter portable to a big endian platform, as brainstormed last night. However, I soon realized what my hastily scrawled, year-old note about that task’s difficulty must have warned about– the outlined approach works for source arguments, but is not as straightforward for destination arguments.

I don’t have immediate access to an x86_64/Linux environment, but I would like to know if the re-targeted code compiles on that platform. The entire point of a re-targeter is to run code on a different platform, though I suppose alternate operating systems on the same CPU architecture is another interpretation.

So, of course the re-targeter is super-naive in its current form. It only implements enough instructions to handle that one function in function.txt. It does not handle branching at all. In order to do so, each of the instruction emitters would also need to output the code that adjusts the appropriate flags after each arithmetic instruction. Then, a branch would map to a simple goto with the correct address label.

Related Posts

Implementing The Re-targeter

It was nearly a year ago that I tried my hand at writing a re-targeter — a program that can take machine opcodes and automatically translate them into a portable C program, which certainly sounds simple and intuitive enough. I was really quite busy last year about this time and I don’t remember how I found time for the re-targeter experiment in the first place. But it looks like I had time to write up some notes that I never fleshed out and published. It was hard enough just to locate the old source code. I was completely surprised to find that I had actually managed to write the re-targeter in Python; I had no idea I knew so much of that language (which, granted, isn’t much).

Here are some of the problems I encountered when I took a stab at writing a re-targeter; let’s see if I can remember the specifics a year later:

Continue reading

Barrett’s Basic Blocks Are Back

Thanks to Sean Barrett for helping me compile his bb86 app. I let it rip on this code snippet from the Unnamed RE Project. It’s interesting stuff. I omitted the push, pop, and ret instructions since basic blocks pertain to linear sequences of load, store, and arithmetic instructions:

$ ./bb86 < ~/basic-block.asm
Reading stdin
Warning: unknown opcode 'bswap' in line 9

Memory locations:
        mem1 EQU dword+(ebp_0)+08
        mem5 EQU dword+(mem4)+((mem3 >> 03))
        mem4 EQU dword+(mem1)+10
        mem3 EQU dword+(mem1)+04
        mem2 EQU dword+(ebp_0)+0c

Integer registers:
  eax = ((mem5 < < cl_0) >> cl_0)
  ebx = mem4
  ecx = (00000020 - mem2)
  edx = (mem3 >> 03)
  esi = mem2
  edi = mem1

Floating point stack:
  st(0) = fp3
  st(1) = fp2
  st(2) = fp1
  st(3) = fp0

Memory locations:
  [dword+(mem1)+04] < = (mem3 + mem2)

I am pretty sure that all of those register states are true at the end of the block, though they are listed in the traditional sequence rather than the logical order. I.e., cl needs to be set before eax could be correct.

I tried out bb86 on a basic block of floating point instructions (using a computation I understand, like the distance between 2 points, rather than a Fourier transform), and it was less than successful (crash). But I can not fault the program since I am feeding it data disassembled by objdump (-Mintel) rather than Microsoft's official format. Again, bb86 is an interesting effort, and I was impressed when I examined the output of test.asm that was packaged with the code (seen in Sean's original comment).