Jump to content
Tuts 4 You

How To Search Bytes In Process ?


Matrix

Recommended Posts

Hi Friends

I Want Search More Bytes In Any Process With Visual Basic

How I Do It ?

Please Help ME :wub:

THanks

Sorry For My Bad English :wub:

Link to comment

basicaly you need to know region you want to search, lets name it bbegin and eend

Then you code a simple loop that will read a chunk of data in a variable, then

just look for accourances of your first byte in your variable - if none then get next chunk (until eend reached)

if you got a match (only one - first byte) then you need to do additional comparing to see if other bytes mach

as well..

so basic idea is to have a function that will read data from specified region and use it in a loop.

Sorry for not providing any sources, but its better you learn it trying then get it completely served.

There are sources of this topic online, just use google.

p.s.

you can use ReadProcessMemory API for read from memory.

BR; ChupaChu!

Edited by ChupaChu
Link to comment

Hey Matrix, I will write you up an example in a sec. I have done this before for some old code but the old code was just tossed together so I will rewrite it and fix it up. Give me a few and I'll post it up. ^_^

Link to comment

Ok all finished with the rewrite. Project example and code are attached to this post. Heres a quick overview of the example project:

'
' This example will scan inside of Minesweeper (winmine.exe) on a Windows XP
' based system. The given byte array is a call opcode which is located just
' after the flag instruction to add or remove a flag when the user right-clicks
' on the game board. The actual memory and opcodes looks like this for this
' memory section:
'
' 100346A 8b 44 24 04 mov eax, [esp+04]
' 100346E 01 05 94 51 00 01 add [01005194], eax
' 1003474 e8 88 f3 ff ff call 01002801
' 1003479 c2 04 00 ret 0004
'
' The below example is told to start scanning at 100346A and scan until
' 100346A+3E8 (1000 in hex)
'
' The ScanForBytes function will locate the process by its name, dump
' the given memory based on the start address and size, then compare
' the byte array given the memory dump to see if it resides in it.
'
' This function does not support wild cards and will not deal with dead
' memory regions and such on its own. So keep the size that you are scanning
' as small as possible and try to limit the address you are scanning to a base
' of a region if possible.
'
' ScanForBytes is setup for parameters like this:
'
' ScanForBytes(szProcessName As String, dwStartAddr As Long, dwSizeToScan As Long, bByteArrayToScan() As Byte) As Long
'
' szProcessName - String - Process name to scan for.
' dwStartAddr - Long - Start address to start the memory dump from.
' dwSizeToScan - Long - Amount of bytes, from the start address, to dump.
' bByteArrayToScan - Byte() - Array of bytes to scan for within the memory dump.
'
' The return value is the address the byte array passed starts at. If the return value is 0
' something failed inside the function. You should always compare the return to 0 for error
' checking when you are using it in a live program for security and such.
'
' Hope this helps!
'
' ~ atomOs
'

ScanMem.rar

Link to comment

Nice code Atomos congratulations. :)

A little question: How fast is this algorithm for searching inside huge blocks of memory?

Cheers

Nacho_dj

Link to comment

I just tested with an allocated block of memory of 1,000,000 bytes which is just about 1 megabyte of memory. I filled the memory with random bytes so its not just dumping 0's as well. Heres my C++ test code to do this:

#pragma comment( linker, "/ENTRY:main" )
#include <windows.h>
#include <stdio.h>int main( int argc, TCHAR* argcv[] )
{
LPVOID lpAddr = VirtualAlloc( NULL, 1000000, MEM_COMMIT, PAGE_EXECUTE_READWRITE ); // Fill Memory With Random Bytes
for( int x=0; x<=1000000; x++ )
*(BYTE*)((DWORD)lpAddr+x) = (BYTE)rand()%255; printf( "Allocated: %x", lpAddr );
getchar();
VirtualFree( lpAddr, 1000000, MEM_DECOMMIT );
return 0;
}

I ran the program and let it sit like that so it will hold the memory until I hit enter. Then I opened Cheat Engine, went to the end of the memory block by going to the address printed +1000000 and took the last line of bytes to scan for in the VB app. In this case the last bytes where:

&H73, &H5B, &HE0, &HC7, &H1D, &HA7, &H58, &H8A, &H8E, &H64, &H2D, &H27, &HAC, &H71, &H14, &H87, &H88

The full line of code was:

Private Sub Command1_Click()
Dim dwLongRet As Long
dwLongRet = ScanForBytes("asdf.exe", &H420000, 1003520, ByteArray(&H73, &H5B, &HE0, &HC7, &H1D, &HA7, &H58, &H8A, &H8E, &H64, &H2D, &H27, &HAC, &H71, &H14, &H87, &H88))
Text1.Text = Hex(dwLongRet)
End Sub

Upon clicking, the return was nearly instant.

So I would say safe to assume its pretty fast. If you need to scan for more then one array though, I suggest altering the code and having it dump the memory once, then make another function to scan the dumped block more then once. But its pretty fast.

Link to comment

Hi Atomos

Thanks For YOur Source

But I Do Not Have Any Address , And I Want Serach Total Of My Process In Memory

May You Help Me Again

Link to comment

Attached is the new version. This time all you need to pass is the process name and the byte array, for example:

ScanForBytes("winmine.exe", ByteArray(&HE8, &H88, &HF3, &HFF, &HFF))

The new function works by looping the processes readable memory regions and dumping them one by one and scanning within them for the given byte array. As far as I know, the memory region code is correct based on comparing the results I obtained to other software that can dump the regions. I've never really worked with them much in the past so I can't guarantee it's perfect.

The example, again, scans within Minesweeper for the flag command bytes. Works perfect for me on WinXP Pro w/SP2.

Hope this is what you needed. :)

ScanMem_2.rar

Link to comment

Not a problem, glad it helps :) I converted the code to C if anyone wants to use it in C/C++ instead:

//
// ScanForBytes Memory Region Scanner
// Coded By: atomOs (Wiccaan) - 2008
// This code is intended to be compiled as 'C' code.
//#include <windows.h>
#include <stdio.h>
#include <tlhelp32.h>unsigned long _GetProcessId( char* szProcName )
{
PROCESSENTRY32 pe32;
HANDLE hHandle; hHandle = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
pe32.dwSize = sizeof( PROCESSENTRY32 ); if( !Process32First( hHandle, &pe32 ) )
return 0; while( Process32Next( hHandle, &pe32 ) )
{
if( strcmp( szProcName, pe32.szExeFile ) == 0 )
{
CloseHandle( hHandle );
return pe32.th32ProcessID;
}
}
CloseHandle( hHandle ); return 0;
}unsigned long _ScanForBytes( char* szProcess, char* szBytes )
{
HANDLE hHandle;
SYSTEM_INFO sysInfo;
MEMORY_BASIC_INFORMATION mbi;
unsigned long dwMemAddr;
unsigned long x; hHandle = OpenProcess( PROCESS_QUERY_INFORMATION|PROCESS_VM_OPERATION|PROCESS_VM_READ, FALSE, _GetProcessId( szProcess ) );
if( hHandle == INVALID_HANDLE_VALUE || hHandle == NULL )
return 0; GetSystemInfo( &sysInfo );
dwMemAddr = (unsigned long)sysInfo.lpMinimumApplicationAddress; while( dwMemAddr < (unsigned long)sysInfo.lpMaximumApplicationAddress )
{
if( VirtualQueryEx( hHandle, (unsigned long*)dwMemAddr, &mbi, sizeof(mbi) ) == sizeof(mbi) )
{
if( (mbi.Protect != PAGE_NOACCESS) && (mbi.State == MEM_COMMIT) )
{
char* szMemDump = (char*)malloc(mbi.RegionSize+1);
ReadProcessMemory( hHandle, (unsigned long*)dwMemAddr, szMemDump, mbi.RegionSize, NULL );
for( x=0; x<mbi.RegionSize; x++ )
{
if( memcmp( (void*)(szMemDump+x), (void*)szBytes, strlen( szBytes ) ) == 0 )
{
free( szMemDump );
return (unsigned long)( dwMemAddr + x );
}
}
free( szMemDump );
}
}
dwMemAddr = (unsigned long)mbi.BaseAddress + mbi.RegionSize;
}
CloseHandle( hHandle ); return 0;
}int main( int argc, TCHAR* argcv[] )
{
UNREFERENCED_PARAMETER( argc );
UNREFERENCED_PARAMETER( argcv ); printf( "Scan Results: 0x%08X\n", _ScanForBytes( "winmine.exe", "\xE8\x88\xF3\xFF\xFF" ) ); getchar();
return 0;
}

Cheers. :)

Edited by Atomos
Link to comment

Hi Atomos

I Have A Problem With ScanMem2

For Exapmle When I Search "EB FE" In My Process The Return Value Is Not Correct

I Attached My Sample , Pleaes Run Sample And Serach "EB FE" With ScanMem2

Offset Of "EB FE" In This Sample Is "00401C9B" , Test Return Value Please

Please Help Me Again

Thanks Dear

Sample.rar

Link to comment
Hi Atomos

I Have A Problem With ScanMem2

For Exapmle When I Search "EB FE" In My Process The Return Value Is Not Correct

I Attached My Sample , Pleaes Run Sample And Serach "EB FE" With ScanMem2

Offset Of "EB FE" In This Sample Is "00401C9B" , Test Return Value Please

Please Help Me Again

Thanks Dear

Could you post your VB project for this? If you need to PM me it if you don't wish to share it with everyone.

EDIT: After quickly debugging this I noticed why you are having issues with this. You are doing a compare then having it endlessly loop inside the compare:

00401C58   > \8B45 E8	   MOV EAX,DWORD PTR SS:[EBP-18]
00401C5B . 50 PUSH EAX
00401C5C . 68 241A4000 PUSH Sample.00401A24 ; UNICODE "Atomos"
00401C61 . FF15 38104000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrCm>; MSVBVM60.__vbaStrCmp
00401C67 . 8BF0 MOV ESI,EAX
00401C69 . 8D4D E8 LEA ECX,DWORD PTR SS:[EBP-18]
00401C6C . F7DE NEG ESI
00401C6E . 1BF6 SBB ESI,ESI
00401C70 . 46 INC ESI
00401C71 . F7DE NEG ESI
00401C73 . FF15 88104000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaFreeS>; MSVBVM60.__vbaFreeStr
00401C79 . 8D4D E4 LEA ECX,DWORD PTR SS:[EBP-1C]
00401C7C . FF15 8C104000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaFreeO>; MSVBVM60.__vbaFreeObj
00401C82 . B9 04000280 MOV ECX,80020004
00401C87 . B8 0A000000 MOV EAX,0A
00401C8C . 66:3BF7 CMP SI,DI
00401C8F . 894D AC MOV DWORD PTR SS:[EBP-54],ECX
00401C92 . 8945 A4 MOV DWORD PTR SS:[EBP-5C],EAX
00401C95 . 894D BC MOV DWORD PTR SS:[EBP-44],ECX
00401C98 . 8945 B4 MOV DWORD PTR SS:[EBP-4C],EAX
00401C9B >- EB FE JMP SHORT Sample.00401C9B

Having the EB FE inside this will never return a value as it will just get stuck at that JMP.

Edited by Atomos
Link to comment

Hi Atomos

This File Is Just An Example And Not Important

For Exaplme I Want When Using Your ScanMem2 For Search "EB FE" ,The Return Value Equal 401C9B

Can You Help Me Dear ?

Link to comment

The return I get scanning inside of the Sample.exe is 14D042 which in theory is correct as that opcode does contain the bytes you are telling it to scan for. Instead, are you able to add more bytes to the string to scan for? It would be better if you could use more instead of just a few. It would limit the amount of same matches found.

For example, the opcodes around 401C9B are

00401C8C   .  66:3BF7	   CMP SI,DI
00401C8F . 894D AC MOV DWORD PTR SS:[EBP-54],ECX
00401C92 . 8945 A4 MOV DWORD PTR SS:[EBP-5C],EAX
00401C95 . 894D BC MOV DWORD PTR SS:[EBP-44],ECX
00401C98 . 8945 B4 MOV DWORD PTR SS:[EBP-4C],EAX
00401C9B >- EB FE JMP SHORT Sample.00401C9B
00401C9D . 8B35 74104000 MOV ESI,DWORD PTR DS:[<&MSVBVM60.__vbaVa>; MSVBVM60.__vbaVarDup
00401CA3 . BB 08000000 MOV EBX,8
00401CA8 . 8D55 84 LEA EDX,DWORD PTR SS:[EBP-7C]
00401CAB . 8D4D C4 LEA ECX,DWORD PTR SS:[EBP-3C]
00401CAE . C745 8C 581A4>MOV DWORD PTR SS:[EBP-74],Sample.00401A5>; UNICODE "Success"
00401CB5 . 895D 84 MOV DWORD PTR SS:[EBP-7C],EBX
00401CB8 . FFD6 CALL ESI ; <&MSVBVM60.__vbaVarDup>

To add to it, you could do the instruction before it as well. For this example I'd use:

00401C98   .  8945 B4	   MOV DWORD PTR SS:[EBP-4C],EAX
00401C9B >- EB FE JMP SHORT Sample.00401C9B
00401C9D . 8B35 74104000 MOV ESI,DWORD PTR DS:[<&MSVBVM60.__vbaVa>; MSVBVM60.__vbaVarDup

So our byte array would be:

&H89, &H45, &HB4, &HEB, &HFE, &H8B, &H35, &H74, &H10, &H40, &H00

Then the code would be:

	Dim dwAddress As Long
dwAddress = ScanForBytes("Sample.exe", ByteArray(&H89, &H45, &HB4, &HEB, &HFE, &H8B, &H35, &H74, &H10, &H40, &H0))
Text1.Text = Hex(dwAddress)

Which returns: 401C98

Then you can add onto the return based on the number of bytes you used before the real ones, so we would add +3 to the return for the actual address. You don't need that many bytes either, instead you could shorten it to the instruction before as well.

Link to comment
00401C98   .  8945 B4	   MOV DWORD PTR SS:[EBP-4C],EAX
00401C9B >- EB FE JMP SHORT Sample.00401C9B
00401C9D . 8B35 74104000 MOV ESI,DWORD PTR DS:[<&MSVBVM60.__vbaVa>; MSVBVM60.__vbaVarDup

So our byte array would be:

&H89, &H45, &HB4, &HEB, &HFE, &H8B, &H35, &H74, &H10, &H40, &H00

If the byte pattern to search for is supposed to be universal/generic it's a bad idea searching on a DWORD!

JW.

Link to comment
The return I get scanning inside of the Sample.exe is 14D042 which in theory is correct as that opcode does contain the bytes you are telling it to scan for. Instead, are you able to add more bytes to the string to scan for? It would be better if you could use more instead of just a few. It would limit the amount of same matches found.

For example, the opcodes around 401C9B are

00401C8C   .  66:3BF7	   CMP SI,DI
00401C8F . 894D AC MOV DWORD PTR SS:[EBP-54],ECX
00401C92 . 8945 A4 MOV DWORD PTR SS:[EBP-5C],EAX
00401C95 . 894D BC MOV DWORD PTR SS:[EBP-44],ECX
00401C98 . 8945 B4 MOV DWORD PTR SS:[EBP-4C],EAX
00401C9B >- EB FE JMP SHORT Sample.00401C9B
00401C9D . 8B35 74104000 MOV ESI,DWORD PTR DS:[<&MSVBVM60.__vbaVa>; MSVBVM60.__vbaVarDup
00401CA3 . BB 08000000 MOV EBX,8
00401CA8 . 8D55 84 LEA EDX,DWORD PTR SS:[EBP-7C]
00401CAB . 8D4D C4 LEA ECX,DWORD PTR SS:[EBP-3C]
00401CAE . C745 8C 581A4>MOV DWORD PTR SS:[EBP-74],Sample.00401A5>; UNICODE "Success"
00401CB5 . 895D 84 MOV DWORD PTR SS:[EBP-7C],EBX
00401CB8 . FFD6 CALL ESI ; <&MSVBVM60.__vbaVarDup>

To add to it, you could do the instruction before it as well. For this example I'd use:

00401C98   .  8945 B4	   MOV DWORD PTR SS:[EBP-4C],EAX
00401C9B >- EB FE JMP SHORT Sample.00401C9B
00401C9D . 8B35 74104000 MOV ESI,DWORD PTR DS:[<&MSVBVM60.__vbaVa>; MSVBVM60.__vbaVarDup

So our byte array would be:

&H89, &H45, &HB4, &HEB, &HFE, &H8B, &H35, &H74, &H10, &H40, &H00

Then the code would be:

	Dim dwAddress As Long
dwAddress = ScanForBytes("Sample.exe", ByteArray(&H89, &H45, &HB4, &HEB, &HFE, &H8B, &H35, &H74, &H10, &H40, &H0))
Text1.Text = Hex(dwAddress)

Which returns: 401C98

Then you can add onto the return based on the number of bytes you used before the real ones, so we would add +3 to the return for the actual address. You don't need that many bytes either, instead you could shorten it to the instruction before as well.

Hi My Friend

I Want Use This Method For Detecting Sniffer , Because Sniffer Write "EB FE" In Your Process For Example For Reading Registers (EAX, EBX,...) For Finding Correct Serial .Now I Search "EB FE" In My Process I Can Know That My Program Run With A Serial Sniffer

I Just Find "EB FE"

Thanks Dear

Link to comment
If the byte pattern to search for is supposed to be universal/generic it's a bad idea searching on a DWORD!

JW.

Yes I know, I was just trying to point out what I meant by using bytes around the given pattern. Searching for specific addresses is something I'd use wildcards for.

Hi My Friend

I Want Use This Method For Detecting Sniffer , Because Sniffer Write "EB FE" In Your Process For Example For Reading Registers (EAX, EBX,...) For Finding Correct Serial .Now I Search "EB FE" In My Process I Can Know That My Program Run With A Serial Sniffer

I Just Find "EB FE"

Thanks Dear

I'm not too sure what you mean by 'detecting sniffer'. The code I gave above will scan for the bytes as needed in each section, I can't really give much more help other then what I have given a I do not really know much about the target you are working on or what the exact problem you are facing is. :(

Link to comment
  • 3 weeks later...
  • 2 weeks later...
anyone got an example in delphi to scan for bytes>?

Here's a very basic and raw example >

http://rapidshare.com/files/128644983/ProcessScan.rar.html

Hope this is what you need.

JW.

Link to comment
  • 2 weeks later...
  • 3 months later...
  • 1 month later...
Hi Friends

I Want Search More Bytes In Any Process With Visual Basic

How I Do It ?

Please Help ME :wub:

THanks

Sorry For My Bad English :wub:

when i can i will upload my clsQuickSearch which does exactly what you need, or better yet you can download my WTLoader from the ToolsOfTrade section and get it inside the source folder

Link to comment
  • 9 months later...

hi guys

and thanks to atom0s for his great example.

1 question to atom0s:is there a way to make it search just in one module?

for example i just want to search just in user32.dll not other modules.

is these possible with your byte scanner example?

waiting for your replay.

thanks.

Link to comment

hi guys

and thanks to atom0s for his great example.

1 question to atom0s:is there a way to make it search just in one module?

for example i just want to search just in user32.dll not other modules.

is these possible with your byte scanner example?

waiting for your replay.

thanks.

Which example are you referring to? I posted a few different ones in this topic.

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...