Help deciphering a few lines of assembly
Asked Answered
P

4

5

I have found these few lines of assembly in ollydbg:

MOV ECX,DWORD PTR DS:[xxxxxxxx] ; xxxxxxxx is an address
MOV EDX,DWORD PTR DS:[ECX]
MOV EAX,DWORD PTR DS:[EDX+116]
CALL EAX

Could someone step through and tell me what's happening here?

Petrinapetrine answered 10/8, 2010 at 20:22 Comment(3)
@x0n - whence the homework tag?Miller
This isn't homework, I'm just not good at assembly.Petrinapetrine
This program you disassembled... what is it similar to out there in the real world that we might imagine it is "very, very much alike"?Miller
M
6

This is an invocation of a function pointer stored in a struct.

This first line obtains a pointer stored at address DS:xxxxxxxx. The square brackets indicate dereferencing of the address, much like * in C. The value from memory is about to be used as a pointer; it is placed into ecx register.

MOV ECX,DWORD PTR DS:[xxxxxxxx] ; xxxxxxxx is an address

The second line dereferences the pointer obtained above. That value from ecx is now used as the address, which is dereferenced. The value found in memory is another pointer. This second pointer is placed into the edx register.

MOV EDX,DWORD PTR DS:[ECX]

The third line again dereferences memory; this time, the access occurs to an address offset from the pointer obtained above by 0x116 bytes. This is not evenly divisible by four, so this function pointer does not appear to come from a C++ vtable. The value obtained from the memory is this time stored in register eax.

MOV EAX,DWORD PTR DS:[EDX+116]

Finally, the function pointed to by eax is executed. This simply invokes the function via a function pointer. The function appears to take zero arguments, but I have a question on revision of my answer: are there PUSH instruction which precede this snippet? Those would be the function arguments. The question marks indicate this function might return a value, we can't tell from our vantage.

CALL EAX

Overall, the code snippet looks like an invocation of an extension function from a plug-in library to OllyDbg. The OllyDbg ABI specifies various structs which contain some function pointers. There are also arrays of function pointers, but the double-indirection to get to the edx-held pointer (also the not-aligned-by-even-multiple offset) makes me think this is a struct and not an array of function pointers or a C++ class's vtable.

In other words, xxxxxxxx is a pointer to a pointer to a struct containing a function pointer.

In the OllyDbg source file PlugIn.h are some candidate struct definitions. Here's an example:

typedef struct t_sorted {              // Descriptor of sorted table
  char           name[MAX_PATH];       // Name of table, as appears in error
  int            n;                    // Actual number of entries
  int            nmax;                 // Maximal number of entries
  int            selected;             // Index of selected entry or -1
  ulong          seladdr;              // Base address of selected entry
  int            itemsize;             // Size of single entry
  ulong          version;              // Unique version of table
  void           *data;                // Entries, sorted by address
  SORTFUNC       *sortfunc;            // Function which sorts data or NULL
  DESTFUNC       *destfunc;            // Destructor function or NULL
  int            sort;                 // Sorting criterium (column)
  int            sorted;               // Whether indexes are sorted
  int            *index;               // Indexes, sorted by criterium
  int            suppresserr;          // Suppress multiple overflow errors
} t_sorted;

Those examples are allowed to be NULL, and your asm snippet does not check for NULL pointer in the function pointer. Therefore, it would have to be DRAWFUNC from t_table or SPECFUNC of t_dump.

You could create a small project which includes the header file and uses printf() and offsetof() to determine whether either of those is at an offset of 0x116.

Otherwise, I imagine that the insides of OllyDbg are written in this same style. So there are likely to be private struct definitions (not published in the Plugin.h file) used for various purposes within OllyDbg.


I would like to add, I think it's a shame that OllyDbg sources are not available. I was under the impression that the statically-linked disassembler it contains was under some kind of ?GPL license, but I haven't had any luck getting the sources to OllyDbg.

Miller answered 10/8, 2010 at 20:34 Comment(7)
"This is probably an invocation..." would be more accurate, no? You have no idea what it really is.Autonomic
@x0n. No, I think I have a very good idea what it is. I've got some experience with OllyDbg. For example, I would never have written anything along the lines of "OllyDbg might have been written in an indeterminate higher level language." It was compiled with MSVC 2005,and I possess that domain-specific knowledge. Of course, the snippet might be inline assembly, but having written an OllyDbg plugin or three and a faux OllyDbg plug-in host test harness... I think I know what it is. xoff.Miller
@heath: I didn't read his question as "this assembly is part of the ollydbg program." I read it as "I disassembled something with ollydbg and found these instructions in the debugeee."Autonomic
@x0n. Well then I see where you were coming from. Yeah, I initially guessed "C++ vtable", so I hope I wrote "probably" on first draft. Later I was 92% sure it's part of the plugin or internal ABI.Miller
@heath - @iron just confirmed on my other post via comment that indeed ollydbg is not the target, so a vtable is probably more likely.Autonomic
@Autonomic - repeating myself again, the pointers in a vtable are aligned on machine-word boundaries and 0x116 is not. So I maintain that it is far from likely to be a vtable.Miller
@heath, sorry, ok you're right about that. I still think the question is completely devoid of any useful context for framing the snippe.tAutonomic
A
2

Take the 32 bit number from the address xxxxxxx and put it in ECX register, then use this value as an address and read the value and put it in EDX register, finally add 116 to this number and read the value of that address into EAX. Then it starts executing the code at the address now held in EAX. When that code encounters a return opcode, execution will continue after the call instruction.

This is pretty basic assembly. It makes me wonder wtf you are doing with a debugger and when your assignment is due ;-)

Autonomic answered 10/8, 2010 at 20:31 Comment(8)
I'm learning assembly via debugging stuff so it's no surprise it's basic. I had a grasp of what it did, but I didn't see a point in the "MOV ECX, DWORD PTR[address]" then "MOV EDX, DWORD PTR[ECX]" so I thought it might be doing something not obvious. So anyway, does this mean that xxxxxxxx is a pointer to a function, or a pointer to a pointer to a function?Petrinapetrine
It doesn't mean anything other than what it means. You can't infer there is a "function" there, or even if functions existed as a concept in whatever higher language was compiled (or even if there was a higher level language involved, tbh) In order to reverse engineer this code, you'd need intimate knowledge of the compiler that generated it.Autonomic
I know it was MSVC++, probably 2005.Petrinapetrine
@iron: ok, so now go disassemble MSVC to figure out its compilation strategy. Oops!Autonomic
More seriously, you should try out IDA Pro disassembler - it is more informative than most, and the 4.9 version is free [for non commercial use] - hex-rays.com/idaproAutonomic
I already use IDA actually, but I am debugging at the moment, and I don't think IDA debugs.Petrinapetrine
@iron are you disassembling ollydbg itself, or another program?Autonomic
Another program, and just so you know, this isn't an assignment I was given, I'm just trying to learn stuff.Petrinapetrine
A
0

It's been awhile since I did ASM (1997) and even then I was only doing i386 ASM so forgive me if my answer isn't all that helpful...

Unfortunately, these 4 lines of code don't tell me much. It's mostly just loading stuff into CPU registers and calling a function.

Specifically, It looks like data or perhaps a pointer is being loaded from that address into your CX register. Then that value is being copied from CX to DX. So you have the value of the pointer of CX located in DX. Then that value in DX plus an offset of 116 is being copied into the AX register (your accumulator?)

Then whatever function located at that address copied into AX is being executed.

Abele answered 10/8, 2010 at 20:30 Comment(4)
Does it modify it in anyway to DWORD PTR something that has already been DWORD PTR'd?Petrinapetrine
I don't see any modifying going on, but CALL'ing EAX may call something that DOES do some altering. I can't say without knowing what's located there...Abele
I'm pretty sure it's loading the value pointed to by DS:[ECX] into EDX, not simply copying ECX to EDX, like x0n said.Sclar
good point. Like I said, it's been awhile... adjusted accordingly.Abele
M
0

I'm 99% sure it's a virtual method call, considering comments about compiler being MSVC.

MOV ECX,DWORD PTR DS:[xxxxxxxx]

Pointer to a class instance is loaded into ECX from a global variable. (NB: default __thiscall calling convention uses ECX to pass the instance pointer, aka the this pointer).

MOV EDX,DWORD PTR DS:[ECX]

vftable (virtual function table) pointer is usually the first item in the class layout. Here the pointer is loaded into EDX.

MOV EAX,DWORD PTR DS:[EDX+116]

A method pointer at offset 116 (0x74) in the table is loaded into EAX. Since each pointer is 4 bytes, this is the 30th virtual method of the class (116/4 + 1).

CALL EAX

The method is called.

In original C++ it would look something like this:

g_pObject1->method30();

To know more about MSVC's implementation of C++ classes, including virtual methods, see my article here.

Minna answered 25/8, 2010 at 22:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.