Page 1 of 3 123 LastLast
Results 1 to 15 of 38

Thread: Hooking a member function from an injected DLL?

  1. #1
    Shakkan
    Guest

    Question Hooking a member function from an injected DLL?

    Hi everyone,

    First post here. I've been reading/learning about reversing and assembly in the past few weeks and I'm quite thrilled. However, I came across a problem that I hope some of you gurus can help me with.

    I am trying to hook a member function in a game. Once my hook function is called, I want to call the original back asap. The sole purpose of that hook is to monitor calls to that method. No cheating/hacking. :|

    My problem relies on the fact that member functions are called with the _thiscall_ calling convention. That means, for MSVC, that parameters are passed from right-to-left (like _cdecl_ and _stdcall_) but ALSO that _this_ is passed to the ECX register. That means that both my hook function and my function pointer to the original method must use the _thiscall_ calling convention.

    There's a sample (named 'member.cpp') in Microsoft Detours library that explains how to do such a thing. The catch is that everything in their sample is in the same source code so it's easy for them to initialize a member function pointer to the target method since they have access to the code, I don't.

    All I have access to is the address of the method. I know it's not virtual since it's not called from a vtable.

    I guess that my main question would be: how can I have a member function pointer point to an arbitrary address? (or how to have function ptr use _thiscall


    Go there: http://pastebin.com/m6faac073 to see Microsoft Detours member function hooking sample. At line 68, they initialize the Real_Target member function pointer to &CMember::Target. Well, anyone hooking from an injected DLL will NOT have access to that code (CMember::Target) but only the address of CMember::Target (like I have, 0x005C5600 for example).

    I just want to mention that I am able to inject myself, and I am able to hook myself to the method. I'm just not able to _properly_ call the original method back (no __thiscall == no more _this in ECX etc.) access violation ensues once original method wants to write a member...

    I hope my problem is clear and I hope that this future discussion can help others.
    Thanks in advance everyone!
    Last edited by Shakkan; March 12th, 2008 at 22:10. Reason: Seems like URL doesn't work...
    I promise that I have read the FAQ and tried to use the Search to answer my question.

  2. #2
    <script>alert(0)</script> disavowed's Avatar
    Join Date
    Apr 2002
    Posts
    1,281
    Quote Originally Posted by Shakkan View Post
    I guess that my main question would be: how can I have a member function pointer point to an arbitrary address?
    Can't you just cast the address to the member function pointer type? Like "FARPROC pFunction = (FARPROC)0x0041ABCD"?

  3. #3
    Shakkan
    Guest
    You can do so with a function, not with a method. Anyhow, I found a way to do the hook, by converting the __thiscall method to a __stdcall hook function (pushing ECX to the stack).

    For further details, see DetourClassFunc from Azorbix on Game Deception. Great work.

    Now my problem lies with anti-cheating software PunkBuster even though I don't want to cheat. I just want to be notified of a certain method call but I can't alter the code at all. SEH could work but apparently, SafeDisc uses the debug registers.

    ...still looking for a way. I'm sure there is, I just need to learn more.
    Anyone has an idea? How to be notified of a call in a certain module without altering any of its code besides SEH and hardware breakpoints?

    Thank you.
    Last edited by Shakkan; March 15th, 2008 at 00:30.
    I promise that I have read the FAQ and tried to use the Search to answer my question.

  4. #4
    <script>alert(0)</script> disavowed's Avatar
    Join Date
    Apr 2002
    Posts
    1,281
    memory breakpoints (setting the pages to page_no_access or page_guard) and seh/veh to catch the exceptions. but it's not very performant.

  5. #5
    Shakkan
    Guest
    And can you set a PAGE_GUARD on only a few bytes of the code segment? (i.e. not 4096)

    Thank you for the suggestion.
    I promise that I have read the FAQ and tried to use the Search to answer my question.

  6. #6
    I'm afraid guarded access necessarily spans the entire page. Commonly, arbitrary granularity is emulated by resetting the guard each time it fires, transparently resuming whenever the hit is out of range. Of course, this doesn't come without a performance penalty, and it can become unworkable if a lot of activity occurs in the surrounding area, which is likely to be the case for executable code.

    A better alternative would be to plant an INT3 at the function's first instruction and use a vectored exception handler to take things from there. This is a great way of efficiently halting the program when the function fires, but resuming execution is a bit of a pain.

    Are you sure SafeDisc is using all the debug registers? You only need one for your purposes, so it may be worth trying to use that last processor breakpoint slot and seeing if things don't fall apart.
    www.ring3circus.com
    Diary of a programmer, journal of a hacker.

  7. #7
    Shakkan
    Guest
    Plant an INT3 and use a VEH would be easy, but planting an INT3 == modifying code ==> PunkBuster angry. :\

    Regarding the debug registers, that's a good question if SafeDisc uses them all. I need to check that out properly. As soon as my SEH would be called, the application would crash. Maybe I'm doing something else wrong that has nothing to do with SafeDisc.

    A quick question since you seem familiar with hardware breakpoints: by default, do hardware breakpoints cause single-step exceptions (i.e. execute the first instruction at the specified address in debug register and then pop the exception, allowing me to continue normal execution of the program)? I recall that with INT3 + VEH, you need to set EFlag to 0x100 to have such a behaviour, am I mistaken? If so, would you be so kind as to enlighten me?

    Thank you!
    I promise that I have read the FAQ and tried to use the Search to answer my question.

  8. #8
    <script>alert(0)</script> disavowed's Avatar
    Join Date
    Apr 2002
    Posts
    1,281
    i forget the actual exception thrown when hitting a hw bp (and i'm too lazy to look it up), but yes, the exception is only caught by the debugger AFTER the instruction responsible for the exception has already executed (unlike software bps that get thrown to the debugger BEFORE executing the target instruction).

  9. #9
    Administrator dELTA's Avatar
    Join Date
    Oct 2000
    Location
    Ring -1
    Posts
    4,206
    Blog Entries
    5
    Shakkan, if you're uncertain if SafeDisc is the culprit or not, maybe you can do some experiments on an un-SafeDisced copy, and then use your result on the real copy once all non-SafeDisc related problems have been solved?
    "Give a man a quote from the FAQ, and he'll ignore it. Print the FAQ, shove it up his ass, kick him in the balls, DDoS his ass and kick/ban him, and the point usually gets through eventually."

  10. #10
    Shakkan
    Guest
    Damn right. I'm trying to skip steps here. :\

    Thank you.
    I promise that I have read the FAQ and tried to use the Search to answer my question.

  11. #11
    Hardware breakpoints do indeed rasie a SINGLE_STEP exception, but IIRC there are some occasions where the exception is raised before the instruction is executed, rather than after. I think this is the exception to the rule (no pun intended) but I believe certain REP instructions will trigger the break prior to their execution. It is for this reason that the Dr7 register contains a flag to specify whether the instruction has completed or not. This information is all being dredged from the depths of my memory so I assume no responsibility if there are technical inaccuracies .

    For clarity, disavowed's 'software' breakpoints in that last post are the guard-page type. By contrast, INT 3 breakpoints (also known as software) trigger the exception after execution.
    www.ring3circus.com
    Diary of a programmer, journal of a hacker.

  12. #12
    Shakkan
    Guest
    Hello again,

    I stopped messing around and made a simple test project to validate my screwups. Admiral, you are right, hardware breakpoints trigger the exception BEFORE instruction execution. That's why I get an infinite loop with the test snippet I posted at http://pastebin.com/m6bbff83. My console gets filled with "SEH CALLED" and "EIP: 2348985" heh

    The solution I would see is remove the breakpoint once I catch the exception in my handler, then set EFlags to |= 0x100 to activate SINGLE_STEP tracing (so it will execute 1 instruction and then break), resume execution by returning EXCEPTION_CONTINUE_EXECUTION and then catch the STATUS_SINGLE_STEP exception and put the breakpoint back at the previous address. Am I being clear? heh

    Two things I'm wondering:

    #1 To catch the STATUS_SINGLE_STEP exception generated by single-step tracing, I would need a VEH to catch it for sure since it has precedence over SEH, right? Also, I don't even know if SEH handles STATUS_SINGLE_STEP exceptions.

    #2 If I have a VEH to catch the STATUS_SINGLE_STEP exception and set the hardware breakpoint again at the previous instruction address, I need to have the concerned thread handle memorized since debug registers are set per thread context, correct?

    I will play with all of this right now. If anyone has anything better to suggest besides the "set hardware breakpoint + enable single-step tracing/remove breakpoint + catch STATUS_SINGLE_STEP exception/re-set breakpoint" proposition, please let me know.

    Thank you all for your constructive replies,
    Alex
    I promise that I have read the FAQ and tried to use the Search to answer my question.

  13. #13
    Shakkan
    Guest
    Hi,

    It does work just fine now _without_ SafeDisc. I have the SEH catch the exception triggered by the hardware breakpoint, enable single-step mode and disable the hardware breakpoint. Then I have a VEH catching the single-step exception, disabling single-step mode and enabling hardware breakpoint back.

    When used with a SafeDisc-enabled exe, the application freezes as soon as a breakpoint is hit.

    I need to look at PAGE_GUARD now. Can it be set on a code segment (so breakpoint triggers once a method is called instead of when a data segment of memory is read or written to)?

    Thanks again.

    ** EDIT ** I tried all 4 debug registers. No go. Damn SafeDisc...
    Last edited by Shakkan; March 17th, 2008 at 15:33.
    I promise that I have read the FAQ and tried to use the Search to answer my question.

  14. #14
    <script>alert(0)</script> disavowed's Avatar
    Join Date
    Apr 2002
    Posts
    1,281
    Quote Originally Posted by Admiral View Post
    For clarity, disavowed's 'software' breakpoints in that last post are the guard-page type. By contrast, INT 3 breakpoints (also known as software) trigger the exception after execution.
    actually, i was referring to int 3 breakpoints. i suppose it's debugger-dependent, but ollydbg breaks on the int 3 before the break-pointed instruction is executed. it's possible for a debugger to receive the int 3 exception, replace the instruction with the original, single-step it, then transfer control to the user, though i've never seen a debugger that does this.

  15. #15
    exceptions are of 2 class: fault (EIP stays before faulting instruction) and trap (EIP point to next instruction).

    Tracing, HR and HW is a trap-class and your EIP points to next instruction, HE is a fault.
    They raise the same interrupt (INT1), but the raised condition is different. You discover the condition by examining DR flags.

    The REP instructions cause some problems due to CPU inherent 'memory optimization' with HW breaks: on older CPUs you had a flag to force CPU to 'step them' right and sequentially, but today it simply does not work anymore. So, dont think to break with HR/W at the middle of a rep in a 'precise' way.

    @disa: olly break before instruction gets executed because it overwrites the instruction with CC. So the instruction (CC) gets executed, and EIP is effectively after CC. Restarting an instruction requires a fair amount of work for a debugger (set EIP-1, remove the break, place the original byte, single step silently the instruction if the user asked to run, place back the breakpoint if it's not a 'one-shot', and finally run if the user asked to run etc.).
    At least, this is the way my debugger resets the breaks. I bet olly is not very different, there are not many ways to do this.

    @OP: maybe coding an INT1 'interleave' driver to slide past its silly antidebug? (unless you are in Vista, which would tell you "bad, bad boy" for hooking IDT).
    Last edited by Maximus; March 17th, 2008 at 21:10.
    I want to know God's thoughts ...the rest are details.
    (A. Einstein)
    --------
    ..."a shellcode is a command you do at the linux shell"...

Similar Threads

  1. Replies: 2
    Last Post: September 4th, 2011, 06:07
  2. Call a dll injected function from the host process
    By Smjert in forum The Newbie Forum
    Replies: 13
    Last Post: June 17th, 2010, 19:05
  3. Replies: 3
    Last Post: February 9th, 2008, 14:30
  4. Replies: 0
    Last Post: December 5th, 2007, 16:45
  5. sXe injected
    By syl in forum The Newbie Forum
    Replies: 5
    Last Post: May 9th, 2007, 16:43

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •