Jump to content

Weird EIP problem

- - - - -

This topic has been archived. This means that you cannot reply to this topic.
21 replies to this topic

#1
RobotGymnast

RobotGymnast

    Programmer

  • Members
  • PipPipPipPip
  • 143 posts
First of all, all the code snippets mentioned in my post are (in sequential order) at:

http://robotgymnast.pastebin.com/f2dfe9b18

http://robotgymnast.pastebin.com/f602de748

http://robotgymnast.pastebin.com/f42c1d70c


My program is basically a DLL, and it gets hooked into different programs (but I'm not sure at compile time exactly what the programs will be), so it's using functors to call functions that it knows are inside the program it gets hooked into.

Oh, and a UID is basically just user ID in a DWORD, nothing special. It's also part of the original program.

Anyway, I'm having a problem: the following code snippet:

// if alt+U is pressed

if(alt('U'))

{

	// the UID string

	char UID[11] = {0};

	// the actual UID value

	DWORD ID = 0;

	// create a functor for the UID (basically it returns a UID and takes no parameters)

	MUID(__cdecl* func)(void) = ZGetMyUID();

	__asm

	{

		// call the UID function

		call func;

		// get the UID return value

		mov eax,dword ptr ds:[eax+4];

		// move it from the register to memory

		mov ID,eax;

	}

	// convert the UID to a string

	_itoa_s(ID,UID,sizeof(UID),10);

	// output the UID

	ZChatOutput()(UID,1,0,0xCC0033);

	// pause

	SleepEx(150,false);

}


works perfectly fine.. the functor might be a bit confusing; it's part of a large program.

however, changing to

void UIDTest()

{

	// the UID string

	char UID[11] = {0};

	// the actual UID value

	DWORD ID = 0;

	// create a functor for the UID (basically it returns a UID and takes no parameters)

	MUID(__cdecl* func)(void) = ZGetMyUID();

	__asm

	{

		// call the UID function

		call func;

		// get the UID return value

		mov eax,dword ptr ds:[eax+4];

		// move it from the register to memory

		mov ID,eax;

	}

	// convert the UID to a string

	_itoa_s(ID,UID,sizeof(UID),10);

	// output the UID

	ZChatOutput()(UID,1,0,0xCC0033);

	// pause

	SleepEx(150,false);

}

...

...

...

// if alt+U is pressed

if(alt('U'))

{

	// the UID test function, just checking if it works

	UIDTest();

}


ends up crashing the program. After using a debugger (OllyDBG), I've found it crashes after returning from UIDTest(), right on the RETN statement (in ASM), because it tries to return to the value in ID (or more accurately, it's jumping to a location equivalent to the value in ID.. It's not coming directly from ID). Now, I've tried commenting out some of the lines to get this:


void UIDTest()

{

	// the UID string

	char UID[11] = {0};

	// the actual UID value

	DWORD ID = 0;

	// create a functor for the UID (basically it returns a UID and takes no parameters)

	MUID(__cdecl* func)(void) = ZGetMyUID();

	__asm

	{

		// call the UID function

		call func;

	}

	// convert the UID to a string

	_itoa_s(ID,UID,sizeof(UID),10);

	// output the UID

	ZChatOutput()(UID,1,0,0xCC0033);

	// pause

	SleepEx(150,false);

}


and it crashes. I'm fairly sure it's being caused by the function call, because the function doesn't know it should be called (because the DLL isn't actually part of the program). That's my theory. It's storing something where it SHOULD be fine, but it's not because the DLL wasn't built like the main program was.

Oh, and weirdly, turning UIDTest() into an inline void doesn't help at ALL. Shouldn't that basically make it the same as the first code snippet? It still crashes when it's an inline void.

#2
FakeRobotGymnast

FakeRobotGymnast

    Learning Programmer

  • Members
  • PipPipPip
  • 43 posts
Try #defining the entire thing as a macro. If that doesn't work, it's something else entirely. If it does, the problem is DEFINITELY in making that bitch a function:

#define UIDTEST() \
	char UID[11] = {0}; \
	DWORD ID = 0; \
	MUID(__cdecl* func)(void) = ZGetMyUID(); \
	__asm \
	{ \
		call func; \
		mov eax,dword ptr ds:[eax+4]; \
		mov ID,eax; \
	} \
	_itoa_s(ID,UID,sizeof(UID),10); \
	ZChatOutput()(UID,1,0,0xCC0033); \
	SleepEx(150,false)
...
...
...
// if alt+U is pressed
if(alt('U'))
{
	UIDTEST();
}


#3
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,714 posts
Check your calling convention. It doesn't look like you're cleaning up the stack properly.

#4
RobotGymnast

RobotGymnast

    Programmer

  • Members
  • PipPipPipPip
  • 143 posts
the entire thing as a macro? That's insanely annoying.
The calling convention is __cdecl from what I know. I thought of that, but.. yeah, it's __cdecl

Oh and the other thing is I can't change much. Inline assembly is automatically cleaned up after, so I can't do anything that won't be undone after the }, so cleaning up the function call won't help much (will it?)

#5
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,714 posts
Yes. You're leaving trash at the top of the stack which will mess up function calls later. And I've never heard of ASM blocks getting cleaned up automatically.

#6
RobotGymnast

RobotGymnast

    Programmer

  • Members
  • PipPipPipPip
  • 143 posts
weird, because anything I try storing using _asm doesn't work..
I've tried pushing something in one ASM block, and poping in another, and it crashed. However, just pushing values didn't screw ANYTHING up.
Any idea how to correct this problem?

#7
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,714 posts
What did you have between those ASM blocks? And more importantly, why are you using ASM? It seems superfluous in some cases.

#8
RobotGymnast

RobotGymnast

    Programmer

  • Members
  • PipPipPipPip
  • 143 posts
Oh, that's true, I had a function call in between. And because I'm calling a function from the original program, it crashes when I call it the conventional way (no pun intended)

#9
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,714 posts
Something like that, yeah. Like I said before--you're improperly cleaning up the stack. My suggestion is to use assembly language as little as possible. I still don't know why you're using it for this.

#10
RobotGymnast

RobotGymnast

    Programmer

  • Members
  • PipPipPipPip
  • 143 posts
Again, because calling the function normally doesn't work.
How do you clean up the stack after __cdecl? I don't think there are supposed to be any arguments

#11
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,714 posts
If there aren't any arguments then you don't need to. Otherwise you need

add esp,<argument-size>

And why doesn't calling the function work?

#12
RobotGymnast

RobotGymnast

    Programmer

  • Members
  • PipPipPipPip
  • 143 posts
It just doesn't.. it gives me a garbage return value and then crashes.
add esp,4
for example? @#*$.. that's called after every call to this function.
It didn't show as an argument in OllyDBG, but I'm looking at it in IDA Pro and there's an argument after all! Thanks. *goes to test*

Hmm.. adding

add esp,4

just crashes it.. my debug output from visual studio tells me ESP wasn't saved properly across a function call.