Any Protectin Bypass (X-Kore only).

Forum closed. All further discussion to be discussed at https://github.com/OpenKore/

Moderator: Moderators

Message
Author
User avatar
kLabMouse
Administrator
Administrator
Posts: 1301
Joined: 24 Apr 2008, 12:02

Any Protectin Bypass (X-Kore only).

#1 Post by kLabMouse »

This topic Is collection of links and Code Snippets on writing new NetRedirect.dll and Injection methods.

I'll start with a little link, that could help us to determinate HackShield and idRO Delphine protected application HANDLE and Inject code:
http://debug.tw/blog/?tag=dll-injection

Dll Cloaking:

Code: Select all

//              CloakDll - by Darawk
//        Featured @ www.RealmGX.com & www.Darawk.com
//

//   The purpose of CloakDll is to allow the user to hide any loaded
//   module from the windows API.  It works by accessing the modules
//   list stored in the PEB, and subsequently unlinking the module
//   in question from all 4 of the doubly-linked lists that it's a
//   node of.  It then zeroes out the structure and the path/file
//   name of the module in memory.  So that even if the memory where
//   the data about this module used to reside is scanned there will
//   still be no conclusive evidence of it's existence.  At present
//   there is only one weakness that I have found in this method.
//   I'll describe how it may still be possible to discover at least
//   that a module has been hidden, after a brief introduction to how
//   the GetModuleHandle function works.
//
//   *The following information is not documented by Microsoft.  This
//    information consists of my findings while reverse-engineering
//    these functions and some of them may be incorrect and/or
//    subject to change at any time(and is almost definitely different
//    in different versions of windows, and maybe even in different
//    service packs).  I've tried to make my code as version independant
//    as possible but certain parts of it may not work on older versions
//    of windows.  I've tested it on XP SP2 and there i'll guarantee
//    that it works, but on any other versions of windows, it's anyone's
//    guess.*
//
//   GetModuleHandle eventually calls GetModuleHandleExW, which in
//   turn accesses the native API function GetDllHandle, which calls
//   GetDllHandleEx.  And it's not until here, that we actually see
//   anything even begin to look up information about loaded modules.
//   Whenever GetModuleHandle is called, it saves the address of the
//   last ModuleInfoNode structure that it found in a global variable
//   inside of ntdll.  This global variable is the first thing
//   checked on all subsequent calls to GetModuleHandle.  If the
//   handle being requested is not the one that was requested the last
//   time GetDllHandleEx calls the LdrpCheckForLoadedDll function.
//   LdrpCheckForLoadedDll begins by converting the first letter of the
//   module name being requested to uppercase, decrementing it by 1 and
//   AND'ing it with 0x1F.  This effectively creates a 0-based index
//   beginning with the letter 'A'.  The purpose of this is so that
//   the module can first be looked up in a hash table.  The hash table
//   consists entirely of LIST_ENTRY structures.  One for each letter
//   'A' through 'Z'.  The LIST_ENTRY structure points to the first
//   and last modules loaded that begin with the letter assigned to
//   that entry in the hash table.  The Flink member being the first
//   loaded beginning with that letter, and the Blink member being the
//   last.  The code scans through this list until it finds the module
//   that it's looking for.  On the off-chance that it doesn't find it
//   there, or if the boolean argument UseLdrpHashTable is set to false
//   it will begin going through one of the other three lists.  If, at
//   this point it still doesn't find it, it will admit defeat and return
//   0 for the module handle.
//
//   Weakness:  The global variable inside ntdll that caches the pointer
//   to the last module looked up could be used to at least detect the
//   fact that a module has been hidden.  The LdrUnloadDll() function
//   will set this value to 0 when it unloads a module, so if the cache
//   variable points to an empty structure, the only logical conclusion
//   would be a hidden module somewhere in the process.  This could be
//   resolved by using the static address of this variable and simply
//   zeroing it out.  However, this would make the code specific to only
//   one version of windows.  You could also scan the address space of
//   ntdll for any occurences of the base address(aka module handle)
//   of the module you're hiding.  However, this would be slow and it
//   would clutter up the CloakDll_stub function, because it'd have to
//   all be done manually.  And i'd have to either use a static base
//   address for ntdll...which would probably work on most versions
//   of windows, however I really don't like using static addresses.
//   Or i'd have to manually locate it by writing my own unicode
//   string comparison code, to lookup ntdll in the list by it's name.
//   Realistically though anyone trying to detect this way would run
//   into the same problem.  That their code would not be version
//   independant.  So, it's unlikely to see any largescale deployment
//   of such a technique.  However, anyone who would like to solve
//   this problem themselves is perfectly free, and encouraged to do
//   so.

#include <windows.h>
#include <winnt.h>
#include <tlhelp32.h>
#include <shlwapi.h>


#pragma comment(lib, "shlwapi.lib")

#define UPPERCASE(x) if((x) >= 'a' && (x) <= 'z') (x) -= 'a' - 'A' ;
#define UNLINK(x) (x).Blink->Flink = (x).Flink;  (x).Flink->Blink = (x).Blink;

#pragma pack(push, 1)

typedef struct _UNICODE_STRING {
  USHORT  Length;
  USHORT  MaximumLength;
  PWSTR  Buffer;
} UNICODE_STRING, *PUNICODE_STRING;

typedef struct _ModuleInfoNode {
   LIST_ENTRY LoadOrder;
   LIST_ENTRY InitOrder;
   LIST_ENTRY MemoryOrder;
   HMODULE baseAddress;      //   Base address AKA module handle
   unsigned long entryPoint;
   unsigned int size;         //   Size of the modules image
   UNICODE_STRING fullPath;
   UNICODE_STRING name;
   unsigned long flags;
   unsigned short LoadCount;
   unsigned short TlsIndex;
   LIST_ENTRY HashTable;   //   A linked list of any other modules that have the same first letter
   unsigned long timestamp;
} ModuleInfoNode, *pModuleInfoNode;

typedef struct _ProcessModuleInfo {
   unsigned int size;         //   Size of a ModuleInfo node?
   unsigned int initialized;
   HANDLE SsHandle;
   LIST_ENTRY LoadOrder;
   LIST_ENTRY InitOrder;
   LIST_ENTRY MemoryOrder;
} ProcessModuleInfo, *pProcessModuleInfo;


#pragma pack(pop)

bool CloakDll_stub(HMODULE);
void CD_stubend();

bool CloakDll(char *, char *);
unsigned long GetProcessIdFromProcname(char *);
HMODULE GetRemoteModuleHandle(unsigned long, char *);


int main(int argc, char **argv) {
   CloakDll("notepad.exe", "kernel32.dll");
   return 0;
}

bool CloakDll(char *process, char *dllName) {
   PathStripPath(dllName);

   unsigned long procId;
   procId = GetProcessIdFromProcname(process);
   HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procId);

   //   Calculate the length of the stub by subtracting it's address
   //   from the beginning of the function directly ahead of it.
   //
   //   NOTE: If the compiler compiles the functions in a different
   //   order than they appear in the code, this will not work as
   //   it's supposed to.  However, most compilers won't do that.
   unsigned int stubLen = (unsigned long)CD_stubend - (unsigned long)CloakDll_stub;

   //   Allocate space for the CloakDll_stub function
   void *stubAddress = VirtualAllocEx(hProcess,
      NULL,
      stubLen,
      MEM_RESERVE | MEM_COMMIT,
      PAGE_EXECUTE_READWRITE);

   //   Write the stub's code to the page we allocated for it
   WriteProcessMemory(hProcess, stubAddress, CloakDll_stub, stubLen, NULL);

   HMODULE hMod = GetRemoteModuleHandle(procId, dllName);

   //   Create a thread in the remote process to execute our code
   CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)stubAddress, hMod, 0, NULL);

   //   Clean up after ourselves, so as to leave as little impact as possible
   //   on the remote process
   VirtualFreeEx(hProcess, stubAddress, stubLen, MEM_RELEASE);
   return true;
}

bool CloakDll_stub(HMODULE hMod) {
   ProcessModuleInfo *pmInfo;
   ModuleInfoNode *module;

   _asm {
      mov eax, fs:[18h]      // TEB
      mov eax, [eax + 30h]   // PEB
      mov eax, [eax + 0Ch]   // PROCESS_MODULE_INFO
      mov pmInfo, eax
   }

    module = (ModuleInfoNode *)(pmInfo->LoadOrder.Flink);

   while(module->baseAddress && module->baseAddress != hMod)
      module = (ModuleInfoNode *)(module->LoadOrder.Flink);

   if(!module->baseAddress)
      return false;

   //   Remove the module entry from the list here
   ///////////////////////////////////////////////////
   //   Unlink from the load order list
   UNLINK(module->LoadOrder);
   //   Unlink from the init order list
   UNLINK(module->InitOrder);
   //   Unlink from the memory order list
   UNLINK(module->MemoryOrder);
   //   Unlink from the hash table
   UNLINK(module->HashTable);

   //   Erase all traces that it was ever there
   ///////////////////////////////////////////////////

   //   This code will pretty much always be optimized into a rep stosb/stosd pair
   //   so it shouldn't cause problems for relocation.
   //   Zero out the module name
   memset(module->fullPath.Buffer, 0, module->fullPath.Length);
   //   Zero out the memory of this module's node
   memset(module, 0, sizeof(ModuleInfoNode));

   return true;
}

__declspec(naked) void CD_stubend() { }

unsigned long GetProcessIdFromProcname(char *procName) {
   PROCESSENTRY32 pe;
   HANDLE thSnapshot;
   BOOL retval, ProcFound = false;

   thSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

   if(thSnapshot == INVALID_HANDLE_VALUE) {
      MessageBox(NULL, "Error: unable to create toolhelp snapshot", "Loader", NULL);
      return false;
   }

   pe.dwSize = sizeof(PROCESSENTRY32);

    retval = Process32First(thSnapshot, &pe);

   while(retval) {
      if(StrStrI(pe.szExeFile, procName) ) {
         ProcFound = true;
         break;
      }

      retval    = Process32Next(thSnapshot,&pe);
      pe.dwSize = sizeof(PROCESSENTRY32);
   }

   return pe.th32ProcessID;
}

HMODULE GetRemoteModuleHandle(unsigned long pId, char *module) {
   MODULEENTRY32 modEntry;
   HANDLE tlh = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pId);

   modEntry.dwSize = sizeof(MODULEENTRY32);
    Module32First(tlh, &modEntry);

   do {
      if(!stricmp(modEntry.szModule, module))
         return modEntry.hModule;
      modEntry.dwSize = sizeof(MODULEENTRY32);
   } while(Module32Next(tlh, &modEntry));

   return NULL;
}

Locked