Перейти к содержанию

Рекомендуемые сообщения

Как и почему Cheat Engine сканирует так быстро ? Обычному сканеру , чтобы просканировать память процесса от 0x0 до 0x7fffffffffffffff , понадобился бы день , а CE хватает несколько секунд .
Кто может в лс кинуть исходник этого сканера или чего-то похожего .

Ссылка на комментарий
Поделиться на другие сайты

У CE открытый исходный код. на сайте исходники в разделе загрузок. Возможно использует видюху вместо процессора при поиске.

Изменено пользователем partoftheworlD
Ссылка на комментарий
Поделиться на другие сайты

partoftheworlD, чё, какая видюга, при помощи неё можно только рас читывать  данные. Я просто, не представляю как можно при помощи видтокарты искать.  

afro228offical, там поиск не с 0, а с адресного пространства игры начинается. Если будешь искать в исходниках Cheat Engine, то ищи API virtualalloc VirtualQuery

 

Ссылка на комментарий
Поделиться на другие сайты

Я чет вообще не понимаю , где тут функция сканирования и как она работает . Объясните пожалуйста.:(
 

Скрытый текст

#pragma warning( disable: 4103)

#include "ntifs.h"
#include <windef.h>
#ifdef CETC
#include "tdiwrapper.h"
#include "kfiles.h"
#endif
#include "memscan.h"
#include "DBKFunc.h"

#include "vmxhelper.h"
/*#include "deepkernel.h"
*/


BOOLEAN IsAddressSafe(UINT_PTR StartAddress)
{
	#ifdef AMD64
	//cannonical check. Bits 48 to 63 must match bit 47
	UINT_PTR toppart=(StartAddress >> 47);
	if (toppart & 1)
	{
		//toppart must be 0x1ffff
		if (toppart != 0x1ffff)
			return FALSE;
	}
	else
	{
		//toppart must be 0
		if (toppart != 0)
			return FALSE;

	}

	#endif

	//return TRUE;
	if (loadedbydbvm)
	{
		BYTE x=0;
		UINT_PTR lasterror;
		disableInterrupts();
		vmx_disable_dataPageFaults();

		x=*(volatile BYTE *)StartAddress;

		vmx_enable_dataPageFaults();
		lasterror=vmx_getLastSkippedPageFault();
		enableInterrupts();

		DbgPrint("IsAddressSafe dbvm-mode: lastError=%p\n", lasterror);
		
		if (lasterror) return FALSE;		
	}


	{
#ifdef AMD64
		UINT_PTR kernelbase=0x7fffffffffffffffULL;

		
		if (StartAddress<kernelbase)
			return TRUE;
		else
		{
			PHYSICAL_ADDRESS physical;
			physical.QuadPart=0;
			physical=MmGetPhysicalAddress((PVOID)StartAddress);
			return (physical.QuadPart!=0);
		}

	    

		return TRUE; //for now untill I ave figure out the win 4 paging scheme
#else
	/*	MDL x;

		
		MmProbeAndLockPages(&x,KernelMode,IoModifyAccess);


		MmUnlockPages(&x);
		*/
		ULONG kernelbase=0x7ffe0000;

		if ((!HiddenDriver) && (StartAddress<kernelbase))
			return TRUE;

		{
			UINT_PTR PTE,PDE;
			struct PTEStruct *x;
			
			/*
			PHYSICAL_ADDRESS physical;
			physical=MmGetPhysicalAddress((PVOID)StartAddress);
			return (physical.QuadPart!=0);*/


			PTE=(UINT_PTR)StartAddress;
			PTE=PTE/0x1000*PTESize+0xc0000000;

    		//now check if the address in PTE is valid by checking the page table directory at 0xc0300000 (same location as CR3 btw)
			PDE=PTE/0x1000*PTESize+0xc0000000; //same formula

			x=(PVOID)PDE;
			if ((x->P==0) && (x->A2==0))
			{
				//Not present or paged, and since paging in this area isn't such a smart thing to do just skip it
				//perhaps this is only for the 4 mb pages, but those should never be paged out, so it should be 1
				//bah, I've got no idea what this is used for
				return FALSE;
			}

			if (x->PS==1)
			{
				//This is a 4 MB page (no pte list)
				//so, (startaddress/0x400000*0x400000) till ((startaddress/0x400000*0x400000)+(0x400000-1) ) ) is specified by this page
			}
			else //if it's not a 4 MB page then check the PTE
			{
				//still here so the page table directory agreed that it is a usable page table entry
				x=(PVOID)PTE;
				if ((x->P==0) && (x->A2==0))
					return FALSE; //see for explenation the part of the PDE
			}

			return TRUE;
		} 
#endif
	}

}

UINT_PTR getPEThread(UINT_PTR threadid)  
{	
    //UINT_PTR *threadid;
	PETHREAD selectedthread;
	UINT_PTR result=0;
	
	

	if (PsLookupThreadByThreadId((PVOID)(UINT_PTR)threadid,&selectedthread)==STATUS_SUCCESS)
	{
		result=(UINT_PTR)selectedthread;
		ObDereferenceObject(selectedthread);
	}

	return result;
}

BOOLEAN WriteProcessMemory(DWORD PID,PEPROCESS PEProcess,PVOID Address,DWORD Size, PVOID Buffer)
{
	PEPROCESS selectedprocess=PEProcess;
	KAPC_STATE apc_state;
	NTSTATUS ntStatus=STATUS_UNSUCCESSFUL;
		
	if (selectedprocess==NULL)
	{
		//DbgPrint("WriteProcessMemory:Getting PEPROCESS\n");
        if (!NT_SUCCESS(PsLookupProcessByProcessId((PVOID)(UINT_PTR)PID,&selectedprocess)))
		   return FALSE; //couldn't get the PID

		//DbgPrint("Retrieved peprocess");  
	}

	//selectedprocess now holds a valid peprocess value
	__try
	{
		UINT_PTR temp=(UINT_PTR)Address;
						
		RtlZeroMemory(&apc_state,sizeof(apc_state));					

    	KeAttachProcess((PEPROCESS)selectedprocess);				

        __try
        {
			char* target;
			char* source;
			unsigned int i;	

			//DbgPrint("Checking safety of memory\n");

			if ((IsAddressSafe((UINT_PTR)Address)) && (IsAddressSafe((UINT_PTR)Address+Size-1)))
			{			

	    		//still here, then I gues it's safe to read. (But I can't be 100% sure though, it's still the users problem if he accesses memory that doesn't exist)

				target=Address;
				source=Buffer;

				if (loadedbydbvm) //add a extra security around it as the PF will not be handled
				{
					disableInterrupts();
					vmx_disable_dataPageFaults();
				}


				for (i=0; i<Size; i++)
				{
				   target[i]=source[i];
				}
				ntStatus = STATUS_SUCCESS;	

				if (loadedbydbvm)
				{
					UINT_PTR lastError;
					lastError=vmx_getLastSkippedPageFault();
					vmx_enable_dataPageFaults();

					enableInterrupts();

					DbgPrint("lastError=%p\n", lastError);
					if (lastError)
						ntStatus=STATUS_UNSUCCESSFUL;
				}

			}

			
		}
		__finally
		{
			KeDetachProcess();
		}
	}			
	__except(1)
	{
		//DbgPrint("Error while writing\n");
		ntStatus = STATUS_UNSUCCESSFUL;
	}
	
	if (PEProcess==NULL) //no valid peprocess was given so I made a reference, so lets also dereference
		ObDereferenceObject(selectedprocess);

	return NT_SUCCESS(ntStatus);
}


BOOLEAN ReadProcessMemory(DWORD PID,PEPROCESS PEProcess,PVOID Address,DWORD Size, PVOID Buffer)
{
	PEPROCESS selectedprocess=PEProcess;
	//KAPC_STATE apc_state;
	NTSTATUS ntStatus=STATUS_UNSUCCESSFUL;

	if (PEProcess==NULL)
	{
		if (!NT_SUCCESS(PsLookupProcessByProcessId((PVOID)(UINT_PTR)PID,&selectedprocess)))
		   return FALSE; //couldn't get the PID
 
	}

	//selectedprocess now holds a valid peprocess value
	__try
	{
		UINT_PTR temp=(UINT_PTR)Address;

    	KeAttachProcess((PEPROCESS)selectedprocess);



        __try
        {
			char* target;
			char* source;
			int i;

		
			if ((IsAddressSafe((UINT_PTR)Address)) && (IsAddressSafe((UINT_PTR)Address+Size-1)))
			{
				


				target=Buffer;
				source=Address;

				if (loadedbydbvm) //add a extra security around it
				{
					disableInterrupts();
					vmx_disable_dataPageFaults();
				}

				RtlCopyMemory(target,source,Size);

				ntStatus = STATUS_SUCCESS;	

				if (loadedbydbvm)
				{
					UINT_PTR lastError;
					lastError=vmx_getLastSkippedPageFault();
					vmx_enable_dataPageFaults();

					enableInterrupts();

					DbgPrint("lastError=%p\n", lastError);
					if (lastError)
						ntStatus=STATUS_UNSUCCESSFUL;
				}

				
			}
				
		}
		__finally
		{

			KeDetachProcess();
		}
	}			
	__except(1)
	{
		//DbgPrint("Error while reading: ReadProcessMemory(%x,%p, %p, %d, %p\n", PID, PEProcess, Address, Size, Buffer);

		ntStatus = STATUS_UNSUCCESSFUL;
	}
	
	if (PEProcess==NULL) //no valid peprocess was given so I made a reference, so lets also dereference
		ObDereferenceObject(selectedprocess);

	return NT_SUCCESS(ntStatus);
}

NTSTATUS ReadPhysicalMemory(char *startaddress, UINT_PTR bytestoread, void *output)
{
	HANDLE			physmem;
	UNICODE_STRING	physmemString;
	OBJECT_ATTRIBUTES attributes;
	WCHAR			physmemName[] = L"\\device\\physicalmemory";
	UCHAR*			memoryview;
	NTSTATUS		ntStatus = STATUS_UNSUCCESSFUL;

	DbgPrint("ReadPhysicalMemory(%p, %d, %p)", startaddress, bytestoread, output);

	__try
	{
		RtlInitUnicodeString( &physmemString, physmemName );	

		InitializeObjectAttributes( &attributes, &physmemString, OBJ_CASE_INSENSITIVE, NULL, NULL );	
		ntStatus=ZwOpenSection( &physmem, SECTION_ALL_ACCESS, &attributes );
		if (ntStatus==STATUS_SUCCESS)
		{
			//hey look, it didn't kill it


			UINT_PTR length;
			PHYSICAL_ADDRESS	viewBase;
			UINT_PTR offset;
			UINT_PTR toread;

			viewBase.QuadPart = (ULONGLONG)(startaddress);					
			
			length=0x2000;//pinp->bytestoread; //in case of a overlapping region
			toread=bytestoread;

			memoryview=NULL;

			DbgPrint("ReadPhysicalMemory:viewBase.QuadPart=%x", viewBase.QuadPart); 


			ntStatus=ZwMapViewOfSection(
				physmem,  //sectionhandle
				NtCurrentProcess(), //processhandle (should be -1)
				&memoryview, //BaseAddress
				0L, //ZeroBits
				length, //CommitSize
				&viewBase, //SectionOffset
				&length, //ViewSize
				ViewShare,
				0,
				PAGE_READWRITE);

			if (ntStatus==STATUS_SUCCESS)
			{
				offset=(UINT_PTR)(startaddress)-(UINT_PTR)viewBase.QuadPart;
				RtlCopyMemory(output,&memoryview[offset],toread);

				ZwUnmapViewOfSection( NtCurrentProcess(), memoryview);
			}
			else
			{
				DbgPrint("ReadPhysicalMemory:ntStatus=%x", ntStatus); 
			}

			ZwClose(physmem);
		};

	}
	__except(1)
	{
		DbgPrint("Error while reading physical memory\n");
	}

	return ntStatus;
}

UINT_PTR SignExtend(UINT_PTR a)
{
#ifdef AMD64
	if ((a >> 47)==1)
		return a | 0xFFFF000000000000ULL; //add sign extended bits
	else
		return a;
#else
	return a;
#endif
}

BOOLEAN GetMemoryRegionData(DWORD PID,PEPROCESS PEProcess, PVOID mempointer,ULONG *regiontype, UINT_PTR *memorysize,UINT_PTR *baseaddress)
{
#ifdef AMD64
	UINT_PTR pagebase=0xfffff68000000000ULL;
#else
	UINT_PTR pagebase=0xc0000000;
#endif

	UINT_PTR StartAddress;
	KAPC_STATE apc_state;
	NTSTATUS ntStatus=STATUS_SUCCESS;
	struct PTEStruct *PPTE,*PPDE, *PPDPE, * PPML4E;
	PEPROCESS selectedprocess=PEProcess;
	BOOL ShowResult=0;

	if ((UINT_PTR)mempointer==(UINT_PTR)0x12000)
		ShowResult=1;

	if (PEProcess==NULL)
	{
		//DbgPrint("GetMemoryRegionData:Getting PEPROCESS\n");
        if (!NT_SUCCESS(PsLookupProcessByProcessId((PVOID)(UINT_PTR)PID,&selectedprocess)))
		   return FALSE; //couldn't get the PID

		//DbgPrint("Retrieved peprocess");  
	}

	StartAddress=(UINT_PTR)mempointer;



	*baseaddress=StartAddress & (UINT_PTR)(~0xfff);


	*memorysize=0;
	*regiontype=0;
	//switch context to the target process

	RtlZeroMemory(&apc_state,sizeof(apc_state));

	__try
	{
		KeAttachProcess((PEPROCESS)selectedprocess);
		__try
		{
			//do my stuff here

			//address -> strip off signed extended bit  , shift left by 12 and increase by 0xfffff68000000000ULL
			(UINT_PTR)PPTE=((*baseaddress & 0xFFFFFFFFFFFFULL) >> 12) *PTESize + pagebase;

			while ((UINT_PTR)PPTE<MAX_PTE_POS)
			{
				(UINT_PTR)PPDE=((((UINT_PTR)PPTE) & 0xFFFFFFFFFFFFULL) >> 12) *PTESize + pagebase;
				if (PTESize==8)
					(UINT_PTR)PPDPE=((((UINT_PTR)PPDE) & 0xFFFFFFFFFFFFULL) >> 12) *PTESize + pagebase; //pagedir pointer entry
				else
					(UINT_PTR)PPDPE=0; 

#ifdef AMD64
				(UINT_PTR)PPML4E=((((UINT_PTR)PPDPE)& 0xFFFFFFFFFFFFULL) >> 12) *PTESize + pagebase; //pagedir pointer entry
#else
				(UINT_PTR)PPML4E=0;
#endif
				

#ifdef AMD64
				if ((PPML4E==0) || (PPML4E->P))
				{
					//DbgPrint("PML4E=valid: %p\n", *(UINT_PTR *)PPML4E);
					//return 0;
#endif
					//PML4E is valid or not needed
					if ((PPDPE==0) || (PPDPE->P))
					{
						//PPDPE is valid or not needed
						if (PPDE->P)
						{
							//PDE is valid
							if (PPDE->PS==1)
							{
								//2/4mb page
								if (*regiontype==0) //first time init
								{
									
									

									*baseaddress=SignExtend(((((UINT_PTR)PPDE)-pagebase) / PTESize) << 12); //PPDE->PPTE
									*baseaddress=SignExtend((((*baseaddress)-pagebase) / PTESize) << 12); //PPTE->address
											
									*memorysize=PAGE_SIZE_LARGE-((UINT_PTR)mempointer-*baseaddress); //size is relative to the start of the mempointer
									if (PPDE->RW==1)
										*regiontype=PAGE_EXECUTE_READWRITE;
									else
										*regiontype=PAGE_EXECUTE_READ;
								}
								else
								{
									//make sure the protection is the same, if not, exit
									if ((PPDE->RW==1) && (*regiontype!=PAGE_EXECUTE_READWRITE))
										return 0;


									if ((PPDE->RW==0) && (*regiontype!=PAGE_EXECUTE_READ))
										return 0;

									//still here so the same
									*memorysize+=4096;
								}

								//still here
								(UINT_PTR)PPDE+=PTESize; //next pagedir entry							
								(UINT_PTR)PPTE=SignExtend(((((UINT_PTR)PPDE)-pagebase) / PTESize) << 12); //set the pagetable to the start of the pagedir table
								continue;

							}
							else
							{
								//has a page table
								if (PPTE->P)
								{
									

									//valid pte
									if (*regiontype==0) //first time init
									{										
										//find the virtual address of this pagetable entry and use it as base address														
										*baseaddress=SignExtend(((((UINT_PTR)PPTE)-pagebase) / PTESize) << 12); //PPTE->address			

										*memorysize=4096-((UINT_PTR)mempointer-*baseaddress); //size is relative to the start of the mempointer

										if (PPTE->RW==1)
											*regiontype=PAGE_EXECUTE_READWRITE;
										else
											*regiontype=PAGE_EXECUTE_READ;

										
									}
									else
									{
										//make sure the protection is the same, if not, exit
										if ((PPTE->RW==1) && (*regiontype!=PAGE_EXECUTE_READWRITE))
											return 0;


										if ((PPTE->RW==0) && (*regiontype!=PAGE_EXECUTE_READ))
											return 0;

										//still here so the same
										*memorysize+=4096;

										//DbgPrint("Extending\n");
									}

									//still here
									(UINT_PTR)PPTE+=PTESize; //next pagetable entry	
									continue;

								}
								else
								{

									if (ShowResult)
										DbgPrint("PTE is not paged in\n");

									//PTE is not paged in
									if (*regiontype==0) //first occurance
									{
										//find the virtual address of this pagetable entry and use it as base address														
										*baseaddress=SignExtend(((((UINT_PTR)PPTE)-pagebase) / PTESize) << 12); //PPTE->address
		
										*memorysize=4096-((UINT_PTR)mempointer-*baseaddress); //size is relative to the start of the mempointer
										*regiontype = PAGE_NOACCESS;
									}
									else 
									if (*regiontype == PAGE_NOACCESS)
									{
										*memorysize=*memorysize+4096; 
									}
									else
										return 0; //new region

								
									//still here
									(UINT_PTR)PPTE+=PTESize; //next pagetable entry	
									continue;
								}


							}
						}
						else
						{
							//PDE is not paged in
							if (ShowResult)
								DbgPrint("PDE is not paged in\n");

							if (*regiontype==0) //first occurance
							{
								//find the virtual address of this pagedir entry and use it as base address														
								*baseaddress=SignExtend(((((UINT_PTR)PPDE)-pagebase) / PTESize) << 12); //PPDE->PPTE
								*baseaddress=SignExtend((((*baseaddress)-pagebase) / PTESize) << 12); //PPTE->address
	

								*memorysize=PAGE_SIZE_LARGE-((UINT_PTR)mempointer-*baseaddress); //size is relative to the start of the mempointer
								*regiontype = PAGE_NOACCESS;

							}
							else
							if (*regiontype == PAGE_NOACCESS)
							{
								*memorysize=*memorysize+PAGE_SIZE_LARGE; //increase with 2 or 4 MB
							}
							else
								return 0; //new section

							//still here
							(UINT_PTR)PPDE+=PTESize; //next pagedir entry							
							(UINT_PTR)PPTE=SignExtend(((((UINT_PTR)PPDE)-pagebase) / PTESize) << 12); //set the pagetable to the start of the pagedir table
							continue;

						}
					}
					else
					{
						//PPDPE is invalid
						if (ShowResult)
							DbgPrint("PDPE is not paged in\n");

						if (*regiontype==0) //first occurance
						{
							//find the virtual address of this pagedir pointer entry and use it as base address							
							*baseaddress=SignExtend(((((UINT_PTR)PPDPE)-pagebase) / PTESize) << 12); //>PPDPE->PPDE
							*baseaddress=SignExtend((((*baseaddress)-pagebase) / PTESize) << 12); //PPDE->PPTE
							*baseaddress=SignExtend((((*baseaddress)-pagebase) / PTESize) << 12); //PPTE->address

							*memorysize=0x40000000-((UINT_PTR)mempointer-*baseaddress); //size is relative to the start of the mempointer
							*regiontype = PAGE_NOACCESS;
						}
						else if (*regiontype==PAGE_NOACCESS)
						{
							*memorysize=*memorysize+0x40000000; //increase with 1GB 
						}
						else
							return 0; //new section

						//still here
						(UINT_PTR)PPDPE+=PTESize; //next pagedirptr entry
						(UINT_PTR)PPDE=SignExtend(((((UINT_PTR)PPDPE)-pagebase) / PTESize) << 12); //set the pagedir entry to the start of the pagedirptr table
						(UINT_PTR)PPTE=SignExtend(((((UINT_PTR)PPDE)-pagebase) / PTESize) << 12); //set the pagetable to the start of the pagedir table
						continue;
					}

#ifdef AMD64
				}

				//no need to compile this in for the 32-bit version
				else
				{
					if (ShowResult)
					    DbgPrint("PML4E is not paged in\n");
					
					//DbgPrint("PML4E=invalid: %p\n", *(UINT_PTR *)PPML4E);
					//return 0;

					//PML4 is invalid (but not 0)
					if (*regiontype==0) //first occurance
					{
						//find the virtual address of this pml4 entry and use it as base address
						*baseaddress=SignExtend(((((UINT_PTR)PPML4E)-pagebase) / PTESize) << 12); //PML4E->PDPTE
						*baseaddress=SignExtend((((*baseaddress)-pagebase) / PTESize) << 12); //PDPTE->PPDE					
						*baseaddress=SignExtend((((*baseaddress)-pagebase) / PTESize) << 12); //PPDE->PPTE
						*baseaddress=SignExtend((((*baseaddress)-pagebase) / PTESize) << 12); //PPTE->address

						*memorysize=0x8000000000ULL-((UINT_PTR)mempointer-*baseaddress); //size is relative to the start of the mempointer

						*regiontype = PAGE_NOACCESS;
					}
					else
					if (*regiontype == PAGE_NOACCESS)
						*memorysize=*memorysize+0x8000000000ULL; //increase with 512GB 
					else
						return 0; //New regiontype reached (inaccessible memory)

					//still here so continue.
					(UINT_PTR)PPML4E+=PTESize;
					(UINT_PTR)PPDPE=SignExtend(((((UINT_PTR)PPML4E)-pagebase) / PTESize) << 12); //set the pagedir ptr entry to the start of the pml4 table
					(UINT_PTR)PPDE=SignExtend(((((UINT_PTR)PPDPE)-pagebase) / PTESize) << 12); //set the pagedir entry to the start of the pagedirptr table
					(UINT_PTR)PPTE=SignExtend(((((UINT_PTR)PPDE)-pagebase) / PTESize) << 12); //set the pagetable to the start of the pagedir table

					continue;
				}
#endif


			}

			ntStatus=STATUS_SUCCESS;
		}
		__finally
		{
			KeDetachProcess();
			if (PEProcess==NULL) //no valid peprocess was given so I made a reference, so lets also dereference
				ObDereferenceObject(selectedprocess);
		}



	}
	__except(1)
	{
		DbgPrint("Exception in GetMemoryRegionData\n");
		DbgPrint("mempointer=%p",mempointer);
		DbgPrint("PPML4E=%p\n", PPML4E);
		DbgPrint("PPDPE=%p\n", PPDPE);
		DbgPrint("PPDE=%p\n", PPDE);
		DbgPrint("PPTE=%p\n", PPTE);
		
		ntStatus=STATUS_UNSUCCESSFUL;
	}
	



	return 0; 

}

#ifdef CETC
//ooh woot, some real public CETC code.....

char ScanresultBuffer[4096];
int ScanresultBufferPos=0;

VOID FlushScanresultBuffer(void)
{
	Send(ScanresultBuffer,ScanresultBufferPos);
	ScanresultBufferPos=0;    
}

VOID ScanResult(ULONG Address,int Size)
{
	char *output;

	if (Size>=4096)
		return; //error, there's no fucking reason to do a scan like this....
	
	if ((ScanresultBufferPos+Size+6)>=4096)
		FlushScanresultBuffer();


	ScanresultBuffer[ScanresultBufferPos]=SC_ScanResult; //address:dword; valuesize:byte; value:array of bytes
	*(PULONG)(&ScanresultBuffer[ScanresultBufferPos+1])=Address;

	__try
	{
		ScanresultBuffer[ScanresultBufferPos+5]=(BYTE)Size;
		RtlCopyMemory(&ScanresultBuffer[ScanresultBufferPos+6],(PVOID)Address,Size);
	}
	__except(1)
	{
		//(unreadable)
	}
	//increase counter with 6+size
	ScanresultBufferPos+=6+Size;
}

VOID ScanResultCount(INT64 errorcode)
{
	char output[9];
	
	output[0]=SC_ScanResultCount;
	*(PINT64)(&output[1])=errorcode;
	Send(output,9);
}

VOID UpdateProgressBar(DWORD max,DWORD pos)
{
	//in case of network scan send , else set global var and let the usermode app poll
	char output[9];
	DWORD a=max / 2;//this way even if you go over 80000000 (signed negative) it wont go wrong
	DWORD b=pos / 2;

	output[0]=SC_UpdateProgressbar;
	*(PDWORD)(&output[1])=a;
	*(PDWORD)(&output[5])=b;
	Send(output,9);
}

VOID FixFPUcrash(void)
{
	__try
	{		
		
		DWORD New8087CW=0x133f; //fuck floating point exceptions
		PDWORD PtoNew8087CW=&New8087CW;
		DbgPrint("Going to set the ControlWord of the FP-Coprocessor\n");
		_asm
		{
			FNCLEX
			FLDCW   [PtoNew8087CW]
		}
	}
	__except(1)
	{
		//bleh

	}
}

VOID UnknownInitialValueScan(IN PVOID StartContext)
{

	__try
	{
		__try
		{
			//this is a unknown initial value scan.
			


		}
		__finally
		{
			CurrentScan.scanning=FALSE;
			CurrentScan.ThreadActive=FALSE;
			PsTerminateSystemThread(STATUS_SUCCESS);
		}
	}
	__except(1)
	{
		//nothing, just go on...

	}
}




VOID FirstScanThread(IN PVOID StartContext)
{
	KAPC_STATE apc_state;
	BYTE bytevalue;
	WORD wordvalue;
	DWORD dwordvalue;
	float floatvalue;  //yes, float. I know... don't use them. but this is intended for winxp, and even runs in it's own thread
	double doublevalue;
	INT64 int64value;
	char* stringvalue;

	BYTE   *ValueList0=NULL;
	WORD   *ValueList1=NULL;
	DWORD  *ValueList2=NULL;
	float  *ValueList3=NULL;
	double *ValueList4=NULL;
	INT64  *ValueList6=NULL;

	DWORD  *AddressList=NULL;
	int AddressListSize=0;
	int found=0,foundsaved=0;


	BOOLEAN error=FALSE;
	BYTE errorcode=-1; //none set
	
	
	PVOID mempointer;
	MEMREGION *memoryregion=NULL;	

	int memoryregionsize=0;
	int memoryregionentries=0;
	int i;

	IO_STATUS_BLOCK iosb;
	NTSTATUS ntStatus;
	BOOLEAN FastScan=((CurrentScan.ScanOptions & SO_FASTSCAN)!=0);



	//this thread scans the memory till it is done scanning or till Scanning equals FALSE
	//there will be a periodic scan for the state of Scanning
	DbgPrint("This is the FirstScanThread\n");	
	CurrentScan.ThreadActive=TRUE;

	FixFPUcrash();

	__try
	{
		ntStatus=CETC_CreateFile(&addressfile,L"\\DosDevices\\C:\\ADDRESS.DAT");
		if (!NT_SUCCESS(ntStatus)) return;

		ntStatus=CETC_CreateFile(&valuefile,L"\\DosDevices\\C:\\VALUES.DAT");
		if (!NT_SUCCESS(ntStatus)) return;
		
		if (!CurrentScan.scanning) return;

	    
		errorcode=SE_IncorrectType;
		DbgPrint("Checking memory type\nVartype=%d\n",CurrentScan.Vartype);	

		//Allocate memory for the addresslist
		AddressList=ExAllocatePoolWithTag(PagedPool,MemscanOptions.buffersize/4,0);
		if (AddressList==NULL)
		{
			DbgPrint("Failed to allocate memory for the AddressList\n");				
			return;
		}
		else
			AddressListSize=MemscanOptions.buffersize/4;

#define InitializeList(nr,varsize,value,type) { \
					DbgPrint("case "#nr"\n");\
					if (CurrentScan.scanvaluelength==varsize)\
					{\
						value=*(##type)(CurrentScan.scanvalue);\
						if (CurrentScan.Scantype==ST_Exact_value)\
						{\
						ValueList##nr=ExAllocatePoolWithTag(PagedPool,AddressListSize*varsize,0);\
						if (ValueList##nr==NULL) \
							{\
								DbgPrint("Failed to allocate memory for ValueList"#nr"\n");\
								return;\
							}\
						}\
					}\
					else\
						error=TRUE;\
}

		//initialize the list to put the values in	
		switch (CurrentScan.Vartype)
		{
			case 0:
				{
					//initialize the list for the byte value
					InitializeList(0,1,bytevalue,PBYTE);
					break;
				}

			case 1:
				{
					InitializeList(1,2,wordvalue,PWORD);
					break;
				}

			case 2:
				{
					InitializeList(2,4,dwordvalue,PDWORD);
					break;
				}

			case 3:
				{
					InitializeList(3,4,floatvalue,PFLOAT);
					break;
				}

			case 4:
				{
					InitializeList(4,8,doublevalue,double*);
					break;
				}


			case 6:
				{
					InitializeList(6,8,int64value,PINT64);
					break;
				}

			case 7:
				{
					//string
					DbgPrint("case 7\n");
					if (CurrentScan.scanvaluelength>1)
					{
						stringvalue=CurrentScan.scanvalue; //just give it the pointer
						CETC_Write(valuefile,stringvalue,CurrentScan.scanvaluelength,&iosb);
					}
					else
						error=TRUE;

					break;

				}
			default:
				{
					//not implemented yet
					DbgPrint("case default\n");
					errorcode=SE_NotSupported;
					error=TRUE;

				}

		}

		if (error)
		{			
			ScanResultCount(errorcode); //send a error count
			return;
		}


		DbgPrint("Trying to attach to process\n");
		
		KeAttachProcess((PEPROCESS)CurrentScan.process);
		__try
		{
			DWORD regiontype=0;
			DWORD memorysize=0x1234;		
			DWORD TotalSize=0;
			DWORD BytesRead=0;			

			DbgPrint("Inside the context of the process I hope\n");
			
			//first time go through to find out the memorysize of the memory to scan
			//by default allocate space for 512 entries (one page)
			memoryregion=ExAllocatePoolWithTag(PagedPool,512*sizeof(MEMREGION),0);
			if (memoryregion==NULL)
			{
				DbgPrint("Failed to allocate memory for the memoryregions\n");				
				return;
			}
			else
				memoryregionsize=512;  //512 entries
			
			__try
			{	
				DWORD baseaddress;
					
				mempointer=(PVOID)CurrentScan.Start;
				while (((ULONG)mempointer<CurrentScan.Stop) && (GetMemoryRegionData(0,CurrentScan.process,mempointer,&regiontype,&memorysize,&baseaddress)))
				{
					BOOLEAN ok=FALSE;
					if (regiontype != PAGE_NOACCESS)
					{
						if ((CurrentScan.ScanOptions & SO_READONLY)==0)
						{
							/*
							skip readonly
							only allow:
							PAGE_READWRITE
							PAGE_WRITECOPY
							PAGE_EXECUTE_READWRITE
							PAGE_EXECUTE_WRITECOPY
							*/
							if  ((regiontype == PAGE_READWRITE) ||
								(regiontype == PAGE_WRITECOPY) ||
								(regiontype == PAGE_EXECUTE_READWRITE) ||
								(regiontype == PAGE_EXECUTE_WRITECOPY))
							{
								ok=TRUE;
								
							}
		
						}
						else
						{
							ok=TRUE;
						}
		
					}

					if (ok)
					{												
						TotalSize+=memorysize;
						DbgPrint("%d:memorysize=%x   -  new TotalSize=%x\n",memoryregionentries,memorysize,TotalSize);

						if (memoryregionentries>=memoryregionsize) //should never be able to go above, but lets check it anyhow...
						{
							MEMREGION *newmemoryregion;
							//allocate another 512 entries
							DbgPrint("Need more regions\n");
							newmemoryregion=ExAllocatePoolWithTag(PagedPool,(memoryregionsize+512)*sizeof(MEMREGION),0);
							if (newmemoryregion!=NULL)
							{
								//copy the old memory to the new one and free the old one
								RtlCopyMemory(newmemoryregion,memoryregion,memoryregionsize*sizeof(MEMREGION));
								ExFreePool(memoryregion);
								memoryregion=newmemoryregion;
								memoryregionsize+=512;
							}
							else
							{
								ExFreePool(memoryregion);
								memoryregion=NULL;
								DbgPrint("Failed to re-allocate memory for the memoryregions\n");
								PsTerminateSystemThread(STATUS_SUCCESS);
								return;
							}
									

						};

						memoryregion[memoryregionentries].BaseAddress=baseaddress;
						memoryregion[memoryregionentries].Size=memorysize;
						memoryregionentries++;	

					}
		
		
					(ULONG)mempointer+=memorysize;
				}

				if (memoryregionentries>0)
				{
					DbgPrint("Adjusting regions\n");
					DbgPrint("before:TotalSize=%x\nmemoryregion[0].BaseAddress=%x\n",TotalSize,memoryregion[0].BaseAddress);
					//adjust start and stop
					if (memoryregion[0].BaseAddress<CurrentScan.Start)
					{
						memoryregion[0].Size-=CurrentScan.Start-memoryregion[0].BaseAddress;
						TotalSize-=CurrentScan.Start-memoryregion[0].BaseAddress;
						memoryregion[0].BaseAddress=CurrentScan.Start;
					}

					if (memoryregion[memoryregionentries-1].BaseAddress+memoryregion[memoryregionentries-1].Size>CurrentScan.Stop)
					{					
						TotalSize-=(memoryregion[memoryregionentries-1].BaseAddress+memoryregion[memoryregionentries-1].Size)-CurrentScan.Stop;
						memoryregion[memoryregionentries-1].Size-=(memoryregion[memoryregionentries-1].BaseAddress+memoryregion[memoryregionentries-1].Size)-CurrentScan.Stop;
					}

					DbgPrint("After:TotalSize=%x\nMemoryregion[0].BaseAddress=%x\n",TotalSize,memoryregion[0].BaseAddress);

				}
	
				/*
				//this works:
				mempointer=(PVOID)CurrentScan.Start;
				if (((PBYTE)mempointer)[0]==12)
					return;
				*/

				DbgPrint("Checking the TotalSize:%x\n",TotalSize);

				if ((TotalSize==0) || (TotalSize>0xf0000000))
				{
					//I don't accept 0 memory
					//and also not if there is more than 0xf0000000 bytes readable memory (more likely a signed underflow or other bug)
					DbgPrint("Error with memory regions\n");		
					ScanResultCount(SE_NoMemoryFound);
					return;
				}

				
	
				//now start the scan
				DbgPrint("Initializing the progressbar. Totalsize=%d (%x)\n",TotalSize,TotalSize);
				UpdateProgressBar(TotalSize,0); //max size of progressbar and the current pos (0) (both devided by 2)
				BytesRead=0;

				if (CurrentScan.Scantype==ST_Exact_value)
					DbgPrint("Scantype=Exact value\n");

				for (i=0; (i<memoryregionentries) && (CurrentScan.scanning);i++)
				{
					ULONG StopAddress;
					DbgPrint("Region %d\n",i);
					
					mempointer=(PVOID)(memoryregion[i].BaseAddress);
					StopAddress=memoryregion[i].BaseAddress+memoryregion[i].Size;

					//adjust the stopaddress so you dont scan unreadable memory
					StopAddress-=CurrentScan.scanvaluelength-1;

					UpdateProgressBar(TotalSize,BytesRead);


#define MemCheckAndHandle(nr,type,varsize,value) if ( /*it's faster to do this in a seperate code segment for each type, but lets try this first (less code)*/ \
	((CurrentScan.Scantype==ST_Exact_value) && (*(##type)mempointer==value)) ||\
	((CurrentScan.Scantype==ST_SmallerThan) && (*(##type)mempointer<value)) ||\
	((CurrentScan.Scantype==ST_BiggerThan) && (*(##type)mempointer>value))\
	)\
	{\
		/*found one*/ \
		DbgPrint("Found one!!!\n");\
		AddressList[found]=(ULONG)mempointer;\
		ValueList##nr[found]=*(##type)mempointer;\
		found++;\
		if (found==AddressListSize)\
		{\
			DbgPrint("Writing tempfile\n");\
			\
			/*write the addresses and values to disk*/ \
			CETC_Write(addressfile,AddressList,found*4,&iosb);\
			CETC_Write(valuefile,ValueList##nr,found*varsize,&iosb);\
\
			foundsaved+=found;\
			found=0;\
		}\
	}

				
					while ((ULONG)mempointer<StopAddress)
					{
						__try
						{
							switch (CurrentScan.Vartype)
							{
							case 0:
								{
									MemCheckAndHandle(0,PBYTE,1,bytevalue);
									((ULONG)mempointer)++;									
									break;
								}


							case 1: //2 byte
								{
									MemCheckAndHandle(1,PWORD,2,wordvalue);
									
									if (FastScan)
										((ULONG)mempointer)+=2;
									else
										((ULONG)mempointer)++;
									break;
								}

							case 2: //4 byte
								{
									MemCheckAndHandle(2,PDWORD,4,dwordvalue);
									
									if (FastScan)
										((ULONG)mempointer)+=4;
									else
										((ULONG)mempointer)++;
									break;
								}

							case 3: //float
								{
									MemCheckAndHandle(3,float*,4,floatvalue)
									
									if (FastScan)
										((ULONG)mempointer)+=4;
									else
										((ULONG)mempointer)++;
									break;
								}

							case 4: //double
								{
									MemCheckAndHandle(4,double*,8,doublevalue)
									
									if (FastScan)
										((ULONG)mempointer)+=8;
									else
										((ULONG)mempointer)++;
									break;
								}

							case 6: //int64
								{
									MemCheckAndHandle(6,PINT64,8,int64value)

									
									if (FastScan)
										((ULONG)mempointer)+=8;
									else
										((ULONG)mempointer)++;
									break;
								}


							case 7:
								{
									if (RtlCompareMemory(mempointer,stringvalue,CurrentScan.scanvaluelength)==CurrentScan.scanvaluelength)
									{
										found++;
										if (found==AddressListSize)
										{
											DbgPrint("Writing tempfile\n");
											
											/*write the addresses to disk*/ 
											CETC_Write(addressfile,AddressList,found*4,&iosb);																
											foundsaved+=found;
											found=0;
										}

										

									}


									break;
								}

							default:
								((ULONG)mempointer)++;

							}

						}
						__except(1)
						{
							//unreadable
							DbgPrint("unreadable %p\n",mempointer);
                            ((ULONG)mempointer)+=PAGE_SIZE; //try the next page
							//align on the base
							(ULONG)mempointer=(ULONG)mempointer/0x1000*0x1000; //shouldn't be neccesary, but lets do it anyhow
						}                       
						
					} //while


					BytesRead+=memoryregion[i].Size;

				}
				
				//now save the results
				if (found>0)
				{
					DbgPrint("Writing tempfile\n");

					ntStatus=CETC_Write(addressfile,AddressList,found*4,&iosb);
					switch (CurrentScan.Vartype)
					{
					case 0:
						{
							//write the addresses and values to disk
							ntStatus=CETC_Write(valuefile,ValueList0,found,&iosb);
							break;
						}

					case 1:
						{
							//write the addresses and values to disk
							ntStatus=CETC_Write(valuefile,ValueList1,found*2,&iosb);
							break;
						}

					case 2:
						{
							//write the addresses and values to disk
							ntStatus=CETC_Write(valuefile,ValueList2,found*4,&iosb);
							break;
						}

					case 3:
						{
							//write the addresses and values to disk
							ntStatus=CETC_Write(valuefile,ValueList3,found*4,&iosb);
							break;
						}

					case 4:
						{
							//write the addresses and values to disk
							ntStatus=CETC_Write(valuefile,ValueList4,found*8,&iosb);
							break;
						}

					case 6:
						{
							//write the addresses and values to disk
							ntStatus=CETC_Write(valuefile,ValueList6,found*8,&iosb);
							break;
						}


					}

					foundsaved+=found;
					found=0;
				}

				//and tell the client the results
				
				DbgPrint("found=%d and foundsaved=%d\n",found,foundsaved);
			    if ((found+foundsaved)<=MemscanOptions.max)
				{			
					
					//read the addresses and values and tell them to the client
					//first reposition the file pointer to the start
					IO_STATUS_BLOCK isb;
					FILE_POSITION_INFORMATION fpi;
					int j,k;					

					fpi.CurrentByteOffset.QuadPart=0;
					DbgPrint("Resetting the file position to 0\n");
					ntStatus=ZwSetInformationFile(addressfile,&isb,&fpi,sizeof(FILE_POSITION_INFORMATION),FilePositionInformation);
					DbgPrint("ntStatus=%d",ntStatus);

					//read the AddressFile
					i=0;
					while ((i<MemscanOptions.max) && (i<foundsaved))
					{	
						

						DbgPrint("Reading addressfile\n");
						DbgPrint("(foundsaved<AddressListSize)? (foundsaved*4):(AddressListSize*4)=%d\n",(foundsaved<AddressListSize)? (foundsaved*4):(AddressListSize*4));
						ntStatus=ZwReadFile(addressfile,NULL,NULL,NULL,&isb,AddressList,(foundsaved<AddressListSize)? (foundsaved*4):(AddressListSize*4),NULL,NULL);

						DbgPrint("ntStatus=%x\n",ntStatus);
						DbgPrint("isb.Information=%d\n",isb.Information);

						if (isb.Information>4)
						{						
							j=(int)isb.Information/4;
							for (k=0; k<j; k++)
							{
								switch (CurrentScan.Vartype)
								{
								case 0://byte
										ScanResult(AddressList[k],1);
										break;
								case 1:
										ScanResult(AddressList[k],2);
										break;

								case 2:
								case 3:
										ScanResult(AddressList[k],4);
										break;

								case 4:
								case 6:
										ScanResult(AddressList[k],8);
										break;

								case 7:
										ScanResult(AddressList[k],CurrentScan.scanvaluelength);
										break;								

								}
								//AddressList[k]


							}

							i+=j;
						}
						else
						{
							DbgPrint("Failed to read AddressList\n");
							break;
						}
						
					}

					FlushScanresultBuffer();
                   

				}		
				ScanResultCount(foundsaved);	
			}
			__finally
			{

				
			}
	
	
	
		}
		__finally
		{	
			DbgPrint("Detaching\n");
			KeDetachProcess();
		}

		DbgPrint("returning\n");
	}
	__finally
	{
		//End of the thread.
		//Free all the used memory and close the files		
		DbgPrint("Terminating\n");	
		DbgPrint("Free memory\n");	
		if (memoryregion!=NULL) ExFreePool(memoryregion);
		if (AddressList!=NULL) ExFreePool(AddressList);
		if (ValueList0!=NULL) ExFreePool(ValueList0);
		if (ValueList1!=NULL) ExFreePool(ValueList1);
		if (ValueList2!=NULL) ExFreePool(ValueList2);
		if (ValueList3!=NULL) ExFreePool(ValueList3);
		if (ValueList4!=NULL) ExFreePool(ValueList4);
		if (ValueList6!=NULL) ExFreePool(ValueList6);

		DbgPrint("Close files\n");
		if (addressfile!=0) ZwClose(addressfile);
		if (valuefile!=0) ZwClose(valuefile);
		
        
		CurrentScan.scanning=FALSE;
		CurrentScan.ThreadActive=FALSE;
		PsTerminateSystemThread(STATUS_SUCCESS);
	}
	return;
}

BOOLEAN FirstScan(PEPROCESS ActivePEPROCESS, DWORD start,DWORD stop,BYTE vartype,BYTE scantype,BYTE scanvaluesize,char *scanvalue,BYTE ScanOptions)
{
	BOOLEAN status=FALSE;
	CurrentScan.process=ActivePEPROCESS;
	CurrentScan.Start=start;
	CurrentScan.Stop=stop;
	CurrentScan.Vartype=vartype;
	CurrentScan.Scantype=scantype;
	CurrentScan.ScanOptions=ScanOptions;

	if (CurrentScan.scanvalue!=NULL)
	{
		//a leftover from last scan (e.g thread crashed...)
		ExFreePool(CurrentScan.scanvalue);
		CurrentScan.scanvalue=NULL;
	}
	CurrentScan.scanvalue=ExAllocatePoolWithTag(PagedPool,scanvaluesize,0);
	if (CurrentScan.scanvalue==NULL)
		return FALSE; //error

	RtlCopyMemory(CurrentScan.scanvalue,scanvalue,scanvaluesize);
	CurrentScan.scanvaluelength=scanvaluesize;

	__try
	{
		OBJECT_ATTRIBUTES oaCreateThread;
		HANDLE th;
		CurrentScan.scanning=TRUE;

		//start the scan
		
		if (scantype==ST_Advanced_Scan)
		{
			//unknown initial value scan
			InitializeObjectAttributes(&oaCreateThread, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
			DbgPrint("Creating scanthread\n");
			if (NT_SUCCESS(PsCreateSystemThread(&th,0L,&oaCreateThread,NULL,NULL,UnknownInitialValueScan,NULL)))
			{
				DbgPrint("Created thread\n");
				ZwClose(th); //I dont want this handle (useless anyhow except for setting priority)
			}
			else
				DbgPrint("Failed to create thread\n");
		}
		else
		{
			//first scan for value
			InitializeObjectAttributes(&oaCreateThread, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
			DbgPrint("Creating scanthread\n");
			if (NT_SUCCESS(PsCreateSystemThread(&th,0L,&oaCreateThread,NULL,NULL,FirstScanThread,NULL)))
			{
				DbgPrint("Created thread\n");
				ZwClose(th); //I dont want this handle (useless anyhow except for setting priority)
			}
			else
				DbgPrint("Failed to create thread\n");
		}

		//and resume the command listener
	}
	__except(1)
	{
		DbgPrint("Error\n");
	}

	return status;
}
#endif

 

 

Ссылка на комментарий
Поделиться на другие сайты

  • 1 месяц спустя...

Я так и не понял , как быстро сканировать в большом диапазоне :( Объясните плез . Ибо функция сканирования , которую я видел в уроке кодера , сканирует очень медленно (

Изменено пользователем afro228offical
Ссылка на комментарий
Поделиться на другие сайты

Чем больше озу тем быстрее...мне вот не хватает 2Гб если делаю полный скан...потом всё тормозит блин...особенно если игра ещё весомая.

приходиться сканить по чу-чу-ть от 0х000000 до 0x2FFFFFFF примерно.

Ссылка на комментарий
Поделиться на другие сайты

41 минуты назад, krocki сказал:

Чем больше озу тем быстрее...мне вот не хватает 2Гб если делаю полный скан...потом всё тормозит блин...особенно если игра ещё весомая.

приходиться сканить по чу-чу-ть от 0х000000 до 0x2FFFFFFF примерно.

Мне бы хотя бы до 7FFFFFFF да и до 2FFFFFFF тоже сканит медленно . Хотя в тот же момент Umse ищет за секунду до FEFEFEFE

Изменено пользователем afro228offical
Ссылка на комментарий
Поделиться на другие сайты

А в чем проблема исходники-то почитать? Там все паскальным по белому. Кстати, когда-то давно существовала программа WGC (Winner Game Cheater, если не ошибаюсь) - она сканировала быстрее СЕ\Артмани раз в 5-10. Наш соотечественник писал, кстати, и там был очень хардкорный алгоритм на ассемблере. :)

Ссылка на комментарий
Поделиться на другие сайты

17 час назад, keng сказал:

А в чем проблема исходники-то почитать? Там все паскальным по белому. Кстати, когда-то давно существовала программа WGC (Winner Game Cheater, если не ошибаюсь) - она сканировала быстрее СЕ\Артмани раз в 5-10. Наш соотечественник писал, кстати, и там был очень хардкорный алгоритм на ассемблере. :)

А исходник где скачать можно ?

Ссылка на комментарий
Поделиться на другие сайты

4 часа назад, afro228offical сказал:

Киньте ссылку пожалуйста.

http://cheatengine.org/downloads.php

Листаем вниз страницы и видим

AAAAAElFTkSuQmCC

 

Первая ссылка ведет на

http://cheatengine.org/download/CheatEngine64src.rar

А можно еще забрать, как написано тут же на скриншоте, из репозитория

https://github.com/cheat-engine/cheat-engine 

Ссылка на комментарий
Поделиться на другие сайты

Да смысл? Там ничего не понятно . У меня есть исходник .Но толку мало . Буду признателен , если кто-то объяснит , как сканер CE работает.
Да и мне вроде не исходник CE нужен...

Изменено пользователем afro228offical
Ссылка на комментарий
Поделиться на другие сайты

Он работает так же, как и все подобные сканеры - открывает доступную для чтения память процесса, последовательно проходит по каждому адресу (учитывая размер переменной), выписывает все найденные адреса, значение которых совпадает с объектом поиска, в файлик. Дальше бегает по этому файлику - все последующие отсеивания.

Ссылка на комментарий
Поделиться на другие сайты

22 минуты назад, keng сказал:

Он работает так же, как и все подобные сканеры - открывает доступную для чтения память процесса, последовательно проходит по каждому адресу (учитывая размер переменной), выписывает все найденные адреса, значение которых совпадает с объектом поиска, в файлик. Дальше бегает по этому файлику - все последующие отсеивания.

Так почему же он сканирует в 100 раз быстрее сканера из урока кодера?

Изменено пользователем afro228offical
Ссылка на комментарий
Поделиться на другие сайты

Just now, afro228offical said:

Так почему же он сканирует в 100 раз быстрее сканера из урока кодера?

Как минимум потому, что он это в несколько потоков одновременно делает.

Ссылка на комментарий
Поделиться на другие сайты

4 минуты назад, keng сказал:

Как минимум потому, что он это в несколько потоков одновременно делает.

и он сканирует все 7fffffffffffffff в потоках ?И сколько потоков в таком случае нужно ?

Изменено пользователем afro228offical
Ссылка на комментарий
Поделиться на другие сайты

Just now, afro228offical said:

и он сканирует все 7fffffffffffffff в потоках ?

В смысле? Представь себе, что у тебя есть пирог. Как его быстрее скушать получится - одним ртом или двумя, четырьмя, десятью? Память - это просто массив. Делишь его на куски и каждому потоку отдаешь сканировать свой кусок. Все просто.

  • Плюс 3
Ссылка на комментарий
Поделиться на другие сайты

×
×
  • Создать...

Важная информация

Находясь на нашем сайте, Вы автоматически соглашаетесь соблюдать наши Условия использования.