Quote:
Originally Posted by Black_and_White
Hello everyone
I recently made a video on Internal Signature (aob) scanning. Hope you enjoy.
If you are only interested in the code here u go:
Code:
DWORD GetAddressFromSignature(std::vector<int> signature, DWORD startaddress=0, DWORD endaddress=0) {
SYSTEM_INFO si;
GetSystemInfo(&si);
if (startaddress == 0) {
startaddress = (DWORD)(si.lpMinimumApplicationAddress);
}
if (endaddress == 0) {
endaddress = (DWORD)(si.lpMaximumApplicationAddress);
}
MEMORY_BASIC_INFORMATION mbi{ 0 };
DWORD protectflags = (PAGE_GUARD | PAGE_NOCACHE | PAGE_NOACCESS);
for (DWORD i = startaddress; i < endaddress -signature.size(); i++) {
//std::cout << "scanning: " << std::hex << i << std::endl;
if (VirtualQuery((LPCVOID)i, &mbi, sizeof(mbi))) {
if (mbi.Protect & protectflags || !(mbi.State & MEM_COMMIT)) {
std::cout << "Bad Region! Region Base Address: " << mbi.BaseAddress << " | Region end address: " << std::hex << (int)((DWORD)mbi.BaseAddress + mbi.RegionSize) << std::endl;
i += mbi.RegionSize;
continue; // if bad adress then dont read from it
}
std::cout << "Good Region! Region Base Address: " << mbi.BaseAddress << " | Region end address: " << std::hex << (int)((DWORD)mbi.BaseAddress + mbi.RegionSize) << std::endl;
for (DWORD k = (DWORD)mbi.BaseAddress; k < (DWORD)mbi.BaseAddress + mbi.RegionSize - signature.size(); k++) {
for (DWORD j = 0; j < signature.size(); j++) {
if (signature.at(j) != -1 && signature.at(j) != *(byte*)(k + j))
break;
if (j + 1 == signature.size())
return k;
}
}
i = (DWORD)mbi.BaseAddress + mbi.RegionSize;
}
}
return NULL;
}
PS: Yes I did sub elitepvpers channel and I will link back to this thread 
|
You can even speed up the process if your pattern can be contained in an ASM register:
For 32bit processors: register size = 4bytes
For 64bit processors: register size = 8bytes
This code is fast for aligned memory, meaning your pattern is aligned between 16bytes (4 bytes aligned for 32 bits processors, 8 bytes aligned for 64bits)
If non aligned memory in pattern, then offset step should be 1, meaning it will be more slow.
Aligned pattern
Aligned 32bits pattern
64bits step size is 8bytes meaning it will skip those bytes, but 32bit will work fine.
Code
Code:
void cPrint(DWORD addr) {
printf("Match found: %X\n", addr);
}
...
//png signature
char pattern[] = { 0x89,0x50,0x4e,0x47,0x00,0x00,0x00,0x00 };
char mask[] = { 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00 };
int count = 0;
auto start = std::chrono::system_clock::now();
int _size = mbi.RegionSize;
char* pointer = mbi.BaseAddress;
__asm {
;int 0xCC //breakpoint debugger
mov eax, dword ptr[_size] //size of region
mov ebx, dword ptr[pointer] //save pointer in register
mov esi, dword ptr[pattern] //pattern in register
mov edi, dword ptr[mask] //mask in register
xor ecx, ecx //pointer offset
myloop :
mov edx, [ebx + ecx] //load current pointer data
and edx, edi //and between data and mask
xor edx, esi //xor between result and pattern
cmp edx, 0
je count_matches
next_offset :
add ecx, 4 //offset step: 4 for 32 bits 8 for 64 bits -- only aligned memory, not alligned should be 1
cmp ecx, eax
jl myloop
;int 0xCC
jmp c_exit
//super fast count, no print call (print is slow)
count_matches:
inc count
jmp next_offset
//print matches replace je count_matches with je match to print matches
match :
;int 0xCC
push eax //save previous value
push ecx //save value
lea edx, [ebx + ecx] //load address and pass it to print method
push edx
call cPrint
pop eax //function result
pop ecx //restore register
pop eax //restore register
jmp next_offset
}
c_exit:
auto end = std::chrono::system_clock::now();
std::chrono::duration<double> diff = end - start;
printf("matches found: %d \n", count);
std::cout << "Scan time: " << diff.count() << std::endl;
return 0;
The way this code works is supper simple:
You have a
pattern lets say:
0x01 ?? 0x03 ?? 0x05 ?? 0x7 0x8
You build a mask for that pattern that replaces ?? for 0x00 and anything else for 0xFF
So
mask:
0xFF 0x00 0xFF 0x00 0xFF 0x00 0xFF 0xFF
You go save your first value in a register -> EAX
You perform an and operation to EAX with mask, to filter ?? values
then you apply a xor between eax and your pattern, to check if they are equal. if cero means they are equal, then you have a match. Repeat until end
Edit:
Didn't saw that bump lol my bad