Welcome to MSDN Blogs Sign in | Join | Help

Don't trust the return address

Sometimes people ask, "So I know how to get my return address [use the _ReturnAddress() intrinsic]; how do I figure out what DLL that return address belongs to?"

Beware.

Even if you figure out which DLL the return address belongs to [use GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS)], that doesn't mean that that is actually the DLL that called you.

A common trick is to search through a "trusted" DLL for some code bytes that coincidentally match ones you (the attacker) want to execute. This can be something as simple as a "retd" instruction, which are quite abundant. The attacker then builds a stack frame that looks like this, for, say, a function that takes two parameters.

trusted_retd
hacked parameter 1
hacked parameter 2
hacker_code_addr

After building this stack frame, the attacker then jumps to the start of the function being attacked.

The function being attacked looks at the return address and sees trusted_retd, which resides in a trusted DLL. It then foolishly trusts the caller and allows some unsafe operation to occur, using hacked parameters 1 and 2. The function being attacked then does a "retd 8" to return and clean the parameters. This transfers control to the trusted_retd, which performs a simple retd, which now gives control to the hacker_code_addr, and the hacker can use the result to continue his nefarious work.

This is why you should be concerned if somebody says, "This code verifies that its caller is trusted..." How do they know who the caller really is?

Published Thursday, January 01, 2004 7:00 AM by oldnewthing
Filed under:

Comments

# re: Don't trust the return address

Thursday, January 01, 2004 8:42 AM by ep
So is there a way to verify that my caller is trusted and allows some operations?

# re: Don't trust the return address

Thursday, January 01, 2004 9:56 AM by zz

# re: Don't trust the return address

Thursday, January 01, 2004 12:02 PM by Peter Torr
Well, in .NET you have IPermission.Demand() to see if all your callers have the right permissions, or SecurityAction.LinkDemand if you just want to check your immediate caller (which is generally a really bad idea -- avoid using LinkDemands to enforce security; they're better suited to improving API usability).

# re: Don't trust the return address

Thursday, January 01, 2004 2:40 PM by Phaeron
There are other reasons why the return address shouldn't be used to determine the caller: the source may be a dynamically generated code fragment, and the call to the DLL function may be a tail call (jmp dword ptr [__imp__DefWindowProc@16]).

Incidentally, what is the "sanctioned" method of emulating GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS) on pre-XP platforms? The only way I know of is to VirtualQuery() the address and case the AllocationBase to HMODULE.

# re: Don't trust the return address

Thursday, January 01, 2004 3:16 PM by Raymond Chen
zz: It looks like they focused on my phrase "You dummy". I didn't mean it to be as insulting to the user as it turned out. I should have written "Psst" instead, but what's done is done.

# re: Don't trust the return address

Thursday, January 01, 2004 8:02 PM by Steve Sheppard
No, you did the right thing. You wrote what you meant, they CHOSE to be insulted by it. Don't play the PC game by trying to guess what they will insulted by because the answer is eveything. Anyone who reads your blog regularly knows what you mean and to hell with idiots like that guy.

Keep up the good work!

# re: Don't trust the return address

Saturday, January 03, 2004 1:54 AM by Peter Lund/firefly@diku.dk
why would anyone try to get the return address?

# re: Don't trust the return address

Saturday, January 03, 2004 8:49 AM by Raymond Chen
Because they want to do things "only if their caller is trusted".

# re: Don't trust the return address

Saturday, January 03, 2004 9:30 AM by Peter Lund/firefly@diku.dk
But, but... that *really* makes no sense :)

Reminds me of the Poly/Turbo/Borland Pascal programmers I've met who wanted an "exit2" pseudo procedure that would leave not just one but /two/ procedures.

(exit is like return in C without an argument, Pascal can have nested functions unlike C (but like gcc))

I thought at least *somebody* had had a real need for it?

# Native code caller verification - and why not to.

Monday, January 12, 2004 11:16 AM by The Millionth Monkey Speaks
Recently on Raymond Chens blog he had a post about not trusting return addresses. Specifically to not use the _ReturnAddress() intrinsic and GetModuleHandleEx to figure out if the caller is trusted. I had to try and come up with a...

# Native code caller verification - and how not to do it.

Thursday, January 15, 2004 11:41 AM by Robert Horvick's Weblog

# Native code caller verification - and how not to do it.

Thursday, January 15, 2004 11:40 AM by Robert Horvick's Weblog

# re: What is the default security descriptor?

Saturday, March 20, 2004 9:18 AM by The Old New Thing

# Why are DLLs unloaded in the "wrong" order?

Monday, May 23, 2005 9:00 AM by The Old New Thing
Because there sometimes isn't enough information to determine what the "right" order is.

# Why does FindFirstFile find short names?

Wednesday, July 20, 2005 10:00 AM by The Old New Thing
Counterintuitive results from the file search.

# You can't even trust the identity of the calling executable

Friday, February 03, 2006 10:00 AM by The Old New Thing
Thanks to code injection.

# Don't trust the return address, no really

Thursday, August 17, 2006 10:00 AM by The Old New Thing
No really, you can't.
New Comments to this post are disabled
 
Page view tracker