Gmail Calendar Documents Reader Web more »
Recently Visited Groups | Help | Sign in
Google Groups Home
Message from discussion DirectShow question
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Alessandro Angeli [MVP::DigitalMedia]  
View profile  
 More options Dec 8 2004, 1:15 pm
Newsgroups: microsoft.public.win32.programmer.directx.audio
From: "Alessandro Angeli [MVP::DigitalMedia]" <nob...@nowhere.in.the.net>
Date: Wed, 8 Dec 2004 19:15:21 +0100
Local: Wed, Dec 8 2004 1:15 pm
Subject: Re: DirectShow question

Chris P. [MVP] wrote:
> I would be interesting in taking a look when you have
> time.

The idea to not use Detours is simple: do the same stuff
Detours does on my own.

In the very end, what Detours does is quite "easy": Detours
copies N bytes from the start of the function (F) to
somewhere else (G), then overwrites the first 5 bytes of F
with a jump instruction to your function (H) and last
appends to G a jump to &F[N]. The difficulty is only in the
choice of N: N must be >= 5, it must not go beyond the end
of F and must contain an integral number of instructions.
This last part requires the code of F to be disassembled and
it is not difficult but very long to write given the mess of
the IA-32 opcodes. Of course, you need to VirtualProtect()
both the segments of F and G so that you can write to them
and them VirtualProtect() them as they were before.

Since I didn't want to write a table of IA-32 opcodes by
hand, I decided that I would copy the whole body of F, that
is N = size_of_body(F). This would also make the appended
jump not needed. Of course, there is no way to know where F
ends without disassembling the code. But I could then copy
the whole code segment where F resides (practically the
whole DLL code chunk). This wastes some memory, but doesn't
require me to know anything about IA-32 opcodes (but the
jump opcode I have to write). The idea is that either F lies
wholly inside this segment, or it has to perform an absolute
jump somewhere else sooner or later, and this jump would
still work to the original code I didn't copy. Since I copy
the whole segment, this works even if F jump backwards in
the segment.

I had to make an assumption that F contains at least 5
bytes, but this quite a safe assumptions (Detours actually
checks) given that shorter-than-5-bytes instructions are not
unconditional jumps and thus there must be other
instructions that follow.

So, let's say I want to detour F with my function H and get
a pointer to the original function in G, I do the following
(no error-checking or resource releasing):

VOID AxlDetourFunction(
 LPVOID  F,  /// function to detour
 LPVOID  H,  /// my new function
 LPVOID* pG) /// old function
{
 LPVOID pv;
 DWORD  dw, ul;
 MEMORY_BASIC_INFORMATION mbi;

 /// find out about F's segment
 VirtualQuery(F,&mbi,sizeof(mbi));

 /// allocate a new writable segment
 pv = VirtualAlloc(NULL,mbi.RegionSize,
    MEM_COMMIT,PAGE_READWRITE);

 /// copy F's segment to the new one
 MoveMemory(pv,mbi.BaseAddress,mbi.RegionSize);

 /// make the new segment read/exec-only
 VirtualProtect(pv,mbi.RegionSize,
    PAGE_EXECUTE_READ,&dw);

 /// the old function starts at the same offset
 /// in the new segment where it started in the old one
 *pG = (LPBYTE)pv + ((LPBYTE)F - (LPBYTE)mbi.BaseAddress);

 /// make F's segment writable
 VirtualProtect(mbi.BaseAddress,mbi.RegionSize,
    PAGE_EXECUTE_READWRITE,&dw);

 /// write the jump opcode
 ((LPBYTE)F)[0] = (BYTE)0xE9;
 /// calculate the jump offset
 ul = (LPBYTE)H - &((LPBYTE)F)[6];
 /// write the jump offset (since there is no guarantee
 /// that the offset's DWORD is DWORD aligned, this is
 /// safer even if not really needed on modern CPUs)
 MoveMemory(((LPBYTE)F)[1],&ul,sizeof(ul));

 /// protected F's segment as it was before
 VirtualProtect(mbi.BaseAddress,
    mbi.RegionSize,dw,&dw);

}

--

// Alessandro Angeli
// MVP :: Digital Media
// a dot angeli at psynet dot net


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.

Create a group - Google Groups - Google Home - Terms of Service - Privacy Policy
©2009 Google