# Source CodePattern Scanning

#### Solaire

##### Respected Hacker
Dank Tier VIP
I was rolling the concept around in my head this morning and decided to see if I could write a pattern scan funct from scratch. This is the result. It's heavily commented, so hopefully it'll help anyone new to pattern scanning understand how it works.

C++:
``````#include <Windows.h>
#include <stdio.h>

int PatternScan(char * arr, int size, char * pattern, char * mask, int len) {
// The index at which the pattern is found
int index = -1;

// Scan for the pattern in the byte array. We do size - len so that we don't
// go out of the bounds of the array we're scanning
for (int i = 0; i < size - len; i++) {
// False until the pattern is found
bool found = false;

// If the byte we're at is equal to the start of our pattern
if (arr[i] == pattern) {
// Loop through the current spot and see if it's the pattern
for (int j = 0; j < len; j++) {
// If the bytes are the same at the index, or the byte is a wildcard, set found to true and continue
if ((arr[i + j] == pattern[j]) || (mask[j] == '?')) {
found = true;
continue;
}

// Otherwise set found to false and break;
else {
found = false;
break;
}
}
}

// Set index to i and break from the loop if the pattern is found
if (found) {
index = i;
break;
}
}

return index;
}

int main() {
// Our array of bytes and its size
char * arr = "\xFF\x24\x1E\xEF\xA7\x99\x90\x4E\xA4\x1E\x99\x4E\x3C\xAB\xB7\x12\x83\x3E\x75";
int arrSize = 19;

// Our pattern and mask, and its length
char * pattern = "\x1E\x99\x4F\x3C\xAC";
int len = 5;

// Scan for the pattern
int index = PatternScan(arr, arrSize, pattern, mask, len);

// Make sure the pattern was found
if (index != -1) {
// Print out our findings
printf("Index: %d\n", index);
printf("Bytes at arr[index]: ");
for (int i = 0; i < len; i++) {
printf("\\x%X", (char)arr[index + i]);
}
}

getchar();

return 0;
}``````

This code is for the most part a concept. You'll have to figure out how to implement it yourself if you want to use it on a game, though that should be fairly simple.

Last edited:

#### Broihon

##### edgy 12 y/o
Escobar Tier VIP
Fleep Tier Donator
C++:
``````bool bCompare(const char * szMask, const BYTE * pPattern, const BYTE * pSource)
{
{
if (*szMask == 'x' && *pPattern != *pSource)
return false;
}
return true;
}

const void * FindPattern(const void * StartAddress, DWORD RegionSize, const BYTE * pPattern, const char * szMask, UINT Alignment = 4, UINT Skip = 0)
{
UINT Count = 0;
{
{
if (Count == Skip)
Count++;
}
}
return nullptr;
}``````
Just leaving this here if you don't mind :3

• #### Solaire

##### Respected Hacker
Dank Tier VIP
Вroihon;40170 said:
C++:
``````bool bCompare(const char * szMask, const BYTE * pPattern, const BYTE * pSource)
{
{
if (*szMask == 'x' && *pPattern != *pSource)
return false;
}
return true;
}

const void * FindPattern(const void * StartAddress, DWORD RegionSize, const BYTE * pPattern, const char * szMask, UINT Alignment = 4, UINT Skip = 0)
{
UINT Count = 0;
{
{
if (Count == Skip)
Count++;
}
}
return nullptr;
}``````
Just leaving this here if you don't mind :3
Yes, yes, we get it, your codenz are much better #### Broihon

##### edgy 12 y/o
Escobar Tier VIP
Fleep Tier Donator
Yes, yes, we get it, your codenz are much better Actually that's not what I wanted to point out. I just think that this thread is a good place to sure different versions of the same function ^^ Also my version is not coded from scratch. For example I'm still not happy with the extra function bCompare.

#### mambda

Escobar Tier VIP
Trump Tier Donator
i prefer pattern scans where you dont have to include a mask, so the pattern is the mask itself

i.e.

FindPattern(module, "83 45 23 ? ? 32 86 ? 50", sizeOfModuleHere);

then you can straight copy it out of IDA or Cheat engine or whatever you like

#### Solaire

##### Respected Hacker
Dank Tier VIP
Вroihon;40172 said:
Actually that's not what I wanted to point out. I just think that this thread is a good place to sure different versions of the same function ^^ Also my version is not coded from scratch. For example I'm still not happy with the extra function bCompare.
Heh no worries, just messing around i prefer pattern scans where you dont have to include a mask, so the pattern is the mask itself

i.e.

FindPattern(module, "83 45 23 ? ? 32 86 ? 50", sizeOfModuleHere);

then you can straight copy it out of IDA or Cheat engine or whatever you like
Nice! I'll have to see if I can implement that and throw it in here #### Solaire

##### Respected Hacker
Dank Tier VIP
@mambda

C++:
``````int GetLen(char * byteArray) {
return (strlen(byteArray) + 1) / 3;
}

// Get the first byte in the string
char * byte = strtok(byteArray, " ");

int i = 0;
while (byte) {
// If the byte is a wild card, set the mask index to '?', get the next byte, and continue
if (byte == '?') {
byte = strtok(NULL, " ");
pattern[i] = 0;
i++;
continue;
}

// Convert the string byte to a regular hex integer
pattern[i] = strtol((const char *)byte, NULL, 16);

// Get the next byte
byte = strtok(NULL, " ");
i++;
}

// Make sure the mask is NULL terminated
}

int PatternScan(char * arr, int size, char * mixedPattern) {
// Get the length of the pattern and allocate memory for the new pattern and mask
int len = GetLen(mixedPattern);
char * pattern = new char[len];
char * mask = new char[len + 1];

// Get the pattern and mask from the mixed pattern

// The index at which the pattern is found
int index = -1;

// Scan for the pattern in the byte array. We do size - len so that we don't
// go out of the bounds of the array we're scanning
for (int i = 0; i < size - len; i++) {
// False until the pattern is found
bool found = false;

// If the byte we're at is equal to the start of our pattern
if (arr[i] == pattern) {
// Loop through the current spot and see if it's the pattern
for (int j = 0; j < len; j++) {
// If the bytes are the same at the index, or the byte is a wildcard, set found to true and continue
if ((arr[i + j] == pattern[j]) || (mask[j] == '?')) {
found = true;
continue;
}

// Otherwise set found to false and break;
else {
found = false;
break;
}
}
}

// Set index to i and break from the loop if the pattern is found
if (found) {
index = i;
break;
}
}

// Clean up and return the index
delete[] pattern;
return index;
}``````
There's just one small (Actually, quite big) problem with it. When delete[] pattern and delete[]mask are called, program flow goes into what looks like an infinite loop. You can remove those two lines, but that leaves a small memory leak. Anywho, I ended up just converting the string into the two char arrays heh. I'm sure there is a better and cleaner way tbh. You also have to send in wildcards as "??" instead of just one "?".

Example call:
C++:
``````    char bytes[] = "\x12\x6E\x53\x27\x38\xE4\x52\x72\x24\x7B\xAB\x42\xF8\xE5\x8B";
char mixedPattern[] = "38 E4 ?? 72 24 7B AB ?? F8";
int index = PatternScan(bytes, 15, mixedPattern);
printf("%d", index);``````
tl;dr This is essentially the same code, I just convert the mixedPattern array into two different char arrays.

EDIT:
Fixed the above code, I was writing to restricted memory with mask, just had to change it to char * mask = new char[len + 1];

Last edited:

#### Broihon

##### edgy 12 y/o
Escobar Tier VIP
Fleep Tier Donator
C++:
``````#include <Windows.h>
#include <iostream>

size_t PatternStringToMask(char * szPattern, BYTE * pPatternOut, char * szMaskOut, UINT MaxCount)
{
size_t Len = lstrlenA(szPattern);
size_t Ret = 0;
for (UINT i = 0;i <= Len - 1 && Ret < MaxCount ;++i)
{
switch (szPattern[i])
{
case '?':
pPatternOut[Ret] = 0;
Ret++;
if (szPattern[i + 1] == '?')
i++;
break;

default:
BYTE HighPart, LowPart;
if (szPattern[i] >= '0' && szPattern[i] <= 'f')
{
HighPart = szPattern[i] - 0x30;
if (HighPart > 0x30)
HighPart -= 0x27;
else if(HighPart > 0x10)
HighPart -= 0x7;
pPatternOut[Ret] = HighPart;
Ret++;
}
if (szPattern[i + 1] >= '0' && szPattern[i + 1] <= 'f')
{
i++;
LowPart = szPattern[i] - 0x30;
if (LowPart > 0x30)
LowPart -= 0x27;
else if (LowPart > 0x10)
LowPart -= 0x7;
pPatternOut[Ret - 1] <<= 4;
pPatternOut[Ret - 1] += LowPart;
}
break;
}
}
return Ret;
}

int main()
{
char* Lel = "Ab cD eF ?? 1A ? 2 0A A\0";
BYTE pOut = { 0 };
char szOut = { 0 };
size_t ret = PatternStringToMask(Lel, pOut, szOut, 50);
std::cout << ret << "\n" << szOut << std::endl;
for (UINT i = 0; i != ret; ++i)
{
std::cout << std::hex << (DWORD)pOut[i] << " ";
}
Sleep(-1);
return 0;
}``````

Last edited:

#### bitm0de

##### Newbie
Full Member
All of the above solutions are going to be slower than molasses because they are all naive byte by byte comparisons with no punch. Why not make use of the STL and functions like std::search with a vector to hold the data? You could dump chunks of memory into an internal byte array then implement a threaded scan with std::async and std::shared_future (C++11 features).

#### Broihon

##### edgy 12 y/o
Escobar Tier VIP
Fleep Tier Donator
All of the above solutions are going to be slower than molasses because they are all naive byte by byte comparisons with no punch. Why not make use of the STL and functions like std::search with a vector to hold the data? You could dump chunks of memory into an internal byte array then implement a threaded scan with std::async and std::shared_future (C++11 features).
Won't be faster nor as dynamic as byte by byte scanning (wildcards/alignment).

#### bitm0de

##### Newbie
Full Member
Вroihon;40651 said:
Won't be faster nor as dynamic as byte by byte scanning (wildcards/alignment).
Asynchronous memory scanning won't be as fast as a byte by byte comparison? And not as dynamic? You should know that you can easily achieve wildcards and surpass any alignment issues with the method I've suggested, so you're still wrong on that idea. I'm curious why you'd think that it would not be any faster -- mind providing your explanation?

Additionally, my suggestion would allow for multiple patterns to be scanned at the same time too.

Last edited:

#### Broihon

##### edgy 12 y/o
Escobar Tier VIP
Fleep Tier Donator
Asynchronous memory scanning won't be as fast as a byte by byte comparison? And not as dynamic? You should know that you can easily achieve wildcards and surpass any alignment issues with the method I've suggested, so you're still wrong on that idea. I'm curious why you'd think that it would not be any faster -- mind providing your explanation?

Additionally, my suggestion would allow for multiple patterns to be scanned at the same time too.
Looking forward to your pattern scanner then. Ain't gonna read up on the whole std namespace when the current patternscanner functions can easily scan through 500kiB of data within >0.1ms. I'm not saying it's the fastest way to do it. I'm saying it's the most convenient for our purposes.
Go ahead and show me the true power of std::search and std::shared_future. Enlighten me instead of playing the arrogant uber coder.

#### bitm0de

##### Newbie
Full Member
Fair enough.

C++:
``````static DWORD WINAPI search_pattern(std::vector<BYTE> mem, DWORD base_address, const BYTE *pattern, const char *pattern_mask, DWORD offset, DWORD match_offset)
{
/* initialize vector pattern */
std::vector<std::pair<BYTE, BOOL>> pat;
for (std::size_t x = 0; x < len; ++x)
pat.push_back({ pattern[x], pattern_mask[x] != '*'} );

/* matches count for multiple results */
DWORD matches = 0;
auto iterBegin = mem.begin();
auto iterEnd = iterBegin;

/* begin searching for pattern in memory chunk vector */
while ((iterEnd = std::search(iterBegin, mem.end(), pat.begin(), pat.end(),
)) != mem.end())
{
/* if match count reached return the result */
if (matches == match_offset)
return (std::distance(mem.begin(), iterEnd) + base_address) + offset;

/* increment number of pattern occurrences found and update iterator scan start offset */
++matches;
iterBegin = iterEnd + 1;
}

return 0;
}``````
Call it with std::async() and you'll get your std::future as the result, use that however you want. Now assuming you can accurately break pieces of memory chunks up, you can scan multiple memory regions asynchronously, and have the addresses calculated for you too for multiple signature scans. This would especially demonstrate its usefulness for larger hacks where you have more than just a single signature to be concerned with. You could store the results in an std::unordered_map if you need to associate the results by some unique key for what they represent, or in a std::vector.

Last edited:

#### Rake

I was trying to make something really simple to take "EF 04 8B 1F 89 83 ?? ?? ?? ?? C7 07 8A" as input but I came up with this as an alternative, not my best work, how can I make it better without using a mask

C++:
``````byte* FindPattern(byte pattern[], int length, byte* begin, byte* end)
{
int i = 0;

for (byte* current = begin; current < end; current++)
{
//if pattern matches 100%
if (i == length)
{
return (current - length);
}

//if wildcard or matching pattern
if (pattern[i] == 0xff || *current == pattern[i])
{
i++;
continue;
}

//if no match
else
{
//reset pattern & advance to next byte
i = 0;
continue;
}
}
return 0;
}

//Call:
//0xff is the wildcard
byte* CG = FindPattern((byte*)"\xEF\04\x8B\x1F\x89\x83\xff\xff\xff\xff\xC7\x07\x8A", 13, codeBase, codeEnd);``````

#### Liduen

##### Hacker
Dank Tier VIP
Rake

C++:
``````byte* findPattern(byte pattern[], int length, byte* begin, byte* end)
{
int i = 0;
for (byte* current = begin; current < end; current++)
{
//if pattern matches 100%
if (i == length) return (current - length);

//if wildcard or matching pattern
if (pattern[i] == 0xff || *current == pattern[i]) i++;
else i = 0; //if no match reset pattern
}
return 0;
}``````
Actually this is a pretty clever way to do it.
Don't know if that 0xFF check is safe though. It could cause problems.

Last edited:

#### Rake

Rake
Actually this is a pretty clever way to do it.
Don't know if that 0xFF check is safe though. It could cause problems.
I was thinking about this last night tho, my code only tests if the pattern is a wildcard, if it is, it skips testing the actual byte in memory. So it will never compare the 0xff against the memory, therefore no problems.

Only problem is if your pattern you found contains 0xff, it will just skip over it. Not likely to find 0xff as an instruction but definately an opperand could contain the byte 0xff.

#### Liduen

##### Hacker
Dank Tier VIP
Rake;40929 said:
[...] Not likely to find 0xff as an instruction but definately an opperand could contain the byte 0xff.
That is what I was aiming at.

#### Broihon

##### edgy 12 y/o
Escobar Tier VIP
Fleep Tier Donator
I thought about this again and it's actually a nice idea and the risk can be minimizied by pointing out that wildcards are mostly used for relative 4/8 byte addresses (eg. in relative call/jmp instructions).
So my idea is not use a single byte as wildcards but a whole dword (or qword) like 0xDEADBEEF:

C++:
``````BYTE * FindPattern(BYTE * pPattern, UINT Len, BYTE * pStart, BYTE * pEnd)
{
UINT Index = 0;
for (; pStart < pEnd; ++pStart)
{
if (Index == Len)
return (pStart - Len);

if (*reinterpret_cast<DWORD*>(pPattern + Index) == 0xEFBEADDE)
{
Index += 4;
pStart += 3;
}
else if (*pStart == pPattern[Index])
Index++;
else
Index = 0;
}
return 0;
}

//EXAMPLE
BYTE ToFind[] = { 0x00, 0x01, 0x13, 0x37, 0x88, 0x99, 0x13, 0x37, 0xAB, 0xBC, 0xCD, 0xEF, 0x12, 0x88 };
int main()
{
std::cout << std::hex << (DWORD)FindPattern((BYTE*)"\x88\x99\x13\x37\xDE\xAD\xBE\xEF\x12", 9, ToFind, ToFind + sizeof(ToFind)) << std::endl;
std::cout << std::hex << (DWORD)&ToFind << std::endl;
Sleep(-1);
}``````

• #### Rake

Pretty similar to Solaire's but this works for pattern+mask combo patterns like this: "29 7b ?? 8b c7"

C++:
``````void ParsePattern(char* combo, char* pattern, char* mask)
{
unsigned int patternLen = (strlen(combo) + 1) / 3;

for (unsigned int i = 0; i < strlen(combo); i++)
{
if (combo[i] == ' ')
{
continue;
}

else if (combo[i] == '?')
{
mask[(i + 1) / 3] = '?';
i += 2;
}

else
{
char byte = (char)strtol(&combo[i], 0, 16);
pattern[(i + 1) / 3] = byte;
mask[(i + 1) / 3] = 'x';
i += 2;
}
}
pattern[patternLen] = '\0';
}

void* PatternScanExCombo(HANDLE hProcess, wchar_t* module, char* combopattern)
{
unsigned int patternLen = ((strlen(combopattern) + 1) / 3) + 1;
char* pattern = new char[patternLen];

void* match = PatternScanExModule(hProcess, module, pattern, mask);

delete[] pattern;
return match;
}``````

• Attention! Before you post:

99% of questions are answered in the Beginner's Guide, do it before asking a question.

No Hack Requests. Post in the correct section.  Search the forum first. Read the rules.

How to make a good post:

• Fill out the form correctly
• Tell us the game name & coding language 