• Welcome to Valhalla Legends Archive.
 

Question about some asm routines in a debugger

Started by warz, October 25, 2006, 03:40 AM

Previous topic - Next topic

warz

I'm debugging an online mmorpg called Myth War, trying to figure out how it's putting together the packets for logging in. I'm trying to track down a specific unsigned short value in the packet, in the assembley. I want to know what it is, whether it be the packet id, possibly some sort of checksum, or what.

I've located where in memory the game is putting the byte information for the final packet result. The first unsigned short value is the constant 'protocol identifier', I'll call it. The second unsigned short is the packet length, excluding this first unsigned long (protocol id + packet len). The next unsigned short value in the packet is EE18h. This is the unsigned short I'm trying to track down. I have a feeling it might be the packet id, but I want to be sure. Let me explain what I saw happening while tracking this value down... (I will reverse the order, as if I was searching in the flow of the program, instead of from the moment EE18h is placed into the packet data towards the initial appearance of this value)

1. EE18h is a unsigned short value located at 0012EDFC.
2. LEA EDX, DWORD PTR SS:[ESP+10]
    Address of [ESP+10] == 0012EDFC

3. EDX now holds 0012EDFC, the address at which our unsigned short value EE18h begins.
4. The function executes about 15 more instructions, pushes EDX to the stack, and then
    calls a new function, @01284270. EDX still holds the same address.
    This function we're now in handles the building of the packet in question.

5. In this new function, EDX is eventually overwritten after another function call, and the address that was in it was not preserved in any registers. It is still visible on the stack though.

6. The stack, after the last function call, now has about 10 things above where this address we need is located. How does this address get restored, and back into one of our registers?

7. MOV ESI, DWORD PTR SS:[ESP+28]
8. ESI now contains the address we need.

This function eventually grabs the unsigned short value at this address in ESI, and adds it to the packet.

I don't really understand what this is doing. I know it must know that this address was push'd prior to this function call. And I understand that it knows [ESP+X] must be [ESP+29] to get back to the spot in the stack that this address was push'd to. I don't understand though how this value traveled so far, and originated from what looks like an irrelevant LEA call (LEA EDX, DWORD PTR SS:[ESP+10]). Is this possibly an indicator of a hardcoded value (a packet id #) or something? Or have I not investigated enough what the possible significance of DWORD PTR SS:[ESP+10] in that lea call was.

Maybe I will get a response that will clear things up, or maybe I was too confusing. Or, maybe I just haven't tracked the meaning of this unsigned long value down long enough. I just feel like throwin this out there, and seeing what response I get. Or, maybe this isn't even a question. I don't know. I'm just confusing myself. lol.

Arta

I'm not entirely sure that I follow, but here are some thoughts...

LEA is used to load addresses, in this case, to load the address of (presumably) the packet id. I'm not sure why you suspect the lea instruction is irrelevant? Incidentally, LEA is also sometimes used just as a quick way of executing expressions -- it can be used to calculate any expression of the form (register * n) + n + register.

Anyway, it sounds to me like the code is loading a pointer to the packet id, pushing it as a parameter, and calling a function which has (perhaps lots of?) local variables. The function will be making space on the stack for these variables, hence the value travelling so far. When the function needs the packet id, it's loading that parameter into esi. This is an offset from ESP because ESP points to the base of the stack frame for the function. [esp - n], therefore, points to the function's parameters, while [esp + n] points to its local variables. [esp] itself points to the base of the frame of the calling function, and [esp+4] points to the return address.

Sorry if this is stuff you already know -- not entirely sure what you're asking so I just thought I'd throw in anything that might be useful!

HTH

warz

Not sure what I was asking, either. But! I think it stems from what's happening with ESP here. If ESP is the base of the stack frame for the function, and ESP+4 is the return address, then ESP+8 should be where this possible packet id pointer is located. Howcome then this function grabs it by doing [ESP+28]? Seems to me like ESP is keeping track of where on the stack things are currently being push'd to.

I dont know if this is a situation in which youd need to see some code, or not, or if this is something that can be answered in general.

Kp

Arta's answer covered the common way of doing stack frames, but there's another method of doing them which seems to be in use here.  It is traditional on x86 to use EBP as the "frame pointer."  When this is being done, you will see:


push ebp
mov ebp, esp
< function body >
mov esp, ebp
pop ebp
ret

or

push ebp
mov ebp, esp
< function body >
leave
ret


in the function.  However, it is also possible to skip using a frame pointer.  This frees up the EBP register for use as a general calculation register, but also makes debugging (and reverse engineering!) harder since a debugger cannot find the base of the stack frame as readily.  When EBP is used as a frame pointer, the debugger just reads EBP to find the base.  When EBP is not used as a frame pointer, the frame occurs at ESP+N for some N, where N varies as parameters for subfunctions are pushed onto the stack.

From the sound of it, the function you are investigating is not using a frame pointer, but rather the compiler kept track of where the frame would be and used biases off ESP to fetch variables (locals and function arguments) from the frame.  Thus, Arta's comments may not apply to it as readily.  It would probably be better to show us the function(s) in question.
[19:20:23] (BotNet) <[vL]Kp> Any idiot can make a bot with CSB, and many do!