Page 1 of 6 123 ... LastLast
Results 1 to 15 of 81

Thread: Question about stealth methods

  1. #1
    Registered User
    Join Date
    Oct 2002
    Posts
    59

    Question about stealth methods & Kernel driver discussion

    *EDIT* since this thread changed focus to kernel driver after second page, I changed subject accordingly.


    After someone posted very good link about injection techniques
    (http://www.codeproject.com/system/hooksys.asp), i wrote about 10 days ago my version of keyreader that inject DLL with SetWindowsHook, and read memory with normal memory read, from inside EQ process. But after completing that, I still continued using ReadProcessMemory version.

    Now after I saw t this very good stealth version of hook DLL that Maggotboy wrote, I still have same questions , namely:

    1) What is way that SOE can detect using of ReadProcessMemory?
    2) What is way that SOE can detect using of hooked DLL direct memory read?
    3) Is it really safer using direct memory inproccess read?

    My answers on those questions are reason I still use ReadProcessMemory. Maybe I'm wrong on some of those issues, thats why I'm posting this here

    1) To detect call of API function, SOE needs to do exactly same techniques as described in above link, one of which is very same SetWindowsHook.So they need to first inject their code in all processes address space, and then to hook to some execution point (with SetHook on some mesages, or modifying Process Table or ..). Or, alternativelly, modify some kernel DLL or tables to hook on kernel level.

    2) to detect hooked DLL, SOE need again to detect only some API function that is used in that DLL. Or it can use VirtualProtect on key data memory . Sniffer can use same VirtualProtect to unlock data, but then again SOE can detect only one API function called for area where key data is (VirtualProtect). Maggotboys example also use another API function easily detectable (SetWindowsHook with process ID of EQ itself), while my version is using global hook and is not detaching and attaching to single process so even intercepted SetWindowsHook would not point to EQ as target...but nevertheless, I still need to use VirtualProtect :\

    3) It seemed to me that detecting in process DLL (which needs to use VirtualProtect) is exatly same job as detecting outprocess ( which needs to use ReadProcessMemory) -- > in both cases SOE only need to detect API CALL of 2 specific functions. Only detecting inprocess is easier since SOE does not need to do first part of all spy programs - hooking into other process. They can just change Process tables or put JMP on start of code of 2 API functions in their own addres space. And inprocess with use of VirtualProtect is more dangerous ( if wrong memory segment start is used in VirtualProtect , then it will fail and memory read will trip trigger, so sniffer will be detected even if SOE does not implement complicated API function interceptions)


    Again, maybe I'm wrong on some of those issues, but so far I'll stay with ReadProcessMemory, and only will add some security measures to check memory footprint of area pointed by ReadProcessMemory pointer ... so even if SOE inject its own sniffer for that, i can detect it and not use API function.
    Last edited by lostinspace; 12-19-2002 at 10:59 AM.

  2. #2
    Registered User
    Join Date
    Nov 2002
    Posts
    115
    This is one of the reasons not to run a sniffer right after a patch. Everyone needs to hold off and wait until someone's had a look at the binaries to see what's going on.

    The life of a sniffer is consigned to be a tit-for-tat life...with us making a sniffer, Verant adjusting their code, and us adjusting the sniffer.

    It's not pleasant, but until I (or someone else) comes up with a ring-0 device driver approach, we're just going to have to live this life for a little bit.

    As for the holes in ReadProcessMemory() ... In order to read another process's memory you first (obviously) must open the process. Verant can make this quite difficult, but not completely impossible. They can also put the key in relocatable global memory and reference it with a handle which cannot be used by another process to lock/unlock the memory. There's really easy ways to prevent another process from browsing your memory. Preventing something injected right into your own address space is completely another matter, though.

    Maggotboy

  3. #3
    Registered User
    Join Date
    Oct 2002
    Posts
    59
    Yes, that 'wait until someone's had a look' is main potential problem here

    That is exatly what I'm trying to avoid. Namely, I dont care if sniffer wont work after new patch and i have to wait till someone find new offset or pointer to offset or anything. What I do care is that I can be reasonably sure that using sniffer on patched version of EQ wont get me detected.

    If we concluded that if SOE manage to intercept API functions on kernel level, they can catch both outside (ReadProcessMemory) and inside (VirtualProtect) version of sniffer - then I still feel more secure with ReadProcessMemory.

    So SOE can do few things:


    a) change offset of key. In that case both implememntations just dont wok till new offset posted, but no danger of detection

    b) offset remain same , but they virtualProtect it. In that case ReadProcessMemory implementation temporary doesnt work, but is not detected, while inprocess DLL version can get detected, or need to be enhanced with VirtualProtect (but still have risk of detection)

    c) change its own proccess to intercept ReadProcessMemory and VirtualProtect calls. In that case inside DLL can be detected

    d) change on Kernel level or global hook to intercept ReadProcessMemory and VirtualProtect calls. In that case both implementations can be detected


    So, I agree that if we wait untill someone carefully review every new patched code, we can rearrange sniffer to not be detected by new patched EQ. But in reallity they can make sneak patch, or people wont notice that exe/dll was changed ... and if they run only once old sniffer, they can be detected.

    And from 4 listed potential types of EQ changes, ReadProcesMemory will be detected only on one of them while inside read memory can be detected on 3 of them.

    Btw, i think that GlobalAlloc, LocalAlloc, VirtualAlloc all do similar things under full Win32, and I did test possibility to read memory allocated with VirtualAlloc from outside process and my inside DLL, and it works in both cases.

    Dont get me wrong, I do think that stealth DLL is good thing. I'm only trying to point out possible weakness in all sniffer approaches that I know of, and to try to find solution for them. So far most serious weakness is posibility to intercept API calls, and I'll try to see if I can make check of memory foorprint of API functions before I call them and compare to previously saved values and in that way detect any interceptor. I would appreciate any other idea about disabling or detecting API function interception

  4. #4
    Registered User
    Join Date
    Nov 2002
    Posts
    115
    b) is wrong, in that VirtualProtect() will protect the key from all readers, including ReadProcessMemory(). Any attemt to read that memory will potentially raise an exception -- both externally and internally.

    c) Intercepting ReadProcessMemory() has no effect on outside processes. They can still put up a guard page on the page containing the key, but they have to block out the entire 4k section of memory and cannot read anything in that block without unguarding the page first. Both methods can be detected using a guard page, I believe.

    d) is complex, and is too cumbersome to implement. Its like throwing a huge net and reeling it in, and then having to sift through what you brought up from the bottom of the sea. Its way too complicated to implement with any satisfactory performance. Its easy to find or look for specific things, but to hook into all processes and redirect VirtualProtectEx means analyizing every single call on every single process and determining whether or not the call in question references EQ's process. That's even assuming they could decode the HANDLE being presented to the call and figure out what process the handle belongs to.

    Maggotboy

  5. #5
    Registered User
    Join Date
    Sep 2002
    Posts
    51
    bear in mind that the offset changing will happen almost every time eqgame.exe is patched because memory structures likely change.

    The offset changing with a patch is a byproduct of change, rather than an intentional change to mess us up.

  6. #6
    Registered User
    Join Date
    Nov 2002
    Posts
    10
    Something to keep in mind is that there is a limit to how far VI will go to detect this. I think they've shown in the past that for the most part, they will lay some speed dumps down on the road occasionally, but beyond that SEQ is tolerated.

    The old arguments were in regard to VI detecting a NIC running in promiscuous mode....heh, the envelope has been pushed so much further from those days.

    Anywho, my point is this. VI never went after promiscuous NICs, they simply broke the encrytion a couple of times. They have also tolerated EQWin, because in and of itself, it really doesn't cause them problems.

    Hooking into EQGame and sniffing the key from inside the EQ process is an entirely different beast however. There are those who will argue both sides about the legality of VI scanning your machine looking for this or that, but nobody questions their right, or the likelihood that they will react to people playing around in their main application process. It's getting too close to a hack for them to simply tolerate it.
    Previous methods that they've employed to hinder the operation of SEQ have been few and far between, running as an external process will likely work for some time.

    Your code is beautiful maggotboy, if I was male code and it was female, I'd be extremely aroused, but VI isn't going to see it that way. This is going to move SEQ, EQWin and Keysniffers, WAY up the priority list.

  7. #7
    Developer Ratt's Avatar
    Join Date
    Dec 2001
    Posts
    533
    Your code is beautiful maggotboy, if I was male code and it was female, I'd be extremely aroused, but VI isn't going to see it that way. This is going to move SEQ, EQWin and Keysniffers, WAY up the priority list.
    That's because SOE is female ... you know how one girl acts when a pretty girl walks by, eh?

    BITCH! *SLAP*

    And the guys hanging around are thinking "Cool, cat fight!"

  8. #8
    Registered User
    Join Date
    Dec 2001
    Posts
    752
    Lol Ratt

    but i think the most important that was said in this thread is :

    This is one of the reasons not to run a sniffer right after a patch. Everyone needs to hold off and wait until someone's had a look at the binaries to see what's going on.
    and that is what i want to implement - i have been thinking about a little proggy which makes a crc over eqgame.exe and some other dll´s and prohibit launching of the sniffer if the crc dont match ... by now i dont know how to implement this with maggotboy´s sniffer cause the rundll is already running before the patcher, but i am thinking over it
    -- Lord Crush

    Greater Faydark has to be cleaned from all Elves !

    This is a HOTKEY !!!

  9. #9
    Registered User
    Join Date
    Nov 2002
    Posts
    22

    Idle Thoughts

    Most of the discussions have centered around cracking the virtual address space of the game. There are a number of potential issues - most notably the issue related to trapping and protecting pages in memory - that could lead to detection by SOE.

    Any in-memory image could be traced and detected. I will admit that but I have not heard anyone (other than a casual mention a few days back) talking about cracking the game externally.

    So what are the difficulties for doing the following:

    1. Convert the address to be sniffed into PTE format.
    2. Access the process header (and related data structures) and determine what physical address is mapped to the desired location.
    3. Map yourself on-top of that space using Native-API calls
    4. Grab the key.

    This is completely undetectable since you will be using YOUR process memory mapping registers instead of EQs. You access the memory of the system totally independent.

    Issues:

    1. You need to make sure the page is in memory
    2. Need elevated privilege to insure it does not get swapped out while you work.
    3. Repeat the procedure every time you want to read the key - because the page could move around in physical memory.

    I have been taking the sysinternals Physical Memory Driver apart to get a feel for the mapping concepts. Right now trying to focus on the conversion of the logical address in virtual space into a physical address.
    Wiz60
    The Lurker at the Threshold

  10. #10
    Registered User
    Join Date
    Nov 2002
    Posts
    10
    Originally posted by LordCrush
    i have been thinking about a little proggy which makes a crc over eqgame.exe and some other dll´s and prohibit launching of the sniffer if the crc dont match ... by now i dont know how to implement this with maggotboy´s sniffer cause the rundll is already running before the patcher, but i am thinking over it
    The code needs to be part of the hook itself, there is no other way to do it. The easiest method of doing it is to fail when the offset has changed, there is no need for a crc check. So much work has gone into streamlining the process of finding the new offset that the benefits of not having it may have been overlooked.

    Of course, DLL modifications wouldn't be flagged with this approach, but I believe any kind of attempt at detecting the sniffer would require an eqgame.exe modification.

  11. #11
    Registered User
    Join Date
    Dec 2001
    Posts
    144
    From what I have read and discussed with other programmers, putting the key in a relocatable global block will really not buy them much. We can just sniff the handle value (using any of the existing technologies after we R.E. the changed code) instead of the key. With the handle, we can mark the page read only, read the key, and mark it back to no access -- all without throwing an exception.

    I suspect that this will be a game of cat and mouse... We just need to stay on top of things.

  12. #12
    Registered User
    Join Date
    Oct 2002
    Posts
    59
    b) is wrong, in that VirtualProtect() will protect the key from all readers, including ReadProcessMemory(). Any attemt to read that memory will potentially raise an exception -- both externally and internally.
    While VirtualProtect will really protect key from all readers, attempt to read from external process will NOT trip guard. I made test program to check this, and even implemented VirtualProtectEx in my ReadProcessMemory version of reader to unguard memory segment.

    c) Intercepting ReadProcessMemory() has no effect on outside processes. They can still put up a guard page on the page containing the key, but they have to block out the entire 4k section of memory and cannot read anything in that block without unguarding the page first. Both methods can be detected using a guard page, I believe.
    This section was about intercepting API function calls from inside process - where intercepting VirtualProtect is more important. And how large part of memory they guard is irrelevant ... inside process DLL will need to use VirtualProtect to unguard page, read mem and use VirtualProtect to guard page back. So if SOE intercept calls to VirtualProtect from its own process ( changing its own Process Tables, or even changing code where kernel procedure start ...) it will be able to catch if someone else is guarding/unguarding their area.

    d) is complex, and is too cumbersome to implement. Its like throwing a huge net and reeling it in, and then having to sift through what you brought up from the bottom of the sea. Its way too complicated to implement with any satisfactory performance. Its easy to find or look for specific things, but to hook into all processes and redirect VirtualProtectEx means analyizing every single call on every single process and determining whether or not the call in question references EQ's process. That's even assuming they could decode the HANDLE being presented to the call and figure out what process the handle belongs to.
    Yes, (d) is too complex and even more, too intrusive into system. Thats why i hope they will not use it. But if they do, it will not be any hit on performances..hell, it needs only compare input parameters with their own parameters, thats few assembly instructions. And calls to VirtualProtect or ReadProcessMemory are not so often anyway. HANDLE in case is same handle you use with OpenProcess, it has unique value for process across processes. Implementin all this in user mode is not so complex, read link i posted in first post here. Implementing in Kernel mode is bit more complex ...

  13. #13
    Registered User
    Join Date
    Dec 2001
    Posts
    752
    The code needs to be part of the hook itself, there is no other way to do it. The easiest method of doing it is to fail when the offset has changed, there is no need for a crc check. So much work has gone into streamlining the process of finding the new offset that the benefits of not having it may have been overlooked.
    Hmm... how do i know in a program that the offset has changed ?

    The sniffer goes to the offset and read 8 byte ... They are random and not preditable ( that's why we have the problem here )

    - sure it has to be in the hook-procedure ...
    Last edited by LordCrush; 11-21-2002 at 03:59 PM.
    -- Lord Crush

    Greater Faydark has to be cleaned from all Elves !

    This is a HOTKEY !!!

  14. #14
    Registered User
    Join Date
    Nov 2002
    Posts
    115
    After doing some research on ring-0, I've discovered that there are some methods out there that can allow code originally running in ring-3 (user mode) to call and get access to ring-0. The papers I've read were from some hard-core virus guys, and most of it pertained to win9x ... so I may mess around with it a bit.

    One of the notable things it talked about was VirtualProtect. It is simply a thin layer with some validation checking that ends up calling in the VMM.VXD through the use of an undocumented VxdCall() function which runs in ring-0.

    So ... I'm still researching ... but my next project will likely be hooking into Explorer.exe, and spawning a worker thread there to read EQ's memory -- possibly using a ring-3 to ring-0 bridge for 9X, or some other interesting method in NT. Haven't finished the research yet.

    Maggotboy

  15. #15
    Registered User
    Join Date
    Nov 2002
    Posts
    10
    Originally posted by maggotboy

    So ... I'm still researching ... but my next project will likely be hooking into Explorer.exe, and spawning a worker thread there to read EQ's memory
    Hooking explorer is messy simply because the hook needs to be in place at the time of explorer being executed.
    You can set it as a ShellExecuteHook but that leaves a blazing trail since it's got to be set in the registry, as explorer is executed by the operating system at boot/login as opposed to eqgame which is executed manually. Under XP, or 2k, explorer can be closed, and the relaunched with the hook set but it's far from a clean way of doing it.

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

You may post new threads
You may post replies
You may post attachments
You may edit your posts
HTML code is Off
vB code is On
Smilies are On
[IMG] code is Off