views:

1306

answers:

12

I am not well acquainted to the compiler magic. The act of transforming human-readable code (or the not really readable Assembly instructions) into machine code is, for me, rocket science combined with sorcery.

I will narrow down the subject of this question to Win32 executables (.exe). When I open these files up in a specialised viewer, I can find strings (usually 16b per character) scattered at various places, but the rest is just garbage. I suppose the unreadable part (majority) is the machine code (or maybe resources, such as images etc...).

Is there any straightforward way of reading the machine code? Opening the exe as a file stream and reading it byte by byte, how could one turn these individual bytes into Assembly? Is there a straightforward mapping between these instruction bytes and the Assembly instruction?

How is the .exe written? Four bytes per instruction? More? Less? I have noticed some applications can create executable files just like that: for example, in ACD See you can export a series of images into a slideshow. But this does not necessarily have to be a SWF slideshow, ACD See is also capable of producing EXEcutable presentations. How is that done?

How can I understand what goes on inside an EXE file?

+3  A: 

You can use debug from the command line, but that's hard.

C:\WINDOWS>debug taskman.exe
-u
0D69:0000 0E            PUSH    CS
0D69:0001 1F            POP     DS
0D69:0002 BA0E00        MOV     DX,000E
0D69:0005 B409          MOV     AH,09
0D69:0007 CD21          INT     21
0D69:0009 B8014C        MOV     AX,4C01
0D69:000C CD21          INT     21
0D69:000E 54            PUSH    SP
0D69:000F 68            DB      68
0D69:0010 69            DB      69
0D69:0011 7320          JNB     0033
0D69:0013 7072          JO      0087
0D69:0015 6F            DB      6F
0D69:0016 67            DB      67
0D69:0017 7261          JB      007A
0D69:0019 6D            DB      6D
0D69:001A 206361        AND     [BP+DI+61],AH
0D69:001D 6E            DB      6E
0D69:001E 6E            DB      6E
0D69:001F 6F            DB      6F
Dead account
learned something new today. I hope I won't break my OS soon. Happened once when I got over-excited about tweaking registry entries... Never saw my desktop again.
Peter Perháč
You can also write new code and save it back to the file. Only a madman [or hacker] would use Debug
Dead account
Count me among the few who still use debug. FYI: Microsoft's DEBUG only unassembles 16-bit real mode. If you want a 32-bit DPMI capable debug, try out japheth's version: http://www.japheth.de/debxxf.html
Coding With Style
+5  A: 

You need a disassembler which will turn the machine code into assembly language. This Wikipedia link describes the process and provides links to free disassemblers. Of course, as you say you don't understand assembly language, this may not be very informative - what exactly are you trying to do here?

anon
Doesn't link to Windbg http://www.microsoft.com/whdc/devtools/debugging/installx86.mspx
Mark
+11  A: 

OllyDbg is an awesome tool that disassembles an EXE into readable instructions and allows you to execute the instructions one-by-one. It also tells you what API functions the program uses and if possible, the arguments that it provides (as long as the arguments are found on the stack).

Generally speaking, CPU instructions are of variable length, some are one byte, others are two, some three, some four etc. It mostly depends on the kind of data that the instruction expects. Some instructions are generalised, like "mov" which tells the CPU to move data from a CPU register to a place in memory, or vice versa. In reality, there are many different "mov" instructions, ones for handling 8-bit, 16-bit, 32-bit data, ones for moving data from different registers and so on.

You could pick up Dr. Paul Carter's PC Assembly Language Tutorial which is a free entry level book that talks about assembly and how the Intel 386 CPU operates. Most of it is applicable even to modern day consumer Intel CPUs.

The EXE format is specific to Windows. The entry-point (i.e. the first executable instruction) is usually found at the same place within the EXE file. It's all kind of difficult to explain all at once, but the resources I've provided should help cure at least some of your curiosity! :)

dreamlax
this is mighty nice answer. you're right about my curiosity. It's not that I NEED to disassemble executables, I am just very interested, and would like to toy with executables a little. Get that wooow feeling when I get to understand something beyond my current horizon :)
Peter Perháč
Some people prefer IDA Pro to OllyDbg: http://www.hex-rays.com/idapro/
Coding With Style
+1  A: 

Win32 exe format on MSDN

I'd suggest taking an bit of Windows C source code and build and start debugging it in Visual Studio. Switch to the disassembly view and step over the commands. You can see how the C code has been compiled into machine code - and watch it run step-by-step.

Aardvark
+5  A: 

The executable file you see is Microsofts PE (Portable Executable) format. It is essentially a container, which holds some operating system specific data about a program and the program data itself split into several sections. For example code, resources, static data are stored in seperate sections.

The format of the section depends on what is in it. The code section holds the machine code according to the executable target architecture. In the most common cases this is Intel x86 or AMD-64 (same as EM64T) for Microsoft PE binaries. The format of the machine code is CISC and originates back to the 8086 and earlier. The important aspect of CISC is that its instruction size is not constant, you have to start reading at the right place to get something valuable out of it. Intel publishes good manuals on the x86/x64 instruction set.

You can use a disassembler to view the machine code directly. In combination with the manuals you can guess the source code most of the time.

And then there's MSIL EXE: The .NET executables holding Microsofts Intermediate Language, these do not contain machine specific code, but .NET CIL code. The specifications for that are available online at the ECMA.

These can be viewed with a tool such as Reflector.

__grover
+5  A: 

The contents of the EXE file are described in Portable Executable. It contains code, data, and instructions to OS on how to load the file.

There is an 1:1 mapping between machine code and assembly. A disassembler program will perform the reverse operation.

There isn't a fixed number of bytes per instruction on i386. Some are a single byte, some are much longer.

MaxVT
+2  A: 

If it's as foreign to you as it seems, I don't think a debugger or disassembler is going to help - you need to learn assembler programming first; study the architecture of the processor (plenty of documentation downloadable from Intel). And then since most machine code is generated by compilers, you'll need to understand how compilers generate code - the simplest way to write lots of small programs and then disassemble them to see what your C/C++ is turned into.

A couple of books that'll help you understand:-

U62
+1  A: 

Just relating to this question, anyone still read things like CD 21?

I remembered Sandra Bullock in one show, actually reading a screenful of hex numbers and figure out what the program does. Sort of like the current version of reading Matrix code.

if you do read stuff like CD 21, how do you remember the different various combinations?

zeroin23
The same way programmers who don't understand english learn to code in languages with english syntax. I think anyone who's coded low level in DOS would remember CD 21, though.
Coding With Style
+1  A: 

Both your curiosity and your level of understanding is exactly where I was at one point. I highly recommend Code: The Hidden Language of Computer Hardware and Software. This will not answer all of the questions you ask here but it will shed light on some of the utterly black magic aspects of computers. It's a thick book but highly readable.

Dinah
+1  A: 

ACD See is probably taking advantage of the fact that .EXE files do no error checking on file length or anything beyond the length of the expected portion of the file. Because of this, you can make an .EXE file that will open its self and load everything beyond a given point as data. This is useful because you can then make a .EXE that works on a given set of data by just tacking that data on the end of a suitably written .EXE

(I have no idea what exactly ACD See is so take that with a big grain of salt but I do know that some program are generated that way.)

BCS
ACD See is by and large photo editing software. http://www.acdsee.com/
Coding With Style
+2  A: 

To get an idea, set a breakpoint on some interesting code, and then go to the CPU window.

If you are interested in more, it is easier to compile short fragments with Free Pascal using the -al parameter.

FPC allows to output the generated assembler in a multitude of assembler formats (TASM,MASM,GAS ) using the -A parameter, and you can have the original pascal code interleaved in comments (and more) for easy crossreference.

Because it is compiler generated assembler, as opposed to assembler from disassembled .exe, it is more symbolic and easier to follow.

Marco van de Voort
+1, I am using Delphi on `casual basis` and I have been intrigued by the CPU, FPU, etc... windows where one can step from one instruction to another and see what's going on. I was wondering how these instructions are then made into an EXE file. And how EXE files can be generated (see ACD See example). I especially like the idea introduced by BCS :)
Peter Perháč
http://www.stack.nl/~marcov/compiler.pdf is a PDF version of the almost impossible to miss Crenshaw's tutorial. Unfortunately for a different CPU (m68k), but it illustrates the fundamentals of a compiler quite nicely.
Marco van de Voort
+1  A: 

Familiarity with low level assembly (and I mean low level assembly, not "macros" and that bull) is probably a must. If you really want to read the raw machine code itself directly, usually you would use a hex editor for that. In order to understand what the instructions do, however, most people would use a disassembler to convert that into the appropriate assembly instructions. If you're one of the minority who wants to understand the machine language itself, I think you'd want the Intel® 64 and IA-32 Architectures Software Developer's Manuals. Volume 2 specifically covers the instruction set, which relates to your query about how to read machine code itself and how assembly relates to it.

Coding With Style